Index: trunk/EventBenchCore/src/de/ugoe/cs/eventbench/IReplayDecorator.java
===================================================================
--- trunk/EventBenchCore/src/de/ugoe/cs/eventbench/IReplayDecorator.java	(revision 425)
+++ 	(revision )
@@ -1,55 +1,0 @@
-package de.ugoe.cs.eventbench;
-
-import java.io.Serializable;
-
-/**
- * <p>
- * This interface defines the structure of decorators used when writing replay
- * files.
- * </p>
- * 
- * @author Steffen Herbold
- * @version 1.0
- */
-public interface IReplayDecorator extends Serializable {
-
-	/**
-	 * <p>
-	 * Header of the file. Called at the beginning of the writing.
-	 * </p>
-	 * 
-	 * @return file header
-	 */
-	String getHeader();
-
-	/**
-	 * <p>
-	 * Footer of the file. Called at the end of the writing.
-	 * </p>
-	 * 
-	 * @return file footer
-	 */
-	String getFooter();
-
-	/**
-	 * <p>
-	 * Session Header. Called before each session.
-	 * </p>
-	 * 
-	 * @param sessionId
-	 *            id of the session
-	 * @return session header
-	 */
-	String getSessionHeader(int sessionId);
-
-	/**
-	 * <p>
-	 * Session Footer. Called after each session.
-	 * </p>
-	 * 
-	 * @param sessionId
-	 *            id of the session
-	 * @return session footer
-	 */
-	String getSessionFooter(int sessionId);
-}
Index: trunk/EventBenchCore/src/de/ugoe/cs/eventbench/SequenceInstanceOf.java
===================================================================
--- trunk/EventBenchCore/src/de/ugoe/cs/eventbench/SequenceInstanceOf.java	(revision 425)
+++ 	(revision )
@@ -1,79 +1,0 @@
-package de.ugoe.cs.eventbench;
-
-import java.util.Collection;
-import java.util.List;
-import java.util.NoSuchElementException;
-
-import de.ugoe.cs.eventbench.data.Event;
-
-/**
- * <p>
- * Helper class that can be used to determine if an object is a sequence or a
- * collection of sequences. {@code instanceof} does not work, because of
- * the type erasure of generics.
- * </p>
- * 
- * @author Steffen Herbold
- * @version 1.0
- */
-public class SequenceInstanceOf {
-	
-	/**
-	 * <p>
-	 * Private constructor to prevent initializing of the class.
-	 * </p>
-	 */
-	private SequenceInstanceOf() {
-		
-	}
-
-	/**
-	 * <p>
-	 * Checks if an object is of type {@link Collection}&lt;{@link List}&lt;
-	 * {@link Event}&lt;?&gt;&gt;&gt;.
-	 * </p>
-	 * 
-	 * @param obj
-	 *            object that is checked
-	 * @return true, if the obj is of type {@link Collection}&lt;{@link List}
-	 *         &lt; {@link Event}&lt;?&gt;&gt;&gt;; false otherwise
-	 */
-	public static boolean isCollectionOfSequences(Object obj) {
-		try {
-			if (obj instanceof Collection<?>) {
-				Object listObj = ((Collection<?>) obj).iterator().next();
-				if (listObj instanceof List<?>) {
-					if (((List<?>) listObj).iterator().next() instanceof Event<?>) {
-						return true;
-					}
-				}
-			}
-		} catch (NoSuchElementException e) {
-		}
-		return false;
-	}
-
-	/**
-	 * <p>
-	 * Checks if an object is of type {@link List}&lt;{@link Event}
-	 * &lt;?&gt;&gt;.
-	 * </p>
-	 * 
-	 * @param obj
-	 *            object that is checked
-	 * @return true, if obj is of type {@link List}&lt;{@link Event}
-	 *         &lt;?&gt;&gt;; false otherwise
-	 */
-	public static boolean isEventSequence(Object obj) {
-		try {
-			if (obj instanceof List<?>) {
-				if (((List<?>) obj).iterator().next() instanceof Event<?>) {
-					return true;
-				}
-			}
-		} catch (NoSuchElementException e) {
-		}
-		return false;
-	}
-
-}
Index: trunk/EventBenchCore/src/de/ugoe/cs/eventbench/data/Event.java
===================================================================
--- trunk/EventBenchCore/src/de/ugoe/cs/eventbench/data/Event.java	(revision 425)
+++ trunk/EventBenchCore/src/de/ugoe/cs/eventbench/data/Event.java	(revision 1)
@@ -1,39 +1,7 @@
 package de.ugoe.cs.eventbench.data;
 
-import java.io.Serializable;
-import java.security.InvalidParameterException;
 
