Changeset 1747 for branches/autoquest-core-tasktrees-alignment/src
- Timestamp:
- 09/16/14 17:48:28 (10 years ago)
- Location:
- branches/autoquest-core-tasktrees-alignment/src/main/java/de/ugoe/cs/autoquest/tasktrees
- Files:
-
- 1 added
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/autoquest-core-tasktrees-alignment/src/main/java/de/ugoe/cs/autoquest/tasktrees/alignment/algorithms/Match.java
r1742 r1747 149 149 * Task id sum. Used for comparing and sorting matches 150 150 * 151 * @return 151 * @return the int 152 152 */ 153 153 public int taskIdSum() { … … 161 161 } 162 162 163 public Match cloneWithoutOccurences() throws CloneNotSupportedException { 164 Match result; 165 result = (Match) this.clone(); 166 result.occurrences.clear(); 163 164 165 /** 166 * Clone without occurrences. 167 * 168 * @return the match 169 * @throws CloneNotSupportedException the clone not supported exception 170 */ 171 public Match cloneWithoutOccurrences() { 172 Match result = new Match(); 173 result.setFirstSequence(this.getFirstSequence()); 174 result.setSecondSequence(this.getSecondSequence()); 167 175 return result; 168 176 } -
branches/autoquest-core-tasktrees-alignment/src/main/java/de/ugoe/cs/autoquest/tasktrees/alignment/algorithms/NumberSequence.java
r1734 r1747 2 2 * 3 3 */ 4 4 5 package de.ugoe.cs.autoquest.tasktrees.alignment.algorithms; 5 6 … … 13 14 */ 14 15 public class NumberSequence implements Serializable { 15 16 /** The Constant serialVersionUID. */ 17 private static final long serialVersionUID = -4604570107534055589L; 18 19 /** The sequence. */ 20 private int[] sequence; 21 22 /** The id. */ 23 private int id; 24 25 /** 26 * Instantiates a new number sequence. 27 * 28 * @param size the size 29 */ 30 public NumberSequence(int size) { 31 32 sequence = new int[size]; 33 } 34 35 // Searching occurrences of pattern 36 /** 37 * Contains pattern. 38 * 39 * @param pattern the pattern 40 * @return the linked list 41 */ 42 public LinkedList<Integer> containsPattern(Match pattern) { 43 final LinkedList<Integer> result = new LinkedList<Integer>(); 44 int i = 0; 45 final int[] pat1 = pattern.getFirstSequence().getSequence(); 46 final int[] pat2 = pattern.getSecondSequence().getSequence(); 47 48 while (i < sequence.length) { 49 if (matches(i, pat1, pat2, 0, 0, false, false, false, false, false)) { 50 result.add(i); 51 } 52 i++; 53 } 54 return result; 55 } 56 57 /** 58 * Equals. 59 * 60 * @param n the n 61 * @return true, if successful 62 */ 63 public boolean equals(NumberSequence n) { 64 final int[] seq = n.getSequence(); 65 if (n.size() != this.size()) { 66 return false; 67 } 68 for (int i = 0; i < n.size(); i++) { 69 if (seq[i] != this.sequence[i]) { 70 return false; 71 } 72 } 73 return true; 74 } 75 76 // Returns the number of times event occurs in this sequence 77 /** 78 * Event count. 79 * 80 * @param event the event 81 * @return the int 82 */ 83 public int eventCount(int event) { 84 int count = 0; 85 for (int i = 0; i < sequence.length; i++) { 86 if (sequence[i] == event) { 87 count++; 88 } 89 } 90 return count; 91 } 92 93 /** 94 * Gets the id. 95 * 96 * @return the id 97 */ 98 public int getId() { 99 return id; 100 } 101 102 /** 103 * Gets the sequence. 104 * 105 * @return the sequence 106 */ 107 public int[] getSequence() { 108 return sequence; 109 } 110 111 // Recursive check if sequence contains pattern at position i 112 /** 113 * Matches. 114 * 115 * @param i the i 116 * @param p1 the p1 117 * @param p2 the p2 118 * @param ip1 the ip1 119 * @param ip2 the ip2 120 * @param jumped1 the jumped1 121 * @param jumped2 the jumped2 122 * @param hadSelection the had selection 123 * @param matchseq1 the matchseq1 124 * @param matchseq2 the matchseq2 125 * @return true, if successful 126 */ 127 private boolean matches(int i, int[] p1, int[] p2, int ip1, int ip2, 128 boolean jumped1, // True if there was a gap in Sequence 1 of the 129 // pattern 130 boolean jumped2, // True if there was a gap in Sequence 2 of the 131 // pattern 132 boolean hadSelection, // True if the last match was a selection 133 boolean matchseq1, boolean matchseq2) { 134 135 if (p1.length == ip1) { 136 return true; 137 } 138 if (p2.length == ip2) { 139 return true; 140 } 141 if (i == sequence.length) { 142 return false; 143 } 144 145 final boolean foundselection = (!(p1[ip1] == p2[ip2]) && !((p1[ip1] == -1) || (p2[ip2] == -1))); 146 final boolean matchInFirstPattern = (p1[ip1] == sequence[i]); 147 final boolean matchInSecondPattern = (p2[ip2] == sequence[i]); 148 149 if (foundselection && hadSelection) { 150 if ((matchInFirstPattern && matchseq1) 151 || (matchInSecondPattern && matchseq2)) { 152 if (jumped1) { 153 return matches(i + 1, p1, p2, ip1 + 1, ip2 + 2, false, 154 false, foundselection, matchInFirstPattern, 155 matchInSecondPattern); 156 } 157 if (jumped2) { 158 return matches(i + 1, p1, p2, ip1 + 2, ip2 + 1, false, 159 false, foundselection, matchInFirstPattern, 160 matchInSecondPattern); 161 } 162 return matches(i + 1, p1, p2, ip1 + 1, ip2 + 1, false, false, 163 foundselection, matchInFirstPattern, 164 matchInSecondPattern); 165 } else { 166 return false; 167 } 168 } 169 170 if ((matchInFirstPattern || matchInSecondPattern) && jumped1) { 171 return matches(i + 1, p1, p2, ip1 + 1, ip2 + 2, false, false, 172 foundselection, matchInFirstPattern, matchInSecondPattern); 173 } 174 if ((matchInFirstPattern || matchInSecondPattern) && jumped2) { 175 return matches(i + 1, p1, p2, ip1 + 2, ip2 + 1, false, false, 176 foundselection, matchInFirstPattern, matchInSecondPattern); 177 } 178 if (matchInFirstPattern || matchInSecondPattern) { 179 return matches(i + 1, p1, p2, ip1 + 1, ip2 + 1, false, false, 180 foundselection, matchInFirstPattern, matchInSecondPattern); 181 } 182 if (p1[ip1] == -1) { 183 return matches(i, p1, p2, ip1 + 1, ip2, true, false, false, false, 184 false); 185 } 186 if (p2[ip2] == -1) { 187 return matches(i, p1, p2, ip1, ip2 + 1, false, true, false, false, 188 false); 189 } 190 191 return false; 192 } 193 194 /** 195 * Prints the sequence. 196 */ 197 public void printSequence() { 198 for (int i = 0; i < sequence.length; i++) { 199 System.out.format("%5d", sequence[i]); 200 } 201 System.out.println(); 202 } 203 204 /** 205 * Sets the id. 206 * 207 * @param id the new id 208 */ 209 public void setId(int id) { 210 this.id = id; 211 } 212 213 /** 214 * Sets the sequence. 215 * 216 * @param sequence the new sequence 217 */ 218 public void setSequence(int[] sequence) { 219 this.sequence = sequence; 220 } 221 222 /** 223 * Shuffle. 224 * 225 * @return the number sequence 226 */ 227 public NumberSequence shuffle() { 228 final NumberSequence result = new NumberSequence(sequence.length); 229 result.setId(getId()); 230 result.setSequence(this.sequence); 231 final Random rgen = new Random(); 232 233 for (int i = 0; i < result.sequence.length; i++) { 234 final int randomPosition = rgen.nextInt(result.sequence.length); 235 final int temp = result.sequence[i]; 236 result.sequence[i] = result.sequence[randomPosition]; 237 result.sequence[randomPosition] = temp; 238 } 239 return result; 240 241 } 242 243 /** 244 * Size. 245 * 246 * @return the int 247 */ 248 public int size() { 249 return sequence.length; 250 } 16 17 /** The Constant serialVersionUID. */ 18 private static final long serialVersionUID = -4604570107534055589L; 19 20 /** The sequence. */ 21 private int[] sequence; 22 23 /** The id. */ 24 private int id; 25 26 /** 27 * Instantiates a new number sequence. 28 * 29 * @param size 30 * the size 31 */ 32 public NumberSequence(int size) { 33 34 sequence = new int[size]; 35 } 36 37 // Searching occurrences of pattern 38 /** 39 * Contains pattern. 40 * 41 * @param pattern 42 * the pattern 43 * @return the linked list 44 */ 45 public LinkedList<Integer> containsPattern(Match pattern) { 46 final LinkedList<Integer> result = new LinkedList<Integer>(); 47 int i = 0; 48 final int[] pat1 = pattern.getFirstSequence().getSequence(); 49 final int[] pat2 = pattern.getSecondSequence().getSequence(); 50 51 while (i < sequence.length) { 52 if (matches(i, pat1, pat2, 0, 0, false, false, false, false, false)) { 53 result.add(i); 54 } 55 i++; 56 } 57 return result; 58 } 59 60 /** 61 * Equals. 62 * 63 * @param n 64 * the n 65 * @return true, if successful 66 */ 67 public boolean equals(NumberSequence n) { 68 final int[] seq = n.getSequence(); 69 if (n.size() != this.size()) { 70 return false; 71 } 72 for (int i = 0; i < n.size(); i++) { 73 if (seq[i] != this.sequence[i]) { 74 return false; 75 } 76 } 77 return true; 78 } 79 80 // Returns the number of times event occurs in this sequence 81 /** 82 * Event count. 83 * 84 * @param event 85 * the event 86 * @return the int 87 */ 88 public int eventCount(int event) { 89 int count = 0; 90 for (int i = 0; i < sequence.length; i++) { 91 if (sequence[i] == event) { 92 count++; 93 } 94 } 95 return count; 96 } 97 98 /** 99 * Gets the id. 100 * 101 * @return the id 102 */ 103 public int getId() { 104 return id; 105 } 106 107 /** 108 * Gets the sequence. 109 * 110 * @return the sequence 111 */ 112 public int[] getSequence() { 113 return sequence; 114 } 115 116 // Recursive check if sequence contains pattern at position i 117 /** 118 * Matches. 119 * 120 * @param i 121 * the position in the sequence 122 * @param p1 123 * the p1 124 * @param p2 125 * the p2 126 * @param ip1 127 * the ip1 128 * @param ip2 129 * the ip2 130 * @param jumped1 131 * the jumped1 132 * @param jumped2 133 * the jumped2 134 * @param hadSelection 135 * the had selection 136 * @param matchseq1 137 * the matchseq1 138 * @param matchseq2 139 * the matchseq2 140 * @return true, if successful 141 */ 142 private boolean matches(int i, int[] p1, int[] p2, int ip1, int ip2, boolean jumped1, // True if 143 // there 144 // was a 145 // gap in 146 // Sequence 147 // 1 of 148 // the 149 // pattern 150 boolean jumped2, // True if there was a gap in Sequence 2 of the 151 // pattern 152 boolean hadSelection, // True if the last match was a selection 153 boolean matchseq1, 154 boolean matchseq2) 155 { 156 157 if (p1.length == ip1) { 158 return true; 159 } 160 if (p2.length == ip2) { 161 return true; 162 } 163 if (i == sequence.length) { 164 return false; 165 } 166 167 final boolean foundselection = 168 (!(p1[ip1] == p2[ip2]) && !((p1[ip1] == -1) || (p2[ip2] == -1))); 169 final boolean matchInFirstPattern = (p1[ip1] == sequence[i]); 170 final boolean matchInSecondPattern = (p2[ip2] == sequence[i]); 171 172 if (foundselection && hadSelection) { 173 if ((matchInFirstPattern && matchseq1) || (matchInSecondPattern && matchseq2)) { 174 if (jumped1) { 175 return matches(i + 1, p1, p2, ip1 + 1, ip2 + 2, false, false, foundselection, 176 matchInFirstPattern, matchInSecondPattern); 177 } 178 if (jumped2) { 179 return matches(i + 1, p1, p2, ip1 + 2, ip2 + 1, false, false, foundselection, 180 matchInFirstPattern, matchInSecondPattern); 181 } 182 return matches(i + 1, p1, p2, ip1 + 1, ip2 + 1, false, false, foundselection, 183 matchInFirstPattern, matchInSecondPattern); 184 } 185 else { 186 return false; 187 } 188 } 189 190 if ((matchInFirstPattern || matchInSecondPattern) && jumped1) { 191 return matches(i + 1, p1, p2, ip1 + 1, ip2 + 2, false, false, foundselection, 192 matchInFirstPattern, matchInSecondPattern); 193 } 194 if ((matchInFirstPattern || matchInSecondPattern) && jumped2) { 195 return matches(i + 1, p1, p2, ip1 + 2, ip2 + 1, false, false, foundselection, 196 matchInFirstPattern, matchInSecondPattern); 197 198 } 199 if (matchInFirstPattern || matchInSecondPattern) { 200 return matches(i + 1, p1, p2, ip1 + 1, ip2 + 1, false, false, foundselection, 201 matchInFirstPattern, matchInSecondPattern); 202 } 203 if (p1[ip1] == -1) { 204 return matches(i, p1, p2, ip1 + 1, ip2, true, false, false, false, false); 205 } 206 if (p2[ip2] == -1) { 207 return matches(i, p1, p2, ip1, ip2 + 1, false, true, false, false, false); 208 } 209 210 return false; 211 } 212 213 /** 214 * Prints the sequence. 215 */ 216 public void printSequence() { 217 for (int i = 0; i < sequence.length; i++) { 218 System.out.format("%5d", sequence[i]); 219 } 220 System.out.println(); 221 } 222 223 /** 224 * Sets the id. 225 * 226 * @param id 227 * the new id 228 */ 229 public void setId(int id) { 230 this.id = id; 231 } 232 233 /** 234 * Sets the sequence. 235 * 236 * @param sequence 237 * the new sequence 238 */ 239 public void setSequence(int[] sequence) { 240 this.sequence = sequence; 241 } 242 243 /** 244 * Shuffle. 245 * 246 * @return the number sequence 247 */ 248 public NumberSequence shuffle() { 249 final NumberSequence result = new NumberSequence(sequence.length); 250 result.setId(getId()); 251 result.setSequence(this.sequence); 252 final Random rgen = new Random(); 253 254 for (int i = 0; i < result.sequence.length; i++) { 255 final int randomPosition = rgen.nextInt(result.sequence.length); 256 final int temp = result.sequence[i]; 257 result.sequence[i] = result.sequence[randomPosition]; 258 result.sequence[randomPosition] = temp; 259 } 260 return result; 261 262 } 263 264 /** 265 * Size. 266 * 267 * @return the int 268 */ 269 public int size() { 270 return sequence.length; 271 } 251 272 252 273 } -
branches/autoquest-core-tasktrees-alignment/src/main/java/de/ugoe/cs/autoquest/tasktrees/alignment/matrix/ObjectDistanceSubstitionMatrix.java
r1741 r1747 109 109 eti1 = (IEventTaskInstance) ti1; 110 110 index1 = getIndex(eti1); 111 distance = distanceBetweenTaskAndInstance(task2, eti1) ;111 distance = distanceBetweenTaskAndInstance(task2, eti1)-3; 112 112 } else if (!(ti1 instanceof IEventTaskInstance) 113 113 && (ti2 instanceof IEventTaskInstance)) { … … 120 120 index1 = getIndex(task1); 121 121 index2 = getIndex(task2); 122 distance = distanceBetweenTasks(task1, task2) ;122 distance = distanceBetweenTasks(task1, task2)-3; 123 123 } else { 124 124 System.out.println("Unknown error"); … … 212 212 this.uniqueTasks = uniqueTasks; 213 213 if (this.calculateNonEventTaskInstances) { 214 matrix = new DynamicTriangleMatrix(uniqueTasks.size() + 1);214 matrix = new PreallocatedDynamicTriangleMatrix(uniqueTasks.size() + 1); 215 215 Console.traceln(Level.INFO, "searching EventTasks in Tasks"); 216 216 //searchEventTaskInstances(); -
branches/autoquest-core-tasktrees-alignment/src/main/java/de/ugoe/cs/autoquest/tasktrees/temporalrelation/RuleUtils.java
r1743 r1747 15 15 package de.ugoe.cs.autoquest.tasktrees.temporalrelation; 16 16 17 import de.ugoe.cs.autoquest.tasktrees.treeifc.IIteration; 17 18 import de.ugoe.cs.autoquest.tasktrees.treeifc.IMarkingTemporalRelationship; 18 19 import de.ugoe.cs.autoquest.tasktrees.treeifc.IStructuringTemporalRelationship; … … 65 66 final ISequenceInstance subsequence = taskFactory 66 67 .createNewTaskInstance(model); 67 /* 68 69 //System.out.println("STARTINDEX: " + startIndex); 70 //System.out.println("PRINTING SEQUENCE: "); 71 //for(int i =0; i< parent.size();i++) { 72 // System.out.println(i + ": " +parent.get(i)); 73 //} 74 System.out.println(); 75 68 76 System.out.println("PRINTING MODEL: "); 69 77 for (int i = 0; i < subsequence.getSequence().getChildren().size(); i++) { … … 97 105 } 98 106 System.out.println(); 99 */107 100 108 // TODO: This is dirty, return this in addition with the sequence 101 109 // instance instead … … 110 118 //System.out.println("Trying to add " + parent.get(startIndex) 111 119 // + " to the model instance " + tempTask); 112 if (tempTask .getType() == "optionality") {113 114 if (((IMarkingTemporalRelationship) tempTask).getMarkedTask() ==parent115 .get(startIndex).getTask()) {116 //System.out.println("Adding OptionalInstance " +120 if (tempTask instanceof IOptional) { 121 122 if (((IMarkingTemporalRelationship) tempTask).getMarkedTask().equals(parent 123 .get(startIndex).getTask())) { 124 //System.out.println("Adding OptionalInstance " + 117 125 // parent.get(startIndex) + " to " + tempTask.getType()); 118 126 final IOptionalInstance optional = taskFactory … … 121 129 taskBuilder.addChild(subsequence, optional); 122 130 } else { 123 //System.out.println("Adding Empty optional, not deleting anything from the input sequence");131 //System.out.println("Adding Empty optional, not deleting anything from the input sequence"); 124 132 final IOptionalInstance optional = taskFactory 125 133 .createNewTaskInstance((IOptional) tempTask); … … 211 219 taskBuilder.addChild(subsequence, selection); 212 220 } 213 } else if (tempTask .getType() == "sequence") {221 } else if (tempTask instanceof ISequence) { 214 222 taskBuilder.addChild(subsequence, parent.get(startIndex)); 215 } else if (tempTask .getType() == "iteration") {223 } else if (tempTask instanceof IIteration) { 216 224 taskBuilder.addChild(subsequence, parent.get(startIndex)); 217 225 } else { … … 227 235 } 228 236 237 238 /* 239 static boolean containsOptional(ISequence seq) { 240 for(int i = 0; i < seq.getChildren().size();i++) { 241 if(seq.getChildren().get(i) instanceof IOptional) { 242 return true; 243 } 244 } 245 return false; 246 } 247 248 private boolean reachesEnd(ITaskInstanceList parent, ISequence model,int sequenceIndex,int modelIndex,int startIndex) { 249 250 if(modelIndex == model.getChildren().size()) { 251 return true; 252 } 253 ITask modelTask = model.getChildren().get(modelIndex); 254 ITask sessionTask = parent.get(startIndex+sequenceIndex).getTask(); 255 if(modelTask instanceof IOptional) { 256 reachesEnd(parent,model,sequenceIndex++,modelIndex++,startIndex); 257 reachesEnd(parent,model,sequenceIndex,modelIndex++,startIndex); 258 } 259 260 boolean taskfits=false; 261 if(modelTask instanceof ISequence) { 262 if(sessionTask.equals(((ISequence)modelTask).getChildren().get(0))) { 263 taskfits=true; 264 } 265 } 266 if(modelTask instanceof IIteration) { 267 if(sessionTask.equals(((ISequence)modelTask).getChildren().get(0))) { 268 taskfits=true; 269 } 270 } 271 if(modelTask instanceof ISelection) { 272 273 } 274 275 return taskfits; 276 277 278 279 } 280 */ 281 282 229 283 /** 230 284 * <p> -
branches/autoquest-core-tasktrees-alignment/src/main/java/de/ugoe/cs/autoquest/tasktrees/temporalrelation/SequenceForTaskDetectionRuleAlignment.java
r1743 r1747 58 58 /** 59 59 * <p> 60 * This class implements the major rule for creating task trees based on a set 61 * of recorded user sessions. For this, it first harmonizes all tasks. This 62 * eases later comparison. Then it searches the sessions for iterations and 63 * replaces them accordingly. Then it searches for sub sequences using alignment 64 * algorithms For each found sub sequence, it replaces the occurrences by 65 * creating appropriate {@link ISequence}s. Afterwards, again searches for 66 * iterations and then again for sub sequences until no more replacements are 67 * done. 60 * This class implements the major rule for creating task trees based on a set of recorded user 61 * sessions. For this, it first harmonizes all tasks. This eases later comparison. Then it searches 62 * the sessions for iterations and replaces them accordingly. Then it searches for sub sequences 63 * using alignment algorithms For each found sub sequence, it replaces the occurrences by creating 64 * appropriate {@link ISequence}s. Afterwards, again searches for iterations and then again for sub 65 * sequences until no more replacements are done. 68 66 * </p> 69 67 * <p> … … 74 72 public class SequenceForTaskDetectionRuleAlignment implements ISessionScopeRule { 75 73 76 /** The n threads. */ 77 //public static int nThreads = Runtime.getRuntime().availableProcessors() - 1; 78 public static int nThreads = 1; 79 80 /** The iteration. */ 81 private int iteration = 0; 82 83 /** 84 * <p> 85 * the task factory to be used for creating substructures for the temporal 86 * relationships identified during rul application 87 * </p> 88 * . 89 */ 90 private final ITaskFactory taskFactory; 91 92 /** 93 * <p> 94 * the task builder to be used for creating substructures for the temporal 95 * relationships identified during rule application 96 * </p> 97 * . 98 */ 99 private final ITaskBuilder taskBuilder; 100 101 /** 102 * <p> 103 * the task handling strategy to be used for comparing tasks for 104 * preparation, i.e., before the tasks are harmonized 105 * </p> 106 */ 107 private final TaskHandlingStrategy preparationTaskHandlingStrategy; 108 109 /** 110 * <p> 111 * instantiates the rule and initializes it with a task equality to be 112 * considered when comparing tasks as well as a task factory and builder to 113 * be used for creating task structures. 114 * </p> 115 * 116 * @param minimalTaskEquality 117 * the task equality to be considered when comparing tasks 118 * @param taskFactory 119 * the task factory to be used for creating substructures 120 * @param taskBuilder 121 * the task builder to be used for creating substructures 122 */ 123 124 SequenceForTaskDetectionRuleAlignment(TaskEquality minimalTaskEquality, 125 ITaskFactory taskFactory, ITaskBuilder taskBuilder) { 126 this.taskFactory = taskFactory; 127 this.taskBuilder = taskBuilder; 128 129 this.preparationTaskHandlingStrategy = new TaskHandlingStrategy( 130 minimalTaskEquality); 131 } 132 133 /* 134 * (non-Javadoc) 135 * 136 * @see 137 * de.ugoe.cs.autoquest.tasktrees.temporalrelation.ISessionScopeRule#apply 138 * (java.util.List) 139 */ 140 @Override 141 public RuleApplicationResult apply(List<IUserSession> sessions) { 142 final RuleApplicationData appData = new RuleApplicationData(sessions); 143 144 harmonizeEventTaskInstancesModel(appData); 145 146 Console.traceln(Level.INFO, "generating substitution matrix from " 147 + appData.getUniqueTasks().size() + " unique tasks"); 148 appData.getStopWatch().start("substitution matrix"); 149 appData.getSubmat().generate(appData.getUniqueTasks()); 150 appData.getStopWatch().stop("substitution matrix"); 151 152 Console.traceln(Level.INFO, "Starting main loop"); 153 do { 154 Console.traceln(Level.INFO, "Iteration Number: " + iteration); 155 iteration++; 156 appData.detectedAndReplacedTasks = false; 157 appData.getStopWatch().start("whole loop"); 158 detectAndReplaceIterations(appData); 159 appData.getStopWatch().start("task replacement"); 160 // Just does anything if the substitution matrix is created with the 161 // option to do so 162 appData.updateSubstitutionMatrix(); 163 detectAndReplaceTasks(appData); // 164 appData.getStopWatch().stop("task replacement"); 165 appData.getStopWatch().stop("whole loop"); 166 // appData.getStopWatch().dumpStatistics(System.out); 167 appData.getStopWatch().reset(); 168 169 } while (appData.detectedAndReplacedTasks()); 170 171 Console.println("created " 172 + appData.getResult().getNewlyCreatedTasks().size() 173 + " new tasks and " 174 + appData.getResult().getNewlyCreatedTaskInstances().size() 175 + " appropriate instances\n"); 176 177 if ((appData.getResult().getNewlyCreatedTasks().size() > 0) 178 || (appData.getResult().getNewlyCreatedTaskInstances().size() > 0)) { 179 appData.getResult().setRuleApplicationStatus( 180 RuleApplicationStatus.FINISHED); 181 } 182 // new TaskTreeValidator().validate(appData.getSessions()); 183 return appData.getResult(); 184 } 185 186 /** 187 * Creates the number sequences. 188 * 189 * @param appData 190 * the app data 191 * @return the array list 192 */ 193 private ArrayList<NumberSequence> createNumberSequences( 194 RuleApplicationData appData) { 195 final ArrayList<NumberSequence> result = new ArrayList<NumberSequence>(); 196 for (int i = 0; i < appData.getSessions().size(); i++) { 197 final IUserSession session = appData.getSessions().get(i); 198 final NumberSequence templist = new NumberSequence(session.size()); 199 for (int j = 0; j < session.size(); j++) { 200 final ITaskInstance taskInstance = session.get(j); 201 templist.getSequence()[j] = taskInstance.getTask().getId(); 202 } 203 // Each NumberSequence is identified by its id, beginning to count 204 // at zero 205 templist.setId(i); 206 result.add(templist); 207 } 208 return result; 209 } 210 211 /** 212 * <p> 213 * searches for direct iterations of single tasks in all sequences and 214 * replaces them with {@link IIteration}s, respectively appropriate 215 * instances. Also all single occurrences of a task that is iterated 216 * somewhen are replaced with iterations to have again an efficient way for 217 * task comparisons. 218 * </p> 219 * 220 * @param appData 221 * the rule application data combining all data used for applying 222 * this rule 223 */ 224 private void detectAndReplaceIterations(RuleApplicationData appData) { 225 Console.traceln(Level.FINE, "detecting iterations"); 226 appData.getStopWatch().start("detecting iterations"); 227 228 final List<IUserSession> sessions = appData.getSessions(); 229 230 final Set<ITask> iteratedTasks = searchIteratedTasks(sessions); 231 232 if (iteratedTasks.size() > 0) { 233 replaceIterationsOf(iteratedTasks, sessions, appData); 234 } 235 236 appData.getStopWatch().stop("detecting iterations"); 237 Console.traceln(Level.INFO, "replaced " + iteratedTasks.size() 238 + " iterated tasks"); 239 } 240 241 /** 242 * Detect and replace tasks. 243 * 244 * @param appData 245 * the rule application data combining all data used for applying 246 * this rule 247 */ 248 private void detectAndReplaceTasks(RuleApplicationData appData) { 249 Console.traceln(Level.FINE, "detecting and replacing tasks"); 250 appData.getStopWatch().start("detecting tasks"); 251 252 // Create NumberSequences 253 appData.setNumberSequences(this.createNumberSequences(appData)); 254 255 // Generate pairwise alignments 256 // appData.setMatchseqs(generatePairwiseAlignments(appData)); 257 generatePairwiseAlignments(appData); 258 Console.traceln(Level.FINE, "Found " + appData.getMatchseqs().size() 259 + " results"); 260 261 //Nothing found, we can end here 262 if(appData.getMatchseqs().size()==0) { 263 appData.detectedAndReplacedTasks=false; 264 return; 265 } 266 267 // Searching each match in all other sessions, counting its occurences 268 searchMatchesInAllSessions(appData); 269 270 // Sort results to get the most occurring results 271 Console.traceln(Level.INFO, "sorting " + appData.getMatchseqs().size() 272 + " results"); 273 final Comparator<Match> comparator = new Comparator<Match>() { 274 @Override 275 public int compare(Match m1, Match m2) { 276 int cmp = m2.occurenceCount() - m1.occurenceCount(); 277 if (cmp != 0) { 278 return cmp; 279 } else { 280 cmp = m2.size() - m1.size(); 281 if (cmp != 0) { 282 return cmp; 283 } else { 284 // This should rarely happen 285 cmp = m2.ocurrenceIDSum() - m1.ocurrenceIDSum(); 286 if (cmp != 0) { 287 return cmp; 288 } else { 289 cmp = m2.taskIdSum() - m1.taskIdSum(); 290 291 return cmp; 292 } 293 } 294 } 295 } 296 }; 297 298 Collections.sort(appData.getMatchseqs(), comparator); 299 appData.getStopWatch().stop("detecting tasks"); 300 301 Console.traceln(Level.INFO, "Preparing replacments"); 302 prepareReplacements(appData); 303 Console.traceln(Level.INFO, "Replacing matches in sessions"); 304 appData.getStopWatch().start("replacing tasks"); 305 replaceMatches(appData); 306 appData.getStopWatch().stop("replacing tasks"); 307 } 308 309 // TODO: DEBUG METHOD 310 @SuppressWarnings("unused") 311 private void printMatches(RuleApplicationData appData) { 312 LinkedList<Match> matchseqs = appData.getMatchseqs(); 313 if (iteration > 1) { 314 System.out.println("PRINTING MATCHES"); 315 for (Iterator<Match> it = matchseqs.iterator(); it.hasNext();) { 316 Match m = it.next(); 317 m.getFirstSequence().printSequence(); 318 m.getSecondSequence().printSequence(); 319 for (Iterator<MatchOccurrence> jt = m.getOccurences() 320 .iterator(); jt.hasNext();) { 321 MatchOccurrence mo = jt.next(); 322 System.out.print(mo.getSequenceId() + " "); 323 } 324 System.out.println(); 325 System.out.println(); 326 } 327 } 328 } 329 330 /** 331 * <p> 332 * harmonizes the event task instances by unifying tasks. This is done, as 333 * initially the event tasks being equal with respect to the considered task 334 * equality are distinct objects. The comparison of these distinct objects 335 * is more time consuming than comparing the object references. 336 * </p> 337 * 338 * @param appData 339 * the rule application data combining all data used for applying 340 * this rule 341 * @return Returns the unique tasks symbol map 342 */ 343 private void harmonizeEventTaskInstancesModel(RuleApplicationData appData) { 344 Console.traceln(Level.INFO, 345 "harmonizing task model of event task instances"); 346 appData.getStopWatch().start("harmonizing event tasks"); 347 final SymbolMap<ITaskInstance, ITask> uniqueTasks = preparationTaskHandlingStrategy 348 .createSymbolMap(); 349 350 final TaskInstanceComparator comparator = preparationTaskHandlingStrategy 351 .getTaskComparator(); 352 353 int unifiedTasks = 0; 354 ITask task; 355 final List<IUserSession> sessions = appData.getSessions(); 356 for (int j = 0; j < sessions.size(); j++) { 357 final IUserSession session = sessions.get(j); 358 359 for (int i = 0; i < session.size(); i++) { 360 final ITaskInstance taskInstance = session.get(i); 361 task = uniqueTasks.getValue(taskInstance); 362 363 if (task == null) { 364 uniqueTasks.addSymbol(taskInstance, taskInstance.getTask()); 365 appData.getUniqueTasks().add(taskInstance.getTask()); 366 appData.getNumber2Task().put( 367 taskInstance.getTask().getId(), 368 taskInstance.getTask()); 369 } else { 370 taskBuilder.setTask(taskInstance, task); 371 unifiedTasks++; 372 } 373 } 374 comparator.clearBuffers(); 375 } 376 377 appData.getStopWatch().stop("harmonizing event tasks"); 378 Console.traceln(Level.INFO, "harmonized " + unifiedTasks 379 + " task occurrences (still " + appData.getUniqueTasks().size() 380 + " different tasks)"); 381 382 appData.getStopWatch().dumpStatistics(System.out); 383 appData.getStopWatch().reset(); 384 } 385 386 /** 387 * <p> 388 * TODO clarify why this is done (in fact, ask Patrick Harms) 389 * </p> 390 * . 391 * 392 * @param iteration 393 * the iteration 394 * @param iterationInstances 395 * the iteration instances 396 */ 397 private void harmonizeIterationInstancesModel(IIteration iteration, 398 List<IIterationInstance> iterationInstances) { 399 final List<ITask> iteratedTaskVariants = new LinkedList<ITask>(); 400 final TaskInstanceComparator comparator = preparationTaskHandlingStrategy 401 .getTaskComparator(); 402 403 // merge the lexically different variants of iterated task to a unique 404 // list 405 for (final IIterationInstance iterationInstance : iterationInstances) { 406 for (final ITaskInstance executionVariant : iterationInstance) { 407 final ITask candidate = executionVariant.getTask(); 408 409 boolean found = false; 410 for (final ITask taskVariant : iteratedTaskVariants) { 411 if (comparator.areLexicallyEqual(taskVariant, candidate)) { 412 taskBuilder.setTask(executionVariant, taskVariant); 413 found = true; 414 break; 415 } 416 } 417 418 if (!found) { 419 iteratedTaskVariants.add(candidate); 420 } 421 } 422 } 423 424 // if there are more than one lexically different variant of iterated 425 // tasks, adapt the 426 // iteration model to be a selection of different variants. In this case 427 // also adapt 428 // the generated iteration instances to correctly contain selection 429 // instances. If there 430 // is only one variant of an iterated task, simply set this as the 431 // marked task of the 432 // iteration. In this case, the instances can be preserved as is 433 if (iteratedTaskVariants.size() > 1) { 434 final ISelection selection = taskFactory.createNewSelection(); 435 436 for (final ITask variant : iteratedTaskVariants) { 437 taskBuilder.addChild(selection, variant); 438 } 439 440 taskBuilder.setMarkedTask(iteration, selection); 441 442 for (final IIterationInstance instance : iterationInstances) { 443 for (int i = 0; i < instance.size(); i++) { 444 final ISelectionInstance selectionInstance = taskFactory 445 .createNewTaskInstance(selection); 446 taskBuilder.setChild(selectionInstance, instance.get(i)); 447 taskBuilder.setTaskInstance(instance, i, selectionInstance); 448 } 449 } 450 } else { 451 taskBuilder.setMarkedTask(iteration, iteratedTaskVariants.get(0)); 452 } 453 } 454 455 /** 456 * Match as sequence. 457 * 458 * @param appData 459 * RuleApplicationData needed to keep track of all created tasks 460 * @param m 461 * The match to be converted into a Task 462 * @return The task of the match with an ISequence as its root 463 */ 464 synchronized public ISequence matchAsSequence(RuleApplicationData appData, 465 Match m) { 466 final ISequence sequence = taskFactory.createNewSequence(); 467 appData.newTaskCreated(sequence); 468 469 final int[] first = m.getFirstSequence().getSequence(); 470 final int[] second = m.getSecondSequence().getSequence(); 471 472 // Both sequences of a match are equally long 473 for (int i = 0; i < m.getFirstSequence().size(); i++) { 474 475 // Two gaps aligned to each other: Have not seen it happening so 476 // far, just to handle it 477 if ((first[i] == -1) && (second[i] == -1)) { 478 // Do nothing here. 479 } 480 // Both events are equal, we can simply add the task referring to 481 // the number 482 else if (first[i] == second[i]) { 483 taskBuilder.addChild(sequence, 484 appData.getNumber2Task().get(first[i])); 485 } 486 // We have a gap in the first sequence, we need to add the task of 487 // the second sequence as optional 488 else if ((first[i] == -1) && (second[i] != -1)) { 489 final IOptional optional = taskFactory.createNewOptional(); 490 appData.newTaskCreated(optional); 491 taskBuilder.setMarkedTask(optional, appData.getNumber2Task() 492 .get(second[i])); 493 taskBuilder.addChild(sequence, optional); 494 } 495 // We have a gap in the second sequence, we need to add the task of 496 // the first sequence as optional 497 else if ((first[i] != -1) && (second[i] == -1)) { 498 final IOptional optional = taskFactory.createNewOptional(); 499 appData.newTaskCreated(optional); 500 taskBuilder.setMarkedTask(optional, appData.getNumber2Task() 501 .get(first[i])); 502 taskBuilder.addChild(sequence, optional); 503 } 504 // Both tasks are not equal, we need to insert a selection here. 505 // Now things get complicated. We first need to check 506 // if the next position is not a selection. Then we can just create 507 // a selection 508 // of the both Tasks 509 // In the other case (more than one selection following this 510 // selection), we want to 511 // create a selection of sequences where each sequence gets the 512 // corresponding task of 513 // the its sequence in the pattern. 514 // 515 else if (i < (first.length - 1)) { 516 517 if ((first[i] != second[i]) 518 && (((first[i + 1] == second[i + 1]) 519 || (first[i + 1] == -1) || (second[i + 1] == -1)))) { 520 521 final ISelection selection = taskFactory 522 .createNewSelection(); 523 appData.newTaskCreated(selection); 524 taskBuilder.addChild(selection, appData.getNumber2Task() 525 .get(first[i])); 526 taskBuilder.addChild(selection, appData.getNumber2Task() 527 .get(second[i])); 528 taskBuilder.addChild(sequence, selection); 529 } else { 530 boolean selectionfound = true; 531 final ISelection selection = taskFactory 532 .createNewSelection(); 533 appData.newTaskCreated(selection); 534 535 final ISequence subsequence1 = taskFactory 536 .createNewSequence(); 537 appData.newTaskCreated(subsequence1); 538 539 final ISequence subsequence2 = taskFactory 540 .createNewSequence(); 541 appData.newTaskCreated(subsequence2); 542 543 taskBuilder.addChild(selection, subsequence1); 544 taskBuilder.addChild(selection, subsequence2); 545 taskBuilder.addChild(sequence, selection); 546 // TODO: We may not run till the end! 547 while ((i < (first.length - 1)) && selectionfound) { 548 selectionfound = false; 549 taskBuilder.addChild(subsequence1, appData 550 .getNumber2Task().get(first[i])); 551 taskBuilder.addChild(subsequence2, appData 552 .getNumber2Task().get(second[i])); 553 if ((first[i + 1] != second[i + 1]) 554 && (first[i + 1] != -1) 555 && (second[i + 1] != -1)) { 556 selectionfound = true; 557 } else { 558 continue; 559 } 560 i++; 561 } 562 if ((i == (first.length - 1)) && selectionfound) { 563 taskBuilder.addChild(subsequence1, appData 564 .getNumber2Task().get(first[i])); 565 taskBuilder.addChild(subsequence2, appData 566 .getNumber2Task().get(second[i])); 567 } 568 } 569 } else { 570 // i = length-1 571 if ((first[i] != second[i])) { 572 573 final ISelection selection = taskFactory 574 .createNewSelection(); 575 appData.newTaskCreated(selection); 576 taskBuilder.addChild(selection, appData.getNumber2Task() 577 .get(first[i])); 578 taskBuilder.addChild(selection, appData.getNumber2Task() 579 .get(second[i])); 580 taskBuilder.addChild(sequence, selection); 581 } 582 } 583 584 } 585 return sequence; 586 } 587 588 /** 589 * <p> 590 * replaces all occurrences of all tasks provided in the set with iterations 591 * </p> 592 * . 593 * 594 * @param iteratedTasks 595 * the tasks to be replaced with iterations 596 * @param sessions 597 * the sessions in which the tasks are to be replaced 598 * @param appData 599 * the rule application data combining all data used for applying 600 * this rule 601 */ 602 private void replaceIterationsOf(Set<ITask> iteratedTasks, 603 List<IUserSession> sessions, RuleApplicationData appData) { 604 final Map<ITask, IIteration> iterations = new HashMap<ITask, IIteration>(); 605 final Map<IIteration, List<IIterationInstance>> iterationInstances = new HashMap<IIteration, List<IIterationInstance>>(); 606 607 for (final ITask iteratedTask : iteratedTasks) { 608 609 final IIteration iteration = taskFactory.createNewIteration(); 610 appData.newTaskCreated(iteration); 611 iterations.put(iteratedTask, iteration); 612 iterationInstances.put(iteration, 613 new LinkedList<IIterationInstance>()); 614 } 615 616 IIterationInstance iterationInstance; 617 618 for (final IUserSession session : sessions) { 619 int index = 0; 620 iterationInstance = null; 621 622 while (index < session.size()) { 623 // we prepared the task instances to refer to unique tasks, if 624 // they are treated 625 // as equal. Therefore, we just compare the identity of the 626 // tasks of the task 627 // instances 628 final ITask currentTask = session.get(index).getTask(); 629 final IIteration iteration = iterations.get(currentTask); 630 if (iteration != null) { 631 if ((iterationInstance == null) 632 || (iterationInstance.getTask() != iteration)) { 633 iterationInstance = taskFactory 634 .createNewTaskInstance(iteration); 635 iterationInstances.get(iteration) 636 .add(iterationInstance);// TODO:: Don't create 637 // TaskInstances here, 638 // use a set of tasks 639 // instead 640 taskBuilder.addTaskInstance(session, index, 641 iterationInstance); 642 index++; 643 } 644 645 taskBuilder.addChild(iterationInstance, session.get(index)); 646 taskBuilder.removeTaskInstance(session, index); 647 } else { 648 if (iterationInstance != null) { 649 iterationInstance = null; 650 } 651 index++; 652 } 653 } 654 } 655 656 for (final Map.Entry<IIteration, List<IIterationInstance>> entry : iterationInstances 657 .entrySet()) { 658 harmonizeIterationInstancesModel(entry.getKey(), entry.getValue()); 659 } 660 } 661 662 private void prepareReplacements(RuleApplicationData appData) { 663 appData.initializeQueues(appData.getSessions().size()); 664 665 for (Iterator<Match> it = appData.getMatchseqs().iterator(); it 666 .hasNext();) { 667 Match m = it.next(); 668 for (Iterator<MatchOccurrence> jt = m.getOccurences().iterator(); jt 669 .hasNext();) { 670 MatchOccurrence mo = jt.next(); 671 672 Match emptyMatch = null; 673 try { 674 emptyMatch = m.cloneWithoutOccurences(); 675 } catch (CloneNotSupportedException e) { 676 e.printStackTrace(); 677 } 678 emptyMatch.addOccurence(mo); 679 appData.getPlannedReplacements()[mo.getSequenceId()].add(m); 680 } 681 } 682 } 683 684 /** 685 * Replace matches. 686 * 687 * @param appData 688 * the app data 689 */ 690 private void replaceMatches(RuleApplicationData appData) { 691 692 final int numberSeqSize = appData.getNumberSequences().size(); 693 Console.traceln(Level.INFO, "replacing matches with " + nThreads + " threads"); 694 int newThreads = nThreads; 695 if (numberSeqSize < nThreads) { 696 newThreads = numberSeqSize; 697 } 698 final int interval = numberSeqSize / newThreads; 699 int rest = numberSeqSize % newThreads; 700 final ExecutorService executor = Executors.newFixedThreadPool(nThreads); 701 for (int i = 0; i <= (numberSeqSize - interval); i += interval) { 702 int offset = 0; 703 if (rest != 0) { 704 offset = 1; 705 rest--; 706 } 707 final int from = i; 708 final int to = i + interval + offset - 1; 709 Console.traceln(Level.FINE, 710 "Match replaceing: Creating thread with matches from " + from 711 + " to " + to); 712 // search each match in every other sequence 713 final ParallelMatchReplacer replacer = new ParallelMatchReplacer( 714 appData, from, to); 715 executor.execute(replacer); 716 i += offset; 717 } 718 executor.shutdown(); 719 try { 720 executor.awaitTermination(2, TimeUnit.HOURS); 721 } catch (final InterruptedException e) { 722 e.printStackTrace(); 723 } 724 } 725 726 /** 727 * <p> 728 * searches the provided sessions for task iterations. If a task is 729 * iterated, it is added to the returned set. 730 * </p> 731 * 732 * @param sessions 733 * the sessions 734 * @return a set of tasks being iterated somewhere 735 */ 736 private Set<ITask> searchIteratedTasks(List<IUserSession> sessions) { 737 final Set<ITask> iteratedTasks = new HashSet<ITask>(); 738 for (final IUserSession session : sessions) { 739 for (int i = 0; i < (session.size() - 1); i++) { 740 // we prepared the task instances to refer to unique tasks, if 741 // they are treated 742 // as equal. Therefore, we just compare the identity of the 743 // tasks of the task 744 // instances 745 if (session.get(i).getTask() == session.get(i + 1).getTask()) { 746 iteratedTasks.add(session.get(i).getTask()); 747 } 748 } 749 } 750 return iteratedTasks; 751 } 752 753 /** 754 * Generate pairwise alignments. 755 * 756 * @param appData 757 * the app data 758 */ 759 private void generatePairwiseAlignments(RuleApplicationData appData) { 760 final int numberSeqSize = appData.getNumberSequences().size(); 761 appData.matchseqs = new LinkedList<Match>(); 762 Console.traceln(Level.INFO, "generating pairwise alignments from " 763 + numberSeqSize + " sessions with " + nThreads + " threads"); 764 765 int newThreads = nThreads; 766 if (numberSeqSize < nThreads) { 767 newThreads = numberSeqSize; 768 } 769 770 final ExecutorService executor = Executors 771 .newFixedThreadPool(newThreads); 772 final int interval = numberSeqSize / newThreads; 773 int rest = numberSeqSize % newThreads; 774 Console.traceln(Level.FINE, "Interval: " + interval + " Rest: " + rest); 775 for (int i = 0; i <= (numberSeqSize - interval); i += interval) { 776 int offset = 0; 777 if (rest != 0) { 778 offset = 1; 779 rest--; 780 } 781 782 final int from = i; 783 final int to = i + interval + offset - 1; 784 Console.traceln(Level.FINER, 785 "Aligning: Creating thread for sessions " + from + " till " 786 + to); 787 final ParallelPairwiseAligner aligner = new ParallelPairwiseAligner( 788 appData, from, to); 789 executor.execute(aligner); 790 i += offset; 791 } 792 executor.shutdown(); 793 try { 794 executor.awaitTermination(2, TimeUnit.HOURS); 795 } catch (final InterruptedException e) { 796 e.printStackTrace(); 797 } 798 } 799 800 /** 801 * Search matches in all sessions. 802 * 803 * @param appData 804 * the app data 805 */ 806 private void searchMatchesInAllSessions(RuleApplicationData appData) { 807 808 // Prepare parallel search of matchseqs 809 final int matchSeqSize = appData.getMatchseqs().size(); 810 Console.traceln(Level.INFO, "searching for patterns (" + matchSeqSize 811 + ") occuring most with " + nThreads + " threads"); 812 int newThreads = nThreads; 813 if (matchSeqSize < nThreads) { 814 newThreads = matchSeqSize; 815 } 816 final int interval = matchSeqSize / newThreads; 817 int rest = matchSeqSize % newThreads; 818 final ExecutorService executor = Executors.newFixedThreadPool(nThreads); 819 Console.traceln(Level.FINER, "Interval: " + interval + " Rest: " + rest); 820 for (int i = 0; i <= (matchSeqSize - interval); i += interval) { 821 int offset = 0; 822 if (rest != 0) { 823 offset = 1; 824 rest--; 825 } 826 final int from = i; 827 final int to = i + interval + offset - 1; 828 Console.traceln(Level.FINE, 829 "Match finding: Creating thread with matches from " + from 830 + " to " + to); 831 // search each match in every other sequence 832 final ParallelMatchOcurrencesFinder finder = new ParallelMatchOcurrencesFinder( 833 appData, from, to); 834 executor.execute(finder); 835 i += offset; 836 } 837 executor.shutdown(); 838 try { 839 executor.awaitTermination(2, TimeUnit.HOURS); 840 } catch (final InterruptedException e) { 841 e.printStackTrace(); 842 } 843 844 } 845 846 /* 847 * (non-Javadoc) 848 * 849 * @see java.lang.Object#toString() 850 */ 851 @Override 852 public String toString() { 853 return "SequenceForTaskDetectionRuleAlignment"; 854 } 855 856 /** 857 * The Class ParallelMatchOcurrencesFinder. 858 */ 859 private class ParallelMatchOcurrencesFinder implements Runnable { 860 861 /** The app data. */ 862 private final RuleApplicationData appData; 863 864 /** The from. */ 865 private final int from; 866 867 /** The to. */ 868 private final int to; 869 870 /** 871 * Instantiates a new parallel match ocurrences finder. 872 * 873 * @param appData 874 * the app data 875 * @param from 876 * the from 877 * @param to 878 * the to 879 */ 880 ParallelMatchOcurrencesFinder(RuleApplicationData appData, int from, 881 int to) { 882 this.appData = appData; 883 this.from = from; 884 this.to = to; 885 } 886 887 /* 888 * (non-Javadoc) 889 * 890 * @see java.lang.Runnable#run() 891 */ 892 @Override 893 public void run() { 894 int count = 0; 895 final int size = to + 1 - from; 896 897 for (int i = from; i <= to; i++) { 898 final Match pattern = appData.getMatchseqs().get(i); 899 count++; 900 RuleUtils.printProgressPercentage("Match finding progress", 901 count, size); 902 // Skip sequences with more 0 events (scrolls) than other 903 // events. 904 // Both of the pattern sequences are equally long, so the zero 905 // counts just need to be smaller than the length of one 906 // sequence 907 if ((pattern.getFirstSequence().eventCount(0) 908 + pattern.getSecondSequence().eventCount(0) + 1) > pattern 909 .getFirstSequence().size()) { 910 continue; 911 } 912 913 for (int j = 0; j < appData.getNumberSequences().size(); j++) { 914 final LinkedList<Integer> startpositions = appData 915 .getNumberSequences().get(j) 916 .containsPattern(pattern); 917 if (startpositions.size() > 0) { 918 for (final Iterator<Integer> jt = startpositions 919 .iterator(); jt.hasNext();) { 920 final int start = jt.next(); 921 pattern.addOccurence(new MatchOccurrence(start, 922 start + pattern.size(), j)); 923 } 924 } 925 } 926 } 927 } 928 } 929 930 /** 931 * The Class ParallelPairwiseAligner. 932 */ 933 private class ParallelPairwiseAligner implements Runnable { 934 935 /** The app data. */ 936 private final RuleApplicationData appData; 937 938 /** The from. */ 939 private final int from; 940 941 /** The to. */ 942 private final int to; 943 944 /** 945 * Instantiates a new parallel pairwise aligner. 946 * 947 * @param appData 948 * the app data 949 * @param from 950 * the from 951 * @param to 952 * the to 953 */ 954 ParallelPairwiseAligner(RuleApplicationData appData, int from, int to) { 955 this.appData = appData; 956 this.from = from; 957 this.to = to; 958 } 959 960 /* 961 * (non-Javadoc) 962 * 963 * @see java.lang.Runnable#run() 964 */ 965 @Override 966 public void run() { 967 int count = 0; 968 final int size = to +1 - from; 969 970 for (int i = from; i <= to; i++) { 971 final NumberSequence ns1 = appData.getNumberSequences().get(i); 972 count++; 973 RuleUtils.printProgressPercentage("Aligning Progress", count, 974 size); 975 for (int j = 0; j < appData.getNumberSequences().size(); j++) { 976 final NumberSequence ns2 = appData.getNumberSequences() 977 .get(j); 978 if (i != j) { 979 final AlignmentAlgorithm aa = AlignmentAlgorithmFactory 980 .create(); 981 aa.align(ns1, ns2, appData.getSubmat(), 9); 982 synchronized (appData.getMatchseqs()) { 983 appData.getMatchseqs().addAll(aa.getMatches()); 984 } 985 } 986 } 987 } 988 } 989 } 990 991 /** 992 * The Class ParallelPairwiseAligner. 993 */ 994 private class ParallelMatchReplacer implements Runnable { 995 996 /** The app data. */ 997 private final RuleApplicationData appData; 998 999 /** The from. */ 1000 private final int from; 1001 1002 /** The to. */ 1003 private final int to; 1004 1005 /** 1006 * Instantiates a new parallel pairwise aligner. 1007 * 1008 * @param appData 1009 * the app data 1010 * @param from 1011 * the from 1012 * @param to 1013 * the to 1014 */ 1015 ParallelMatchReplacer(RuleApplicationData appData, int from, int to) { 1016 this.appData = appData; 1017 this.from = from; 1018 this.to = to; 1019 } 1020 1021 /* 1022 * (non-Javadoc) 1023 * 1024 * @see java.lang.Runnable#run() 1025 */ 1026 @Override 1027 public void run() { 1028 for (int i = from; i <= to; i++) { 1029 1030 /* 1031 * HashMap for keeping track in which sequence which replacement has 1032 * been performed. Neccessary for updating the indices of other 1033 * occurrences accordingly 1034 */ 1035 LinkedList<MatchOccurrence> replacedOccurrences = new LinkedList<MatchOccurrence>(); 1036 invalidOccurence: while (!appData.getPlannedReplacements()[i] 1037 .isEmpty()) { 1038 1039 Match m = appData.getPlannedReplacements()[i].remove(); 1040 // Occurrences list has just one child 1041 MatchOccurrence oc = m.getOccurences().getFirst(); 1042 // check if we have any replaced occurrence with 1043 // indexes 1044 // smaller than ours. If so, we need to adjust 1045 // our start and end points of the replacement. 1046 // Also do a check if we have replaced this 1047 // specific MatchOccurence in this sequence already. 1048 // Jump to the next occurrence if this is the case. 1049 // This is no more necessary once the matches 1050 // are harmonized. 1051 1052 for (final Iterator<MatchOccurrence> jt = replacedOccurrences 1053 .iterator(); jt.hasNext();) { 1054 final MatchOccurrence tmpOC = jt.next(); 1055 1056 if ((oc.getStartindex() >= tmpOC.getStartindex()) 1057 && (oc.getStartindex() <= tmpOC.getEndindex())) { 1058 continue invalidOccurence; 1059 } 1060 if (oc.getEndindex() >= tmpOC.getStartindex()) { 1061 continue invalidOccurence; 1062 1063 } else if (oc.getStartindex() > tmpOC.getEndindex()) { 1064 final int diff = tmpOC.getEndindex() 1065 - tmpOC.getStartindex(); 1066 // Just to be sure. 1067 if (diff > 0) { 1068 oc.setStartindex((oc.getStartindex() - diff) + 1); 1069 oc.setEndindex((oc.getEndindex() - diff) + 1); 1070 } else { 1071 Console.traceln(Level.WARNING, 1072 "End index of a Match before start. This should never happen"); 1073 } 1074 } 1075 } 1076 synchronized (appData) { 1077 appData.detectedAndReplacedTasks = true; 1078 } 1079 final ISequence task = matchAsSequence(appData, m); 1080 final ISequenceInstance sequenceInstances = RuleUtils 1081 .createNewSubSequenceInRange(appData.getSessions() 1082 .get(oc.getSequenceId()), oc 1083 .getStartindex(), oc.getEndindex(), task, 1084 taskFactory, taskBuilder); 1085 1086 // Adjust the length of the match regarding to the 1087 // length of 1088 // instance. (OptionalInstances may be shorter) 1089 oc.setEndindex((oc.getStartindex() + sequenceInstances 1090 .size()) - RuleUtils.missedOptionals); 1091 1092 replacedOccurrences.add(oc); 1093 } 1094 } 1095 } 1096 } 1097 1098 /** 1099 * The Class RuleApplicationData. 1100 */ 1101 private static class RuleApplicationData implements Serializable { 1102 1103 /** The Constant serialVersionUID. */ 1104 private static final long serialVersionUID = -7559657686755522960L; 1105 1106 /** 1107 * The number2task HashMap. Since we align the tasks just by their 1108 * integer id, we need this to convert them back to Tasks again 1109 */ 1110 private final HashMap<Integer, ITask> number2task; 1111 1112 /** 1113 * The unique tasks, keeps track about all unique tasks TODO: We 1114 * Actually just need number2task here, this structure can be removed in 1115 * the future. 1116 */ 1117 private final HashSet<ITask> uniqueTasks; 1118 1119 /** 1120 * The substitution matrix used by the alignment algorithm to be able to 1121 * compare distances of tasks 1122 */ 1123 private final ObjectDistanceSubstitionMatrix submat; 1124 1125 private PriorityQueue<Match>[] plannedReplacements; 1126 1127 /** The list of all found matches */ 1128 private LinkedList<Match> matchseqs; 1129 1130 /** 1131 * The generated NumberSequences. This is the integer representation of 1132 * the user sessions 1133 */ 1134 private ArrayList<NumberSequence> numberseqs; 1135 1136 /** The list of newly created tasks (of one iteration). */ 1137 private final LinkedList<ITask> newTasks; 1138 1139 /** The user sessions containing all EventTasks/Instances */ 1140 private final List<IUserSession> sessions; 1141 1142 /** True if we replaced something in the user sessions in one iteration. */ 1143 private boolean detectedAndReplacedTasks; 1144 1145 /** The result we return from this rule */ 1146 private final RuleApplicationResult result; 1147 1148 /** Stop Watch to measure performance */ 1149 private final StopWatch stopWatch; 1150 1151 /** 1152 * Instantiates a new rule application data. 1153 * 1154 * @param sessions 1155 * The user sessions 1156 */ 1157 private RuleApplicationData(List<IUserSession> sessions) { 1158 this.sessions = sessions; 1159 numberseqs = new ArrayList<NumberSequence>(); 1160 uniqueTasks = new HashSet<ITask>(); 1161 number2task = new HashMap<Integer, ITask>(); 1162 stopWatch = new StopWatch(); 1163 result = new RuleApplicationResult(); 1164 submat = new ObjectDistanceSubstitionMatrix(6, -3, false); 1165 newTasks = new LinkedList<ITask>(); 1166 this.detectedAndReplacedTasks = true; 1167 } 1168 1169 private void initializeQueues(int size) { 1170 plannedReplacements = new PriorityQueue[size]; 1171 for (int i = 0; i < size; i++) { 1172 plannedReplacements[i] = new PriorityQueue<Match>(); 1173 } 1174 } 1175 1176 public Queue<Match>[] getPlannedReplacements() { 1177 return plannedReplacements; 1178 } 1179 1180 /** 1181 * Detected and replaced tasks. 1182 * 1183 * @return true, if successful 1184 */ 1185 private boolean detectedAndReplacedTasks() { 1186 return detectedAndReplacedTasks; 1187 } 1188 1189 /** 1190 * Gets the match sequences. 1191 * 1192 * @return the match sequences 1193 */ 1194 public LinkedList<Match> getMatchseqs() { 1195 return matchseqs; 1196 } 1197 1198 /** 1199 * Gets the new tasks. 1200 * 1201 * @return the new tasks 1202 */ 1203 public LinkedList<ITask> getNewTasks() { 1204 return newTasks; 1205 } 1206 1207 /** 1208 * Gets the number2task. 1209 * 1210 * @return the number2task HashMap 1211 */ 1212 private HashMap<Integer, ITask> getNumber2Task() { 1213 return number2task; 1214 } 1215 1216 /** 1217 * Gets the number sequences. 1218 * 1219 * @return the number sequences 1220 */ 1221 private ArrayList<NumberSequence> getNumberSequences() { 1222 return numberseqs; 1223 } 1224 1225 /** 1226 * Gets the result. 1227 * 1228 * @return the result 1229 */ 1230 private RuleApplicationResult getResult() { 1231 return result; 1232 } 1233 1234 /** 1235 * Gets the sessions. 1236 * 1237 * @return the UserSessions as List. 1238 */ 1239 private List<IUserSession> getSessions() { 1240 return sessions; 1241 } 1242 1243 /** 1244 * Gets the stop watch. 1245 * 1246 * @return the stopWatch 1247 */ 1248 private StopWatch getStopWatch() { 1249 return stopWatch; 1250 } 1251 1252 /** 1253 * Gets the substitution matrix. 1254 * 1255 * @return the substitution matrix 1256 */ 1257 private ObjectDistanceSubstitionMatrix getSubmat() { 1258 return submat; 1259 } 1260 1261 /** 1262 * Gets the unique tasks. 1263 * 1264 * @return the unique tasks 1265 */ 1266 private HashSet<ITask> getUniqueTasks() { 1267 return uniqueTasks; 1268 } 1269 1270 /** 1271 * New task created. 1272 * 1273 * @param task 1274 * can be called when new tasks are created to keep track of 1275 * all newly created tasks 1276 */ 1277 private void newTaskCreated(ITask task) { 1278 number2task.put(task.getId(), task); 1279 newTasks.add(task); 1280 } 1281 1282 /** 1283 * Reset newly created tasks. 1284 */ 1285 synchronized private void resetNewlyCreatedTasks() { 1286 uniqueTasks.addAll(newTasks); 1287 newTasks.clear(); 1288 } 1289 1290 /** 1291 * Sets the number sequences. 1292 * 1293 * @param numberseqs 1294 * the new number sequences 1295 */ 1296 private void setNumberSequences(ArrayList<NumberSequence> numberseqs) { 1297 this.numberseqs = numberseqs; 1298 } 1299 1300 /** 1301 * Update substitution matrix. 1302 */ 1303 private void updateSubstitutionMatrix() { 1304 submat.update(getNewTasks()); 1305 resetNewlyCreatedTasks(); 1306 } 1307 1308 } 74 /** The n threads. */ 75 // public static int nThreads = Runtime.getRuntime().availableProcessors() - 1; 76 public static int nThreads = 1; 77 78 /** The iteration. */ 79 private int iteration = 0; 80 81 private int maxIterations = 1; 82 83 private static int alignmentThreshold = 9; 84 private static int gapPenalty = -3; 85 86 private static float maxSubstitutionScore = 6; 87 88 /** 89 * <p> 90 * the task factory to be used for creating substructures for the temporal relationships 91 * identified during rul application 92 * </p> 93 * . 94 */ 95 private final ITaskFactory taskFactory; 96 97 /** 98 * <p> 99 * the task builder to be used for creating substructures for the temporal relationships 100 * identified during rule application 101 * </p> 102 * . 103 */ 104 private final ITaskBuilder taskBuilder; 105 106 /** 107 * <p> 108 * the task handling strategy to be used for comparing tasks for preparation, i.e., before the 109 * tasks are harmonized 110 * </p> 111 */ 112 private final TaskHandlingStrategy preparationTaskHandlingStrategy; 113 114 /** 115 * <p> 116 * instantiates the rule and initializes it with a task equality to be considered when comparing 117 * tasks as well as a task factory and builder to be used for creating task structures. 118 * </p> 119 * 120 * @param minimalTaskEquality 121 * the task equality to be considered when comparing tasks 122 * @param taskFactory 123 * the task factory to be used for creating substructures 124 * @param taskBuilder 125 * the task builder to be used for creating substructures 126 */ 127 128 SequenceForTaskDetectionRuleAlignment(TaskEquality minimalTaskEquality, 129 ITaskFactory taskFactory, 130 ITaskBuilder taskBuilder) 131 { 132 this.taskFactory = taskFactory; 133 this.taskBuilder = taskBuilder; 134 135 this.preparationTaskHandlingStrategy = new TaskHandlingStrategy(minimalTaskEquality); 136 } 137 138 /* 139 * (non-Javadoc) 140 * 141 * @see de.ugoe.cs.autoquest.tasktrees.temporalrelation.ISessionScopeRule#apply (java.util.List) 142 */ 143 @Override 144 public RuleApplicationResult apply(List<IUserSession> sessions) { 145 final RuleApplicationData appData = new RuleApplicationData(sessions); 146 147 harmonizeEventTaskInstancesModel(appData); 148 149 Console.traceln(Level.INFO, "generating substitution matrix from " + 150 appData.getUniqueTasks().size() + " unique tasks"); 151 appData.getStopWatch().start("substitution matrix"); 152 appData.getSubmat().generate(appData.getUniqueTasks()); 153 appData.getStopWatch().stop("substitution matrix"); 154 155 Console.traceln(Level.INFO, "Starting main loop"); 156 do { 157 Console.traceln(Level.INFO, "Iteration Number: " + iteration); 158 iteration++; 159 appData.detectedAndReplacedTasks = false; 160 appData.getStopWatch().start("whole loop"); 161 detectAndReplaceIterations(appData); 162 appData.getStopWatch().start("task replacement"); 163 // Just does anything if the substitution matrix is created with the 164 // option to do so 165 appData.updateSubstitutionMatrix(); 166 detectAndReplaceTasks(appData); // 167 appData.getStopWatch().stop("task replacement"); 168 appData.getStopWatch().stop("whole loop"); 169 // appData.getStopWatch().dumpStatistics(System.out); 170 appData.getStopWatch().reset(); 171 172 // } while (appData.detectedAndReplacedTasks()||iteration < maxIterations); 173 } 174 while (iteration < maxIterations); 175 Console.println("created " + appData.getResult().getNewlyCreatedTasks().size() + 176 " new tasks and " + appData.getResult().getNewlyCreatedTaskInstances().size() + 177 " appropriate instances\n"); 178 179 if ((appData.getResult().getNewlyCreatedTasks().size() > 0) || 180 (appData.getResult().getNewlyCreatedTaskInstances().size() > 0)) 181 { 182 appData.getResult().setRuleApplicationStatus(RuleApplicationStatus.FINISHED); 183 } 184 // new TaskTreeValidator().validate(appData.getSessions()); 185 return appData.getResult(); 186 } 187 188 /** 189 * Creates the number sequences. 190 * 191 * @param appData 192 * the app data 193 * @return the array list 194 */ 195 private ArrayList<NumberSequence> createNumberSequences(RuleApplicationData appData) { 196 final ArrayList<NumberSequence> result = new ArrayList<NumberSequence>(); 197 for (int i = 0; i < appData.getSessions().size(); i++) { 198 final IUserSession session = appData.getSessions().get(i); 199 final NumberSequence templist = new NumberSequence(session.size()); 200 for (int j = 0; j < session.size(); j++) { 201 final ITaskInstance taskInstance = session.get(j); 202 templist.getSequence()[j] = taskInstance.getTask().getId(); 203 } 204 // Each NumberSequence is identified by its id, beginning to count 205 // at zero 206 templist.setId(i); 207 result.add(templist); 208 } 209 return result; 210 } 211 212 /** 213 * <p> 214 * searches for direct iterations of single tasks in all sequences and replaces them with 215 * {@link IIteration}s, respectively appropriate instances. Also all single occurrences of a 216 * task that is iterated somewhen are replaced with iterations to have again an efficient way 217 * for task comparisons. 218 * </p> 219 * 220 * @param appData 221 * the rule application data combining all data used for applying this rule 222 */ 223 private void detectAndReplaceIterations(RuleApplicationData appData) { 224 Console.traceln(Level.FINE, "detecting iterations"); 225 appData.getStopWatch().start("detecting iterations"); 226 227 final List<IUserSession> sessions = appData.getSessions(); 228 229 final Set<ITask> iteratedTasks = searchIteratedTasks(sessions); 230 231 if (iteratedTasks.size() > 0) { 232 replaceIterationsOf(iteratedTasks, sessions, appData); 233 } 234 235 appData.getStopWatch().stop("detecting iterations"); 236 Console.traceln(Level.INFO, "replaced " + iteratedTasks.size() + " iterated tasks"); 237 } 238 239 /** 240 * Detect and replace tasks. 241 * 242 * @param appData 243 * the rule application data combining all data used for applying this rule 244 */ 245 private void detectAndReplaceTasks(RuleApplicationData appData) { 246 Console.traceln(Level.FINE, "detecting and replacing tasks"); 247 appData.getStopWatch().start("detecting tasks"); 248 249 // Create NumberSequences 250 appData.setNumberSequences(this.createNumberSequences(appData)); 251 252 // Generate pairwise alignments 253 // appData.setMatchseqs(generatePairwiseAlignments(appData)); 254 generatePairwiseAlignments(appData); 255 Console.traceln(Level.FINE, "Found " + appData.getMatchseqs().size() + " results"); 256 257 // Nothing found, we can end here 258 if (appData.getMatchseqs().size() == 0) { 259 appData.detectedAndReplacedTasks = false; 260 return; 261 } 262 263 // Searching each match in all other sessions, counting its occurences 264 searchMatchesInAllSessions(appData); 265 266 // Sort results to get the most occurring results 267 Console.traceln(Level.INFO, "sorting " + appData.getMatchseqs().size() + " results"); 268 final Comparator<Match> comparator = new Comparator<Match>() { 269 @Override 270 public int compare(Match m1, Match m2) { 271 int cmp = m2.occurenceCount() - m1.occurenceCount(); 272 if (cmp != 0) { 273 return cmp; 274 } 275 else { 276 cmp = m2.size() - m1.size(); 277 if (cmp != 0) { 278 return cmp; 279 } 280 else { 281 // This should rarely happen 282 cmp = m2.ocurrenceIDSum() - m1.ocurrenceIDSum(); 283 if (cmp != 0) { 284 return cmp; 285 } 286 else { 287 cmp = m2.taskIdSum() - m1.taskIdSum(); 288 289 return cmp; 290 } 291 } 292 } 293 } 294 }; 295 296 Collections.sort(appData.getMatchseqs(), comparator); 297 appData.getStopWatch().stop("detecting tasks"); 298 299 Console.traceln(Level.INFO, "Preparing replacments"); 300 prepareReplacements(appData); 301 Console.traceln(Level.INFO, "Replacing matches in sessions"); 302 appData.getStopWatch().start("replacing tasks"); 303 replaceMatches(appData); 304 appData.getStopWatch().stop("replacing tasks"); 305 } 306 307 // TODO: DEBUG METHOD 308 @SuppressWarnings("unused") 309 private void printMatches(RuleApplicationData appData) { 310 LinkedList<Match> matchseqs = appData.getMatchseqs(); 311 if (iteration > 1) { 312 System.out.println("PRINTING MATCHES"); 313 for (Iterator<Match> it = matchseqs.iterator(); it.hasNext();) { 314 Match m = it.next(); 315 m.getFirstSequence().printSequence(); 316 m.getSecondSequence().printSequence(); 317 for (Iterator<MatchOccurrence> jt = m.getOccurences().iterator(); jt.hasNext();) { 318 MatchOccurrence mo = jt.next(); 319 System.out.print(mo.getSequenceId() + " "); 320 } 321 System.out.println(); 322 System.out.println(); 323 } 324 } 325 } 326 327 /** 328 * <p> 329 * harmonizes the event task instances by unifying tasks. This is done, as initially the event 330 * tasks being equal with respect to the considered task equality are distinct objects. The 331 * comparison of these distinct objects is more time consuming than comparing the object 332 * references. 333 * </p> 334 * 335 * @param appData 336 * the rule application data combining all data used for applying this rule 337 * @return Returns the unique tasks symbol map 338 */ 339 private void harmonizeEventTaskInstancesModel(RuleApplicationData appData) { 340 Console.traceln(Level.INFO, "harmonizing task model of event task instances"); 341 appData.getStopWatch().start("harmonizing event tasks"); 342 final SymbolMap<ITaskInstance, ITask> uniqueTasks = 343 preparationTaskHandlingStrategy.createSymbolMap(); 344 345 final TaskInstanceComparator comparator = 346 preparationTaskHandlingStrategy.getTaskComparator(); 347 348 int unifiedTasks = 0; 349 ITask task; 350 final List<IUserSession> sessions = appData.getSessions(); 351 for (int j = 0; j < sessions.size(); j++) { 352 final IUserSession session = sessions.get(j); 353 354 for (int i = 0; i < session.size(); i++) { 355 final ITaskInstance taskInstance = session.get(i); 356 task = uniqueTasks.getValue(taskInstance); 357 358 if (task == null) { 359 uniqueTasks.addSymbol(taskInstance, taskInstance.getTask()); 360 appData.getUniqueTasks().add(taskInstance.getTask()); 361 appData.getNumber2Task().put(taskInstance.getTask().getId(), 362 taskInstance.getTask()); 363 } 364 else { 365 taskBuilder.setTask(taskInstance, task); 366 unifiedTasks++; 367 } 368 } 369 comparator.clearBuffers(); 370 } 371 372 appData.getStopWatch().stop("harmonizing event tasks"); 373 Console.traceln(Level.INFO, "harmonized " + unifiedTasks + " task occurrences (still " + 374 appData.getUniqueTasks().size() + " different tasks)"); 375 376 appData.getStopWatch().dumpStatistics(System.out); 377 appData.getStopWatch().reset(); 378 } 379 380 /** 381 * <p> 382 * TODO clarify why this is done (in fact, ask Patrick Harms) 383 * </p> 384 * . 385 * 386 * @param iteration 387 * the iteration 388 * @param iterationInstances 389 * the iteration instances 390 */ 391 private void harmonizeIterationInstancesModel(IIteration iteration, 392 List<IIterationInstance> iterationInstances) 393 { 394 final List<ITask> iteratedTaskVariants = new LinkedList<ITask>(); 395 final TaskInstanceComparator comparator = 396 preparationTaskHandlingStrategy.getTaskComparator(); 397 398 // merge the lexically different variants of iterated task to a unique 399 // list 400 for (final IIterationInstance iterationInstance : iterationInstances) { 401 for (final ITaskInstance executionVariant : iterationInstance) { 402 final ITask candidate = executionVariant.getTask(); 403 404 boolean found = false; 405 for (final ITask taskVariant : iteratedTaskVariants) { 406 if (comparator.areLexicallyEqual(taskVariant, candidate)) { 407 taskBuilder.setTask(executionVariant, taskVariant); 408 found = true; 409 break; 410 } 411 } 412 413 if (!found) { 414 iteratedTaskVariants.add(candidate); 415 } 416 } 417 } 418 419 // if there are more than one lexically different variant of iterated 420 // tasks, adapt the 421 // iteration model to be a selection of different variants. In this case 422 // also adapt 423 // the generated iteration instances to correctly contain selection 424 // instances. If there 425 // is only one variant of an iterated task, simply set this as the 426 // marked task of the 427 // iteration. In this case, the instances can be preserved as is 428 if (iteratedTaskVariants.size() > 1) { 429 final ISelection selection = taskFactory.createNewSelection(); 430 431 for (final ITask variant : iteratedTaskVariants) { 432 taskBuilder.addChild(selection, variant); 433 } 434 435 taskBuilder.setMarkedTask(iteration, selection); 436 437 for (final IIterationInstance instance : iterationInstances) { 438 for (int i = 0; i < instance.size(); i++) { 439 final ISelectionInstance selectionInstance = 440 taskFactory.createNewTaskInstance(selection); 441 taskBuilder.setChild(selectionInstance, instance.get(i)); 442 taskBuilder.setTaskInstance(instance, i, selectionInstance); 443 } 444 } 445 } 446 else { 447 taskBuilder.setMarkedTask(iteration, iteratedTaskVariants.get(0)); 448 } 449 } 450 451 /** 452 * Match as sequence. 453 * 454 * @param appData 455 * RuleApplicationData needed to keep track of all created tasks 456 * @param m 457 * The match to be converted into a Task 458 * @return The task of the match with an ISequence as its root 459 */ 460 synchronized public ISequence matchAsSequence(RuleApplicationData appData, Match m) { 461 final ISequence sequence = taskFactory.createNewSequence(); 462 appData.newTaskCreated(sequence); 463 464 final int[] first = m.getFirstSequence().getSequence(); 465 final int[] second = m.getSecondSequence().getSequence(); 466 467 // Both sequences of a match are equally long 468 for (int i = 0; i < m.getFirstSequence().size(); i++) { 469 470 // Two gaps aligned to each other: Have not seen it happening so 471 // far, just to handle it 472 if ((first[i] == -1) && (second[i] == -1)) { 473 // Do nothing here. 474 } 475 // Both events are equal, we can simply add the task referring to 476 // the number 477 else if (first[i] == second[i]) { 478 taskBuilder.addChild(sequence, appData.getNumber2Task().get(first[i])); 479 } 480 // We have a gap in the first sequence, we need to add the task of 481 // the second sequence as optional 482 else if ((first[i] == -1) && (second[i] != -1)) { 483 final IOptional optional = taskFactory.createNewOptional(); 484 appData.newTaskCreated(optional); 485 taskBuilder.setMarkedTask(optional, appData.getNumber2Task().get(second[i])); 486 taskBuilder.addChild(sequence, optional); 487 } 488 // We have a gap in the second sequence, we need to add the task of 489 // the first sequence as optional 490 else if ((first[i] != -1) && (second[i] == -1)) { 491 final IOptional optional = taskFactory.createNewOptional(); 492 appData.newTaskCreated(optional); 493 taskBuilder.setMarkedTask(optional, appData.getNumber2Task().get(first[i])); 494 taskBuilder.addChild(sequence, optional); 495 } 496 // Both tasks are not equal, we need to insert a selection here. 497 // Now things get complicated. We first need to check 498 // if the next position is not a selection. Then we can just create 499 // a selection 500 // of the both Tasks 501 // In the other case (more than one selection following this 502 // selection), we want to 503 // create a selection of sequences where each sequence gets the 504 // corresponding task of 505 // the its sequence in the pattern. 506 // 507 else if (i < (first.length - 1)) { 508 509 if ((first[i] != second[i]) && 510 (((first[i + 1] == second[i + 1]) || (first[i + 1] == -1) || (second[i + 1] == -1)))) 511 { 512 513 final ISelection selection = taskFactory.createNewSelection(); 514 appData.newTaskCreated(selection); 515 taskBuilder.addChild(selection, appData.getNumber2Task().get(first[i])); 516 taskBuilder.addChild(selection, appData.getNumber2Task().get(second[i])); 517 taskBuilder.addChild(sequence, selection); 518 } 519 else { 520 boolean selectionfound = true; 521 final ISelection selection = taskFactory.createNewSelection(); 522 appData.newTaskCreated(selection); 523 524 final ISequence subsequence1 = taskFactory.createNewSequence(); 525 appData.newTaskCreated(subsequence1); 526 527 final ISequence subsequence2 = taskFactory.createNewSequence(); 528 appData.newTaskCreated(subsequence2); 529 530 taskBuilder.addChild(selection, subsequence1); 531 taskBuilder.addChild(selection, subsequence2); 532 taskBuilder.addChild(sequence, selection); 533 // TODO: We may not run till the end! 534 while ((i < (first.length - 1)) && selectionfound) { 535 selectionfound = false; 536 taskBuilder.addChild(subsequence1, appData.getNumber2Task().get(first[i])); 537 taskBuilder.addChild(subsequence2, appData.getNumber2Task().get(second[i])); 538 if ((first[i + 1] != second[i + 1]) && (first[i + 1] != -1) && 539 (second[i + 1] != -1)) 540 { 541 selectionfound = true; 542 } 543 else { 544 continue; 545 } 546 i++; 547 } 548 if ((i == (first.length - 1)) && selectionfound) { 549 taskBuilder.addChild(subsequence1, appData.getNumber2Task().get(first[i])); 550 taskBuilder.addChild(subsequence2, appData.getNumber2Task().get(second[i])); 551 } 552 } 553 } 554 else { 555 // i = length-1 556 if ((first[i] != second[i])) { 557 558 final ISelection selection = taskFactory.createNewSelection(); 559 appData.newTaskCreated(selection); 560 taskBuilder.addChild(selection, appData.getNumber2Task().get(first[i])); 561 taskBuilder.addChild(selection, appData.getNumber2Task().get(second[i])); 562 taskBuilder.addChild(sequence, selection); 563 } 564 } 565 566 } 567 return sequence; 568 } 569 570 /** 571 * <p> 572 * replaces all occurrences of all tasks provided in the set with iterations 573 * </p> 574 * . 575 * 576 * @param iteratedTasks 577 * the tasks to be replaced with iterations 578 * @param sessions 579 * the sessions in which the tasks are to be replaced 580 * @param appData 581 * the rule application data combining all data used for applying this rule 582 */ 583 private void replaceIterationsOf(Set<ITask> iteratedTasks, 584 List<IUserSession> sessions, 585 RuleApplicationData appData) 586 { 587 final Map<ITask, IIteration> iterations = new HashMap<ITask, IIteration>(); 588 final Map<IIteration, List<IIterationInstance>> iterationInstances = 589 new HashMap<IIteration, List<IIterationInstance>>(); 590 591 for (final ITask iteratedTask : iteratedTasks) { 592 593 final IIteration iteration = taskFactory.createNewIteration(); 594 appData.newTaskCreated(iteration); 595 iterations.put(iteratedTask, iteration); 596 iterationInstances.put(iteration, new LinkedList<IIterationInstance>()); 597 } 598 599 IIterationInstance iterationInstance; 600 601 for (final IUserSession session : sessions) { 602 int index = 0; 603 iterationInstance = null; 604 605 while (index < session.size()) { 606 // we prepared the task instances to refer to unique tasks, if 607 // they are treated 608 // as equal. Therefore, we just compare the identity of the 609 // tasks of the task 610 // instances 611 final ITask currentTask = session.get(index).getTask(); 612 final IIteration iteration = iterations.get(currentTask); 613 if (iteration != null) { 614 if ((iterationInstance == null) || (iterationInstance.getTask() != iteration)) { 615 iterationInstance = taskFactory.createNewTaskInstance(iteration); 616 iterationInstances.get(iteration).add(iterationInstance);// TODO:: Don't 617 // create 618 // TaskInstances here, 619 // use a set of tasks 620 // instead 621 taskBuilder.addTaskInstance(session, index, iterationInstance); 622 index++; 623 } 624 625 taskBuilder.addChild(iterationInstance, session.get(index)); 626 taskBuilder.removeTaskInstance(session, index); 627 } 628 else { 629 if (iterationInstance != null) { 630 iterationInstance = null; 631 } 632 index++; 633 } 634 } 635 } 636 637 for (final Map.Entry<IIteration, List<IIterationInstance>> entry : iterationInstances 638 .entrySet()) 639 { 640 harmonizeIterationInstancesModel(entry.getKey(), entry.getValue()); 641 } 642 } 643 644 /** 645 * Prepare replacements. 646 * 647 * @param appData 648 * the app data 649 */ 650 private void prepareReplacements(RuleApplicationData appData) { 651 appData.initializeQueues(appData.getSessions().size()); 652 int taskId=0; 653 for (Iterator<Match> it = appData.getMatchseqs().iterator(); it.hasNext();) { 654 Match m = it.next(); 655 if (m.getOccurences().size() > 2) { 656 final ISequence task = matchAsSequence(appData, m); 657 appData.getPreparedTasks().add(task); 658 659 for (Iterator<MatchOccurrence> jt = m.getOccurences().iterator(); jt.hasNext();) { 660 MatchOccurrence mo = jt.next(); 661 // System.out.println("Found this match in sequence " +mo.getSequenceId()); 662 PlannedReplacement pr = new PlannedReplacement(taskId,mo); 663 // System.out.println("Adding match to sequence " + mo.getSequenceId()); 664 appData.getPlannedReplacements()[mo.getSequenceId()].add(pr); 665 } 666 taskId++; 667 } 668 } 669 } 670 671 /** 672 * Replace matches. 673 * 674 * @param appData 675 * the app data 676 */ 677 private void replaceMatches(RuleApplicationData appData) { 678 679 final int numberSeqSize = appData.getNumberSequences().size(); 680 Console.traceln(Level.INFO, "replacing matches with " + nThreads + " threads"); 681 int newThreads = nThreads; 682 if (numberSeqSize < nThreads) { 683 newThreads = numberSeqSize; 684 } 685 final int interval = numberSeqSize / newThreads; 686 int rest = numberSeqSize % newThreads; 687 final ExecutorService executor = Executors.newFixedThreadPool(nThreads); 688 for (int i = 0; i <= (numberSeqSize - interval); i += interval) { 689 int offset = 0; 690 if (rest != 0) { 691 offset = 1; 692 rest--; 693 } 694 final int from = i; 695 final int to = i + interval + offset - 1; 696 Console.traceln(Level.FINE, "Match replacing: Creating thread with matches from " + 697 from + " to " + to); 698 // search each match in every other sequence 699 final ParallelMatchReplacer replacer = new ParallelMatchReplacer(appData, from, to); 700 executor.execute(replacer); 701 i += offset; 702 } 703 executor.shutdown(); 704 try { 705 executor.awaitTermination(2, TimeUnit.HOURS); 706 } 707 catch (final InterruptedException e) { 708 e.printStackTrace(); 709 } 710 } 711 712 /** 713 * <p> 714 * searches the provided sessions for task iterations. If a task is iterated, it is added to the 715 * returned set. 716 * </p> 717 * 718 * @param sessions 719 * the sessions 720 * @return a set of tasks being iterated somewhere 721 */ 722 private Set<ITask> searchIteratedTasks(List<IUserSession> sessions) { 723 final Set<ITask> iteratedTasks = new HashSet<ITask>(); 724 for (final IUserSession session : sessions) { 725 for (int i = 0; i < (session.size() - 1); i++) { 726 // we prepared the task instances to refer to unique tasks, if 727 // they are treated 728 // as equal. Therefore, we just compare the identity of the 729 // tasks of the task 730 // instances 731 if (session.get(i).getTask() == session.get(i + 1).getTask()) { 732 iteratedTasks.add(session.get(i).getTask()); 733 } 734 } 735 } 736 return iteratedTasks; 737 } 738 739 /** 740 * Generate pairwise alignments. 741 * 742 * @param appData 743 * the app data 744 */ 745 private void generatePairwiseAlignments(RuleApplicationData appData) { 746 final int numberSeqSize = appData.getNumberSequences().size(); 747 appData.matchseqs = new LinkedList<Match>(); 748 Console.traceln(Level.INFO, "generating pairwise alignments from " + numberSeqSize + 749 " sessions with " + nThreads + " threads"); 750 751 int newThreads = nThreads; 752 if (numberSeqSize < nThreads) { 753 newThreads = numberSeqSize; 754 } 755 756 final ExecutorService executor = Executors.newFixedThreadPool(newThreads); 757 final int interval = numberSeqSize / newThreads; 758 int rest = numberSeqSize % newThreads; 759 Console.traceln(Level.FINE, "Interval: " + interval + " Rest: " + rest); 760 for (int i = 0; i <= (numberSeqSize - interval); i += interval) { 761 int offset = 0; 762 if (rest != 0) { 763 offset = 1; 764 rest--; 765 } 766 767 final int from = i; 768 final int to = i + interval + offset - 1; 769 Console.traceln(Level.FINER, "Aligning: Creating thread for sessions " + from + 770 " till " + to); 771 final ParallelPairwiseAligner aligner = new ParallelPairwiseAligner(appData, from, to); 772 executor.execute(aligner); 773 i += offset; 774 } 775 executor.shutdown(); 776 try { 777 executor.awaitTermination(2, TimeUnit.HOURS); 778 } 779 catch (final InterruptedException e) { 780 e.printStackTrace(); 781 } 782 } 783 784 /** 785 * Search matches in all sessions. 786 * 787 * @param appData 788 * the app data 789 */ 790 private void searchMatchesInAllSessions(RuleApplicationData appData) { 791 792 // Prepare parallel search of matchseqs 793 final int matchSeqSize = appData.getMatchseqs().size(); 794 Console.traceln(Level.INFO, "searching for patterns (" + matchSeqSize + 795 ") occuring most with " + nThreads + " threads"); 796 int newThreads = nThreads; 797 if (matchSeqSize < nThreads) { 798 newThreads = matchSeqSize; 799 } 800 final int interval = matchSeqSize / newThreads; 801 int rest = matchSeqSize % newThreads; 802 final ExecutorService executor = Executors.newFixedThreadPool(nThreads); 803 Console.traceln(Level.FINER, "Interval: " + interval + " Rest: " + rest); 804 for (int i = 0; i <= (matchSeqSize - interval); i += interval) { 805 int offset = 0; 806 if (rest != 0) { 807 offset = 1; 808 rest--; 809 } 810 final int from = i; 811 final int to = i + interval + offset - 1; 812 Console.traceln(Level.FINE, "Match finding: Creating thread with matches from " + from + 813 " to " + to); 814 // search each match in every other sequence 815 final ParallelMatchOcurrencesFinder finder = 816 new ParallelMatchOcurrencesFinder(appData, from, to); 817 executor.execute(finder); 818 i += offset; 819 } 820 executor.shutdown(); 821 try { 822 executor.awaitTermination(2, TimeUnit.HOURS); 823 } 824 catch (final InterruptedException e) { 825 e.printStackTrace(); 826 } 827 828 } 829 830 /* 831 * (non-Javadoc) 832 * 833 * @see java.lang.Object#toString() 834 */ 835 @Override 836 public String toString() { 837 return "SequenceForTaskDetectionRuleAlignment"; 838 } 839 840 /** 841 * The Class ParallelMatchOcurrencesFinder. 842 */ 843 private class ParallelMatchOcurrencesFinder implements Runnable { 844 845 /** The app data. */ 846 private final RuleApplicationData appData; 847 848 /** The from. */ 849 private final int from; 850 851 /** The to. */ 852 private final int to; 853 854 /** 855 * Instantiates a new parallel match ocurrences finder. 856 * 857 * @param appData 858 * the app data 859 * @param from 860 * the from 861 * @param to 862 * the to 863 */ 864 ParallelMatchOcurrencesFinder(RuleApplicationData appData, int from, int to) { 865 this.appData = appData; 866 this.from = from; 867 this.to = to; 868 } 869 870 /* 871 * (non-Javadoc) 872 * 873 * @see java.lang.Runnable#run() 874 */ 875 @Override 876 public void run() { 877 int count = 0; 878 final int size = to + 1 - from; 879 880 for (int i = from; i <= to; i++) { 881 final Match pattern = appData.getMatchseqs().get(i); 882 count++; 883 RuleUtils.printProgressPercentage("Match finding progress", count, size); 884 // Skip sequences with more 0 events (scrolls) than other 885 // events. 886 // Both of the pattern sequences are equally long, so the zero 887 // counts just need to be smaller than the length of one 888 // sequence 889 if ((pattern.getFirstSequence().eventCount(0) + 890 pattern.getSecondSequence().eventCount(0) + 1) > pattern.getFirstSequence() 891 .size()) 892 { 893 continue; 894 } 895 896 for (int j = 0; j < appData.getNumberSequences().size(); j++) { 897 final LinkedList<Integer> startpositions = 898 appData.getNumberSequences().get(j).containsPattern(pattern); 899 if (startpositions.size() > 0) { 900 for (final Iterator<Integer> jt = startpositions.iterator(); jt.hasNext();) 901 { 902 final int start = jt.next(); 903 pattern.addOccurence(new MatchOccurrence(start, start + pattern.size(), 904 j)); 905 } 906 } 907 } 908 } 909 } 910 } 911 912 /** 913 * The Class ParallelPairwiseAligner. 914 */ 915 private class ParallelPairwiseAligner implements Runnable { 916 917 /** The app data. */ 918 private final RuleApplicationData appData; 919 920 /** The from. */ 921 private final int from; 922 923 /** The to. */ 924 private final int to; 925 926 /** 927 * Instantiates a new parallel pairwise aligner. 928 * 929 * @param appData 930 * the app data 931 * @param from 932 * the from 933 * @param to 934 * the to 935 */ 936 ParallelPairwiseAligner(RuleApplicationData appData, int from, int to) { 937 this.appData = appData; 938 this.from = from; 939 this.to = to; 940 } 941 942 /* 943 * (non-Javadoc) 944 * 945 * @see java.lang.Runnable#run() 946 */ 947 @Override 948 public void run() { 949 int count = 0; 950 final int size = to + 1 - from; 951 952 for (int i = from; i <= to; i++) { 953 final NumberSequence ns1 = appData.getNumberSequences().get(i); 954 count++; 955 RuleUtils.printProgressPercentage("Aligning Progress", count, size); 956 for (int j = 0; j < appData.getNumberSequences().size(); j++) { 957 final NumberSequence ns2 = appData.getNumberSequences().get(j); 958 if (i != j) { 959 final AlignmentAlgorithm aa = AlignmentAlgorithmFactory.create(); 960 // threshold was 9 961 aa.align(ns1, ns2, appData.getSubmat(), 962 SequenceForTaskDetectionRuleAlignment.alignmentThreshold); 963 synchronized (appData.getMatchseqs()) { 964 appData.getMatchseqs().addAll(aa.getMatches()); 965 } 966 } 967 } 968 } 969 } 970 } 971 972 /** 973 * The Class ParallelPairwiseAligner. 974 */ 975 private class ParallelMatchReplacer implements Runnable { 976 977 /** The app data. */ 978 private final RuleApplicationData appData; 979 980 /** The from. */ 981 private final int from; 982 983 /** The to. */ 984 private final int to; 985 986 /** 987 * Instantiates a new parallel pairwise aligner. 988 * 989 * @param appData 990 * the app data 991 * @param from 992 * the from 993 * @param to 994 * the to 995 */ 996 ParallelMatchReplacer(RuleApplicationData appData, int from, int to) { 997 this.appData = appData; 998 this.from = from; 999 this.to = to; 1000 } 1001 1002 /* 1003 * (non-Javadoc) 1004 * 1005 * @see java.lang.Runnable#run() 1006 */ 1007 @Override 1008 public void run() { 1009 for (int i = from; i <= to; i++) { 1010 System.out.println("Replacing in SEQUENCE " + i); 1011 /* 1012 * HashMap for keeping track in which sequence which replacement has been performed. 1013 * Neccessary for updating the indices of other occurrences accordingly 1014 */ 1015 LinkedList<MatchOccurrence> replacedOccurrences = new LinkedList<MatchOccurrence>(); 1016 invalidOccurence: while (!appData.getPlannedReplacements()[i].isEmpty()) { 1017 1018 PlannedReplacement pr = appData.getPlannedReplacements()[i].remove(); 1019 1020 MatchOccurrence oc = pr.getOccurrence(); 1021 // check if we have any replaced occurrence with 1022 // indexes 1023 // smaller than ours. If so, we need to adjust 1024 // our start and end points of the replacement. 1025 // Also do a check if we have replaced this 1026 // specific MatchOccurence in this sequence already. 1027 // Jump to the next occurrence if this is the case. 1028 // This is no more necessary once the matches 1029 // are harmonized. 1030 1031 for (final Iterator<MatchOccurrence> jt = replacedOccurrences.iterator(); jt 1032 .hasNext();) 1033 { 1034 final MatchOccurrence tmpOC = jt.next(); 1035 1036 if ((oc.getStartindex() >= tmpOC.getStartindex()) && 1037 (oc.getStartindex() <= tmpOC.getEndindex())) 1038 { 1039 continue invalidOccurence; 1040 } 1041 if (oc.getEndindex() >= tmpOC.getStartindex()) { 1042 continue invalidOccurence; 1043 1044 } 1045 else if (oc.getStartindex() > tmpOC.getEndindex()) { 1046 final int diff = tmpOC.getEndindex() - tmpOC.getStartindex(); 1047 // Just to be sure. 1048 if (diff > 0) { 1049 oc.setStartindex((oc.getStartindex() - diff) + 1); 1050 oc.setEndindex((oc.getEndindex() - diff) + 1); 1051 } 1052 else { 1053 Console 1054 .traceln(Level.WARNING, 1055 "End index of a Match before start. This should never happen"); 1056 } 1057 } 1058 } 1059 synchronized (appData) { 1060 appData.detectedAndReplacedTasks = true; 1061 } 1062 1063 1064 System.out.println("Replacing in Sequence " + oc.getSequenceId() + 1065 " at position " + oc.getStartindex() + " till " + oc.getEndindex()); 1066 final ISequenceInstance sequenceInstances = 1067 RuleUtils.createNewSubSequenceInRange(appData.getSessions() 1068 .get(oc.getSequenceId()), oc 1069 .getStartindex(), oc 1070 .getEndindex(), (ISequence) appData.getPreparedTasks().get(pr.getMatchId()), 1071 taskFactory, taskBuilder); 1072 1073 // Adjust the length of the match regarding to the 1074 // length of 1075 // instance. (OptionalInstances may be shorter) 1076 oc.setEndindex((oc.getStartindex() + sequenceInstances.size()) - 1077 RuleUtils.missedOptionals); 1078 1079 replacedOccurrences.add(oc); 1080 1081 } 1082 } 1083 } 1084 } 1085 1086 private static class PlannedReplacement { 1087 private int matchId; 1088 private int getMatchId() { 1089 return matchId; 1090 } 1091 1092 private MatchOccurrence getOccurrence() { 1093 return occurrence; 1094 } 1095 1096 private MatchOccurrence occurrence; 1097 1098 private PlannedReplacement(int matchId,MatchOccurrence occurrence) { 1099 this.matchId = matchId; 1100 this.occurrence = occurrence; 1101 } 1102 } 1103 1104 /** 1105 * The Class RuleApplicationData. 1106 */ 1107 private static class RuleApplicationData implements Serializable { 1108 1109 /** The Constant serialVersionUID. */ 1110 private static final long serialVersionUID = -7559657686755522960L; 1111 1112 /** 1113 * The number2task HashMap. Since we align the tasks just by their integer id, we need this 1114 * to convert them back to Tasks again 1115 */ 1116 private final HashMap<Integer, ITask> number2task; 1117 1118 /** 1119 * The unique tasks, keeps track about all unique tasks TODO: We Actually just need 1120 * number2task here, this structure can be removed in the future. 1121 */ 1122 private final HashSet<ITask> uniqueTasks; 1123 1124 /** 1125 * The substitution matrix used by the alignment algorithm to be able to compare distances 1126 * of tasks 1127 */ 1128 private final ObjectDistanceSubstitionMatrix submat; 1129 1130 private LinkedList<PlannedReplacement>[] plannedReplacements; 1131 1132 /** The list of all found matches */ 1133 private LinkedList<Match> matchseqs; 1134 1135 private ArrayList<ITask> preparedTasks; 1136 1137 public ArrayList<ITask> getPreparedTasks() { 1138 return preparedTasks; 1139 } 1140 1141 /** 1142 * The generated NumberSequences. This is the integer representation of the user sessions 1143 */ 1144 private ArrayList<NumberSequence> numberseqs; 1145 1146 /** The list of newly created tasks (of one iteration). */ 1147 private final LinkedList<ITask> newTasks; 1148 1149 /** The user sessions containing all EventTasks/Instances */ 1150 private final List<IUserSession> sessions; 1151 1152 /** True if we replaced something in the user sessions in one iteration. */ 1153 private boolean detectedAndReplacedTasks; 1154 1155 /** The result we return from this rule */ 1156 private final RuleApplicationResult result; 1157 1158 /** Stop Watch to measure performance */ 1159 private final StopWatch stopWatch; 1160 1161 /** 1162 * Instantiates a new rule application data. 1163 * 1164 * @param sessions 1165 * The user sessions 1166 */ 1167 private RuleApplicationData(List<IUserSession> sessions) { 1168 this.sessions = sessions; 1169 numberseqs = new ArrayList<NumberSequence>(); 1170 uniqueTasks = new HashSet<ITask>(); 1171 number2task = new HashMap<Integer, ITask>(); 1172 stopWatch = new StopWatch(); 1173 result = new RuleApplicationResult(); 1174 preparedTasks = new ArrayList<ITask>(); 1175 submat = new ObjectDistanceSubstitionMatrix(maxSubstitutionScore, gapPenalty, false); 1176 newTasks = new LinkedList<ITask>(); 1177 this.detectedAndReplacedTasks = true; 1178 } 1179 1180 private void initializeQueues(int size) { 1181 plannedReplacements = new LinkedList[size]; 1182 for (int i = 0; i < size; i++) { 1183 plannedReplacements[i] = new LinkedList<PlannedReplacement>(); 1184 } 1185 } 1186 1187 public Queue<PlannedReplacement>[] getPlannedReplacements() { 1188 return plannedReplacements; 1189 } 1190 1191 /** 1192 * Detected and replaced tasks. 1193 * 1194 * @return true, if successful 1195 */ 1196 private boolean detectedAndReplacedTasks() { 1197 return detectedAndReplacedTasks; 1198 } 1199 1200 /** 1201 * Gets the match sequences. 1202 * 1203 * @return the match sequences 1204 */ 1205 public LinkedList<Match> getMatchseqs() { 1206 return matchseqs; 1207 } 1208 1209 /** 1210 * Gets the new tasks. 1211 * 1212 * @return the new tasks 1213 */ 1214 public LinkedList<ITask> getNewTasks() { 1215 return newTasks; 1216 } 1217 1218 /** 1219 * Gets the number2task. 1220 * 1221 * @return the number2task HashMap 1222 */ 1223 private HashMap<Integer, ITask> getNumber2Task() { 1224 return number2task; 1225 } 1226 1227 /** 1228 * Gets the number sequences. 1229 * 1230 * @return the number sequences 1231 */ 1232 private ArrayList<NumberSequence> getNumberSequences() { 1233 return numberseqs; 1234 } 1235 1236 /** 1237 * Gets the result. 1238 * 1239 * @return the result 1240 */ 1241 private RuleApplicationResult getResult() { 1242 return result; 1243 } 1244 1245 /** 1246 * Gets the sessions. 1247 * 1248 * @return the UserSessions as List. 1249 */ 1250 private List<IUserSession> getSessions() { 1251 return sessions; 1252 } 1253 1254 /** 1255 * Gets the stop watch. 1256 * 1257 * @return the stopWatch 1258 */ 1259 private StopWatch getStopWatch() { 1260 return stopWatch; 1261 } 1262 1263 /** 1264 * Gets the substitution matrix. 1265 * 1266 * @return the substitution matrix 1267 */ 1268 private ObjectDistanceSubstitionMatrix getSubmat() { 1269 return submat; 1270 } 1271 1272 /** 1273 * Gets the unique tasks. 1274 * 1275 * @return the unique tasks 1276 */ 1277 private HashSet<ITask> getUniqueTasks() { 1278 return uniqueTasks; 1279 } 1280 1281 /** 1282 * New task created. 1283 * 1284 * @param task 1285 * can be called when new tasks are created to keep track of all newly created 1286 * tasks 1287 */ 1288 private void newTaskCreated(ITask task) { 1289 number2task.put(task.getId(), task); 1290 newTasks.add(task); 1291 } 1292 1293 /** 1294 * Reset newly created tasks. 1295 */ 1296 synchronized private void resetNewlyCreatedTasks() { 1297 uniqueTasks.addAll(newTasks); 1298 newTasks.clear(); 1299 } 1300 1301 /** 1302 * Sets the number sequences. 1303 * 1304 * @param numberseqs 1305 * the new number sequences 1306 */ 1307 private void setNumberSequences(ArrayList<NumberSequence> numberseqs) { 1308 this.numberseqs = numberseqs; 1309 } 1310 1311 /** 1312 * Update substitution matrix. 1313 */ 1314 private void updateSubstitutionMatrix() { 1315 submat.update(getNewTasks()); 1316 resetNewlyCreatedTasks(); 1317 } 1318 1319 } 1309 1320 1310 1321 }
Note: See TracChangeset
for help on using the changeset viewer.