Index: branches/autoquest-core-tasktrees-alignment/src/main/java/de/ugoe/cs/autoquest/tasktrees/alignment/algorithms/Match.java
===================================================================
--- branches/autoquest-core-tasktrees-alignment/src/main/java/de/ugoe/cs/autoquest/tasktrees/alignment/algorithms/Match.java	(revision 1743)
+++ branches/autoquest-core-tasktrees-alignment/src/main/java/de/ugoe/cs/autoquest/tasktrees/alignment/algorithms/Match.java	(revision 1747)
@@ -149,5 +149,5 @@
 	 * Task id sum. Used for comparing and sorting matches
 	 *
-	 * @return 
+	 * @return the int
 	 */
 	public int taskIdSum() {
@@ -161,8 +161,16 @@
 	}
 	
-	public Match cloneWithoutOccurences() throws CloneNotSupportedException  {
-		Match result;
-		result = (Match) this.clone();
-		result.occurrences.clear();
+	
+	
+	/**
+	 * Clone without occurrences.
+	 *
+	 * @return the match
+	 * @throws CloneNotSupportedException the clone not supported exception
+	 */
+	public Match cloneWithoutOccurrences()   {
+		Match result = new Match();
+		result.setFirstSequence(this.getFirstSequence());
+		result.setSecondSequence(this.getSecondSequence());
 		return result;
 	}
Index: branches/autoquest-core-tasktrees-alignment/src/main/java/de/ugoe/cs/autoquest/tasktrees/alignment/algorithms/NumberSequence.java
===================================================================
--- branches/autoquest-core-tasktrees-alignment/src/main/java/de/ugoe/cs/autoquest/tasktrees/alignment/algorithms/NumberSequence.java	(revision 1743)
+++ branches/autoquest-core-tasktrees-alignment/src/main/java/de/ugoe/cs/autoquest/tasktrees/alignment/algorithms/NumberSequence.java	(revision 1747)
@@ -2,4 +2,5 @@
  * 
  */
+
 package de.ugoe.cs.autoquest.tasktrees.alignment.algorithms;
 
@@ -13,240 +14,260 @@
  */
 public class NumberSequence implements Serializable {
-	
-	/** The Constant serialVersionUID. */
-	private static final long serialVersionUID = -4604570107534055589L;
-	
-	/** The sequence. */
-	private int[] sequence;
-	
-	/** The id. */
-	private int id;
-
-	/**
-	 * Instantiates a new number sequence.
-	 *
-	 * @param size the size
-	 */
-	public NumberSequence(int size) {
-
-		sequence = new int[size];
-	}
-
-	// Searching occurrences of pattern
-	/**
-	 * Contains pattern.
-	 *
-	 * @param pattern the pattern
-	 * @return the linked list
-	 */
-	public LinkedList<Integer> containsPattern(Match pattern) {
-		final LinkedList<Integer> result = new LinkedList<Integer>();
-		int i = 0;
-		final int[] pat1 = pattern.getFirstSequence().getSequence();
-		final int[] pat2 = pattern.getSecondSequence().getSequence();
-
-		while (i < sequence.length) {
-			if (matches(i, pat1, pat2, 0, 0, false, false, false, false, false)) {
-				result.add(i);
-			}
-			i++;
-		}
-		return result;
-	}
-
-	/**
-	 * Equals.
-	 *
-	 * @param n the n
-	 * @return true, if successful
-	 */
-	public boolean equals(NumberSequence n) {
-		final int[] seq = n.getSequence();
-		if (n.size() != this.size()) {
-			return false;
-		}
-		for (int i = 0; i < n.size(); i++) {
-			if (seq[i] != this.sequence[i]) {
-				return false;
-			}
-		}
-		return true;
-	}
-
-	// Returns the number of times event occurs in this sequence
-	/**
-	 * Event count.
-	 *
-	 * @param event the event
-	 * @return the int
-	 */
-	public int eventCount(int event) {
-		int count = 0;
-		for (int i = 0; i < sequence.length; i++) {
-			if (sequence[i] == event) {
-				count++;
-			}
-		}
-		return count;
-	}
-
-	/**
-	 * Gets the id.
-	 *
-	 * @return the id
-	 */
-	public int getId() {
-		return id;
-	}
-
-	/**
-	 * Gets the sequence.
-	 *
-	 * @return the sequence
-	 */
-	public int[] getSequence() {
-		return sequence;
-	}
-
-	// Recursive check if sequence contains pattern at position i
-	/**
-	 * Matches.
-	 *
-	 * @param i the i
-	 * @param p1 the p1
-	 * @param p2 the p2
-	 * @param ip1 the ip1
-	 * @param ip2 the ip2
-	 * @param jumped1 the jumped1
-	 * @param jumped2 the jumped2
-	 * @param hadSelection the had selection
-	 * @param matchseq1 the matchseq1
-	 * @param matchseq2 the matchseq2
-	 * @return true, if successful
-	 */
-	private boolean matches(int i, int[] p1, int[] p2, int ip1, int ip2,
-			boolean jumped1, // True if there was a gap in Sequence 1 of the
-								// pattern
-			boolean jumped2, // True if there was a gap in Sequence 2 of the
-								// pattern
-			boolean hadSelection, // True if the last match was a selection
-			boolean matchseq1, boolean matchseq2) {
-
-		if (p1.length == ip1) {
-			return true;
-		}
-		if (p2.length == ip2) {
-			return true;
-		}
-		if (i == sequence.length) {
-			return false;
-		}
-
-		final boolean foundselection = (!(p1[ip1] == p2[ip2]) && !((p1[ip1] == -1) || (p2[ip2] == -1)));
-		final boolean matchInFirstPattern = (p1[ip1] == sequence[i]);
-		final boolean matchInSecondPattern = (p2[ip2] == sequence[i]);
-
-		if (foundselection && hadSelection) {
-			if ((matchInFirstPattern && matchseq1)
-					|| (matchInSecondPattern && matchseq2)) {
-				if (jumped1) {
-					return matches(i + 1, p1, p2, ip1 + 1, ip2 + 2, false,
-							false, foundselection, matchInFirstPattern,
-							matchInSecondPattern);
-				}
-				if (jumped2) {
-					return matches(i + 1, p1, p2, ip1 + 2, ip2 + 1, false,
-							false, foundselection, matchInFirstPattern,
-							matchInSecondPattern);
-				}
-				return matches(i + 1, p1, p2, ip1 + 1, ip2 + 1, false, false,
-						foundselection, matchInFirstPattern,
-						matchInSecondPattern);
-			} else {
-				return false;
-			}
-		}
-
-		if ((matchInFirstPattern || matchInSecondPattern) && jumped1) {
-			return matches(i + 1, p1, p2, ip1 + 1, ip2 + 2, false, false,
-					foundselection, matchInFirstPattern, matchInSecondPattern);
-		}
-		if ((matchInFirstPattern || matchInSecondPattern) && jumped2) {
-			return matches(i + 1, p1, p2, ip1 + 2, ip2 + 1, false, false,
-					foundselection, matchInFirstPattern, matchInSecondPattern);
-		}
-		if (matchInFirstPattern || matchInSecondPattern) {
-			return matches(i + 1, p1, p2, ip1 + 1, ip2 + 1, false, false,
-					foundselection, matchInFirstPattern, matchInSecondPattern);
-		}
-		if (p1[ip1] == -1) {
-			return matches(i, p1, p2, ip1 + 1, ip2, true, false, false, false,
-					false);
-		}
-		if (p2[ip2] == -1) {
-			return matches(i, p1, p2, ip1, ip2 + 1, false, true, false, false,
-					false);
-		}
-
-		return false;
-	}
-
-	/**
-	 * Prints the sequence.
-	 */
-	public void printSequence() {
-		for (int i = 0; i < sequence.length; i++) {
-			System.out.format("%5d", sequence[i]);
-		}
-		System.out.println();
-	}
-
-	/**
-	 * Sets the id.
-	 *
-	 * @param id the new id
-	 */
-	public void setId(int id) {
-		this.id = id;
-	}
-
-	/**
-	 * Sets the sequence.
-	 *
-	 * @param sequence the new sequence
-	 */
-	public void setSequence(int[] sequence) {
-		this.sequence = sequence;
-	}
-
-	/**
-	 * Shuffle.
-	 *
-	 * @return the number sequence
-	 */
-	public NumberSequence shuffle() {
-		final NumberSequence result = new NumberSequence(sequence.length);
-		result.setId(getId());
-		result.setSequence(this.sequence);
-		final Random rgen = new Random();
-
-		for (int i = 0; i < result.sequence.length; i++) {
-			final int randomPosition = rgen.nextInt(result.sequence.length);
-			final int temp = result.sequence[i];
-			result.sequence[i] = result.sequence[randomPosition];
-			result.sequence[randomPosition] = temp;
-		}
-		return result;
-
-	}
-
-	/**
-	 * Size.
-	 *
-	 * @return the int
-	 */
-	public int size() {
-		return sequence.length;
-	}
+
+    /** The Constant serialVersionUID. */
+    private static final long serialVersionUID = -4604570107534055589L;
+
+    /** The sequence. */
+    private int[] sequence;
+
+    /** The id. */
+    private int id;
+
+    /**
+     * Instantiates a new number sequence.
+     *
+     * @param size
+     *            the size
+     */
+    public NumberSequence(int size) {
+
+        sequence = new int[size];
+    }
+
+    // Searching occurrences of pattern
+    /**
+     * Contains pattern.
+     *
+     * @param pattern
+     *            the pattern
+     * @return the linked list
+     */
+    public LinkedList<Integer> containsPattern(Match pattern) {
+        final LinkedList<Integer> result = new LinkedList<Integer>();
+        int i = 0;
+        final int[] pat1 = pattern.getFirstSequence().getSequence();
+        final int[] pat2 = pattern.getSecondSequence().getSequence();
+
+        while (i < sequence.length) {
+            if (matches(i, pat1, pat2, 0, 0, false, false, false, false, false)) {
+                result.add(i);
+            }
+            i++;
+        }
+        return result;
+    }
+
+    /**
+     * Equals.
+     *
+     * @param n
+     *            the n
+     * @return true, if successful
+     */
+    public boolean equals(NumberSequence n) {
+        final int[] seq = n.getSequence();
+        if (n.size() != this.size()) {
+            return false;
+        }
+        for (int i = 0; i < n.size(); i++) {
+            if (seq[i] != this.sequence[i]) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    // Returns the number of times event occurs in this sequence
+    /**
+     * Event count.
+     *
+     * @param event
+     *            the event
+     * @return the int
+     */
+    public int eventCount(int event) {
+        int count = 0;
+        for (int i = 0; i < sequence.length; i++) {
+            if (sequence[i] == event) {
+                count++;
+            }
+        }
+        return count;
+    }
+
+    /**
+     * Gets the id.
+     *
+     * @return the id
+     */
+    public int getId() {
+        return id;
+    }
+
+    /**
+     * Gets the sequence.
+     *
+     * @return the sequence
+     */
+    public int[] getSequence() {
+        return sequence;
+    }
+
+    // Recursive check if sequence contains pattern at position i
+    /**
+     * Matches.
+     *
+     * @param i
+     *            the position in the sequence
+     * @param p1
+     *            the p1
+     * @param p2
+     *            the p2
+     * @param ip1
+     *            the ip1
+     * @param ip2
+     *            the ip2
+     * @param jumped1
+     *            the jumped1
+     * @param jumped2
+     *            the jumped2
+     * @param hadSelection
+     *            the had selection
+     * @param matchseq1
+     *            the matchseq1
+     * @param matchseq2
+     *            the matchseq2
+     * @return true, if successful
+     */
+    private boolean matches(int i, int[] p1, int[] p2, int ip1, int ip2, boolean jumped1, // True if
+                                                                                          // there
+                                                                                          // was a
+                                                                                          // gap in
+                                                                                          // Sequence
+                                                                                          // 1 of
+                                                                                          // the
+                                                                                          // pattern
+                            boolean jumped2, // True if there was a gap in Sequence 2 of the
+                                             // pattern
+                            boolean hadSelection, // True if the last match was a selection
+                            boolean matchseq1,
+                            boolean matchseq2)
+    {
+
+        if (p1.length == ip1) {
+            return true;
+        }
+        if (p2.length == ip2) {
+            return true;
+        }
+        if (i == sequence.length) {
+            return false;
+        }
+
+        final boolean foundselection =
+            (!(p1[ip1] == p2[ip2]) && !((p1[ip1] == -1) || (p2[ip2] == -1)));
+        final boolean matchInFirstPattern = (p1[ip1] == sequence[i]);
+        final boolean matchInSecondPattern = (p2[ip2] == sequence[i]);
+
+        if (foundselection && hadSelection) {
+            if ((matchInFirstPattern && matchseq1) || (matchInSecondPattern && matchseq2)) {
+                if (jumped1) {
+                    return matches(i + 1, p1, p2, ip1 + 1, ip2 + 2, false, false, foundselection,
+                                   matchInFirstPattern, matchInSecondPattern);
+                }
+                if (jumped2) {
+                    return matches(i + 1, p1, p2, ip1 + 2, ip2 + 1, false, false, foundselection,
+                                   matchInFirstPattern, matchInSecondPattern);
+                }
+                return matches(i + 1, p1, p2, ip1 + 1, ip2 + 1, false, false, foundselection,
+                               matchInFirstPattern, matchInSecondPattern);
+            }
+            else {
+                return false;
+            }
+        }
+
+        if ((matchInFirstPattern || matchInSecondPattern) && jumped1) {
+            return matches(i + 1, p1, p2, ip1 + 1, ip2 + 2, false, false, foundselection,
+                           matchInFirstPattern, matchInSecondPattern);
+        }
+        if ((matchInFirstPattern || matchInSecondPattern) && jumped2) {
+            return matches(i + 1, p1, p2, ip1 + 2, ip2 + 1, false, false, foundselection,
+                           matchInFirstPattern, matchInSecondPattern);
+
+        }
+        if (matchInFirstPattern || matchInSecondPattern) {
+            return matches(i + 1, p1, p2, ip1 + 1, ip2 + 1, false, false, foundselection,
+                           matchInFirstPattern, matchInSecondPattern);
+        }
+        if (p1[ip1] == -1) {
+            return matches(i, p1, p2, ip1 + 1, ip2, true, false, false, false, false);
+        }
+        if (p2[ip2] == -1) {
+            return matches(i, p1, p2, ip1, ip2 + 1, false, true, false, false, false);
+        }
+
+        return false;
+    }
+
+    /**
+     * Prints the sequence.
+     */
+    public void printSequence() {
+        for (int i = 0; i < sequence.length; i++) {
+            System.out.format("%5d", sequence[i]);
+        }
+        System.out.println();
+    }
+
+    /**
+     * Sets the id.
+     *
+     * @param id
+     *            the new id
+     */
+    public void setId(int id) {
+        this.id = id;
+    }
+
+    /**
+     * Sets the sequence.
+     *
+     * @param sequence
+     *            the new sequence
+     */
+    public void setSequence(int[] sequence) {
+        this.sequence = sequence;
+    }
+
+    /**
+     * Shuffle.
+     *
+     * @return the number sequence
+     */
+    public NumberSequence shuffle() {
+        final NumberSequence result = new NumberSequence(sequence.length);
+        result.setId(getId());
+        result.setSequence(this.sequence);
+        final Random rgen = new Random();
+
+        for (int i = 0; i < result.sequence.length; i++) {
+            final int randomPosition = rgen.nextInt(result.sequence.length);
+            final int temp = result.sequence[i];
+            result.sequence[i] = result.sequence[randomPosition];
+            result.sequence[randomPosition] = temp;
+        }
+        return result;
+
+    }
+
+    /**
+     * Size.
+     *
+     * @return the int
+     */
+    public int size() {
+        return sequence.length;
+    }
 
 }
Index: branches/autoquest-core-tasktrees-alignment/src/main/java/de/ugoe/cs/autoquest/tasktrees/alignment/matrix/ObjectDistanceSubstitionMatrix.java
===================================================================
--- branches/autoquest-core-tasktrees-alignment/src/main/java/de/ugoe/cs/autoquest/tasktrees/alignment/matrix/ObjectDistanceSubstitionMatrix.java	(revision 1743)
+++ branches/autoquest-core-tasktrees-alignment/src/main/java/de/ugoe/cs/autoquest/tasktrees/alignment/matrix/ObjectDistanceSubstitionMatrix.java	(revision 1747)
@@ -109,5 +109,5 @@
 			eti1 = (IEventTaskInstance) ti1;
 			index1 = getIndex(eti1);
-			distance = distanceBetweenTaskAndInstance(task2, eti1);
+			distance = distanceBetweenTaskAndInstance(task2, eti1)-3;
 		} else if (!(ti1 instanceof IEventTaskInstance)
 				&& (ti2 instanceof IEventTaskInstance)) {
@@ -120,5 +120,5 @@
 			index1 = getIndex(task1);
 			index2 = getIndex(task2);
-			distance = distanceBetweenTasks(task1, task2);
+			distance = distanceBetweenTasks(task1, task2)-3;
 		} else {
 			System.out.println("Unknown error");
@@ -212,5 +212,5 @@
 		this.uniqueTasks = uniqueTasks;
 		if (this.calculateNonEventTaskInstances) {
-			matrix = new DynamicTriangleMatrix(uniqueTasks.size() + 1);
+			matrix = new PreallocatedDynamicTriangleMatrix(uniqueTasks.size() + 1);
 			Console.traceln(Level.INFO, "searching EventTasks in Tasks");
 			//searchEventTaskInstances();
Index: branches/autoquest-core-tasktrees-alignment/src/main/java/de/ugoe/cs/autoquest/tasktrees/alignment/matrix/PreallocatedDynamicTriangleMatrix.java
===================================================================
--- branches/autoquest-core-tasktrees-alignment/src/main/java/de/ugoe/cs/autoquest/tasktrees/alignment/matrix/PreallocatedDynamicTriangleMatrix.java	(revision 1747)
+++ branches/autoquest-core-tasktrees-alignment/src/main/java/de/ugoe/cs/autoquest/tasktrees/alignment/matrix/PreallocatedDynamicTriangleMatrix.java	(revision 1747)
@@ -0,0 +1,119 @@
+/*
+ * 
+ */
+package de.ugoe.cs.autoquest.tasktrees.alignment.matrix;
+
+import java.io.Serializable;
+
+// TODO: Auto-generated Javadoc
+/**
+ * The Class StaticTriangleMatrix.
+ */
+public class PreallocatedDynamicTriangleMatrix implements ITriangleMatrix, Serializable {
+
+	/** The Constant serialVersionUID. */
+	private static final long serialVersionUID = 7599542322424894866L;
+	
+	/** The matrix. */
+	private float[] matrix;
+	
+	/** The size. */
+	protected int size;
+	
+	private int actualsize;
+	private float initalizationValue;
+
+	/**
+	 * Instantiates a new static triangle matrix.
+	 *
+	 * @param size the size
+	 */
+	public PreallocatedDynamicTriangleMatrix(int size) {
+		this.size = size;
+		this.actualsize = size*10;
+		matrix = new float[(actualsize * (actualsize + 1)) / 2];
+	}
+
+	/* (non-Javadoc)
+	 * @see de.ugoe.cs.autoquest.tasktrees.alignment.matrix.ITriangleMatrix#get(int, int)
+	 */
+	@Override
+	public float get(int first, int second) {
+		final int row = Math.min(first, second);
+		final int col = Math.max(first, second);
+		return matrix[(row * actualsize) - (((row * (row + 1)) / 2) - (actualsize - col))];
+
+	}
+
+	/* (non-Javadoc)
+	 * @see de.ugoe.cs.autoquest.tasktrees.alignment.matrix.ITriangleMatrix#increaseSize(int)
+	 */
+	@Override
+	public void increaseSize(int count) throws Exception {
+	    final int oldsize = size;
+            this.size += count;
+            if(size>actualsize) {
+                int newElements = ((oldsize * count) + ((count * (count + 1)) / 2));
+                actualsize*=2;
+                float[] newmatrix = new float[actualsize];
+                System.arraycopy(this.matrix, 0, newmatrix, 0,matrix.length);
+                for(int i=oldsize;i<actualsize;i++) {
+                    newmatrix[i]=this.initalizationValue;
+                }
+                matrix = newmatrix;
+            }
+	}
+
+	/* (non-Javadoc)
+	 * @see de.ugoe.cs.autoquest.tasktrees.alignment.matrix.ITriangleMatrix#initialize(float)
+	 */
+	@Override
+	public void initialize(float value) {
+	        this.initalizationValue = value;
+		for (int i = 0; i < matrix.length; i++) {
+			matrix[i] = value;
+		}
+	}
+
+	/* (non-Javadoc)
+	 * @see de.ugoe.cs.autoquest.tasktrees.alignment.matrix.ITriangleMatrix#set(int, int, float)
+	 */
+	@Override
+	public void set(int first, int second, float value) {
+		final int row = Math.min(first, second);
+		final int col = Math.max(first, second);
+		matrix[(row * actualsize) - (((row * (row + 1)) / 2) - (actualsize - col))] = value;
+	}
+
+	/* (non-Javadoc)
+	 * @see de.ugoe.cs.autoquest.tasktrees.alignment.matrix.ITriangleMatrix#size()
+	 */
+	@Override
+	public int size() {
+		return size;
+	}
+
+	/* (non-Javadoc)
+	 * @see java.lang.Object#toString()
+	 */
+	@Override
+	public String toString() {
+		String result = "";
+		for (int i = 0; i < actualsize; i++) {
+			for (int j = 0; j < actualsize; j++) {
+				if (i < j) {
+					if (Float.isInfinite(this.get(i, j))) {
+						result = result + " -------";
+					} else {
+						result = result
+								+ String.format("%+8.2f", this.get(i, j));
+					}
+				} else {
+					result = result + ("        ");
+				}
+			}
+			result = result + "\n";
+		}
+		return result;
+	}
+}
Index: branches/autoquest-core-tasktrees-alignment/src/main/java/de/ugoe/cs/autoquest/tasktrees/temporalrelation/RuleUtils.java
===================================================================
--- branches/autoquest-core-tasktrees-alignment/src/main/java/de/ugoe/cs/autoquest/tasktrees/temporalrelation/RuleUtils.java	(revision 1743)
+++ branches/autoquest-core-tasktrees-alignment/src/main/java/de/ugoe/cs/autoquest/tasktrees/temporalrelation/RuleUtils.java	(revision 1747)
@@ -15,4 +15,5 @@
 package de.ugoe.cs.autoquest.tasktrees.temporalrelation;
 
+import de.ugoe.cs.autoquest.tasktrees.treeifc.IIteration;
 import de.ugoe.cs.autoquest.tasktrees.treeifc.IMarkingTemporalRelationship;
 import de.ugoe.cs.autoquest.tasktrees.treeifc.IStructuringTemporalRelationship;
@@ -65,5 +66,12 @@
 		final ISequenceInstance subsequence = taskFactory
 				.createNewTaskInstance(model);
-		/*
+		
+		//System.out.println("STARTINDEX: " + startIndex);
+		//System.out.println("PRINTING SEQUENCE: ");
+		//for(int i =0; i< parent.size();i++) {
+		//    System.out.println(i + ": " +parent.get(i));
+		//}
+		System.out.println();
+		
 		System.out.println("PRINTING MODEL: ");
 		for (int i = 0; i < subsequence.getSequence().getChildren().size(); i++) {
@@ -97,5 +105,5 @@
 		}
 		System.out.println();
-                */
+                
 		// TODO: This is dirty, return this in addition with the sequence
 		// instance instead
@@ -110,9 +118,9 @@
 			//System.out.println("Trying to add " + parent.get(startIndex)
 			// + " to the model instance " + tempTask);
-			if (tempTask.getType() == "optionality") {
-
-				if (((IMarkingTemporalRelationship) tempTask).getMarkedTask() == parent
-						.get(startIndex).getTask()) {
-					// System.out.println("Adding OptionalInstance " +
+			if (tempTask instanceof IOptional) {
+
+			        if (((IMarkingTemporalRelationship) tempTask).getMarkedTask().equals(parent
+                                              .get(startIndex).getTask())) {
+					 //System.out.println("Adding OptionalInstance " +
 					// parent.get(startIndex) + " to " + tempTask.getType());
 					final IOptionalInstance optional = taskFactory
@@ -121,5 +129,5 @@
 					taskBuilder.addChild(subsequence, optional);
 				} else {
-					// System.out.println("Adding Empty optional, not deleting anything from the input sequence");
+					 //System.out.println("Adding Empty optional, not deleting anything from the input sequence");
 					final IOptionalInstance optional = taskFactory
 							.createNewTaskInstance((IOptional) tempTask);
@@ -211,7 +219,7 @@
 					taskBuilder.addChild(subsequence, selection);
 				}
-			} else if (tempTask.getType() == "sequence") {
+			} else if (tempTask instanceof ISequence) {
 				taskBuilder.addChild(subsequence, parent.get(startIndex));
-			} else if (tempTask.getType() == "iteration") {
+			} else if (tempTask instanceof IIteration) {
 				taskBuilder.addChild(subsequence, parent.get(startIndex));
 			} else {
@@ -227,4 +235,50 @@
 	}
 
+	
+	/*
+	static boolean containsOptional(ISequence seq) {
+	  for(int i = 0; i < seq.getChildren().size();i++) {
+	      if(seq.getChildren().get(i) instanceof IOptional) {
+	          return true;
+	      }
+	  }  
+	      return false;
+	}
+	
+	private boolean reachesEnd(ITaskInstanceList parent, ISequence model,int sequenceIndex,int modelIndex,int startIndex) {
+	    
+	    if(modelIndex == model.getChildren().size()) {
+	        return true;
+	    }
+	    ITask modelTask = model.getChildren().get(modelIndex);
+	    ITask sessionTask = parent.get(startIndex+sequenceIndex).getTask();
+	    if(modelTask instanceof IOptional) {
+	            reachesEnd(parent,model,sequenceIndex++,modelIndex++,startIndex);
+	            reachesEnd(parent,model,sequenceIndex,modelIndex++,startIndex);
+	    }
+	    
+	    boolean taskfits=false;
+	    if(modelTask instanceof ISequence) {
+	        if(sessionTask.equals(((ISequence)modelTask).getChildren().get(0))) {
+	            taskfits=true;
+	        }
+	    }
+	    if(modelTask instanceof IIteration) {
+	        if(sessionTask.equals(((ISequence)modelTask).getChildren().get(0))) {
+                    taskfits=true;
+                }
+	    }
+	    if(modelTask instanceof ISelection) {
+	        
+	    }
+	    
+        return taskfits;
+	    
+	    
+	    
+	}
+	*/
+
+	
 	/**
 	 * <p>
Index: branches/autoquest-core-tasktrees-alignment/src/main/java/de/ugoe/cs/autoquest/tasktrees/temporalrelation/SequenceForTaskDetectionRuleAlignment.java
===================================================================
--- branches/autoquest-core-tasktrees-alignment/src/main/java/de/ugoe/cs/autoquest/tasktrees/temporalrelation/SequenceForTaskDetectionRuleAlignment.java	(revision 1743)
+++ branches/autoquest-core-tasktrees-alignment/src/main/java/de/ugoe/cs/autoquest/tasktrees/temporalrelation/SequenceForTaskDetectionRuleAlignment.java	(revision 1747)
@@ -58,12 +58,10 @@
 /**
  * <p>
- * This class implements the major rule for creating task trees based on a set
- * of recorded user sessions. For this, it first harmonizes all tasks. This
- * eases later comparison. Then it searches the sessions for iterations and
- * replaces them accordingly. Then it searches for sub sequences using alignment
- * algorithms For each found sub sequence, it replaces the occurrences by
- * creating appropriate {@link ISequence}s. Afterwards, again searches for
- * iterations and then again for sub sequences until no more replacements are
- * done.
+ * This class implements the major rule for creating task trees based on a set of recorded user
+ * sessions. For this, it first harmonizes all tasks. This eases later comparison. Then it searches
+ * the sessions for iterations and replaces them accordingly. Then it searches for sub sequences
+ * using alignment algorithms For each found sub sequence, it replaces the occurrences by creating
+ * appropriate {@link ISequence}s. Afterwards, again searches for iterations and then again for sub
+ * sequences until no more replacements are done.
  * </p>
  * <p>
@@ -74,1237 +72,1250 @@
 public class SequenceForTaskDetectionRuleAlignment implements ISessionScopeRule {
 
-	/** The n threads. */
-	//public static int nThreads = Runtime.getRuntime().availableProcessors() - 1;
-	public static int nThreads = 1;
-
-	/** The iteration. */
-	private int iteration = 0;
-
-	/**
-	 * <p>
-	 * the task factory to be used for creating substructures for the temporal
-	 * relationships identified during rul application
-	 * </p>
-	 * .
-	 */
-	private final ITaskFactory taskFactory;
-
-	/**
-	 * <p>
-	 * the task builder to be used for creating substructures for the temporal
-	 * relationships identified during rule application
-	 * </p>
-	 * .
-	 */
-	private final ITaskBuilder taskBuilder;
-
-	/**
-	 * <p>
-	 * the task handling strategy to be used for comparing tasks for
-	 * preparation, i.e., before the tasks are harmonized
-	 * </p>
-	 */
-	private final TaskHandlingStrategy preparationTaskHandlingStrategy;
-
-	/**
-	 * <p>
-	 * instantiates the rule and initializes it with a task equality to be
-	 * considered when comparing tasks as well as a task factory and builder to
-	 * be used for creating task structures.
-	 * </p>
-	 * 
-	 * @param minimalTaskEquality
-	 *            the task equality to be considered when comparing tasks
-	 * @param taskFactory
-	 *            the task factory to be used for creating substructures
-	 * @param taskBuilder
-	 *            the task builder to be used for creating substructures
-	 */
-
-	SequenceForTaskDetectionRuleAlignment(TaskEquality minimalTaskEquality,
-			ITaskFactory taskFactory, ITaskBuilder taskBuilder) {
-		this.taskFactory = taskFactory;
-		this.taskBuilder = taskBuilder;
-
-		this.preparationTaskHandlingStrategy = new TaskHandlingStrategy(
-				minimalTaskEquality);
-	}
-
-	/*
-	 * (non-Javadoc)
-	 * 
-	 * @see
-	 * de.ugoe.cs.autoquest.tasktrees.temporalrelation.ISessionScopeRule#apply
-	 * (java.util.List)
-	 */
-	@Override
-	public RuleApplicationResult apply(List<IUserSession> sessions) {
-		final RuleApplicationData appData = new RuleApplicationData(sessions);
-
-		harmonizeEventTaskInstancesModel(appData);
-
-		Console.traceln(Level.INFO, "generating substitution matrix from "
-				+ appData.getUniqueTasks().size() + " unique tasks");
-		appData.getStopWatch().start("substitution matrix");
-		appData.getSubmat().generate(appData.getUniqueTasks());
-		appData.getStopWatch().stop("substitution matrix");
-
-		Console.traceln(Level.INFO, "Starting main loop");
-		do {
-			Console.traceln(Level.INFO, "Iteration Number: " + iteration);
-			iteration++;
-			appData.detectedAndReplacedTasks = false;
-			appData.getStopWatch().start("whole loop");
-			detectAndReplaceIterations(appData);
-			appData.getStopWatch().start("task replacement");
-			// Just does anything if the substitution matrix is created with the
-			// option to do so
-			appData.updateSubstitutionMatrix();
-			detectAndReplaceTasks(appData); //
-			appData.getStopWatch().stop("task replacement");
-			appData.getStopWatch().stop("whole loop");
-			// appData.getStopWatch().dumpStatistics(System.out);
-			appData.getStopWatch().reset();
-
-		} while (appData.detectedAndReplacedTasks());
-
-		Console.println("created "
-				+ appData.getResult().getNewlyCreatedTasks().size()
-				+ " new tasks and "
-				+ appData.getResult().getNewlyCreatedTaskInstances().size()
-				+ " appropriate instances\n");
-
-		if ((appData.getResult().getNewlyCreatedTasks().size() > 0)
-				|| (appData.getResult().getNewlyCreatedTaskInstances().size() > 0)) {
-			appData.getResult().setRuleApplicationStatus(
-					RuleApplicationStatus.FINISHED);
-		}
-		// new TaskTreeValidator().validate(appData.getSessions());
-		return appData.getResult();
-	}
-
-	/**
-	 * Creates the number sequences.
-	 *
-	 * @param appData
-	 *            the app data
-	 * @return the array list
-	 */
-	private ArrayList<NumberSequence> createNumberSequences(
-			RuleApplicationData appData) {
-		final ArrayList<NumberSequence> result = new ArrayList<NumberSequence>();
-		for (int i = 0; i < appData.getSessions().size(); i++) {
-			final IUserSession session = appData.getSessions().get(i);
-			final NumberSequence templist = new NumberSequence(session.size());
-			for (int j = 0; j < session.size(); j++) {
-				final ITaskInstance taskInstance = session.get(j);
-				templist.getSequence()[j] = taskInstance.getTask().getId();
-			}
-			// Each NumberSequence is identified by its id, beginning to count
-			// at zero
-			templist.setId(i);
-			result.add(templist);
-		}
-		return result;
-	}
-
-	/**
-	 * <p>
-	 * searches for direct iterations of single tasks in all sequences and
-	 * replaces them with {@link IIteration}s, respectively appropriate
-	 * instances. Also all single occurrences of a task that is iterated
-	 * somewhen are replaced with iterations to have again an efficient way for
-	 * task comparisons.
-	 * </p>
-	 * 
-	 * @param appData
-	 *            the rule application data combining all data used for applying
-	 *            this rule
-	 */
-	private void detectAndReplaceIterations(RuleApplicationData appData) {
-		Console.traceln(Level.FINE, "detecting iterations");
-		appData.getStopWatch().start("detecting iterations");
-
-		final List<IUserSession> sessions = appData.getSessions();
-
-		final Set<ITask> iteratedTasks = searchIteratedTasks(sessions);
-
-		if (iteratedTasks.size() > 0) {
-			replaceIterationsOf(iteratedTasks, sessions, appData);
-		}
-
-		appData.getStopWatch().stop("detecting iterations");
-		Console.traceln(Level.INFO, "replaced " + iteratedTasks.size()
-				+ " iterated tasks");
-	}
-
-	/**
-	 * Detect and replace tasks.
-	 *
-	 * @param appData
-	 *            the rule application data combining all data used for applying
-	 *            this rule
-	 */
-	private void detectAndReplaceTasks(RuleApplicationData appData) {
-		Console.traceln(Level.FINE, "detecting and replacing tasks");
-		appData.getStopWatch().start("detecting tasks");
-
-		// Create NumberSequences
-		appData.setNumberSequences(this.createNumberSequences(appData));
-
-		// Generate pairwise alignments
-		// appData.setMatchseqs(generatePairwiseAlignments(appData));
-		generatePairwiseAlignments(appData);
-		Console.traceln(Level.FINE, "Found " + appData.getMatchseqs().size()
-				+ " results");
-		
-		//Nothing found, we can end here
-		if(appData.getMatchseqs().size()==0) {
-			appData.detectedAndReplacedTasks=false;
-			return;
-		}
-		
-		// Searching each match in all other sessions, counting its occurences
-		searchMatchesInAllSessions(appData);
-
-		// Sort results to get the most occurring results
-		Console.traceln(Level.INFO, "sorting " + appData.getMatchseqs().size()
-				+ " results");
-		final Comparator<Match> comparator = new Comparator<Match>() {
-			@Override
-			public int compare(Match m1, Match m2) {
-				int cmp = m2.occurenceCount() - m1.occurenceCount();
-				if (cmp != 0) {
-					return cmp;
-				} else {
-					cmp = m2.size() - m1.size();
-					if (cmp != 0) {
-						return cmp;
-					} else {
-						// This should rarely happen
-						cmp = m2.ocurrenceIDSum() - m1.ocurrenceIDSum();
-						if (cmp != 0) {
-							return cmp;
-						} else {
-							cmp = m2.taskIdSum() - m1.taskIdSum();
-
-							return cmp;
-						}
-					}
-				}
-			}
-		};
-
-		Collections.sort(appData.getMatchseqs(), comparator);
-		appData.getStopWatch().stop("detecting tasks");
-
-		Console.traceln(Level.INFO, "Preparing replacments");
-		prepareReplacements(appData);
-		Console.traceln(Level.INFO, "Replacing matches in sessions");
-		appData.getStopWatch().start("replacing tasks");
-		replaceMatches(appData);
-		appData.getStopWatch().stop("replacing tasks");
-	}
-
-	// TODO: DEBUG METHOD
-	@SuppressWarnings("unused")
-	private void printMatches(RuleApplicationData appData) {
-		LinkedList<Match> matchseqs = appData.getMatchseqs();
-		if (iteration > 1) {
-			System.out.println("PRINTING MATCHES");
-			for (Iterator<Match> it = matchseqs.iterator(); it.hasNext();) {
-				Match m = it.next();
-				m.getFirstSequence().printSequence();
-				m.getSecondSequence().printSequence();
-				for (Iterator<MatchOccurrence> jt = m.getOccurences()
-						.iterator(); jt.hasNext();) {
-					MatchOccurrence mo = jt.next();
-					System.out.print(mo.getSequenceId() + " ");
-				}
-				System.out.println();
-				System.out.println();
-			}
-		}
-	}
-
-	/**
-	 * <p>
-	 * harmonizes the event task instances by unifying tasks. This is done, as
-	 * initially the event tasks being equal with respect to the considered task
-	 * equality are distinct objects. The comparison of these distinct objects
-	 * is more time consuming than comparing the object references.
-	 * </p>
-	 * 
-	 * @param appData
-	 *            the rule application data combining all data used for applying
-	 *            this rule
-	 * @return Returns the unique tasks symbol map
-	 */
-	private void harmonizeEventTaskInstancesModel(RuleApplicationData appData) {
-		Console.traceln(Level.INFO,
-				"harmonizing task model of event task instances");
-		appData.getStopWatch().start("harmonizing event tasks");
-		final SymbolMap<ITaskInstance, ITask> uniqueTasks = preparationTaskHandlingStrategy
-				.createSymbolMap();
-
-		final TaskInstanceComparator comparator = preparationTaskHandlingStrategy
-				.getTaskComparator();
-
-		int unifiedTasks = 0;
-		ITask task;
-		final List<IUserSession> sessions = appData.getSessions();
-		for (int j = 0; j < sessions.size(); j++) {
-			final IUserSession session = sessions.get(j);
-
-			for (int i = 0; i < session.size(); i++) {
-				final ITaskInstance taskInstance = session.get(i);
-				task = uniqueTasks.getValue(taskInstance);
-
-				if (task == null) {
-					uniqueTasks.addSymbol(taskInstance, taskInstance.getTask());
-					appData.getUniqueTasks().add(taskInstance.getTask());
-					appData.getNumber2Task().put(
-							taskInstance.getTask().getId(),
-							taskInstance.getTask());
-				} else {
-					taskBuilder.setTask(taskInstance, task);
-					unifiedTasks++;
-				}
-			}
-			comparator.clearBuffers();
-		}
-
-		appData.getStopWatch().stop("harmonizing event tasks");
-		Console.traceln(Level.INFO, "harmonized " + unifiedTasks
-				+ " task occurrences (still " + appData.getUniqueTasks().size()
-				+ " different tasks)");
-
-		appData.getStopWatch().dumpStatistics(System.out);
-		appData.getStopWatch().reset();
-	}
-
-	/**
-	 * <p>
-	 * TODO clarify why this is done (in fact, ask Patrick Harms)
-	 * </p>
-	 * .
-	 *
-	 * @param iteration
-	 *            the iteration
-	 * @param iterationInstances
-	 *            the iteration instances
-	 */
-	private void harmonizeIterationInstancesModel(IIteration iteration,
-			List<IIterationInstance> iterationInstances) {
-		final List<ITask> iteratedTaskVariants = new LinkedList<ITask>();
-		final TaskInstanceComparator comparator = preparationTaskHandlingStrategy
-				.getTaskComparator();
-
-		// merge the lexically different variants of iterated task to a unique
-		// list
-		for (final IIterationInstance iterationInstance : iterationInstances) {
-			for (final ITaskInstance executionVariant : iterationInstance) {
-				final ITask candidate = executionVariant.getTask();
-
-				boolean found = false;
-				for (final ITask taskVariant : iteratedTaskVariants) {
-					if (comparator.areLexicallyEqual(taskVariant, candidate)) {
-						taskBuilder.setTask(executionVariant, taskVariant);
-						found = true;
-						break;
-					}
-				}
-
-				if (!found) {
-					iteratedTaskVariants.add(candidate);
-				}
-			}
-		}
-
-		// if there are more than one lexically different variant of iterated
-		// tasks, adapt the
-		// iteration model to be a selection of different variants. In this case
-		// also adapt
-		// the generated iteration instances to correctly contain selection
-		// instances. If there
-		// is only one variant of an iterated task, simply set this as the
-		// marked task of the
-		// iteration. In this case, the instances can be preserved as is
-		if (iteratedTaskVariants.size() > 1) {
-			final ISelection selection = taskFactory.createNewSelection();
-
-			for (final ITask variant : iteratedTaskVariants) {
-				taskBuilder.addChild(selection, variant);
-			}
-
-			taskBuilder.setMarkedTask(iteration, selection);
-
-			for (final IIterationInstance instance : iterationInstances) {
-				for (int i = 0; i < instance.size(); i++) {
-					final ISelectionInstance selectionInstance = taskFactory
-							.createNewTaskInstance(selection);
-					taskBuilder.setChild(selectionInstance, instance.get(i));
-					taskBuilder.setTaskInstance(instance, i, selectionInstance);
-				}
-			}
-		} else {
-			taskBuilder.setMarkedTask(iteration, iteratedTaskVariants.get(0));
-		}
-	}
-
-	/**
-	 * Match as sequence.
-	 *
-	 * @param appData
-	 *            RuleApplicationData needed to keep track of all created tasks
-	 * @param m
-	 *            The match to be converted into a Task
-	 * @return The task of the match with an ISequence as its root
-	 */
-	synchronized public ISequence matchAsSequence(RuleApplicationData appData,
-			Match m) {
-		final ISequence sequence = taskFactory.createNewSequence();
-		appData.newTaskCreated(sequence);
-
-		final int[] first = m.getFirstSequence().getSequence();
-		final int[] second = m.getSecondSequence().getSequence();
-
-		// Both sequences of a match are equally long
-		for (int i = 0; i < m.getFirstSequence().size(); i++) {
-
-			// Two gaps aligned to each other: Have not seen it happening so
-			// far, just to handle it
-			if ((first[i] == -1) && (second[i] == -1)) {
-				// Do nothing here.
-			}
-			// Both events are equal, we can simply add the task referring to
-			// the number
-			else if (first[i] == second[i]) {
-				taskBuilder.addChild(sequence,
-						appData.getNumber2Task().get(first[i]));
-			}
-			// We have a gap in the first sequence, we need to add the task of
-			// the second sequence as optional
-			else if ((first[i] == -1) && (second[i] != -1)) {
-				final IOptional optional = taskFactory.createNewOptional();
-				appData.newTaskCreated(optional);
-				taskBuilder.setMarkedTask(optional, appData.getNumber2Task()
-						.get(second[i]));
-				taskBuilder.addChild(sequence, optional);
-			}
-			// We have a gap in the second sequence, we need to add the task of
-			// the first sequence as optional
-			else if ((first[i] != -1) && (second[i] == -1)) {
-				final IOptional optional = taskFactory.createNewOptional();
-				appData.newTaskCreated(optional);
-				taskBuilder.setMarkedTask(optional, appData.getNumber2Task()
-						.get(first[i]));
-				taskBuilder.addChild(sequence, optional);
-			}
-			// Both tasks are not equal, we need to insert a selection here.
-			// Now things get complicated. We first need to check
-			// if the next position is not a selection. Then we can just create
-			// a selection
-			// of the both Tasks
-			// In the other case (more than one selection following this
-			// selection), we want to
-			// create a selection of sequences where each sequence gets the
-			// corresponding task of
-			// the its sequence in the pattern.
-			//
-			else if (i < (first.length - 1)) {
-
-				if ((first[i] != second[i])
-						&& (((first[i + 1] == second[i + 1])
-								|| (first[i + 1] == -1) || (second[i + 1] == -1)))) {
-
-					final ISelection selection = taskFactory
-							.createNewSelection();
-					appData.newTaskCreated(selection);
-					taskBuilder.addChild(selection, appData.getNumber2Task()
-							.get(first[i]));
-					taskBuilder.addChild(selection, appData.getNumber2Task()
-							.get(second[i]));
-					taskBuilder.addChild(sequence, selection);
-				} else {
-					boolean selectionfound = true;
-					final ISelection selection = taskFactory
-							.createNewSelection();
-					appData.newTaskCreated(selection);
-
-					final ISequence subsequence1 = taskFactory
-							.createNewSequence();
-					appData.newTaskCreated(subsequence1);
-
-					final ISequence subsequence2 = taskFactory
-							.createNewSequence();
-					appData.newTaskCreated(subsequence2);
-
-					taskBuilder.addChild(selection, subsequence1);
-					taskBuilder.addChild(selection, subsequence2);
-					taskBuilder.addChild(sequence, selection);
-					// TODO: We may not run till the end!
-					while ((i < (first.length - 1)) && selectionfound) {
-						selectionfound = false;
-						taskBuilder.addChild(subsequence1, appData
-								.getNumber2Task().get(first[i]));
-						taskBuilder.addChild(subsequence2, appData
-								.getNumber2Task().get(second[i]));
-						if ((first[i + 1] != second[i + 1])
-								&& (first[i + 1] != -1)
-								&& (second[i + 1] != -1)) {
-							selectionfound = true;
-						} else {
-							continue;
-						}
-						i++;
-					}
-					if ((i == (first.length - 1)) && selectionfound) {
-						taskBuilder.addChild(subsequence1, appData
-								.getNumber2Task().get(first[i]));
-						taskBuilder.addChild(subsequence2, appData
-								.getNumber2Task().get(second[i]));
-					}
-				}
-			} else {
-				// i = length-1
-				if ((first[i] != second[i])) {
-
-					final ISelection selection = taskFactory
-							.createNewSelection();
-					appData.newTaskCreated(selection);
-					taskBuilder.addChild(selection, appData.getNumber2Task()
-							.get(first[i]));
-					taskBuilder.addChild(selection, appData.getNumber2Task()
-							.get(second[i]));
-					taskBuilder.addChild(sequence, selection);
-				}
-			}
-
-		}
-		return sequence;
-	}
-
-	/**
-	 * <p>
-	 * replaces all occurrences of all tasks provided in the set with iterations
-	 * </p>
-	 * .
-	 *
-	 * @param iteratedTasks
-	 *            the tasks to be replaced with iterations
-	 * @param sessions
-	 *            the sessions in which the tasks are to be replaced
-	 * @param appData
-	 *            the rule application data combining all data used for applying
-	 *            this rule
-	 */
-	private void replaceIterationsOf(Set<ITask> iteratedTasks,
-			List<IUserSession> sessions, RuleApplicationData appData) {
-		final Map<ITask, IIteration> iterations = new HashMap<ITask, IIteration>();
-		final Map<IIteration, List<IIterationInstance>> iterationInstances = new HashMap<IIteration, List<IIterationInstance>>();
-
-		for (final ITask iteratedTask : iteratedTasks) {
-
-			final IIteration iteration = taskFactory.createNewIteration();
-			appData.newTaskCreated(iteration);
-			iterations.put(iteratedTask, iteration);
-			iterationInstances.put(iteration,
-					new LinkedList<IIterationInstance>());
-		}
-
-		IIterationInstance iterationInstance;
-
-		for (final IUserSession session : sessions) {
-			int index = 0;
-			iterationInstance = null;
-
-			while (index < session.size()) {
-				// we prepared the task instances to refer to unique tasks, if
-				// they are treated
-				// as equal. Therefore, we just compare the identity of the
-				// tasks of the task
-				// instances
-				final ITask currentTask = session.get(index).getTask();
-				final IIteration iteration = iterations.get(currentTask);
-				if (iteration != null) {
-					if ((iterationInstance == null)
-							|| (iterationInstance.getTask() != iteration)) {
-						iterationInstance = taskFactory
-								.createNewTaskInstance(iteration);
-						iterationInstances.get(iteration)
-								.add(iterationInstance);// TODO:: Don't create
-						// TaskInstances here,
-						// use a set of tasks
-						// instead
-						taskBuilder.addTaskInstance(session, index,
-								iterationInstance);
-						index++;
-					}
-
-					taskBuilder.addChild(iterationInstance, session.get(index));
-					taskBuilder.removeTaskInstance(session, index);
-				} else {
-					if (iterationInstance != null) {
-						iterationInstance = null;
-					}
-					index++;
-				}
-			}
-		}
-
-		for (final Map.Entry<IIteration, List<IIterationInstance>> entry : iterationInstances
-				.entrySet()) {
-			harmonizeIterationInstancesModel(entry.getKey(), entry.getValue());
-		}
-	}
-
-	private void prepareReplacements(RuleApplicationData appData) {
-		appData.initializeQueues(appData.getSessions().size());
-		
-		for (Iterator<Match> it = appData.getMatchseqs().iterator(); it
-				.hasNext();) {
-			Match m = it.next();
-			for (Iterator<MatchOccurrence> jt = m.getOccurences().iterator(); jt
-					.hasNext();) {
-				MatchOccurrence mo = jt.next();
-
-				Match emptyMatch = null;
-				try {
-					emptyMatch = m.cloneWithoutOccurences();
-				} catch (CloneNotSupportedException e) {
-					e.printStackTrace();
-				}
-				emptyMatch.addOccurence(mo);
-				appData.getPlannedReplacements()[mo.getSequenceId()].add(m);
-			}
-		}
-	}
-
-	/**
-	 * Replace matches.
-	 *
-	 * @param appData
-	 *            the app data
-	 */
-	private void replaceMatches(RuleApplicationData appData) {
-	
-		final int numberSeqSize = appData.getNumberSequences().size();
-		Console.traceln(Level.INFO, "replacing matches with " + nThreads + " threads");
-		int newThreads = nThreads;
-		if (numberSeqSize < nThreads) {
-			newThreads = numberSeqSize;
-		}
-		final int interval = numberSeqSize / newThreads;
-		int rest = numberSeqSize % newThreads;
-		final ExecutorService executor = Executors.newFixedThreadPool(nThreads);
-		for (int i = 0; i <= (numberSeqSize - interval); i += interval) {
-			int offset = 0;
-			if (rest != 0) {
-				offset = 1;
-				rest--;
-			}
-			final int from = i;
-			final int to = i + interval + offset - 1;
-			Console.traceln(Level.FINE,
-					"Match replaceing: Creating thread with matches from " + from
-							+ " to " + to);
-			// search each match in every other sequence
-			final ParallelMatchReplacer replacer = new ParallelMatchReplacer(
-					appData, from, to);
-			executor.execute(replacer);
-			i += offset;
-		}
-		executor.shutdown();
-		try {
-			executor.awaitTermination(2, TimeUnit.HOURS);
-		} catch (final InterruptedException e) {
-			e.printStackTrace();
-		}
-	}
-
-	/**
-	 * <p>
-	 * searches the provided sessions for task iterations. If a task is
-	 * iterated, it is added to the returned set.
-	 * </p>
-	 *
-	 * @param sessions
-	 *            the sessions
-	 * @return a set of tasks being iterated somewhere
-	 */
-	private Set<ITask> searchIteratedTasks(List<IUserSession> sessions) {
-		final Set<ITask> iteratedTasks = new HashSet<ITask>();
-		for (final IUserSession session : sessions) {
-			for (int i = 0; i < (session.size() - 1); i++) {
-				// we prepared the task instances to refer to unique tasks, if
-				// they are treated
-				// as equal. Therefore, we just compare the identity of the
-				// tasks of the task
-				// instances
-				if (session.get(i).getTask() == session.get(i + 1).getTask()) {
-					iteratedTasks.add(session.get(i).getTask());
-				}
-			}
-		}
-		return iteratedTasks;
-	}
-
-	/**
-	 * Generate pairwise alignments.
-	 *
-	 * @param appData
-	 *            the app data
-	 */
-	private void generatePairwiseAlignments(RuleApplicationData appData) {
-		final int numberSeqSize = appData.getNumberSequences().size();
-		appData.matchseqs = new LinkedList<Match>();
-		Console.traceln(Level.INFO, "generating pairwise alignments from "
-				+ numberSeqSize + " sessions with " + nThreads + " threads");
-
-		int newThreads = nThreads;
-		if (numberSeqSize < nThreads) {
-			newThreads = numberSeqSize;
-		}
-
-		final ExecutorService executor = Executors
-				.newFixedThreadPool(newThreads);
-		final int interval = numberSeqSize / newThreads;
-		int rest = numberSeqSize % newThreads;
-		Console.traceln(Level.FINE, "Interval: " + interval + " Rest: " + rest);
-		for (int i = 0; i <= (numberSeqSize - interval); i += interval) {
-			int offset = 0;
-			if (rest != 0) {
-				offset = 1;
-				rest--;
-			}
-
-			final int from = i;
-			final int to = i + interval + offset - 1;
-			Console.traceln(Level.FINER,
-					"Aligning: Creating thread for sessions " + from + " till "
-							+ to);
-			final ParallelPairwiseAligner aligner = new ParallelPairwiseAligner(
-					appData, from, to);
-			executor.execute(aligner);
-			i += offset;
-		}
-		executor.shutdown();
-		try {
-			executor.awaitTermination(2, TimeUnit.HOURS);
-		} catch (final InterruptedException e) {
-			e.printStackTrace();
-		}
-	}
-
-	/**
-	 * Search matches in all sessions.
-	 *
-	 * @param appData
-	 *            the app data
-	 */
-	private void searchMatchesInAllSessions(RuleApplicationData appData) {
-
-		// Prepare parallel search of matchseqs
-		final int matchSeqSize = appData.getMatchseqs().size();
-		Console.traceln(Level.INFO, "searching for patterns (" + matchSeqSize
-				+ ") occuring most with " + nThreads + " threads");
-		int newThreads = nThreads;
-		if (matchSeqSize < nThreads) {
-			newThreads = matchSeqSize;
-		}
-		final int interval = matchSeqSize / newThreads;
-		int rest = matchSeqSize % newThreads;
-		final ExecutorService executor = Executors.newFixedThreadPool(nThreads);
-		Console.traceln(Level.FINER, "Interval: " + interval + " Rest: " + rest);
-		for (int i = 0; i <= (matchSeqSize - interval); i += interval) {
-			int offset = 0;
-			if (rest != 0) {
-				offset = 1;
-				rest--;
-			}
-			final int from = i;
-			final int to = i + interval + offset - 1;
-			Console.traceln(Level.FINE,
-					"Match finding: Creating thread with matches from " + from
-							+ " to " + to);
-			// search each match in every other sequence
-			final ParallelMatchOcurrencesFinder finder = new ParallelMatchOcurrencesFinder(
-					appData, from, to);
-			executor.execute(finder);
-			i += offset;
-		}
-		executor.shutdown();
-		try {
-			executor.awaitTermination(2, TimeUnit.HOURS);
-		} catch (final InterruptedException e) {
-			e.printStackTrace();
-		}
-
-	}
-
-	/*
-	 * (non-Javadoc)
-	 * 
-	 * @see java.lang.Object#toString()
-	 */
-	@Override
-	public String toString() {
-		return "SequenceForTaskDetectionRuleAlignment";
-	}
-
-	/**
-	 * The Class ParallelMatchOcurrencesFinder.
-	 */
-	private class ParallelMatchOcurrencesFinder implements Runnable {
-
-		/** The app data. */
-		private final RuleApplicationData appData;
-
-		/** The from. */
-		private final int from;
-
-		/** The to. */
-		private final int to;
-
-		/**
-		 * Instantiates a new parallel match ocurrences finder.
-		 *
-		 * @param appData
-		 *            the app data
-		 * @param from
-		 *            the from
-		 * @param to
-		 *            the to
-		 */
-		ParallelMatchOcurrencesFinder(RuleApplicationData appData, int from,
-				int to) {
-			this.appData = appData;
-			this.from = from;
-			this.to = to;
-		}
-
-		/*
-		 * (non-Javadoc)
-		 * 
-		 * @see java.lang.Runnable#run()
-		 */
-		@Override
-		public void run() {
-			int count = 0;
-			final int size = to + 1 - from;
-
-			for (int i = from; i <= to; i++) {
-				final Match pattern = appData.getMatchseqs().get(i);
-				count++;
-				RuleUtils.printProgressPercentage("Match finding progress",
-						count, size);
-				// Skip sequences with more 0 events (scrolls) than other
-				// events.
-				// Both of the pattern sequences are equally long, so the zero
-				// counts just need to be smaller than the length of one
-				// sequence
-				if ((pattern.getFirstSequence().eventCount(0)
-						+ pattern.getSecondSequence().eventCount(0) + 1) > pattern
-						.getFirstSequence().size()) {
-					continue;
-				}
-
-				for (int j = 0; j < appData.getNumberSequences().size(); j++) {
-					final LinkedList<Integer> startpositions = appData
-							.getNumberSequences().get(j)
-							.containsPattern(pattern);
-					if (startpositions.size() > 0) {
-						for (final Iterator<Integer> jt = startpositions
-								.iterator(); jt.hasNext();) {
-							final int start = jt.next();
-							pattern.addOccurence(new MatchOccurrence(start,
-									start + pattern.size(), j));
-						}
-					}
-				}
-			}
-		}
-	}
-
-	/**
-	 * The Class ParallelPairwiseAligner.
-	 */
-	private class ParallelPairwiseAligner implements Runnable {
-
-		/** The app data. */
-		private final RuleApplicationData appData;
-
-		/** The from. */
-		private final int from;
-
-		/** The to. */
-		private final int to;
-
-		/**
-		 * Instantiates a new parallel pairwise aligner.
-		 *
-		 * @param appData
-		 *            the app data
-		 * @param from
-		 *            the from
-		 * @param to
-		 *            the to
-		 */
-		ParallelPairwiseAligner(RuleApplicationData appData, int from, int to) {
-			this.appData = appData;
-			this.from = from;
-			this.to = to;
-		}
-
-		/*
-		 * (non-Javadoc)
-		 * 
-		 * @see java.lang.Runnable#run()
-		 */
-		@Override
-		public void run() {
-			int count = 0;
-			final int size = to +1 - from;
-
-			for (int i = from; i <= to; i++) {
-				final NumberSequence ns1 = appData.getNumberSequences().get(i);
-				count++;
-				RuleUtils.printProgressPercentage("Aligning Progress", count,
-						size);
-				for (int j = 0; j < appData.getNumberSequences().size(); j++) {
-					final NumberSequence ns2 = appData.getNumberSequences()
-							.get(j);
-					if (i != j) {
-						final AlignmentAlgorithm aa = AlignmentAlgorithmFactory
-								.create();
-						aa.align(ns1, ns2, appData.getSubmat(), 9);
-						synchronized (appData.getMatchseqs()) {
-							appData.getMatchseqs().addAll(aa.getMatches());
-						}
-					}
-				}
-			}
-		}
-	}
-
-	/**
-	 * The Class ParallelPairwiseAligner.
-	 */
-	private class ParallelMatchReplacer implements Runnable {
-
-		/** The app data. */
-		private final RuleApplicationData appData;
-
-		/** The from. */
-		private final int from;
-
-		/** The to. */
-		private final int to;
-
-		/**
-		 * Instantiates a new parallel pairwise aligner.
-		 *
-		 * @param appData
-		 *            the app data
-		 * @param from
-		 *            the from
-		 * @param to
-		 *            the to
-		 */
-		ParallelMatchReplacer(RuleApplicationData appData, int from, int to) {
-			this.appData = appData;
-			this.from = from;
-			this.to = to;
-		}
-
-		/*
-		 * (non-Javadoc)
-		 * 
-		 * @see java.lang.Runnable#run()
-		 */
-		@Override
-		public void run() {
-			for (int i = from; i <= to; i++) {
-				
-				/*
-				 * HashMap for keeping track in which sequence which replacement has
-				 * been performed. Neccessary for updating the indices of other
-				 * occurrences accordingly
-				 */
-				LinkedList<MatchOccurrence> replacedOccurrences = new LinkedList<MatchOccurrence>();
-				invalidOccurence: while (!appData.getPlannedReplacements()[i]
-						.isEmpty()) {
-
-					Match m = appData.getPlannedReplacements()[i].remove();
-					// Occurrences list has just one child
-					MatchOccurrence oc = m.getOccurences().getFirst();
-					// check if we have any replaced occurrence with
-					// indexes
-					// smaller than ours. If so, we need to adjust
-					// our start and end points of the replacement.
-					// Also do a check if we have replaced this
-					// specific MatchOccurence in this sequence already.
-					// Jump to the next occurrence if this is the case.
-					// This is no more necessary once the matches
-					// are harmonized.
-
-					for (final Iterator<MatchOccurrence> jt = replacedOccurrences
-							.iterator(); jt.hasNext();) {
-						final MatchOccurrence tmpOC = jt.next();
-
-						if ((oc.getStartindex() >= tmpOC.getStartindex())
-								&& (oc.getStartindex() <= tmpOC.getEndindex())) {
-							continue invalidOccurence;
-						}
-						if (oc.getEndindex() >= tmpOC.getStartindex()) {
-							continue invalidOccurence;
-
-						} else if (oc.getStartindex() > tmpOC.getEndindex()) {
-							final int diff = tmpOC.getEndindex()
-									- tmpOC.getStartindex();
-							// Just to be sure.
-							if (diff > 0) {
-								oc.setStartindex((oc.getStartindex() - diff) + 1);
-								oc.setEndindex((oc.getEndindex() - diff) + 1);
-							} else {
-								Console.traceln(Level.WARNING,
-										"End index of a Match before start. This should never happen");
-							}
-						}
-					}
-					synchronized (appData) {
-						appData.detectedAndReplacedTasks = true;
-					}
-					final ISequence task = matchAsSequence(appData, m);
-					final ISequenceInstance sequenceInstances = RuleUtils
-							.createNewSubSequenceInRange(appData.getSessions()
-									.get(oc.getSequenceId()), oc
-									.getStartindex(), oc.getEndindex(), task,
-									taskFactory, taskBuilder);
-
-					// Adjust the length of the match regarding to the
-					// length of
-					// instance. (OptionalInstances may be shorter)
-					oc.setEndindex((oc.getStartindex() + sequenceInstances
-							.size()) - RuleUtils.missedOptionals);
-
-					replacedOccurrences.add(oc);
-				}
-			}
-		}
-	}
-
-	/**
-	 * The Class RuleApplicationData.
-	 */
-	private static class RuleApplicationData implements Serializable {
-
-		/** The Constant serialVersionUID. */
-		private static final long serialVersionUID = -7559657686755522960L;
-
-		/**
-		 * The number2task HashMap. Since we align the tasks just by their
-		 * integer id, we need this to convert them back to Tasks again
-		 */
-		private final HashMap<Integer, ITask> number2task;
-
-		/**
-		 * The unique tasks, keeps track about all unique tasks TODO: We
-		 * Actually just need number2task here, this structure can be removed in
-		 * the future.
-		 */
-		private final HashSet<ITask> uniqueTasks;
-
-		/**
-		 * The substitution matrix used by the alignment algorithm to be able to
-		 * compare distances of tasks
-		 */
-		private final ObjectDistanceSubstitionMatrix submat;
-
-		private PriorityQueue<Match>[] plannedReplacements;
-
-		/** The list of all found matches */
-		private LinkedList<Match> matchseqs;
-
-		/**
-		 * The generated NumberSequences. This is the integer representation of
-		 * the user sessions
-		 */
-		private ArrayList<NumberSequence> numberseqs;
-
-		/** The list of newly created tasks (of one iteration). */
-		private final LinkedList<ITask> newTasks;
-
-		/** The user sessions containing all EventTasks/Instances */
-		private final List<IUserSession> sessions;
-
-		/** True if we replaced something in the user sessions in one iteration. */
-		private boolean detectedAndReplacedTasks;
-
-		/** The result we return from this rule */
-		private final RuleApplicationResult result;
-
-		/** Stop Watch to measure performance */
-		private final StopWatch stopWatch;
-
-		/**
-		 * Instantiates a new rule application data.
-		 *
-		 * @param sessions
-		 *            The user sessions
-		 */
-		private RuleApplicationData(List<IUserSession> sessions) {
-			this.sessions = sessions;
-			numberseqs = new ArrayList<NumberSequence>();
-			uniqueTasks = new HashSet<ITask>();
-			number2task = new HashMap<Integer, ITask>();
-			stopWatch = new StopWatch();
-			result = new RuleApplicationResult();
-			submat = new ObjectDistanceSubstitionMatrix(6, -3, false);
-			newTasks = new LinkedList<ITask>();
-			this.detectedAndReplacedTasks = true;
-		}
-
-		private void initializeQueues(int size) {
-			plannedReplacements = new PriorityQueue[size];
-			for (int i = 0; i < size; i++) {
-				plannedReplacements[i] = new PriorityQueue<Match>();
-			}
-		}
-
-		public Queue<Match>[] getPlannedReplacements() {
-			return plannedReplacements;
-		}
-
-		/**
-		 * Detected and replaced tasks.
-		 *
-		 * @return true, if successful
-		 */
-		private boolean detectedAndReplacedTasks() {
-			return detectedAndReplacedTasks;
-		}
-
-		/**
-		 * Gets the match sequences.
-		 *
-		 * @return the match sequences
-		 */
-		public LinkedList<Match> getMatchseqs() {
-			return matchseqs;
-		}
-
-		/**
-		 * Gets the new tasks.
-		 *
-		 * @return the new tasks
-		 */
-		public LinkedList<ITask> getNewTasks() {
-			return newTasks;
-		}
-
-		/**
-		 * Gets the number2task.
-		 *
-		 * @return the number2task HashMap
-		 */
-		private HashMap<Integer, ITask> getNumber2Task() {
-			return number2task;
-		}
-
-		/**
-		 * Gets the number sequences.
-		 *
-		 * @return the number sequences
-		 */
-		private ArrayList<NumberSequence> getNumberSequences() {
-			return numberseqs;
-		}
-
-		/**
-		 * Gets the result.
-		 *
-		 * @return the result
-		 */
-		private RuleApplicationResult getResult() {
-			return result;
-		}
-
-		/**
-		 * Gets the sessions.
-		 *
-		 * @return the UserSessions as List.
-		 */
-		private List<IUserSession> getSessions() {
-			return sessions;
-		}
-
-		/**
-		 * Gets the stop watch.
-		 *
-		 * @return the stopWatch
-		 */
-		private StopWatch getStopWatch() {
-			return stopWatch;
-		}
-
-		/**
-		 * Gets the substitution matrix.
-		 *
-		 * @return the substitution matrix
-		 */
-		private ObjectDistanceSubstitionMatrix getSubmat() {
-			return submat;
-		}
-
-		/**
-		 * Gets the unique tasks.
-		 *
-		 * @return the unique tasks
-		 */
-		private HashSet<ITask> getUniqueTasks() {
-			return uniqueTasks;
-		}
-
-		/**
-		 * New task created.
-		 *
-		 * @param task
-		 *            can be called when new tasks are created to keep track of
-		 *            all newly created tasks
-		 */
-		private void newTaskCreated(ITask task) {
-			number2task.put(task.getId(), task);
-			newTasks.add(task);
-		}
-
-		/**
-		 * Reset newly created tasks.
-		 */
-		synchronized private void resetNewlyCreatedTasks() {
-			uniqueTasks.addAll(newTasks);
-			newTasks.clear();
-		}
-
-		/**
-		 * Sets the number sequences.
-		 *
-		 * @param numberseqs
-		 *            the new number sequences
-		 */
-		private void setNumberSequences(ArrayList<NumberSequence> numberseqs) {
-			this.numberseqs = numberseqs;
-		}
-
-		/**
-		 * Update substitution matrix.
-		 */
-		private void updateSubstitutionMatrix() {
-			submat.update(getNewTasks());
-			resetNewlyCreatedTasks();
-		}
-
-	}
+    /** The n threads. */
+    // public static int nThreads = Runtime.getRuntime().availableProcessors() - 1;
+    public static int nThreads = 1;
+
+    /** The iteration. */
+    private int iteration = 0;
+
+    private int maxIterations = 1;
+
+    private static int alignmentThreshold = 9;
+    private static int gapPenalty = -3;
+
+    private static float maxSubstitutionScore = 6;
+
+    /**
+     * <p>
+     * the task factory to be used for creating substructures for the temporal relationships
+     * identified during rul application
+     * </p>
+     * .
+     */
+    private final ITaskFactory taskFactory;
+
+    /**
+     * <p>
+     * the task builder to be used for creating substructures for the temporal relationships
+     * identified during rule application
+     * </p>
+     * .
+     */
+    private final ITaskBuilder taskBuilder;
+
+    /**
+     * <p>
+     * the task handling strategy to be used for comparing tasks for preparation, i.e., before the
+     * tasks are harmonized
+     * </p>
+     */
+    private final TaskHandlingStrategy preparationTaskHandlingStrategy;
+
+    /**
+     * <p>
+     * instantiates the rule and initializes it with a task equality to be considered when comparing
+     * tasks as well as a task factory and builder to be used for creating task structures.
+     * </p>
+     * 
+     * @param minimalTaskEquality
+     *            the task equality to be considered when comparing tasks
+     * @param taskFactory
+     *            the task factory to be used for creating substructures
+     * @param taskBuilder
+     *            the task builder to be used for creating substructures
+     */
+
+    SequenceForTaskDetectionRuleAlignment(TaskEquality minimalTaskEquality,
+                                          ITaskFactory taskFactory,
+                                          ITaskBuilder taskBuilder)
+    {
+        this.taskFactory = taskFactory;
+        this.taskBuilder = taskBuilder;
+
+        this.preparationTaskHandlingStrategy = new TaskHandlingStrategy(minimalTaskEquality);
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see de.ugoe.cs.autoquest.tasktrees.temporalrelation.ISessionScopeRule#apply (java.util.List)
+     */
+    @Override
+    public RuleApplicationResult apply(List<IUserSession> sessions) {
+        final RuleApplicationData appData = new RuleApplicationData(sessions);
+
+        harmonizeEventTaskInstancesModel(appData);
+
+        Console.traceln(Level.INFO, "generating substitution matrix from " +
+            appData.getUniqueTasks().size() + " unique tasks");
+        appData.getStopWatch().start("substitution matrix");
+        appData.getSubmat().generate(appData.getUniqueTasks());
+        appData.getStopWatch().stop("substitution matrix");
+
+        Console.traceln(Level.INFO, "Starting main loop");
+        do {
+            Console.traceln(Level.INFO, "Iteration Number: " + iteration);
+            iteration++;
+            appData.detectedAndReplacedTasks = false;
+            appData.getStopWatch().start("whole loop");
+            detectAndReplaceIterations(appData);
+            appData.getStopWatch().start("task replacement");
+            // Just does anything if the substitution matrix is created with the
+            // option to do so
+            appData.updateSubstitutionMatrix();
+            detectAndReplaceTasks(appData); //
+            appData.getStopWatch().stop("task replacement");
+            appData.getStopWatch().stop("whole loop");
+            // appData.getStopWatch().dumpStatistics(System.out);
+            appData.getStopWatch().reset();
+
+            // } while (appData.detectedAndReplacedTasks()||iteration < maxIterations);
+        }
+        while (iteration < maxIterations);
+        Console.println("created " + appData.getResult().getNewlyCreatedTasks().size() +
+            " new tasks and " + appData.getResult().getNewlyCreatedTaskInstances().size() +
+            " appropriate instances\n");
+
+        if ((appData.getResult().getNewlyCreatedTasks().size() > 0) ||
+            (appData.getResult().getNewlyCreatedTaskInstances().size() > 0))
+        {
+            appData.getResult().setRuleApplicationStatus(RuleApplicationStatus.FINISHED);
+        }
+        // new TaskTreeValidator().validate(appData.getSessions());
+        return appData.getResult();
+    }
+
+    /**
+     * Creates the number sequences.
+     *
+     * @param appData
+     *            the app data
+     * @return the array list
+     */
+    private ArrayList<NumberSequence> createNumberSequences(RuleApplicationData appData) {
+        final ArrayList<NumberSequence> result = new ArrayList<NumberSequence>();
+        for (int i = 0; i < appData.getSessions().size(); i++) {
+            final IUserSession session = appData.getSessions().get(i);
+            final NumberSequence templist = new NumberSequence(session.size());
+            for (int j = 0; j < session.size(); j++) {
+                final ITaskInstance taskInstance = session.get(j);
+                templist.getSequence()[j] = taskInstance.getTask().getId();
+            }
+            // Each NumberSequence is identified by its id, beginning to count
+            // at zero
+            templist.setId(i);
+            result.add(templist);
+        }
+        return result;
+    }
+
+    /**
+     * <p>
+     * searches for direct iterations of single tasks in all sequences and replaces them with
+     * {@link IIteration}s, respectively appropriate instances. Also all single occurrences of a
+     * task that is iterated somewhen are replaced with iterations to have again an efficient way
+     * for task comparisons.
+     * </p>
+     * 
+     * @param appData
+     *            the rule application data combining all data used for applying this rule
+     */
+    private void detectAndReplaceIterations(RuleApplicationData appData) {
+        Console.traceln(Level.FINE, "detecting iterations");
+        appData.getStopWatch().start("detecting iterations");
+
+        final List<IUserSession> sessions = appData.getSessions();
+
+        final Set<ITask> iteratedTasks = searchIteratedTasks(sessions);
+
+        if (iteratedTasks.size() > 0) {
+            replaceIterationsOf(iteratedTasks, sessions, appData);
+        }
+
+        appData.getStopWatch().stop("detecting iterations");
+        Console.traceln(Level.INFO, "replaced " + iteratedTasks.size() + " iterated tasks");
+    }
+
+    /**
+     * Detect and replace tasks.
+     *
+     * @param appData
+     *            the rule application data combining all data used for applying this rule
+     */
+    private void detectAndReplaceTasks(RuleApplicationData appData) {
+        Console.traceln(Level.FINE, "detecting and replacing tasks");
+        appData.getStopWatch().start("detecting tasks");
+
+        // Create NumberSequences
+        appData.setNumberSequences(this.createNumberSequences(appData));
+
+        // Generate pairwise alignments
+        // appData.setMatchseqs(generatePairwiseAlignments(appData));
+        generatePairwiseAlignments(appData);
+        Console.traceln(Level.FINE, "Found " + appData.getMatchseqs().size() + " results");
+
+        // Nothing found, we can end here
+        if (appData.getMatchseqs().size() == 0) {
+            appData.detectedAndReplacedTasks = false;
+            return;
+        }
+
+        // Searching each match in all other sessions, counting its occurences
+        searchMatchesInAllSessions(appData);
+
+        // Sort results to get the most occurring results
+        Console.traceln(Level.INFO, "sorting " + appData.getMatchseqs().size() + " results");
+        final Comparator<Match> comparator = new Comparator<Match>() {
+            @Override
+            public int compare(Match m1, Match m2) {
+                int cmp = m2.occurenceCount() - m1.occurenceCount();
+                if (cmp != 0) {
+                    return cmp;
+                }
+                else {
+                    cmp = m2.size() - m1.size();
+                    if (cmp != 0) {
+                        return cmp;
+                    }
+                    else {
+                        // This should rarely happen
+                        cmp = m2.ocurrenceIDSum() - m1.ocurrenceIDSum();
+                        if (cmp != 0) {
+                            return cmp;
+                        }
+                        else {
+                            cmp = m2.taskIdSum() - m1.taskIdSum();
+
+                            return cmp;
+                        }
+                    }
+                }
+            }
+        };
+
+        Collections.sort(appData.getMatchseqs(), comparator);
+        appData.getStopWatch().stop("detecting tasks");
+
+        Console.traceln(Level.INFO, "Preparing replacments");
+        prepareReplacements(appData);
+        Console.traceln(Level.INFO, "Replacing matches in sessions");
+        appData.getStopWatch().start("replacing tasks");
+        replaceMatches(appData);
+        appData.getStopWatch().stop("replacing tasks");
+    }
+
+    // TODO: DEBUG METHOD
+    @SuppressWarnings("unused")
+    private void printMatches(RuleApplicationData appData) {
+        LinkedList<Match> matchseqs = appData.getMatchseqs();
+        if (iteration > 1) {
+            System.out.println("PRINTING MATCHES");
+            for (Iterator<Match> it = matchseqs.iterator(); it.hasNext();) {
+                Match m = it.next();
+                m.getFirstSequence().printSequence();
+                m.getSecondSequence().printSequence();
+                for (Iterator<MatchOccurrence> jt = m.getOccurences().iterator(); jt.hasNext();) {
+                    MatchOccurrence mo = jt.next();
+                    System.out.print(mo.getSequenceId() + " ");
+                }
+                System.out.println();
+                System.out.println();
+            }
+        }
+    }
+
+    /**
+     * <p>
+     * harmonizes the event task instances by unifying tasks. This is done, as initially the event
+     * tasks being equal with respect to the considered task equality are distinct objects. The
+     * comparison of these distinct objects is more time consuming than comparing the object
+     * references.
+     * </p>
+     * 
+     * @param appData
+     *            the rule application data combining all data used for applying this rule
+     * @return Returns the unique tasks symbol map
+     */
+    private void harmonizeEventTaskInstancesModel(RuleApplicationData appData) {
+        Console.traceln(Level.INFO, "harmonizing task model of event task instances");
+        appData.getStopWatch().start("harmonizing event tasks");
+        final SymbolMap<ITaskInstance, ITask> uniqueTasks =
+            preparationTaskHandlingStrategy.createSymbolMap();
+
+        final TaskInstanceComparator comparator =
+            preparationTaskHandlingStrategy.getTaskComparator();
+
+        int unifiedTasks = 0;
+        ITask task;
+        final List<IUserSession> sessions = appData.getSessions();
+        for (int j = 0; j < sessions.size(); j++) {
+            final IUserSession session = sessions.get(j);
+
+            for (int i = 0; i < session.size(); i++) {
+                final ITaskInstance taskInstance = session.get(i);
+                task = uniqueTasks.getValue(taskInstance);
+
+                if (task == null) {
+                    uniqueTasks.addSymbol(taskInstance, taskInstance.getTask());
+                    appData.getUniqueTasks().add(taskInstance.getTask());
+                    appData.getNumber2Task().put(taskInstance.getTask().getId(),
+                                                 taskInstance.getTask());
+                }
+                else {
+                    taskBuilder.setTask(taskInstance, task);
+                    unifiedTasks++;
+                }
+            }
+            comparator.clearBuffers();
+        }
+
+        appData.getStopWatch().stop("harmonizing event tasks");
+        Console.traceln(Level.INFO, "harmonized " + unifiedTasks + " task occurrences (still " +
+            appData.getUniqueTasks().size() + " different tasks)");
+
+        appData.getStopWatch().dumpStatistics(System.out);
+        appData.getStopWatch().reset();
+    }
+
+    /**
+     * <p>
+     * TODO clarify why this is done (in fact, ask Patrick Harms)
+     * </p>
+     * .
+     *
+     * @param iteration
+     *            the iteration
+     * @param iterationInstances
+     *            the iteration instances
+     */
+    private void harmonizeIterationInstancesModel(IIteration iteration,
+                                                  List<IIterationInstance> iterationInstances)
+    {
+        final List<ITask> iteratedTaskVariants = new LinkedList<ITask>();
+        final TaskInstanceComparator comparator =
+            preparationTaskHandlingStrategy.getTaskComparator();
+
+        // merge the lexically different variants of iterated task to a unique
+        // list
+        for (final IIterationInstance iterationInstance : iterationInstances) {
+            for (final ITaskInstance executionVariant : iterationInstance) {
+                final ITask candidate = executionVariant.getTask();
+
+                boolean found = false;
+                for (final ITask taskVariant : iteratedTaskVariants) {
+                    if (comparator.areLexicallyEqual(taskVariant, candidate)) {
+                        taskBuilder.setTask(executionVariant, taskVariant);
+                        found = true;
+                        break;
+                    }
+                }
+
+                if (!found) {
+                    iteratedTaskVariants.add(candidate);
+                }
+            }
+        }
+
+        // if there are more than one lexically different variant of iterated
+        // tasks, adapt the
+        // iteration model to be a selection of different variants. In this case
+        // also adapt
+        // the generated iteration instances to correctly contain selection
+        // instances. If there
+        // is only one variant of an iterated task, simply set this as the
+        // marked task of the
+        // iteration. In this case, the instances can be preserved as is
+        if (iteratedTaskVariants.size() > 1) {
+            final ISelection selection = taskFactory.createNewSelection();
+
+            for (final ITask variant : iteratedTaskVariants) {
+                taskBuilder.addChild(selection, variant);
+            }
+
+            taskBuilder.setMarkedTask(iteration, selection);
+
+            for (final IIterationInstance instance : iterationInstances) {
+                for (int i = 0; i < instance.size(); i++) {
+                    final ISelectionInstance selectionInstance =
+                        taskFactory.createNewTaskInstance(selection);
+                    taskBuilder.setChild(selectionInstance, instance.get(i));
+                    taskBuilder.setTaskInstance(instance, i, selectionInstance);
+                }
+            }
+        }
+        else {
+            taskBuilder.setMarkedTask(iteration, iteratedTaskVariants.get(0));
+        }
+    }
+
+    /**
+     * Match as sequence.
+     *
+     * @param appData
+     *            RuleApplicationData needed to keep track of all created tasks
+     * @param m
+     *            The match to be converted into a Task
+     * @return The task of the match with an ISequence as its root
+     */
+    synchronized public ISequence matchAsSequence(RuleApplicationData appData, Match m) {
+        final ISequence sequence = taskFactory.createNewSequence();
+        appData.newTaskCreated(sequence);
+
+        final int[] first = m.getFirstSequence().getSequence();
+        final int[] second = m.getSecondSequence().getSequence();
+
+        // Both sequences of a match are equally long
+        for (int i = 0; i < m.getFirstSequence().size(); i++) {
+
+            // Two gaps aligned to each other: Have not seen it happening so
+            // far, just to handle it
+            if ((first[i] == -1) && (second[i] == -1)) {
+                // Do nothing here.
+            }
+            // Both events are equal, we can simply add the task referring to
+            // the number
+            else if (first[i] == second[i]) {
+                taskBuilder.addChild(sequence, appData.getNumber2Task().get(first[i]));
+            }
+            // We have a gap in the first sequence, we need to add the task of
+            // the second sequence as optional
+            else if ((first[i] == -1) && (second[i] != -1)) {
+                final IOptional optional = taskFactory.createNewOptional();
+                appData.newTaskCreated(optional);
+                taskBuilder.setMarkedTask(optional, appData.getNumber2Task().get(second[i]));
+                taskBuilder.addChild(sequence, optional);
+            }
+            // We have a gap in the second sequence, we need to add the task of
+            // the first sequence as optional
+            else if ((first[i] != -1) && (second[i] == -1)) {
+                final IOptional optional = taskFactory.createNewOptional();
+                appData.newTaskCreated(optional);
+                taskBuilder.setMarkedTask(optional, appData.getNumber2Task().get(first[i]));
+                taskBuilder.addChild(sequence, optional);
+            }
+            // Both tasks are not equal, we need to insert a selection here.
+            // Now things get complicated. We first need to check
+            // if the next position is not a selection. Then we can just create
+            // a selection
+            // of the both Tasks
+            // In the other case (more than one selection following this
+            // selection), we want to
+            // create a selection of sequences where each sequence gets the
+            // corresponding task of
+            // the its sequence in the pattern.
+            //
+            else if (i < (first.length - 1)) {
+
+                if ((first[i] != second[i]) &&
+                    (((first[i + 1] == second[i + 1]) || (first[i + 1] == -1) || (second[i + 1] == -1))))
+                {
+
+                    final ISelection selection = taskFactory.createNewSelection();
+                    appData.newTaskCreated(selection);
+                    taskBuilder.addChild(selection, appData.getNumber2Task().get(first[i]));
+                    taskBuilder.addChild(selection, appData.getNumber2Task().get(second[i]));
+                    taskBuilder.addChild(sequence, selection);
+                }
+                else {
+                    boolean selectionfound = true;
+                    final ISelection selection = taskFactory.createNewSelection();
+                    appData.newTaskCreated(selection);
+
+                    final ISequence subsequence1 = taskFactory.createNewSequence();
+                    appData.newTaskCreated(subsequence1);
+
+                    final ISequence subsequence2 = taskFactory.createNewSequence();
+                    appData.newTaskCreated(subsequence2);
+
+                    taskBuilder.addChild(selection, subsequence1);
+                    taskBuilder.addChild(selection, subsequence2);
+                    taskBuilder.addChild(sequence, selection);
+                    // TODO: We may not run till the end!
+                    while ((i < (first.length - 1)) && selectionfound) {
+                        selectionfound = false;
+                        taskBuilder.addChild(subsequence1, appData.getNumber2Task().get(first[i]));
+                        taskBuilder.addChild(subsequence2, appData.getNumber2Task().get(second[i]));
+                        if ((first[i + 1] != second[i + 1]) && (first[i + 1] != -1) &&
+                            (second[i + 1] != -1))
+                        {
+                            selectionfound = true;
+                        }
+                        else {
+                            continue;
+                        }
+                        i++;
+                    }
+                    if ((i == (first.length - 1)) && selectionfound) {
+                        taskBuilder.addChild(subsequence1, appData.getNumber2Task().get(first[i]));
+                        taskBuilder.addChild(subsequence2, appData.getNumber2Task().get(second[i]));
+                    }
+                }
+            }
+            else {
+                // i = length-1
+                if ((first[i] != second[i])) {
+
+                    final ISelection selection = taskFactory.createNewSelection();
+                    appData.newTaskCreated(selection);
+                    taskBuilder.addChild(selection, appData.getNumber2Task().get(first[i]));
+                    taskBuilder.addChild(selection, appData.getNumber2Task().get(second[i]));
+                    taskBuilder.addChild(sequence, selection);
+                }
+            }
+
+        }
+        return sequence;
+    }
+
+    /**
+     * <p>
+     * replaces all occurrences of all tasks provided in the set with iterations
+     * </p>
+     * .
+     *
+     * @param iteratedTasks
+     *            the tasks to be replaced with iterations
+     * @param sessions
+     *            the sessions in which the tasks are to be replaced
+     * @param appData
+     *            the rule application data combining all data used for applying this rule
+     */
+    private void replaceIterationsOf(Set<ITask> iteratedTasks,
+                                     List<IUserSession> sessions,
+                                     RuleApplicationData appData)
+    {
+        final Map<ITask, IIteration> iterations = new HashMap<ITask, IIteration>();
+        final Map<IIteration, List<IIterationInstance>> iterationInstances =
+            new HashMap<IIteration, List<IIterationInstance>>();
+
+        for (final ITask iteratedTask : iteratedTasks) {
+
+            final IIteration iteration = taskFactory.createNewIteration();
+            appData.newTaskCreated(iteration);
+            iterations.put(iteratedTask, iteration);
+            iterationInstances.put(iteration, new LinkedList<IIterationInstance>());
+        }
+
+        IIterationInstance iterationInstance;
+
+        for (final IUserSession session : sessions) {
+            int index = 0;
+            iterationInstance = null;
+
+            while (index < session.size()) {
+                // we prepared the task instances to refer to unique tasks, if
+                // they are treated
+                // as equal. Therefore, we just compare the identity of the
+                // tasks of the task
+                // instances
+                final ITask currentTask = session.get(index).getTask();
+                final IIteration iteration = iterations.get(currentTask);
+                if (iteration != null) {
+                    if ((iterationInstance == null) || (iterationInstance.getTask() != iteration)) {
+                        iterationInstance = taskFactory.createNewTaskInstance(iteration);
+                        iterationInstances.get(iteration).add(iterationInstance);// TODO:: Don't
+                                                                                 // create
+                        // TaskInstances here,
+                        // use a set of tasks
+                        // instead
+                        taskBuilder.addTaskInstance(session, index, iterationInstance);
+                        index++;
+                    }
+
+                    taskBuilder.addChild(iterationInstance, session.get(index));
+                    taskBuilder.removeTaskInstance(session, index);
+                }
+                else {
+                    if (iterationInstance != null) {
+                        iterationInstance = null;
+                    }
+                    index++;
+                }
+            }
+        }
+
+        for (final Map.Entry<IIteration, List<IIterationInstance>> entry : iterationInstances
+            .entrySet())
+        {
+            harmonizeIterationInstancesModel(entry.getKey(), entry.getValue());
+        }
+    }
+
+    /**
+     * Prepare replacements.
+     *
+     * @param appData
+     *            the app data
+     */
+    private void prepareReplacements(RuleApplicationData appData) {
+        appData.initializeQueues(appData.getSessions().size());
+        int taskId=0;
+        for (Iterator<Match> it = appData.getMatchseqs().iterator(); it.hasNext();) {
+            Match m = it.next();
+            if (m.getOccurences().size() > 2) {
+                final ISequence task = matchAsSequence(appData, m);
+                appData.getPreparedTasks().add(task);
+                
+                for (Iterator<MatchOccurrence> jt = m.getOccurences().iterator(); jt.hasNext();) {
+                    MatchOccurrence mo = jt.next();
+                    // System.out.println("Found this match in sequence " +mo.getSequenceId());
+                    PlannedReplacement pr = new PlannedReplacement(taskId,mo);
+                    // System.out.println("Adding match to sequence " + mo.getSequenceId());
+                    appData.getPlannedReplacements()[mo.getSequenceId()].add(pr);
+                }
+                taskId++;
+            }
+        }
+    }
+
+    /**
+     * Replace matches.
+     *
+     * @param appData
+     *            the app data
+     */
+    private void replaceMatches(RuleApplicationData appData) {
+
+        final int numberSeqSize = appData.getNumberSequences().size();
+        Console.traceln(Level.INFO, "replacing matches with " + nThreads + " threads");
+        int newThreads = nThreads;
+        if (numberSeqSize < nThreads) {
+            newThreads = numberSeqSize;
+        }
+        final int interval = numberSeqSize / newThreads;
+        int rest = numberSeqSize % newThreads;
+        final ExecutorService executor = Executors.newFixedThreadPool(nThreads);
+        for (int i = 0; i <= (numberSeqSize - interval); i += interval) {
+            int offset = 0;
+            if (rest != 0) {
+                offset = 1;
+                rest--;
+            }
+            final int from = i;
+            final int to = i + interval + offset - 1;
+            Console.traceln(Level.FINE, "Match replacing: Creating thread with matches from " +
+                from + " to " + to);
+            // search each match in every other sequence
+            final ParallelMatchReplacer replacer = new ParallelMatchReplacer(appData, from, to);
+            executor.execute(replacer);
+            i += offset;
+        }
+        executor.shutdown();
+        try {
+            executor.awaitTermination(2, TimeUnit.HOURS);
+        }
+        catch (final InterruptedException e) {
+            e.printStackTrace();
+        }
+    }
+
+    /**
+     * <p>
+     * searches the provided sessions for task iterations. If a task is iterated, it is added to the
+     * returned set.
+     * </p>
+     *
+     * @param sessions
+     *            the sessions
+     * @return a set of tasks being iterated somewhere
+     */
+    private Set<ITask> searchIteratedTasks(List<IUserSession> sessions) {
+        final Set<ITask> iteratedTasks = new HashSet<ITask>();
+        for (final IUserSession session : sessions) {
+            for (int i = 0; i < (session.size() - 1); i++) {
+                // we prepared the task instances to refer to unique tasks, if
+                // they are treated
+                // as equal. Therefore, we just compare the identity of the
+                // tasks of the task
+                // instances
+                if (session.get(i).getTask() == session.get(i + 1).getTask()) {
+                    iteratedTasks.add(session.get(i).getTask());
+                }
+            }
+        }
+        return iteratedTasks;
+    }
+
+    /**
+     * Generate pairwise alignments.
+     *
+     * @param appData
+     *            the app data
+     */
+    private void generatePairwiseAlignments(RuleApplicationData appData) {
+        final int numberSeqSize = appData.getNumberSequences().size();
+        appData.matchseqs = new LinkedList<Match>();
+        Console.traceln(Level.INFO, "generating pairwise alignments from " + numberSeqSize +
+            " sessions with " + nThreads + " threads");
+
+        int newThreads = nThreads;
+        if (numberSeqSize < nThreads) {
+            newThreads = numberSeqSize;
+        }
+
+        final ExecutorService executor = Executors.newFixedThreadPool(newThreads);
+        final int interval = numberSeqSize / newThreads;
+        int rest = numberSeqSize % newThreads;
+        Console.traceln(Level.FINE, "Interval: " + interval + " Rest: " + rest);
+        for (int i = 0; i <= (numberSeqSize - interval); i += interval) {
+            int offset = 0;
+            if (rest != 0) {
+                offset = 1;
+                rest--;
+            }
+
+            final int from = i;
+            final int to = i + interval + offset - 1;
+            Console.traceln(Level.FINER, "Aligning: Creating thread for sessions " + from +
+                " till " + to);
+            final ParallelPairwiseAligner aligner = new ParallelPairwiseAligner(appData, from, to);
+            executor.execute(aligner);
+            i += offset;
+        }
+        executor.shutdown();
+        try {
+            executor.awaitTermination(2, TimeUnit.HOURS);
+        }
+        catch (final InterruptedException e) {
+            e.printStackTrace();
+        }
+    }
+
+    /**
+     * Search matches in all sessions.
+     *
+     * @param appData
+     *            the app data
+     */
+    private void searchMatchesInAllSessions(RuleApplicationData appData) {
+
+        // Prepare parallel search of matchseqs
+        final int matchSeqSize = appData.getMatchseqs().size();
+        Console.traceln(Level.INFO, "searching for patterns (" + matchSeqSize +
+            ") occuring most with " + nThreads + " threads");
+        int newThreads = nThreads;
+        if (matchSeqSize < nThreads) {
+            newThreads = matchSeqSize;
+        }
+        final int interval = matchSeqSize / newThreads;
+        int rest = matchSeqSize % newThreads;
+        final ExecutorService executor = Executors.newFixedThreadPool(nThreads);
+        Console.traceln(Level.FINER, "Interval: " + interval + " Rest: " + rest);
+        for (int i = 0; i <= (matchSeqSize - interval); i += interval) {
+            int offset = 0;
+            if (rest != 0) {
+                offset = 1;
+                rest--;
+            }
+            final int from = i;
+            final int to = i + interval + offset - 1;
+            Console.traceln(Level.FINE, "Match finding: Creating thread with matches from " + from +
+                " to " + to);
+            // search each match in every other sequence
+            final ParallelMatchOcurrencesFinder finder =
+                new ParallelMatchOcurrencesFinder(appData, from, to);
+            executor.execute(finder);
+            i += offset;
+        }
+        executor.shutdown();
+        try {
+            executor.awaitTermination(2, TimeUnit.HOURS);
+        }
+        catch (final InterruptedException e) {
+            e.printStackTrace();
+        }
+
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see java.lang.Object#toString()
+     */
+    @Override
+    public String toString() {
+        return "SequenceForTaskDetectionRuleAlignment";
+    }
+
+    /**
+     * The Class ParallelMatchOcurrencesFinder.
+     */
+    private class ParallelMatchOcurrencesFinder implements Runnable {
+
+        /** The app data. */
+        private final RuleApplicationData appData;
+
+        /** The from. */
+        private final int from;
+
+        /** The to. */
+        private final int to;
+
+        /**
+         * Instantiates a new parallel match ocurrences finder.
+         *
+         * @param appData
+         *            the app data
+         * @param from
+         *            the from
+         * @param to
+         *            the to
+         */
+        ParallelMatchOcurrencesFinder(RuleApplicationData appData, int from, int to) {
+            this.appData = appData;
+            this.from = from;
+            this.to = to;
+        }
+
+        /*
+         * (non-Javadoc)
+         * 
+         * @see java.lang.Runnable#run()
+         */
+        @Override
+        public void run() {
+            int count = 0;
+            final int size = to + 1 - from;
+
+            for (int i = from; i <= to; i++) {
+                final Match pattern = appData.getMatchseqs().get(i);
+                count++;
+                RuleUtils.printProgressPercentage("Match finding progress", count, size);
+                // Skip sequences with more 0 events (scrolls) than other
+                // events.
+                // Both of the pattern sequences are equally long, so the zero
+                // counts just need to be smaller than the length of one
+                // sequence
+                if ((pattern.getFirstSequence().eventCount(0) +
+                    pattern.getSecondSequence().eventCount(0) + 1) > pattern.getFirstSequence()
+                    .size())
+                {
+                    continue;
+                }
+
+                for (int j = 0; j < appData.getNumberSequences().size(); j++) {
+                    final LinkedList<Integer> startpositions =
+                        appData.getNumberSequences().get(j).containsPattern(pattern);
+                    if (startpositions.size() > 0) {
+                        for (final Iterator<Integer> jt = startpositions.iterator(); jt.hasNext();)
+                        {
+                            final int start = jt.next();
+                            pattern.addOccurence(new MatchOccurrence(start, start + pattern.size(),
+                                                                     j));
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    /**
+     * The Class ParallelPairwiseAligner.
+     */
+    private class ParallelPairwiseAligner implements Runnable {
+
+        /** The app data. */
+        private final RuleApplicationData appData;
+
+        /** The from. */
+        private final int from;
+
+        /** The to. */
+        private final int to;
+
+        /**
+         * Instantiates a new parallel pairwise aligner.
+         *
+         * @param appData
+         *            the app data
+         * @param from
+         *            the from
+         * @param to
+         *            the to
+         */
+        ParallelPairwiseAligner(RuleApplicationData appData, int from, int to) {
+            this.appData = appData;
+            this.from = from;
+            this.to = to;
+        }
+
+        /*
+         * (non-Javadoc)
+         * 
+         * @see java.lang.Runnable#run()
+         */
+        @Override
+        public void run() {
+            int count = 0;
+            final int size = to + 1 - from;
+
+            for (int i = from; i <= to; i++) {
+                final NumberSequence ns1 = appData.getNumberSequences().get(i);
+                count++;
+                RuleUtils.printProgressPercentage("Aligning Progress", count, size);
+                for (int j = 0; j < appData.getNumberSequences().size(); j++) {
+                    final NumberSequence ns2 = appData.getNumberSequences().get(j);
+                    if (i != j) {
+                        final AlignmentAlgorithm aa = AlignmentAlgorithmFactory.create();
+                        // threshold was 9
+                        aa.align(ns1, ns2, appData.getSubmat(),
+                                 SequenceForTaskDetectionRuleAlignment.alignmentThreshold);
+                        synchronized (appData.getMatchseqs()) {
+                            appData.getMatchseqs().addAll(aa.getMatches());
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    /**
+     * The Class ParallelPairwiseAligner.
+     */
+    private class ParallelMatchReplacer implements Runnable {
+
+        /** The app data. */
+        private final RuleApplicationData appData;
+
+        /** The from. */
+        private final int from;
+
+        /** The to. */
+        private final int to;
+
+        /**
+         * Instantiates a new parallel pairwise aligner.
+         *
+         * @param appData
+         *            the app data
+         * @param from
+         *            the from
+         * @param to
+         *            the to
+         */
+        ParallelMatchReplacer(RuleApplicationData appData, int from, int to) {
+            this.appData = appData;
+            this.from = from;
+            this.to = to;
+        }
+
+        /*
+         * (non-Javadoc)
+         * 
+         * @see java.lang.Runnable#run()
+         */
+        @Override
+        public void run() {
+            for (int i = from; i <= to; i++) {
+                System.out.println("Replacing in SEQUENCE " + i);
+                /*
+                 * HashMap for keeping track in which sequence which replacement has been performed.
+                 * Neccessary for updating the indices of other occurrences accordingly
+                 */
+                LinkedList<MatchOccurrence> replacedOccurrences = new LinkedList<MatchOccurrence>();
+                invalidOccurence: while (!appData.getPlannedReplacements()[i].isEmpty()) {
+
+                    PlannedReplacement pr = appData.getPlannedReplacements()[i].remove();
+                    
+                    MatchOccurrence oc = pr.getOccurrence();
+                    // check if we have any replaced occurrence with
+                    // indexes
+                    // smaller than ours. If so, we need to adjust
+                    // our start and end points of the replacement.
+                    // Also do a check if we have replaced this
+                    // specific MatchOccurence in this sequence already.
+                    // Jump to the next occurrence if this is the case.
+                    // This is no more necessary once the matches
+                    // are harmonized.
+
+                    for (final Iterator<MatchOccurrence> jt = replacedOccurrences.iterator(); jt
+                        .hasNext();)
+                    {
+                        final MatchOccurrence tmpOC = jt.next();
+
+                        if ((oc.getStartindex() >= tmpOC.getStartindex()) &&
+                            (oc.getStartindex() <= tmpOC.getEndindex()))
+                        {
+                            continue invalidOccurence;
+                        }
+                        if (oc.getEndindex() >= tmpOC.getStartindex()) {
+                            continue invalidOccurence;
+
+                        }
+                        else if (oc.getStartindex() > tmpOC.getEndindex()) {
+                            final int diff = tmpOC.getEndindex() - tmpOC.getStartindex();
+                            // Just to be sure.
+                            if (diff > 0) {
+                                oc.setStartindex((oc.getStartindex() - diff) + 1);
+                                oc.setEndindex((oc.getEndindex() - diff) + 1);
+                            }
+                            else {
+                                Console
+                                    .traceln(Level.WARNING,
+                                             "End index of a Match before start. This should never happen");
+                            }
+                        }
+                    }
+                    synchronized (appData) {
+                        appData.detectedAndReplacedTasks = true;
+                    }
+                   
+
+                    System.out.println("Replacing in Sequence " + oc.getSequenceId() +
+                        " at position " + oc.getStartindex() + " till " + oc.getEndindex());
+                    final ISequenceInstance sequenceInstances =
+                        RuleUtils.createNewSubSequenceInRange(appData.getSessions()
+                                                                  .get(oc.getSequenceId()), oc
+                                                                  .getStartindex(), oc
+                                                                  .getEndindex(), (ISequence) appData.getPreparedTasks().get(pr.getMatchId()),
+                                                              taskFactory, taskBuilder);
+
+                    // Adjust the length of the match regarding to the
+                    // length of
+                    // instance. (OptionalInstances may be shorter)
+                    oc.setEndindex((oc.getStartindex() + sequenceInstances.size()) -
+                        RuleUtils.missedOptionals);
+
+                    replacedOccurrences.add(oc);
+
+                }
+            }
+        }
+    }
+    
+    private static class PlannedReplacement {
+        private int matchId;
+        private int getMatchId() {
+            return matchId;
+        }
+
+        private MatchOccurrence getOccurrence() {
+            return occurrence;
+        }
+
+        private MatchOccurrence occurrence;
+        
+        private PlannedReplacement(int matchId,MatchOccurrence occurrence) {
+            this.matchId = matchId;
+            this.occurrence = occurrence;
+        }
+    }
+
+    /**
+     * The Class RuleApplicationData.
+     */
+    private static class RuleApplicationData implements Serializable {
+
+        /** The Constant serialVersionUID. */
+        private static final long serialVersionUID = -7559657686755522960L;
+
+        /**
+         * The number2task HashMap. Since we align the tasks just by their integer id, we need this
+         * to convert them back to Tasks again
+         */
+        private final HashMap<Integer, ITask> number2task;
+
+        /**
+         * The unique tasks, keeps track about all unique tasks TODO: We Actually just need
+         * number2task here, this structure can be removed in the future.
+         */
+        private final HashSet<ITask> uniqueTasks;
+
+        /**
+         * The substitution matrix used by the alignment algorithm to be able to compare distances
+         * of tasks
+         */
+        private final ObjectDistanceSubstitionMatrix submat;
+
+        private LinkedList<PlannedReplacement>[] plannedReplacements;
+
+        /** The list of all found matches */
+        private LinkedList<Match> matchseqs;
+        
+        private ArrayList<ITask> preparedTasks;
+
+        public ArrayList<ITask> getPreparedTasks() {
+            return preparedTasks;
+        }
+
+        /**
+         * The generated NumberSequences. This is the integer representation of the user sessions
+         */
+        private ArrayList<NumberSequence> numberseqs;
+
+        /** The list of newly created tasks (of one iteration). */
+        private final LinkedList<ITask> newTasks;
+
+        /** The user sessions containing all EventTasks/Instances */
+        private final List<IUserSession> sessions;
+
+        /** True if we replaced something in the user sessions in one iteration. */
+        private boolean detectedAndReplacedTasks;
+
+        /** The result we return from this rule */
+        private final RuleApplicationResult result;
+
+        /** Stop Watch to measure performance */
+        private final StopWatch stopWatch;
+
+        /**
+         * Instantiates a new rule application data.
+         *
+         * @param sessions
+         *            The user sessions
+         */
+        private RuleApplicationData(List<IUserSession> sessions) {
+            this.sessions = sessions;
+            numberseqs = new ArrayList<NumberSequence>();
+            uniqueTasks = new HashSet<ITask>();
+            number2task = new HashMap<Integer, ITask>();
+            stopWatch = new StopWatch();
+            result = new RuleApplicationResult();
+            preparedTasks = new ArrayList<ITask>();
+            submat = new ObjectDistanceSubstitionMatrix(maxSubstitutionScore, gapPenalty, false);
+            newTasks = new LinkedList<ITask>();
+            this.detectedAndReplacedTasks = true;
+        }
+
+        private void initializeQueues(int size) {
+            plannedReplacements = new LinkedList[size];
+            for (int i = 0; i < size; i++) {
+                plannedReplacements[i] = new LinkedList<PlannedReplacement>();
+            }
+        }
+
+        public Queue<PlannedReplacement>[] getPlannedReplacements() {
+            return plannedReplacements;
+        }
+
+        /**
+         * Detected and replaced tasks.
+         *
+         * @return true, if successful
+         */
+        private boolean detectedAndReplacedTasks() {
+            return detectedAndReplacedTasks;
+        }
+
+        /**
+         * Gets the match sequences.
+         *
+         * @return the match sequences
+         */
+        public LinkedList<Match> getMatchseqs() {
+            return matchseqs;
+        }
+
+        /**
+         * Gets the new tasks.
+         *
+         * @return the new tasks
+         */
+        public LinkedList<ITask> getNewTasks() {
+            return newTasks;
+        }
+
+        /**
+         * Gets the number2task.
+         *
+         * @return the number2task HashMap
+         */
+        private HashMap<Integer, ITask> getNumber2Task() {
+            return number2task;
+        }
+
+        /**
+         * Gets the number sequences.
+         *
+         * @return the number sequences
+         */
+        private ArrayList<NumberSequence> getNumberSequences() {
+            return numberseqs;
+        }
+
+        /**
+         * Gets the result.
+         *
+         * @return the result
+         */
+        private RuleApplicationResult getResult() {
+            return result;
+        }
+
+        /**
+         * Gets the sessions.
+         *
+         * @return the UserSessions as List.
+         */
+        private List<IUserSession> getSessions() {
+            return sessions;
+        }
+
+        /**
+         * Gets the stop watch.
+         *
+         * @return the stopWatch
+         */
+        private StopWatch getStopWatch() {
+            return stopWatch;
+        }
+
+        /**
+         * Gets the substitution matrix.
+         *
+         * @return the substitution matrix
+         */
+        private ObjectDistanceSubstitionMatrix getSubmat() {
+            return submat;
+        }
+
+        /**
+         * Gets the unique tasks.
+         *
+         * @return the unique tasks
+         */
+        private HashSet<ITask> getUniqueTasks() {
+            return uniqueTasks;
+        }
+
+        /**
+         * New task created.
+         *
+         * @param task
+         *            can be called when new tasks are created to keep track of all newly created
+         *            tasks
+         */
+        private void newTaskCreated(ITask task) {
+            number2task.put(task.getId(), task);
+            newTasks.add(task);
+        }
+
+        /**
+         * Reset newly created tasks.
+         */
+        synchronized private void resetNewlyCreatedTasks() {
+            uniqueTasks.addAll(newTasks);
+            newTasks.clear();
+        }
+
+        /**
+         * Sets the number sequences.
+         *
+         * @param numberseqs
+         *            the new number sequences
+         */
+        private void setNumberSequences(ArrayList<NumberSequence> numberseqs) {
+            this.numberseqs = numberseqs;
+        }
+
+        /**
+         * Update substitution matrix.
+         */
+        private void updateSubstitutionMatrix() {
+            submat.update(getNewTasks());
+            resetNewlyCreatedTasks();
+        }
+
+    }
 
 }