-/**
- * <p>
- * Base class for all events. An event is described by its {@link #type} and its
- * {@link #target}.
- * </p>
- * 
- * @author Steffen Herbold
- * @version 1.0
- * 
- * @param <T>
- *            Can be used to declare that events belong to a specific platform
- *            without subclassing.
- */
-public class Event<T> implements Serializable {
 
-	/**
-	 * Id for object serialization.
-	 */
-	private static final long serialVersionUID = 1L;
-
-	/**
-	 * <p>
-	 * Global start event that can be used to indicate the start of a sequence.
-	 * </p>
-	 */
-	public static final Event<Object> STARTEVENT = new Event<Object>("START");
-
-	/**
-	 * <p>
-	 * Global end event that can be used to indicate the end of a sequence.
-	 */
-	public static final Event<Object> ENDEVENT = new Event<Object>("END");
+public class Event<T> {
 
 	/**
@@ -42,11 +10,12 @@
 	 * </p>
 	 */
-	protected String type;
-
+	private String type;
+	
 	/**
-	 * </p> Target of the event.
+	 * </p>
+	 * Target of the event.
 	 */
-	protected String target = null;
-
+	private String target = null;
+	
 	/**
 	 * <p>
@@ -54,57 +23,24 @@
 	 * </p>
 	 */
-	protected String targetShort = null;
+	private String targetShort = null;
 
-	/**
-	 * Further information about the event that shall be included in its Id.
-	 */
-	protected String idInfo = "";
 
-	/**
-	 * <p>
-	 * Constructor. Creates a new Event with a given type.
-	 * </p>
-	 * 
-	 * @param type
-	 *            type of the event
-	 */
+	
+
+	private String idInfo = null;
+	
 	public Event(String type) {
-		if (type == null) {
-			throw new InvalidParameterException("Event type must not be null");
-		}
 		this.type = type;
 	}
 
-	/**
-	 * <p>
-	 * Two events are equal, if their {@link #type} and {@link #target} are
-	 * equal.
-	 * </p>
-	 * <p>
-	 * See {@link Object#equals(Object)} for further information.
-	 * </p>
-	 * 
-	 * @param other
-	 *            Event that is compared to this
-	 * @return true, if events are equal, false otherwise
-	 */
 	@Override
 	public boolean equals(Object other) {
-		if (this == other) {
+		if( this==other ) {
 			return true;
 		}
 		if (other instanceof Event<?>) {
-			Event<?> otherEvent = (Event<?>) other;
-			if (otherEvent.canEqual(this)) {
-				if (type != null) {
-					return targetEquals(otherEvent.target)
-							&& type.equals(otherEvent.type);
-				} else {
-					return targetEquals(otherEvent.target)
-							&& otherEvent.type == null;
-				}
-			} else {
-				return false;
-			}
+			Event<?> otherToken = (Event<?>) other;
+			return otherToken.type.equals(this.type)
+					&& otherToken.target.equals(this.target);
 		} else {
 			return false;
@@ -112,69 +48,22 @@
 	}
 
-	public boolean canEqual(Object other) {
-		return (other instanceof Event<?>);
-	}
-
-	/**
-	 * <p>
-	 * Returns {@link #getStandardId()} as String representation of the event.
-	 * </p>
-	 * 
-	 * @return String represenation of the event
-	 */
-	@Override
-	public String toString() {
-		return getStandardId();
-	}
-
-	/**
-	 * Informations about the event important for its Id that is neither target
-	 * nor type.
-	 * 
-	 * @return {@link #idInfo} of the event
-	 */
 	public String getIdInfo() {
 		return idInfo;
 	}
 
-	/**
-	 * <p>
-	 * If {@link #targetShort} is set, a shortend version of the Id is returned
-	 * of the form {@link #targetShort}.{@link #type}.{@link #idInfo} is
-	 * returned. Otherwise the standard Id is returned (see
-	 * {@link #getStandardId()}).
-	 * </p>
-	 * 
-	 * @return if available, shortend Id string; {@link #getStandardId()}
-	 *         otherwise
-	 */
 	public String getShortId() {
 		String shortId = null;
-		if (targetShort != null) {
-			shortId = targetShort + "." + getType();
-			if (!"".equals(idInfo)) {
-				shortId += "." + idInfo;
+		if (targetShort!=null) {
+			shortId = targetShort+"."+getType();
+			if (idInfo!=null) {
+				shortId += "."+idInfo;
 			}
-		} else {
-			shortId = getStandardId();
 		}
 		return shortId;
 	}
 
-	/**
-	 * <p>
-	 * Returns the Id string of the event. It has the form {@link #target}.
-	 * {@link #type}.{@link #idInfo};
-	 * <p>
-	 * 
-	 * @return Id string of the event
-	 */
 	public String getStandardId() {
-		String id = "";
-		if (target != null) {
-			id += target + ".";
-		}
-		id += getType();
-		if (!"".equals(idInfo)) {
+		String id = target + "." + getType();
+		if ( idInfo!=null ) {
 			id += "." + idInfo;
 		}
@@ -182,79 +71,41 @@
 	}
 
-	/**
-	 * <p>
-	 * Returns the {@link #target} of the event.
-	 * </p>
-	 * 
-	 * @return {@link #target} of the event
-	 */
 	public String getTarget() {
 		return target;
 	}
-
-	/**
-	 * <p>
-	 * Returns the {@link #targetShort} of the event.
-	 * </p>
-	 * 
-	 * @return {@link #targetShort} of the event
-	 */
-	protected String getTargetShort() {
+	
+	public String getTargetShort() {
 		return targetShort;
 	}
 
-	/**
-	 * <p>
-	 * Returns the {@link #type} of the event.
-	 * </p>
-	 * 
-	 * @return {@link #type} of the event
-	 */
 	public String getType() {
 		return type;
 	}
 
-	/*
-	 * (non-Javadoc)
-	 * 
-	 * @see java.lang.Object#hashCode()
-	 */
 	@Override
 	public int hashCode() {
 		int multiplier = 17;
 		int hash = 42;
-		if (type != null) {
-			hash = multiplier * hash + type.hashCode();
+		hash = multiplier * hash + type.hashCode();
+		if( target!=null ) {
+			hash = multiplier * hash + target.hashCode();
 		}
-		hash = multiplier * hash + targetHashCode();
 
 		return hash;
 	}
 
-	/**
-	 * <p>
-	 * Sets the {@link #idInfo} of the event. The idInfo is optional and
-	 * contains information important for the event's Id that is neither target
-	 * nor type.
-	 * </p>
-	 * 
-	 * @param info
-	 *            {@link #idInfo} of the event
-	 */
 	public void setIdInfo(String info) {
 		idInfo = info;
 	}
-
+	
 	/**
 	 * <p>
 	 * Sets the target of the event. Once set, the target cannot be changed.
-	 * </p>
-	 * 
-	 * @param target
-	 *            target of the event
+	 * </p> 
+	 * @param target target of the event
 	 * @return true, if target was changed, false otherwise
 	 */
 	public boolean setTarget(String target) {
-		if (this.target != null) {
+		if( this.target!=null ) {
 			return false;
 		}
@@ -262,17 +113,14 @@
 		return true;
 	}
-
+	
 	/**
 	 * <p>
-	 * Sets the short description of the event target. Once set, the target
-	 * cannot be changed.
-	 * </p>
-	 * 
-	 * @param targetShort
-	 *            short target description
+	 * Sets the short description of the event target. Once set, the target cannot be changed.
+	 * </p> 
+	 * @param targetShort short target description
 	 * @return true, if target was changed, false otherwise
 	 */
 	public boolean setTargetShort(String targetShort) {
-		if (this.targetShort != null) {
+		if( this.targetShort!=null ) {
 			return false;
 		}
@@ -280,48 +128,3 @@
 		return true;
 	}
-
-	/**
-	 * <p>
-	 * This function is used by {@link #equals(Object)} to determine if the
-	 * targets of both events are equal. The standard implementation provided by
-	 * this class performs a String comparison between the target strings.
-	 * </p>
-	 * <p>
-	 * Subclasses can override this method to implemented more sophisticated
-	 * means for the target comparison, e.g., to account for changes in the
-	 * title of a widget.
-	 * </p>
-	 * 
-	 * @param otherTarget
-	 *            other target string to which the target if this event is
-	 *            compared to
-	 * @return true if the targets are equals; false otherwise
-	 */
-	protected boolean targetEquals(String otherTarget) {
-		boolean retVal;
-		if (target != null) {
-			retVal = target.equals(otherTarget);
-		} else {
-			retVal = (otherTarget == null);
-		}
-		return retVal;
-	}
-
-	/**
-	 * <p>
-	 * This function is used by {@link #hashCode()} to determine how the hash of
-	 * the {@link #target}. It has to be overridden by subclasses that implement
-	 * {@link #targetEquals(String)}, to ensure that the equals/hashCode
-	 * contract remains valid.
-	 * </p>
-	 * 
-	 * @return hash of the target
-	 */
-	protected int targetHashCode() {
-		if (target != null) {
-			return target.hashCode();
-		} else {
-			return 0;
-		}
-	}
 }
Index: trunk/EventBenchCore/src/de/ugoe/cs/eventbench/data/IReplayable.java
===================================================================
--- trunk/EventBenchCore/src/de/ugoe/cs/eventbench/data/IReplayable.java	(revision 425)
+++ trunk/EventBenchCore/src/de/ugoe/cs/eventbench/data/IReplayable.java	(revision 1)
@@ -1,35 +1,8 @@
 package de.ugoe.cs.eventbench.data;
 
-import java.io.Serializable;
-
-/**
- * <p>
- * This interface is used by {@link ReplayableEvent}to describe how events can
- * be replayed. It can be used to define a sequence of fine-grained platform
- * events that make up an abstract event.
- * </p>
- * 
- * @author Steffen Herbold
- * @version 1.0
- */
-public interface IReplayable extends Serializable {
-
-	/**
-	 * <p>
-	 * Returns a string to be written to the replay script that describes the
-	 * replayable platform event.
-	 * </p>
-	 * 
-	 * @return string for the replay script
-	 */
-	String getReplay();
-
-	/**
-	 * <p>
-	 * Returns the target of the replayable.
-	 * </p>
-	 * 
-	 * @return target of the replayable
-	 */
+public interface IReplayable {
+	
+	String getReplayXml();
+	
 	String getTarget();
 }
Index: trunk/EventBenchCore/src/de/ugoe/cs/eventbench/data/ReplayableEvent.java
===================================================================
--- trunk/EventBenchCore/src/de/ugoe/cs/eventbench/data/ReplayableEvent.java	(revision 425)
+++ trunk/EventBenchCore/src/de/ugoe/cs/eventbench/data/ReplayableEvent.java	(revision 1)
@@ -1,167 +1,46 @@
 package de.ugoe.cs.eventbench.data;
 
-import java.security.InvalidParameterException;
 import java.util.LinkedList;
 import java.util.List;
 
-import de.ugoe.cs.eventbench.IReplayDecorator;
-
-/**
- * <p>
- * Subclass of {@link Event} for events that contain all informations required
- * for replaying them, i.e., generating scripts that can used for automated
- * software execution.
- * </p>
- * 
- * @author Steffen Herbold
- * @version 1.0
- * 
- * @param <T>
- *            Allows only types that extend {@link IReplayable} and is used to
- *            define a list of replayables that describe the replay of the
- *            event.
- */
 public class ReplayableEvent<T extends IReplayable> extends Event<T> {
 
-	/**
-	 * Id for object serialization.
-	 */
-	private static final long serialVersionUID = 1L;
+	private List<T> replayEvents = new LinkedList<T>();;
 
-	/**
-	 * <p>
-	 * List of {@link IReplayable}s of type T that describes the replay of an
-	 * event. The {@link IReplayable}s can be interpreted as <it>sub-events</it>
-	 * on the platform level that make up the abstract event.
-	 * </p>
-	 */
-	protected List<T> replayEvents = new LinkedList<T>();;
-
-	/**
-	 * <p>
-	 * Defines whether the replay is valid or invalid. It may be invalid, e.g.,
-	 * due to errors during the generation of the event or lack of vital
-	 * information.
-	 * </p>
-	 */
-	protected boolean replayValid = true;
-
-	/**
-	 * <p>
-	 * {@link IReplayDecorator} used when replays of this type are written.
-	 * </p>
-	 */
-	protected IReplayDecorator decorator = null;
-
-	/**
-	 * <p>
-	 * Constructor. Creates a new event with the given type.
-	 * <p>
-	 * 
-	 * @param type
-	 *            type of the event
-	 * @see Event#Event(String)
-	 */
+	private boolean replayValid = true;
+	
 	public ReplayableEvent(String type) {
 		super(type);
 	}
-
-	/**
-	 * <p>
-	 * Adds a new {@link IReplayable} of type T to the replay sequence.
-	 * </p>
-	 * 
-	 * @param replayable
-	 *            element that is added to the sequence
-	 * @throws InvalidParameterException
-	 *             thrown is replayable is null
-	 */
-	public void addReplayEvent(T replayable) {
-		if (replayable == null) {
-			throw new InvalidParameterException("replayble must not be null");
-		}
-		replayEvents.add(replayable);
-	}
-
-	/**
-	 * <p>
-	 * Adds a {@link List}ist of {@link IReplayable} to the replay sequence.
-	 * </p>
-	 * 
-	 * @param generatedReplaySeq
-	 *            {@link List} that is added to the sequence
-	 * @throws InvalidParameterException
-	 *             thrown if generatedReplaySeq is null
-	 */
+	
 	public void addReplaySequence(List<T> generatedReplaySeq) {
-		if (generatedReplaySeq == null) {
-			throw new InvalidParameterException(
-					"generatedReplaySeq must not be null");
-		}
 		replayEvents.addAll(generatedReplaySeq);
 	}
 
-	/**
-	 * <p>
-	 * Returns the {@link IReplayDecorator} of the event.
-	 * </p>
-	 * 
-	 * @return {@link IReplayDecorator} of the event; null if no decorator has
-	 *         been set
-	 */
-	public IReplayDecorator getReplayDecorator() {
-		return decorator;
+	public void addReplayEvent(T replayable) {
+		replayEvents.add(replayable);
 	}
-
+	
 	/**
 	 * <p>
 	 * Returns a the list of replay events.
-	 * </p>
+	 * </p> 
 	 * <p>
 	 * The return value is a copy of the list used internally!
 	 * </p>
-	 * 
-	 * @return list of replay events.
+	 * @return list of replay events. 
 	 */
 	public List<T> getReplayMessages() {
 		return new LinkedList<T>(replayEvents);
 	}
-
-	/**
-	 * <p>
-	 * Returns whether the replay is valid or not.
-	 * </p>
-	 * 
-	 * @return true, if replay is valid; false otherwise.
-	 */
+	
 	public boolean hasValidReplay() {
 		return replayValid;
 	}
 
-	/**
-	 * <p>
-	 * Marks the replay as invalid. Once marked as invalid, it remains so and
-	 * cannot be changed back to valid.
-	 * </p>
-	 */
 	public void invalidateReplay() {
 		replayValid = false;
 	}
 
-	/**
-	 * <p>
-	 * Sets the {@link IReplayDecorator} associated with the event.
-	 * </p>
-	 * 
-	 * @param decorator
-	 *            decorator associated with the event
-	 */
-	public void setDecorator(IReplayDecorator decorator) {
-		this.decorator = decorator;
-	}
-	
-	@Override
-	public boolean canEqual(Object other) {
-		return (other instanceof ReplayableEvent<?>);
-	}
+
 }
Index: trunk/EventBenchCore/src/de/ugoe/cs/eventbench/markov/DotPrinter.java
===================================================================
--- trunk/EventBenchCore/src/de/ugoe/cs/eventbench/markov/DotPrinter.java	(revision 1)
+++ trunk/EventBenchCore/src/de/ugoe/cs/eventbench/markov/DotPrinter.java	(revision 1)
@@ -0,0 +1,5 @@
+package de.ugoe.cs.eventbench.markov;
+
+public interface DotPrinter {
+	public abstract void printDot();
+}
Index: trunk/EventBenchCore/src/de/ugoe/cs/eventbench/markov/IMemory.java
===================================================================
--- trunk/EventBenchCore/src/de/ugoe/cs/eventbench/markov/IMemory.java	(revision 1)
+++ trunk/EventBenchCore/src/de/ugoe/cs/eventbench/markov/IMemory.java	(revision 1)
@@ -0,0 +1,40 @@
+package de.ugoe.cs.eventbench.markov;
+
+import java.util.List;
+
+/**
+ * <p>
+ * This interface defines basic functions for classes that implement a memory
+ * about the recent events of a sequences.
+ * </p>
+ * 
+ * @author Steffen Herbold
+ * @version 1.0
+ * 
+ * @param <T>
+ *            Type of the sequence elements that are memorized.
+ */
+public interface IMemory<T> {
+
+	/**
+	 * Adds an element to the end of the memory.
+	 * 
+	 * @param element
+	 *            Element to be added.
+	 */
+	public void add(T element);
+
+	/**
+	 * <p>
+	 * Returns the last <code>num</code> memorized elements. If the history is
+	 * shorter than <code>num</code>, the length of the returned
+	 * {@link java.util.List} may be less than <code>num</code>.
+	 * </p>
+	 * 
+	 * @param num
+	 *            Number of states from the end of the memory to be returned.
+	 * @return {@link java.util.List} of memorized elements.
+	 */
+	public List<T> getLast(int num);
+
+}
Index: trunk/EventBenchCore/src/de/ugoe/cs/eventbench/markov/IncompleteMemory.java
===================================================================
--- trunk/EventBenchCore/src/de/ugoe/cs/eventbench/markov/IncompleteMemory.java	(revision 1)
+++ trunk/EventBenchCore/src/de/ugoe/cs/eventbench/markov/IncompleteMemory.java	(revision 1)
@@ -0,0 +1,33 @@
+package de.ugoe.cs.eventbench.markov;
+
+import java.util.LinkedList;
+import java.util.List;
+
+public class IncompleteMemory<T> implements IMemory<T> {
+
+	private int length;
+	
+	private List<T> history;
+	
+	public IncompleteMemory(int length) {
+		this.length = length;
+		history = new LinkedList<T>();
+	}
+	
+	@Override
+	public void add(T state) {
+		if( history.size()==length ) {
+			history.remove(0);
+		}
+		history.add(state);
+	}
+
+	@Override
+	public List<T> getLast(int num) {
+		return new LinkedList<T>(history); // defensive copy
+	}
+
+	public int getLength() {
+		return history.size();
+	}
+}
Index: trunk/EventBenchCore/src/de/ugoe/cs/eventbench/markov/MarkovModel.java
===================================================================
--- trunk/EventBenchCore/src/de/ugoe/cs/eventbench/markov/MarkovModel.java	(revision 1)
+++ trunk/EventBenchCore/src/de/ugoe/cs/eventbench/markov/MarkovModel.java	(revision 1)
@@ -0,0 +1,242 @@
+package de.ugoe.cs.eventbench.markov;
+
+import java.util.ArrayList;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Random;
+
+import Jama.Matrix;
+
+import de.ugoe.cs.eventbench.data.Event;
+import de.ugoe.cs.util.console.Console;
+import edu.uci.ics.jung.graph.Graph;
+import edu.uci.ics.jung.graph.SparseMultigraph;
+import edu.uci.ics.jung.graph.util.EdgeType;
+
+public class MarkovModel implements DotPrinter {
+
+	private State initialState;
+	private State endState;
+	
+	private List<State> states;
+	private List<String> stateIdList;
+	
+	private Random r;
+	
+	final static int MAX_STATDIST_ITERATIONS = 1000;
+	
+	/**
+	 * <p>
+	 * Default constructor. Creates a new random number generator.
+	 * </p>
+	 */
+	public MarkovModel() {
+		this(new Random());
+	}
+	
+	/**
+	 * <p>
+	 * Creates a new {@link MarkovModel} with a predefined random number generator.
+	 * </p>
+	 * 
+	 * @param r random number generator
+	 */
+	public MarkovModel(Random r) {
+		this.r = r; // defensive copy would be better, but constructor Random(r) does not seem to exist.
+	}
+	
+	public void printRandomWalk() {
+		State currentState = initialState;
+		IMemory<State> history = new IncompleteMemory<State>(5); // this is NOT used here, just for testing ...
+		history.add(currentState);
+		Console.println(currentState.getId());
+		while(!currentState.equals(endState)) {
+			currentState = currentState.getNextState();
+			Console.println(currentState.getId());
+			history.add(currentState);
+		}
+	}
+	
+	public List<? extends Event<?>> randomSequence() {
+		List<Event<?>> sequence = new LinkedList<Event<?>>();
+		State currentState = initialState;
+		if( currentState.getAction()!=null ) {
+			sequence.add(currentState.getAction());
+		}
+		System.out.println(currentState.getId());
+		while(!currentState.equals(endState)) {
+			currentState = currentState.getNextState();
+			if( currentState.getAction()!=null ) {
+				sequence.add(currentState.getAction());
+			}
+			System.out.println(currentState.getId());
+		}
+		return sequence;
+	}
+	
+	public void printDot() {
+		int numUnprintableStates = 0;
+		System.out.println("digraph model {");
+		for( State state : states ) {
+			if( state instanceof DotPrinter ) {
+				((DotPrinter) state).printDot();
+			} else {
+				numUnprintableStates++;
+			}
+		}
+		System.out.println('}');
+		if( numUnprintableStates>0 ) {
+			Console.println("" + numUnprintableStates + "/" + states.size() + "were unprintable!");
+		}
+	}
+	
+	public Graph<String, MarkovEdge> getGraph() {
+		Graph<String, MarkovEdge> graph = new SparseMultigraph<String, MarkovEdge>();
+		
+		for( State state : states) {
+			try {
+				SimpleState simpleState = (SimpleState) state;
+				String from = simpleState.getShortId();
+				for( int i=0 ; i<simpleState.toStates.size() ; i++ ) {
+					SimpleState toState = (SimpleState) simpleState.toStates.get(i);
+					String to = toState.getShortId();
+					MarkovEdge prob = new MarkovEdge(simpleState.transitionProbs.get(i));
+					graph.addEdge(prob, from, to, EdgeType.DIRECTED);
+				}
+			} catch (ClassCastException e) {
+				// TODO: handle exception
+			}
+		}
+		
+		return graph;
+	}
+	
+	static public class MarkovEdge {
+		double weight;
+		MarkovEdge(double weight) { this.weight = weight; }
+		public String toString() { return ""+weight; }
+	}
+	
+	/////////////////////////////////////////////////////////////////////////////////////
+	// Code to learn type1 model: states are wndid.action and transitions are unlabled //
+	/////////////////////////////////////////////////////////////////////////////////////
+	
+	public void train(List<List<Event<?>>> sequences) {
+		Event<?> fromElement = null;
+		Event<?> toElement = null;
+		SimpleState fromState;
+		SimpleState toState;
+		
+		states = new ArrayList<State>();
+		stateIdList = new ArrayList<String>();
+		initialState = new SimpleState("GLOBALSTARTSTATE", null);
+		initialState.setRandom(r);
+		states.add(initialState);
+		stateIdList.add("GLOBALSTARTSTATE");
+		endState = new SimpleState("GLOBALENDSTATE", null);
+		endState.setRandom(r);
+		states.add(endState);
+		stateIdList.add("GLOBALENDSTATE");
+		for( List<Event<?>> sequence : sequences ) {
+			for( int i=0; i<sequence.size() ; i++ ) {
+				if( i==0 ) {
+					fromState = (SimpleState) initialState;
+				} else {
+					fromElement = sequence.get(i-1);
+					fromState = findOrCreateSimpleState(fromElement);
+				}
+				
+				toElement = sequence.get(i);
+				toState = findOrCreateSimpleState(toElement);
+				
+				fromState.incTransTo(toState);
+				
+				if( i==sequence.size()-1 ) {
+					toState.incTransTo(endState);
+				}
+			}
+		}
+	}
+	
+	private SimpleState findOrCreateSimpleState(Event<?> action) {
+		SimpleState state = null;
+		String id = action.getStandardId();
+		String idShort = action.getShortId();
+		int index = stateIdList.indexOf(id);
+		if( index!=-1 ) {
+			state = (SimpleState) states.get(index);
+		} else {
+			state = new SimpleState(id, action, idShort);
+			state.setRandom(r);
+			states.add(state);
+			stateIdList.add(id);
+		}
+		return state;
+	}
+	
+	///////////////////////////////////////////////////////////
+	
+	// states must be SimpleState, this functions will throw bad cast exceptions
+	public double calcEntropy() {
+		int numStates = states.size();
+		// create transmission matrix
+		Matrix transmissionMatrix = new Matrix(numStates, numStates);
+		for( int i=0 ; i<numStates ; i++ ) {
+			State tmpState = states.get(i);
+			if( SimpleState.class.isInstance(tmpState) ) {
+				SimpleState currentState = (SimpleState) tmpState;
+				for( int j=0 ; j<numStates ; j++ ) {
+					double prob = currentState.getProb(states.get(j));
+					transmissionMatrix.set(i, j, prob);
+				}
+			} else {
+				Console.printerr("Error calculating entropy. Only allowed for first-order markov models.");
+				return Double.NaN;
+			}
+		}
+		
+		// Add transition from endState to startState. This makes the markov chain irreducible and recurrent. 
+		int startStateIndex = states.indexOf(initialState);
+		int endStateIndex = states.indexOf(endState);
+		if( startStateIndex==-1 ) {
+			Console.printerrln("Error calculating entropy. Initial state of markov chain not found.");
+			return Double.NaN;
+		}
+		if( endStateIndex==-1 ) {
+			Console.printerrln("Error calculating entropy. End state of markov chain not found.");
+			return Double.NaN;
+		}
+		transmissionMatrix.set(endStateIndex, startStateIndex, 1);
+		
+		// Calculate stationary distribution by raising the power of the transmission matrix.
+		// The rank of the matrix should fall to 1 and each two should be the vector of the
+		// stationory distribution. 
+		int iter = 0;
+		int rank = transmissionMatrix.rank();
+		Matrix stationaryMatrix = (Matrix) transmissionMatrix.clone();
+		while( iter<MAX_STATDIST_ITERATIONS && rank>1 ) {
+			stationaryMatrix = stationaryMatrix.times(stationaryMatrix);
+			rank = stationaryMatrix.rank();
+			iter++;
+		}
+		
+		if( rank!=1 ) {
+			Console.traceln("rank: " + rank);
+			Console.printerrln("Unable to calculate stationary distribution.");
+			return Double.NaN;
+		}
+		
+		double entropy = 0.0;
+		for( int i=0 ; i<numStates ; i++ ) {
+			for( int j=0 ; j<numStates ; j++ ) {
+				if( transmissionMatrix.get(i,j)!=0 ) {
+					double tmp = stationaryMatrix.get(i, 0);
+					tmp *= transmissionMatrix.get(i, j);
+					tmp *= Math.log(transmissionMatrix.get(i,j))/Math.log(2);
+					entropy -= tmp;
+				}
+			}
+		}
+		return entropy;
+	}
+}
Index: trunk/EventBenchCore/src/de/ugoe/cs/eventbench/markov/SimpleState.java
===================================================================
--- trunk/EventBenchCore/src/de/ugoe/cs/eventbench/markov/SimpleState.java	(revision 1)
+++ trunk/EventBenchCore/src/de/ugoe/cs/eventbench/markov/SimpleState.java	(revision 1)
@@ -0,0 +1,100 @@
+package de.ugoe.cs.eventbench.markov;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import de.ugoe.cs.eventbench.data.Event;
+
+
+/**
+ * This class implements a simple first-order markov state. 
+ * Transitions are unlabled.
+ * @author Steffen Herbold
+ */
+public class SimpleState extends State implements DotPrinter {
+	
+	List<Double> transitionProbs;
+	List<State> toStates;
+	
+	// members for learning
+	private int transitionsObserved;
+	
+	private String idShort = null;
+	
+	public SimpleState(String id, Event<?> action) {
+		super(id, action);
+		transitionsObserved = 0;
+		toStates = new ArrayList<State>();
+		transitionProbs = new ArrayList<Double>();
+	}
+	
+	public SimpleState(String id, Event<?> action, String idShort) {
+		this(id, action);
+		this.idShort = idShort;
+	}
+	
+	@Override
+	public State getNextState() {
+		double randVal = rand.nextDouble();
+		double probSum = 0;
+		int index = 0;
+		while( index<transitionProbs.size() && probSum+transitionProbs.get(index) < randVal ) {
+			probSum += transitionProbs.get(index);
+			index++;
+		}
+		return toStates.get(index);
+	}
+	
+	public void incTransTo(State state) {
+		int index = toStates.indexOf(state);
+		if( index==-1 ) {
+			toStates.add(state);
+			transitionProbs.add(0.0);
+			index = toStates.size()-1;
+		}
+		// update trans probs
+		for( int i=0 ; i<toStates.size() ; i++ ) {
+			double currentProb = transitionProbs.get(i);
+			double newProb = 0.0;
+			if( i!=index ) {
+				newProb = (currentProb*transitionsObserved)/(transitionsObserved+1);
+			} else {
+				newProb = ((currentProb*transitionsObserved)+1)/(transitionsObserved+1);
+			}
+			transitionProbs.set(i, newProb);
+		}
+		transitionsObserved++;
+	}
+	
+	// get the transition probability to the given state
+	public double getProb(State state) {
+		double prob = 0.0;
+		int index = toStates.indexOf(state);
+		if( index>=0 ) {
+			prob = transitionProbs.get(index);
+		}
+		return prob;
+	}
+	
+	public String getShortId() {
+		String shortId;
+		if( idShort!=null ) {
+			shortId = idShort;
+		} else {
+			shortId = getId();
+		}
+		return shortId;
+	}
+
+	@Override
+	public void printDot() {
+		final String thisSaneId = getShortId().replace("\"", "\\\"").replaceAll("[\r\n]","");
+		System.out.println(" " + hashCode() + " [label=\""+thisSaneId+"\"];");
+		for(int i=0 ; i<toStates.size() ; i++ ) {
+			System.out.print(" "+hashCode()+" -> " + toStates.get(i).hashCode() + " ");
+			System.out.println("[label=\"" + transitionProbs.get(i) + "\"];");
+		}
+		
+	}
+	
+}
Index: trunk/EventBenchCore/src/de/ugoe/cs/eventbench/markov/State.java
===================================================================
--- trunk/EventBenchCore/src/de/ugoe/cs/eventbench/markov/State.java	(revision 1)
+++ trunk/EventBenchCore/src/de/ugoe/cs/eventbench/markov/State.java	(revision 1)
@@ -0,0 +1,97 @@
+package de.ugoe.cs.eventbench.markov;
+
+import java.util.Random;
+
+import de.ugoe.cs.eventbench.data.Event;
+
+public abstract class State {
+	
+	/**
+	 * {@link Event} associated with the state. 
+	 */
+	private Event<?> action;
+	
+	/**
+	 * Identifier of the state
+	 */
+	private String id;
+	
+	/**
+	 * Random number generator used for state transmissions. 
+	 */
+	protected Random rand;
+	
+	/**
+	 * State transmission function to be used by models. 
+	 * @return
+	 */
+	public abstract State getNextState();
+	
+	/**
+	 * Creates a new State object. The id should be unique.
+	 * @param id identifier string of the state
+	 */
+	protected State(String id, Event<?> action) {
+		this.id = id;
+		this.action = action;
+	}
+
+	/**
+	 * Dummy method for history-less state implementations.
+	 */
+	public void setHistoryObject() {}
+	
+	/**
+	 * Defines a random number generator to be used by getNextState.
+	 * @param r Random number generator
+	 */
+	public void setRandom(Random r) {
+		rand = r;
+	}
+	
+	/**
+	 * Returns the id of the state. 
+	 * @return id of the state
+	 */
+	public String getId() {
+		return id;
+	}
+	
+	/**
+	 * The {@link Event} associated with this state. 
+	 * @return {@link Event} associated with this state
+	 */
+	public Event<?> getAction() {
+		return action;
+	}
+	
+	/**
+	 * Two states are equal if their id string is equal.
+	 */
+	@Override
+	public boolean equals(Object other) {
+		if( other==this ) {
+			return true;
+		}
+		boolean isEqual = false;
+		if( other instanceof State ) {
+			isEqual = id.equals(((State) other).id);
+		}
+		return isEqual;
+	}
+	
+	
+	/* (non-Javadoc)
+	 * @see java.lang.Object#hashCode()
+	 */
+	@Override
+	public int hashCode() {
+		int multiplier = 37;
+		int hash = 42;
+		
+		hash = multiplier*hash + id.hashCode();
+		
+		return hash;
+	}
+	
+}
Index: trunk/EventBenchCore/src/de/ugoe/cs/eventbench/ppm/PredictionByPartialMatch.java
===================================================================
--- trunk/EventBenchCore/src/de/ugoe/cs/eventbench/ppm/PredictionByPartialMatch.java	(revision 1)
+++ trunk/EventBenchCore/src/de/ugoe/cs/eventbench/ppm/PredictionByPartialMatch.java	(revision 1)
@@ -0,0 +1,106 @@
+package de.ugoe.cs.eventbench.ppm;
+
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Random;
+import java.util.Set;
+
+import de.ugoe.cs.eventbench.data.Event;
+import de.ugoe.cs.eventbench.markov.IncompleteMemory;
+import de.ugoe.cs.util.console.Console;
+
+public class PredictionByPartialMatch {
+	
+	private String initialSymbol = "GLOBALSTARTSTATE";
+	private String endSymbol = "GLOBALENDSTATE";
+	
+	private int maxOrder = 3;
+	
+	private Trie<String> trie;
+	
+	private Set<String> knownSymbols;
+	
+	// the training is basically the generation of the trie
+	public void train(List<List<Event<?>>> sequences) {
+		trie = new Trie<String>();
+		knownSymbols = new LinkedHashSet<String>();
+		knownSymbols.add(initialSymbol);
+		knownSymbols.add(endSymbol);
+		
+		for(List<Event<?>> sequence : sequences) {
+			IncompleteMemory<String> latestActions = new IncompleteMemory<String>(maxOrder); // TODO need to check if it should be maxOrder+1
+			latestActions.add(initialSymbol);
+			for(Event<?> currentAction : sequence) {
+				String currentId = currentAction.getStandardId();
+				latestActions.add(currentId);
+				knownSymbols.add(currentId);
+				if( latestActions.getLength()==maxOrder ) { // FIXME needs special case for sequences shorter than maxOrder
+					trie.add(latestActions.getLast(maxOrder));
+				}
+			}
+			latestActions.add(endSymbol);
+			if( latestActions.getLength()==maxOrder ) { // FIXME needs special case for sequences shorter than maxOrder
+				trie.add(latestActions.getLast(maxOrder));
+			}
+		}
+	}
+	
+	public void printRandomWalk(Random r) {
+		IncompleteMemory<String> context = new IncompleteMemory<String>(maxOrder-1);
+		
+		context.add(initialSymbol);
+		
+		String currentState = initialSymbol;
+		
+		Console.println(currentState);
+		while(!endSymbol.equals(currentState)) {
+			double randVal = r.nextDouble();
+			double probSum = 0.0;
+			List<String> currentContext = context.getLast(maxOrder);
+			for( String symbol : knownSymbols ) {
+				probSum += getProbability(currentContext, symbol);
+				if( probSum>=randVal ) {
+					currentContext.add(symbol);
+					currentState = symbol;
+					Console.println(currentState);
+					break;
+				}
+			}
+		}
+	}
+	
+	private double getProbability(List<String> context, String symbol) {
+		double result = 0.0; 
+		int countContextSymbol = 0;
+		List<String> contextSuffix = trie.getContextSuffix(context);
+		if( contextSuffix.isEmpty() ) {
+			result = 1.0d / knownSymbols.size(); 
+		} else {
+			countContextSymbol = trie.getCount(contextSuffix, symbol);
+			List<String> followers = trie.getFollowingSymbols(contextSuffix);
+			int countContextFollowers = 0;
+			for( String follower : followers ) {
+				countContextFollowers += trie.getCount(contextSuffix, follower);
+			}
+			
+			if( followers.isEmpty() ) {
+				throw new AssertionError("Invalid return value of getContextSuffix!");
+			}
+			if( countContextSymbol!=0 ) {
+				result = ((double) countContextSymbol) / (followers.size()+countContextFollowers);
+			} else { // escape
+				double probEscape = ((double) followers.size()) / (followers.size()+countContextFollowers);
+				contextSuffix.remove(0);
+				double probSuffix = getProbability(contextSuffix, symbol);
+				result = probEscape*probSuffix;
+			}
+		}
+
+		return result;
+	}
+	
+	@Override
+	public String toString() {
+		return trie.toString();
+	}
+}
Index: trunk/EventBenchCore/src/de/ugoe/cs/eventbench/ppm/Trie.java
===================================================================
--- trunk/EventBenchCore/src/de/ugoe/cs/eventbench/ppm/Trie.java	(revision 1)
+++ trunk/EventBenchCore/src/de/ugoe/cs/eventbench/ppm/Trie.java	(revision 1)
@@ -0,0 +1,100 @@
+package de.ugoe.cs.eventbench.ppm;
+
+import java.util.LinkedList;
+import java.util.List;
+
+public class Trie<T> {
+	
+	private List<TrieNode<T>> children = new LinkedList<TrieNode<T>>();
+	
+
+	public void add(List<T> subsequence) {
+		if( !subsequence.isEmpty() ) {
+			subsequence = new LinkedList<T>(subsequence);  // copy list!
+			T firstSymbol = subsequence.get(0);
+			getChildCreate(firstSymbol).add(subsequence);
+		}
+	}
+
+	// FIXME clones of TrieNode.getChildCreate
+	protected TrieNode<T>  getChildCreate(T symbol) {
+		TrieNode<T> node = getChild(symbol);
+		if( node==null ) {
+			node = new TrieNode<T>(symbol);
+			children.add(node);
+		}
+		return node;
+	}
+	
+	// FIXME clones of TrieNode.getChild
+	protected TrieNode<T> getChild(T symbol) {
+		for( TrieNode<T> child : children ) {
+			if( child.getSymbol().equals(symbol) ) {
+				return child;
+			}
+		}
+		return null;
+	}
+
+	public int getCount(List<T> sequence) {
+		int count = 0;
+		TrieNode<T> node = find(sequence);
+		if( node!=null ) {
+			count = node.getCount();
+		}
+		return count;
+	}
+	
+	public int getCount(List<T> sequence, T follower) {
+		List<T> tmpSequence = new LinkedList<T>(sequence);
+		tmpSequence.add(follower);
+		return getCount(tmpSequence);
+		
+	}
+	
+	public TrieNode<T> find(List<T> sequence) {
+		TrieNode<T> result = null;
+		if( !sequence.isEmpty() ) {
+			TrieNode<T> node = getChild(sequence.get(0));
+			if( node!=null ) {
+				result = node.find(sequence);
+			}
+		}
+		return result;
+	}
+	
+	public List<T> getFollowingSymbols(List<T> sequence) {
+		List<T> result = null;
+		TrieNode<T> node = find(sequence);
+		if( node!=null ) {
+			result = node.getFollowingSymbols();
+		}
+		return result;
+	}
+	
+	public List<T> getContextSuffix(List<T> context) {
+		List<T> contextSuffix = new LinkedList<T>(context);
+		boolean suffixFound = false;
+		
+		while(!suffixFound) {
+			if( contextSuffix.isEmpty() ) {
+				suffixFound = true; // suffix is the empty word
+			} else {
+				TrieNode<T> node = find(contextSuffix);
+				if( node!=null ) {
+					if( !node.getFollowingSymbols().isEmpty() ) {
+						suffixFound = true;
+					}
+				}
+				contextSuffix.remove(0);
+			}
+		}
+		
+		return contextSuffix;
+	}
+	
+	@Override
+	public String toString() {
+		return children.toString();
+	}
+}
Index: trunk/EventBenchCore/src/de/ugoe/cs/eventbench/ppm/TrieNode.java
===================================================================
--- trunk/EventBenchCore/src/de/ugoe/cs/eventbench/ppm/TrieNode.java	(revision 1)
+++ trunk/EventBenchCore/src/de/ugoe/cs/eventbench/ppm/TrieNode.java	(revision 1)
@@ -0,0 +1,99 @@
+package de.ugoe.cs.eventbench.ppm;
+
+import java.security.InvalidParameterException;
+import java.util.LinkedList;
+import java.util.List;
+
+import de.ugoe.cs.util.StringTools;
+
+
+class TrieNode<T> {
+	
+	private int count;
+	private final T symbol;
+	
+	private List<TrieNode<T>> children;
+	
+	public TrieNode(T symbol) {
+		if( symbol==null ) {
+			throw new InvalidParameterException("symbol must not be null.");
+		}
+		this.symbol = symbol;
+		count = 0;
+		children = new LinkedList<TrieNode<T>>();
+	}
+
+	public void add(List<T> subsequence) {
+		if( !subsequence.isEmpty() ) {
+			if( !symbol.equals(subsequence.get(0)) ) { // should be guaranteed by the recursion/TrieRoot!
+				throw new AssertionError("Invalid trie operation!");
+			}
+			count++;
+			subsequence.remove(0);
+			if( !subsequence.isEmpty() ) {
+				T nextSymbol = subsequence.get(0);
+				getChildCreate(nextSymbol).add(subsequence);
+			}
+		}
+	}
+	
+	public T getSymbol() {
+		return symbol;
+	}
+	
+	public int getCount() {
+		return count;
+	}
+	
+	protected TrieNode<T>  getChildCreate(T symbol) {
+		TrieNode<T> node = getChild(symbol);
+		if( node==null ) {
+			node = new TrieNode<T>(symbol);
+			children.add(node);
+		}
+		return node;
+	}
+	
+	protected TrieNode<T> getChild(T symbol) {
+		for( TrieNode<T> child : children ) {
+			if( child.getSymbol().equals(symbol) ) {
+				return child;
+			}
+		}
+		return null;
+	}
+	
+
+	
+	public TrieNode<T> find(List<T> subsequence) {
+		TrieNode<T> result = null;
+		if( subsequence.isEmpty() ) {
+			result = this;
+		} else {
+			TrieNode<T> node = getChild(subsequence.get(0));
+			if( node!=null ) {
+				subsequence.remove(0);
+				result = node.find(subsequence);
+			}
+		}
+		return result;
+	}
+	
+	public List<T> getFollowingSymbols() {
+		List<T> followingSymbols = new LinkedList<T>();
+		for( TrieNode<T> child : children ) {
+			followingSymbols.add(child.getSymbol());
+		}
+		return followingSymbols;
+	}
+	
+	@Override
+	public String toString() {
+		String str = symbol.toString()+" #"+count;
+		if( !children.isEmpty() ) {
+			str += StringTools.ENDLINE + children.toString();
+		}
+		return str; 
+	}
+
+}
