Changeset 1559 for branches/ralph
- Timestamp:
- 06/04/14 16:42:02 (11 years ago)
- Location:
- branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees
- Files:
-
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/alignment/algorithms/MatrixEntry.java
r1558 r1559 4 4 private float score; 5 5 private MatrixEntry previous; 6 private int xvalue; 7 private int yvalue; 6 8 7 9 public MatrixEntry(float score, MatrixEntry previous) { … … 25 27 this.previous = previous; 26 28 } 29 30 public int getXvalue() { 31 return xvalue; 32 } 33 34 public void setXvalue(int xvalue) { 35 this.xvalue = xvalue; 36 } 37 38 public int getYvalue() { 39 return yvalue; 40 } 41 42 public void setYvalue(int yvalue) { 43 this.yvalue = yvalue; 44 } 27 45 } -
branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/alignment/algorithms/NumberSequence.java
r1558 r1559 29 29 { 30 30 for (int i = 0; i < sequence.length; i++) { 31 System.out.format("% 4d", sequence[i]);31 System.out.format("%5d", sequence[i]); 32 32 } 33 33 System.out.println(); -
branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/alignment/algorithms/SmithWatermanRepeated.java
r1558 r1559 51 51 matrix = new MatrixEntry[length1+2][length2+1]; 52 52 53 for (int i = 0; i <= length1 ; i++) {53 for (int i = 0; i <= length1+1; i++) { 54 54 for(int j = 0; j< length2; j++) { 55 55 matrix[i][j] = new MatrixEntry(); … … 71 71 * @return Cost of substitution of the character in str1 by the one in str2 72 72 */ 73 private float similarity(int i, int j) { 74 if (i == 0 || j == 0) { 75 // it's a gap 76 return submat.getGapPenalty(); 77 } 78 // System.out.println("Diag letters: " + input1[i-1] + " " + 79 // input2[j-1]); 80 // return (input1[i - 1] == input2[j - 1]) ? MATCH_SCORE : 81 // MISMATCH_SCORE; 73 private float similarity(int i, int j) { 82 74 return submat.getDistance(input1[i - 1], input2[j - 1]); 83 75 } 84 76 85 77 /** 86 * Build the score matrix using dynamic programming. Note: The indel scores 87 * must be negative. Otherwise, the part handling the first row and column 88 * has to be modified. 78 * Build the score matrix using dynamic programming. 89 79 */ 90 80 private void buildMatrix() { … … 93 83 } 94 84 95 96 // base case 85 // it's a gap 97 86 matrix[0][0].setScore(0); 98 87 matrix[0][0].setPrevious(null); // starting point … … 107 96 108 97 109 for (int i = 1; i <= length1 ; i++) {98 for (int i = 1; i <= length1 + 1; i++) { 110 99 111 100 // Formula for first row: … … 113 102 114 103 float firstRowLeftScore = matrix[i-1][0].getScore(); 115 float tempMax = matrix[i-1][1].getScore(); 116 117 //position of the maximal score of the previous row 118 int maxRowIndex = 1; 119 120 for(int j = 2; j < length2;j++) { 121 if(matrix[i-1][j].getScore() > tempMax) { 122 tempMax = matrix[i-1][j].getScore(); 123 maxRowIndex = j; 124 } 125 } 126 104 //for sequences of length 1 105 float tempMax; 106 int maxRowIndex; 107 if(length2 == 1) { 108 tempMax = matrix[i-1][0].getScore(); 109 maxRowIndex = 0; 110 } else { 111 tempMax = matrix[i-1][1].getScore(); 112 maxRowIndex = 1; 113 //position of the maximal score of the previous row 114 115 for(int j = 2; j < length2;j++) { 116 if(matrix[i-1][j].getScore() > tempMax) { 117 tempMax = matrix[i-1][j].getScore(); 118 maxRowIndex = j; 119 } 120 } 121 122 } 123 124 127 125 tempMax -= scoreThreshold; 128 126 matrix[i][0].setScore(Math.max(firstRowLeftScore, tempMax)); 127 if(tempMax ==matrix[i][0].getScore()){ 128 matrix[i][0].setPrevious(matrix[i-1][maxRowIndex]); 129 } 130 131 if(firstRowLeftScore == matrix[i][0].getScore()) { 132 matrix[i][0].setPrevious(matrix[i-1][0]); 133 } 134 135 //The last additional score is not related to a character in the input sequence, it's the total score. Therefore we don't need to save something for it 136 if(i<length1+1) 137 { 138 matrix[i][0].setXvalue(input1[i-1]); 139 matrix[i][0].setYvalue(-2); 140 141 } 142 else { 143 //End after we calculated final score 144 return; 145 } 129 146 130 147 131 148 for (int j = 1; j < length2; j++) { 132 149 float diagScore = matrix[i - 1][j - 1].getScore() + similarity(i, j); 133 float upScore = matrix[i][j - 1].getScore() + s imilarity(0, j);134 float leftScore = matrix[i - 1][j].getScore() + s imilarity(i, 0);150 float upScore = matrix[i][j - 1].getScore() + submat.getGapPenalty(); 151 float leftScore = matrix[i - 1][j].getScore() + submat.getGapPenalty(); 135 152 136 153 matrix[i][j].setScore(Math.max(diagScore,Math.max(upScore, Math.max(leftScore,matrix[i][0].getScore())))); … … 138 155 // find the directions that give the maximum scores. 139 156 // Multiple directions are ignored TODO 157 //True if we had a match 140 158 if (diagScore == matrix[i][j].getScore()) { 141 159 matrix[i][j].setPrevious(matrix[i-1][j-1]); 142 } 160 matrix[i][j].setXvalue(input1[i-1]); 161 matrix[i][j].setYvalue(input2[j-1]); 162 } 163 //true if we took an event from sequence x and not from y 143 164 if (leftScore == matrix[i][j].getScore()) { 165 matrix[i][j].setXvalue(input1[i-1]); 166 matrix[i][j].setYvalue(-1); 144 167 matrix[i][j].setPrevious(matrix[i-1][j]); 145 168 } 169 //true if we took an event from sequence y and not from x 146 170 if (upScore == matrix[i][j].getScore()) { 171 matrix[i][j].setXvalue(-1); 172 matrix[i][j].setYvalue(input2[j-1]); 147 173 matrix[i][j].setPrevious(matrix[i][j-1]); 148 174 } 175 //true if we ended a matching region 149 176 if (matrix[i][0].getScore() == matrix[i][j].getScore()) { 150 matrix[i][j].setPrevious(matrix[i-1][maxRowIndex]); 151 } 152 } 177 matrix[i][j].setPrevious(matrix[i][0]); 178 matrix[i][j].setXvalue(input1[i-1]); 179 matrix[i][j].setYvalue(-2); 180 } 181 } 182 183 //Set the complete score cell 184 153 185 } 154 186 } … … 175 207 * Get the alignment score between the two input strings. 176 208 */ 177 public doublegetAlignmentScore() {178 return getMaxScore();209 public float getAlignmentScore() { 210 return matrix[length1+1][0].getScore(); 179 211 } 180 212 … … 188 220 */ 189 221 private int[] traceback(int i, int j) { 190 222 223 191 224 return null; 192 225 } 226 227 public void traceback() { 228 MatrixEntry tmp = matrix[length1+1][0]; 229 String aligned1 = ""; 230 String aligned2 = ""; 231 int count = 0; 232 do 233 { 234 String append1=""; 235 String append2=""; 236 237 if(tmp.getXvalue() == -1) { 238 append1 = " ___"; 239 } 240 else if(tmp.getXvalue() == -2) { 241 append1 = " ..."; 242 } 243 else { 244 append1 = String.format("%5d", tmp.getXvalue()); 245 } 246 247 if(tmp.getYvalue() == -1) { 248 append2 = " ___"; 249 } 250 else if(tmp.getYvalue() == -2) { 251 append2 = " ..."; 252 } 253 else { 254 append2 = String.format("%5d", tmp.getYvalue()); 255 } 256 if(count != 0) 257 { 258 aligned1 = append1 + aligned1; 259 aligned2 = append2 + aligned2; 260 } 261 262 tmp = tmp.getPrevious(); 263 count++; 264 265 } while(tmp != null); 266 System.out.println(aligned1); 267 System.out.println(aligned2); 268 } 269 193 270 194 271 … … 207 284 System.out.print(" "); 208 285 } 209 for (int i = 0; i <= length1; i++) { 210 System.out.format("%4.1f ",matrix[i][j].getScore()); 211 } 286 for (int i = 0; i <= length1 + 1; i++) { 287 if((i<length1+1) || (i==length1+1 && j==0)) { 288 System.out.format("%4.1f ",matrix[i][j].getScore()); 289 } 290 291 } 212 292 System.out.println(); 213 293 } -
branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/alignment/substitution/ObjectDistanceSubstitionMatrix.java
r1558 r1559 35 35 idmapping = new HashMap<Integer, Integer>(); 36 36 matrix = new TriangleMatrix(uniqueTasks.size()+1); 37 gapPenalty = - 10;37 gapPenalty = -5; 38 38 39 39 } -
branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/temporalrelation/SequenceForTaskDetectionRuleAlignment.java
r1558 r1559 51 51 /** 52 52 * <p> 53 * This class implements the major rule for creating task trees based on a set of recorded 54 * user sessions. For this, it first harmonizes all tasks. This eases later comparison. Then it 55 * searches the sessions for iterations and replaces them accordingly. Then it searches for sub 56 * sequences being the longest and occurring most often. For each found sub sequence, it replaces 57 * the occurrences by creating appropriate {@link ISequence}s. Afterwards, again searches for 58 * iterations and then again for sub sequences until no more replacements are done. 53 * This class implements the major rule for creating task trees based on a set 54 * of recorded user sessions. For this, it first harmonizes all tasks. This 55 * eases later comparison. Then it searches the sessions for iterations and 56 * replaces them accordingly. Then it searches for sub sequences being the 57 * longest and occurring most often. For each found sub sequence, it replaces 58 * the occurrences by creating appropriate {@link ISequence}s. Afterwards, again 59 * searches for iterations and then again for sub sequences until no more 60 * replacements are done. 59 61 * </p> 60 62 * <p> 61 * For determining the longest sequence occurring most often, the implementation uses a62 * {@link Trie}. The depth of the tree is initially 3. If the algorithm has a longest sequence63 * occurring most often whose length is equal to the depth of the trie, it recalculates the trie64 * with an increased depth.63 * For determining the longest sequence occurring most often, the implementation 64 * uses a {@link Trie}. The depth of the tree is initially 3. If the algorithm 65 * has a longest sequence occurring most often whose length is equal to the 66 * depth of the trie, it recalculates the trie with an increased depth. 65 67 * </p> 66 68 * … … 68 70 */ 69 71 class SequenceForTaskDetectionRuleAlignment implements ISessionScopeRule { 70 71 /** 72 * <p> 73 * the task factory to be used for creating substructures for the temporal 74 * relationships identified during rul application 75 * </p> 76 */ 77 private ITaskFactory taskFactory; 78 /** 79 * <p> 80 * the task builder to be used for creating substructures for the temporal relationships 81 * identified during rule application 82 * </p> 83 */ 84 private ITaskBuilder taskBuilder; 85 86 /** 87 * <p> 88 * the task handling strategy to be used for comparing tasks for preparation, i.e., before 89 * the tasks are harmonized 90 * </p> 91 */ 92 private TaskHandlingStrategy preparationTaskHandlingStrategy; 93 94 /** 95 * <p> 96 * the task handling strategy to be used for comparing tasks during iteration detection an trie 97 * generation, i.e., after the tasks are harmonized 98 * </p> 99 */ 100 private TaskHandlingStrategy identityTaskHandlingStrategy;; 101 102 103 private ArrayList<NumberSequence> numberseqs; 104 105 /** 106 * <p> 107 * instantiates the rule and initializes it with a task equality to be considered when 108 * comparing tasks as well as a task factory and builder to be used for creating task 109 * structures. 110 * </p> 111 * 112 * @param minimalTaskEquality the task equality to be considered when comparing tasks 113 * @param taskFactory the task factory to be used for creating substructures 114 * @param taskBuilder the task builder to be used for creating substructures 115 */ 116 117 118 SequenceForTaskDetectionRuleAlignment(TaskEquality minimalTaskEquality, 119 ITaskFactory taskFactory, 120 ITaskBuilder taskBuilder) 121 { 122 this.taskFactory = taskFactory; 123 this.taskBuilder = taskBuilder; 124 125 this.preparationTaskHandlingStrategy = new TaskHandlingStrategy(minimalTaskEquality); 126 this.identityTaskHandlingStrategy = new TaskHandlingStrategy(TaskEquality.IDENTICAL); 127 numberseqs = new ArrayList<NumberSequence>(); 128 129 } 130 131 /* (non-Javadoc) 132 * @see java.lang.Object#toString() 133 */ 134 @Override 135 public String toString() { 136 return "SequenceForTaskDetectionRuleAlignment"; 137 } 138 139 /* (non-Javadoc) 140 * @see de.ugoe.cs.autoquest.tasktrees.temporalrelation.ISessionScopeRule#apply(java.util.List) 141 */ 142 @Override 143 public RuleApplicationResult apply(List<IUserSession> sessions) { 144 RuleApplicationData appData = new RuleApplicationData(sessions); 145 146 147 148 // this is the real rule application. Loop while something is replaced. 149 SymbolMap<ITaskInstance, ITask> uniqueTasks = harmonizeEventTaskInstancesModel(appData); 150 ObjectDistanceSubstitionMatrix submat = new ObjectDistanceSubstitionMatrix(uniqueTasks,20); 151 submat.generate(); 152 153 154 155 System.out.print("Sequence 1: "); 156 NumberSequence ns1 = numberseqs.get(7); 157 NumberSequence ns2 = numberseqs.get(8); 158 ns1.printSequence(); 159 System.out.print("Sequence 2: "); 160 ns2.printSequence(); 161 //SmithWatermanRepeated sw = new SmithWatermanRepeated(numberseqs.get(20).getSequence(), numberseqs.get(24).getSequence(), submat,10); 162 SmithWatermanRepeated sw = new SmithWatermanRepeated(ns1.getSequence(), ns2.getSequence(), submat,15); 163 System.out.println("Max Scrore: " + sw.getMaxScore()); 164 165 sw.printDPMatrix(); 166 167 168 169 170 do { 171 System.out.println(); 172 FengDoolittle fd = new FengDoolittle(); 173 174 175 //appData.getStopWatch().start("whole loop"); 176 //detectAndReplaceIterations(appData); 177 178 //appData.getStopWatch().start("task replacement"); 179 //detectAndReplaceTasks(appData); 180 //appData.getStopWatch().stop("task replacement"); 181 //appData.getStopWatch().stop("whole loop"); 182 183 184 //appData.getStopWatch().dumpStatistics(System.out); 185 //appData.getStopWatch().reset(); 186 187 } 188 while (appData.detectedAndReplacedTasks()); 189 190 Console.println 191 ("created " + appData.getResult().getNewlyCreatedTasks().size() + 192 " new tasks and " + appData.getResult().getNewlyCreatedTaskInstances().size() + 193 " appropriate instances\n"); 194 195 if ((appData.getResult().getNewlyCreatedTasks().size() > 0) || 196 (appData.getResult().getNewlyCreatedTaskInstances().size() > 0)) 197 { 198 appData.getResult().setRuleApplicationStatus(RuleApplicationStatus.FINISHED); 199 } 200 201 return appData.getResult(); 202 } 203 204 /** 205 * <p> 206 * harmonizes the event task instances by unifying tasks. This is done, as initially the 207 * event tasks being equal with respect to the considered task equality are distinct objects. 208 * The comparison of these distinct objects is more time consuming than comparing the object 209 * references. 210 * </p> 211 * 212 * @param appData the rule application data combining all data used for applying this rule 213 * @return Returns the unique tasks symbol map 214 */ 215 private SymbolMap<ITaskInstance, ITask> harmonizeEventTaskInstancesModel(RuleApplicationData appData) { 216 Console.traceln(Level.INFO, "harmonizing task model of event task instances"); 217 appData.getStopWatch().start("harmonizing event tasks"); 218 219 SymbolMap<ITaskInstance, ITask> uniqueTasks = 220 preparationTaskHandlingStrategy.createSymbolMap(); 221 TaskInstanceComparator comparator = preparationTaskHandlingStrategy.getTaskComparator(); 222 223 int unifiedTasks = 0; 224 ITask task; 225 List<IUserSession> sessions = appData.getSessions(); 226 int sessionNo = 0; 227 numberseqs = new ArrayList<NumberSequence>(); 228 for (IUserSession session : sessions) { 229 Console.traceln(Level.FINE, "handling " + (++sessionNo) + ". " + session); 230 NumberSequence templist = new NumberSequence(session.size()) ; 231 232 for (int i = 0; i < session.size(); i++) { 233 ITaskInstance taskInstance = session.get(i); 234 task = uniqueTasks.getValue(taskInstance); 235 236 if (task == null) { 237 uniqueTasks.addSymbol(taskInstance, taskInstance.getTask()); 238 templist.getSequence()[i]=taskInstance.getTask().getId(); 239 } 240 else { 241 taskBuilder.setTask(taskInstance, task); 242 templist.getSequence()[i]=task.getId(); 243 unifiedTasks++; 244 } 245 } 246 numberseqs.add(templist); 247 comparator.clearBuffers(); 248 } 249 250 appData.getStopWatch().stop("harmonizing event tasks"); 251 Console.traceln(Level.INFO, "harmonized " + unifiedTasks + " task occurrences (still " + 252 uniqueTasks.size() + " different tasks)"); 253 254 appData.getStopWatch().dumpStatistics(System.out); 255 appData.getStopWatch().reset(); 72 73 /** 74 * <p> 75 * the task factory to be used for creating substructures for the temporal 76 * relationships identified during rul application 77 * </p> 78 */ 79 private ITaskFactory taskFactory; 80 /** 81 * <p> 82 * the task builder to be used for creating substructures for the temporal 83 * relationships identified during rule application 84 * </p> 85 */ 86 private ITaskBuilder taskBuilder; 87 88 /** 89 * <p> 90 * the task handling strategy to be used for comparing tasks for 91 * preparation, i.e., before the tasks are harmonized 92 * </p> 93 */ 94 private TaskHandlingStrategy preparationTaskHandlingStrategy; 95 96 /** 97 * <p> 98 * the task handling strategy to be used for comparing tasks during 99 * iteration detection an trie generation, i.e., after the tasks are 100 * harmonized 101 * </p> 102 */ 103 private TaskHandlingStrategy identityTaskHandlingStrategy;; 104 105 private ArrayList<NumberSequence> numberseqs; 106 107 /** 108 * <p> 109 * instantiates the rule and initializes it with a task equality to be 110 * considered when comparing tasks as well as a task factory and builder to 111 * be used for creating task structures. 112 * </p> 113 * 114 * @param minimalTaskEquality 115 * the task equality to be considered when comparing tasks 116 * @param taskFactory 117 * the task factory to be used for creating substructures 118 * @param taskBuilder 119 * the task builder to be used for creating substructures 120 */ 121 122 SequenceForTaskDetectionRuleAlignment(TaskEquality minimalTaskEquality, 123 ITaskFactory taskFactory, ITaskBuilder taskBuilder) { 124 this.taskFactory = taskFactory; 125 this.taskBuilder = taskBuilder; 126 127 this.preparationTaskHandlingStrategy = new TaskHandlingStrategy( 128 minimalTaskEquality); 129 this.identityTaskHandlingStrategy = new TaskHandlingStrategy( 130 TaskEquality.IDENTICAL); 131 numberseqs = new ArrayList<NumberSequence>(); 132 133 } 134 135 /* 136 * (non-Javadoc) 137 * 138 * @see java.lang.Object#toString() 139 */ 140 @Override 141 public String toString() { 142 return "SequenceForTaskDetectionRuleAlignment"; 143 } 144 145 /* 146 * (non-Javadoc) 147 * 148 * @see 149 * de.ugoe.cs.autoquest.tasktrees.temporalrelation.ISessionScopeRule#apply 150 * (java.util.List) 151 */ 152 @Override 153 public RuleApplicationResult apply(List<IUserSession> sessions) { 154 RuleApplicationData appData = new RuleApplicationData(sessions); 155 156 // this is the real rule application. Loop while something is replaced. 157 SymbolMap<ITaskInstance, ITask> uniqueTasks = harmonizeEventTaskInstancesModel(appData); 158 ObjectDistanceSubstitionMatrix submat = new ObjectDistanceSubstitionMatrix( 159 uniqueTasks, 5); 160 submat.generate(); 161 162 // good tests: 7/8 20/24 163 for (int i = 0; i < numberseqs.size(); i++) { 164 for (int j = 0; j < numberseqs.size(); j++) { 165 166 NumberSequence ns1 = numberseqs.get(i); 167 NumberSequence ns2 = numberseqs.get(j); 168 169 170 171 SmithWatermanRepeated sw = new SmithWatermanRepeated( 172 ns1.getSequence(), ns2.getSequence(), submat, 10); 173 174 if(sw.getAlignmentScore() > 0) 175 { 176 System.out.println("================================================="); 177 System.out.println("| Sequence " + String.format("%3d", i) +" Sequence " + String.format("%3d", j) + " |"); 178 System.out.println("================================================="); 179 //System.out.print("Sequence " + i + ": "); 180 //ns1.printSequence(); 181 //System.out.print("Sequence " + j + ": "); 182 //ns2.printSequence(); 183 //System.out.println("Max Scrore: " + sw.getMaxScore()); 184 System.out.println("Alignment Score: " + sw.getAlignmentScore()); 185 //sw.printDPMatrix(); 186 sw.traceback(); 187 System.out.println(); 188 System.out.println(); 189 } 190 } 191 } 192 193 do { 194 System.out.println(); 195 FengDoolittle fd = new FengDoolittle(); 196 197 // appData.getStopWatch().start("whole loop"); 198 // detectAndReplaceIterations(appData); 199 200 // appData.getStopWatch().start("task replacement"); 201 // detectAndReplaceTasks(appData); 202 // appData.getStopWatch().stop("task replacement"); 203 // appData.getStopWatch().stop("whole loop"); 204 205 // appData.getStopWatch().dumpStatistics(System.out); 206 // appData.getStopWatch().reset(); 207 208 } while (appData.detectedAndReplacedTasks()); 209 210 Console.println("created " 211 + appData.getResult().getNewlyCreatedTasks().size() 212 + " new tasks and " 213 + appData.getResult().getNewlyCreatedTaskInstances().size() 214 + " appropriate instances\n"); 215 216 if ((appData.getResult().getNewlyCreatedTasks().size() > 0) 217 || (appData.getResult().getNewlyCreatedTaskInstances().size() > 0)) { 218 appData.getResult().setRuleApplicationStatus( 219 RuleApplicationStatus.FINISHED); 220 } 221 222 return appData.getResult(); 223 } 224 225 /** 226 * <p> 227 * harmonizes the event task instances by unifying tasks. This is done, as 228 * initially the event tasks being equal with respect to the considered task 229 * equality are distinct objects. The comparison of these distinct objects 230 * is more time consuming than comparing the object references. 231 * </p> 232 * 233 * @param appData 234 * the rule application data combining all data used for applying 235 * this rule 236 * @return Returns the unique tasks symbol map 237 */ 238 private SymbolMap<ITaskInstance, ITask> harmonizeEventTaskInstancesModel( 239 RuleApplicationData appData) { 240 Console.traceln(Level.INFO, 241 "harmonizing task model of event task instances"); 242 appData.getStopWatch().start("harmonizing event tasks"); 243 244 SymbolMap<ITaskInstance, ITask> uniqueTasks = preparationTaskHandlingStrategy 245 .createSymbolMap(); 246 TaskInstanceComparator comparator = preparationTaskHandlingStrategy 247 .getTaskComparator(); 248 249 int unifiedTasks = 0; 250 ITask task; 251 List<IUserSession> sessions = appData.getSessions(); 252 int sessionNo = 0; 253 numberseqs = new ArrayList<NumberSequence>(); 254 for (IUserSession session : sessions) { 255 Console.traceln(Level.FINE, "handling " + (++sessionNo) + ". " 256 + session); 257 NumberSequence templist = new NumberSequence(session.size()); 258 259 for (int i = 0; i < session.size(); i++) { 260 ITaskInstance taskInstance = session.get(i); 261 task = uniqueTasks.getValue(taskInstance); 262 263 if (task == null) { 264 uniqueTasks.addSymbol(taskInstance, taskInstance.getTask()); 265 templist.getSequence()[i] = taskInstance.getTask().getId(); 266 } else { 267 taskBuilder.setTask(taskInstance, task); 268 templist.getSequence()[i] = task.getId(); 269 unifiedTasks++; 270 } 271 } 272 numberseqs.add(templist); 273 comparator.clearBuffers(); 274 } 275 276 appData.getStopWatch().stop("harmonizing event tasks"); 277 Console.traceln(Level.INFO, "harmonized " + unifiedTasks 278 + " task occurrences (still " + uniqueTasks.size() 279 + " different tasks)"); 280 281 appData.getStopWatch().dumpStatistics(System.out); 282 appData.getStopWatch().reset(); 256 283 return uniqueTasks; 257 } 258 259 /** 260 * <p> 261 * searches for direct iterations of single tasks in all sequences and replaces them with 262 * {@link IIteration}s, respectively appropriate instances. Also all single occurrences of 263 * a task that is iterated somewhen are replaced with iterations to have again an efficient 264 * way for task comparisons. 265 * </p> 266 * 267 * @param appData the rule application data combining all data used for applying this rule 268 */ 269 private void detectAndReplaceIterations(RuleApplicationData appData) { 270 Console.traceln(Level.FINE, "detecting iterations"); 271 appData.getStopWatch().start("detecting iterations"); 272 273 List<IUserSession> sessions = appData.getSessions(); 274 275 Set<ITask> iteratedTasks = searchIteratedTasks(sessions); 276 277 if (iteratedTasks.size() > 0) { 278 replaceIterationsOf(iteratedTasks, sessions, appData); 279 } 280 281 appData.getStopWatch().stop("detecting iterations"); 282 Console.traceln(Level.INFO, "replaced " + iteratedTasks.size() + " iterated tasks"); 283 } 284 285 /** 286 * <p> 287 * searches the provided sessions for task iterations. If a task is iterated, it is added 288 * to the returned set. 289 * </p> 290 * 291 * @param the session to search for iterations in 292 * 293 * @return a set of tasks being iterated somewhere 294 */ 295 private Set<ITask> searchIteratedTasks(List<IUserSession> sessions) { 296 Set<ITask> iteratedTasks = new HashSet<ITask>(); 297 for (IUserSession session : sessions) { 298 for (int i = 0; i < (session.size() - 1); i++) { 299 // we prepared the task instances to refer to unique tasks, if they are treated 300 // as equal. Therefore, we just compare the identity of the tasks of the task 301 // instances 302 if (session.get(i).getTask() == session.get(i + 1).getTask()) { 303 iteratedTasks.add(session.get(i).getTask()); 304 } 305 } 306 } 307 308 return iteratedTasks; 309 } 310 311 /** 312 * <p> 313 * replaces all occurrences of all tasks provided in the set with iterations 314 * </p> 315 * 316 * @param iteratedTasks the tasks to be replaced with iterations 317 * @param sessions the sessions in which the tasks are to be replaced 318 * @param appData the rule application data combining all data used for applying this rule 319 */ 320 private void replaceIterationsOf(Set<ITask> iteratedTasks, 321 List<IUserSession> sessions, 322 RuleApplicationData appData) 323 { 324 Map<ITask, IIteration> iterations = new HashMap<ITask, IIteration>(); 325 Map<IIteration, List<IIterationInstance>> iterationInstances = 326 new HashMap<IIteration, List<IIterationInstance>>(); 327 328 for (ITask iteratedTask : iteratedTasks) { 329 IIteration iteration = taskFactory.createNewIteration(); 330 iterations.put(iteratedTask, iteration); 331 iterationInstances.put(iteration, new LinkedList<IIterationInstance>()); 332 } 333 334 IIterationInstance iterationInstance; 335 336 for (IUserSession session : sessions) { 337 int index = 0; 338 iterationInstance = null; 339 340 while (index < session.size()) { 341 // we prepared the task instances to refer to unique tasks, if they are treated 342 // as equal. Therefore, we just compare the identity of the tasks of the task 343 // instances 344 ITask currentTask = session.get(index).getTask(); 345 IIteration iteration = iterations.get(currentTask); 346 if (iteration != null) { 347 if ((iterationInstance == null) || (iterationInstance.getTask() != iteration)) 348 { 349 iterationInstance = taskFactory.createNewTaskInstance(iteration); 350 iterationInstances.get(iteration).add(iterationInstance); 351 taskBuilder.addTaskInstance(session, index, iterationInstance); 352 index++; 353 } 354 355 taskBuilder.addChild(iterationInstance, session.get(index)); 356 taskBuilder.removeTaskInstance(session, index); 357 } 358 else { 359 if (iterationInstance != null) { 360 iterationInstance = null; 361 } 362 index++; 363 } 364 } 365 } 366 367 for (Map.Entry<IIteration, List<IIterationInstance>> entry : iterationInstances.entrySet()) 368 { 369 harmonizeIterationInstancesModel(entry.getKey(), entry.getValue()); 370 } 371 } 372 373 /** 374 * <p> 375 * TODO clarify why this is done 376 * </p> 377 */ 378 private void harmonizeIterationInstancesModel(IIteration iteration, 379 List<IIterationInstance> iterationInstances) 380 { 381 List<ITask> iteratedTaskVariants = new LinkedList<ITask>(); 382 TaskInstanceComparator comparator = preparationTaskHandlingStrategy.getTaskComparator(); 383 384 // merge the lexically different variants of iterated task to a unique list 385 for (IIterationInstance iterationInstance : iterationInstances) { 386 for (ITaskInstance executionVariant : iterationInstance) { 387 ITask candidate = executionVariant.getTask(); 388 389 boolean found = false; 390 for (ITask taskVariant : iteratedTaskVariants) { 391 if (comparator.areLexicallyEqual(taskVariant, candidate)) { 392 taskBuilder.setTask(executionVariant, taskVariant); 393 found = true; 394 break; 395 } 396 } 397 398 if (!found) { 399 iteratedTaskVariants.add(candidate); 400 } 401 } 402 } 403 404 // if there are more than one lexically different variant of iterated tasks, adapt the 405 // iteration model to be a selection of different variants. In this case also adapt 406 // the generated iteration instances to correctly contain selection instances. If there 407 // is only one variant of an iterated task, simply set this as the marked task of the 408 // iteration. In this case, the instances can be preserved as is 409 if (iteratedTaskVariants.size() > 1) { 410 ISelection selection = taskFactory.createNewSelection(); 411 412 for (ITask variant : iteratedTaskVariants) { 413 taskBuilder.addChild(selection, variant); 414 } 415 416 taskBuilder.setMarkedTask(iteration, selection); 417 418 for (IIterationInstance instance : iterationInstances) { 419 for (int i = 0; i < instance.size(); i++) { 420 ISelectionInstance selectionInstance = 421 taskFactory.createNewTaskInstance(selection); 422 taskBuilder.setChild(selectionInstance, instance.get(i)); 423 taskBuilder.setTaskInstance(instance, i, selectionInstance); 424 } 425 } 426 } 427 else { 428 taskBuilder.setMarkedTask(iteration, iteratedTaskVariants.get(0)); 429 } 430 } 431 432 /** 433 * TODO go on commenting 434 * @param appData the rule application data combining all data used for applying this rule 435 */ 436 private void detectAndReplaceTasks(RuleApplicationData appData) { 437 Console.traceln(Level.FINE, "detecting and replacing tasks"); 438 appData.getStopWatch().start("detecting tasks"); 439 440 getSequencesOccuringMostOften(appData); 441 442 appData.getStopWatch().stop("detecting tasks"); 443 appData.getStopWatch().start("replacing tasks"); 444 445 replaceSequencesOccurringMostOften(appData); 446 447 appData.getStopWatch().stop("replacing tasks"); 448 Console.traceln(Level.INFO, "detected and replaced " + appData.getLastFoundTasks().size() + 449 " tasks occuring " + appData.getLastFoundTasks().getOccurrenceCount() + 450 " times"); 451 } 452 453 /** 454 * @param appData the rule application data combining all data used for applying this rule 455 */ 456 private void getSequencesOccuringMostOften(RuleApplicationData appData) { 457 Console.traceln(Level.FINE, "determining most prominent tasks"); 458 459 Tasks tasks; 460 boolean createNewTrie = (appData.getLastTrie() == null) || 461 appData.detectedAndReplacedTasks(); // tree has changed 462 463 do { 464 if (createNewTrie) { 465 createNewTrie(appData); 466 } 467 468 MaxCountAndLongestTasksFinder finder = new MaxCountAndLongestTasksFinder(); 469 appData.getLastTrie().process(finder); 470 471 tasks = finder.getFoundTasks(); 472 473 createNewTrie = false; 474 475 for (List<ITaskInstance> task : tasks) { 476 if (task.size() >= appData.getTrainedSequenceLength()) { 477 // Trie must be recreated with a longer sequence length to be sure that 478 // the found sequences occurring most often are found in their whole length 479 appData.setTrainedSequenceLength(appData.getTrainedSequenceLength() + 1); 480 createNewTrie = true; 481 break; 482 } 483 } 484 } 485 while (createNewTrie); 486 487 // create a normal trie for comparison 488 /*System.out.println("creating test trie for comparison"); 489 490 appData.getStopWatch().start("testtrie"); 491 Trie<ITaskInstance> trie = new Trie<ITaskInstance>(identityTaskComparator); 492 493 for (IUserSession session : appData.getSessions()) { 494 trie.train(session.getExecutedTasks(), appData.getTrainedSequenceLength()); 495 } 496 497 appData.getStopWatch().stop("testtrie"); 498 499 MaxCountAndLongestTasksFinder finder = new MaxCountAndLongestTasksFinder(); 500 trie.process(finder); 501 502 boolean allTasksEqual = finder.getFoundTasks().size() == tasks.size(); 503 504 allTasksEqual &= finder.getFoundTasks().occurrenceCount == tasks.occurrenceCount; 505 506 for (List<ITaskInstance> task1 : finder.getFoundTasks()) { 507 boolean foundTask = false; 508 for (List<ITaskInstance> task2 : tasks) { 509 boolean tasksEqual = false; 510 if (task1.size() == task2.size()) { 511 tasksEqual = true; 512 for (int i = 0; i < task1.size(); i++) { 513 if (!identityTaskComparator.equals(task1.get(i).getTask(), task2.get(i).getTask())) 514 { 515 tasksEqual = false; 516 } 517 } 518 } 519 520 if (tasksEqual) { 521 foundTask = true; 522 break; 523 } 524 } 525 526 if (!foundTask) { 527 System.out.println("different is " + task1); 528 allTasksEqual = false; 529 break; 530 } 531 } 532 533 if (!allTasksEqual) { 534 System.out.println(finder.getFoundTasks()); 535 System.out.println(tasks); 536 537 throw new IllegalArgumentException("both tries calculated different subsequences"); 538 } 539 540 /*TrieStatisticsDumper dumper = new TrieStatisticsDumper(); 541 appData.getLastTrie().process(dumper); 542 dumper.dumpCounters();*/ 543 544 appData.setLastFoundTasks(tasks); 545 546 Console.traceln(Level.FINE, "found " + appData.getLastFoundTasks().size() + " tasks " + 547 "occurring " + appData.getLastFoundTasks().getOccurrenceCount() + " times"); 548 } 549 550 /** 551 * @param appData the rule application data combining all data used for applying this rule 552 */ 553 private void createNewTrie(RuleApplicationData appData) { 554 Console.traceln(Level.FINER, "training trie with a maximum sequence length of " + 555 appData.getTrainedSequenceLength()); 556 557 appData.getStopWatch().start("training trie"); 558 559 // we prepared the task instances to refer to unique tasks, if they are treated 560 // as equal. Therefore, we just compare the identity of the tasks of the task 561 // instances 562 appData.setLastTrie(new TaskInstanceTrie(identityTaskHandlingStrategy)); 563 564 appData.getLastTrie().trainSessions 565 (appData.getSessions(), appData.getTrainedSequenceLength()); 566 567 appData.getStopWatch().stop("training trie"); 568 } 569 570 /** 571 * @param appData the rule application data combining all data used for applying this rule 572 */ 573 private void replaceSequencesOccurringMostOften(RuleApplicationData appData) { 574 appData.detectedAndReplacedTasks(false); 575 576 if ((appData.getLastFoundTasks().size() > 0) && 577 (appData.getLastFoundTasks().getOccurrenceCount() > 1)) 578 { 579 Console.traceln(Level.FINER, "replacing tasks occurrences"); 580 581 for (List<ITaskInstance> task : appData.getLastFoundTasks()) { 582 ISequence sequence = taskFactory.createNewSequence(); 583 584 Console.traceln(Level.FINEST, "replacing " + sequence.getId() + ": " + task); 585 586 List<ISequenceInstance> sequenceInstances = 587 replaceTaskOccurrences(task, appData.getSessions(), sequence); 588 589 harmonizeSequenceInstancesModel(sequence, sequenceInstances,task.size()); 590 appData.detectedAndReplacedTasks 591 (appData.detectedAndReplacedTasks() || (sequenceInstances.size() > 0)); 592 593 if (sequenceInstances.size() < appData.getLastFoundTasks().getOccurrenceCount()) { 594 Console.traceln(Level.FINE, sequence.getId() + ": replaced task only " + 595 sequenceInstances.size() + " times instead of expected " + 596 appData.getLastFoundTasks().getOccurrenceCount()); 597 } 598 } 599 } 600 601 } 602 603 /** 284 } 285 286 /** 287 * <p> 288 * searches for direct iterations of single tasks in all sequences and 289 * replaces them with {@link IIteration}s, respectively appropriate 290 * instances. Also all single occurrences of a task that is iterated 291 * somewhen are replaced with iterations to have again an efficient way for 292 * task comparisons. 293 * </p> 294 * 295 * @param appData 296 * the rule application data combining all data used for applying 297 * this rule 298 */ 299 private void detectAndReplaceIterations(RuleApplicationData appData) { 300 Console.traceln(Level.FINE, "detecting iterations"); 301 appData.getStopWatch().start("detecting iterations"); 302 303 List<IUserSession> sessions = appData.getSessions(); 304 305 Set<ITask> iteratedTasks = searchIteratedTasks(sessions); 306 307 if (iteratedTasks.size() > 0) { 308 replaceIterationsOf(iteratedTasks, sessions, appData); 309 } 310 311 appData.getStopWatch().stop("detecting iterations"); 312 Console.traceln(Level.INFO, "replaced " + iteratedTasks.size() 313 + " iterated tasks"); 314 } 315 316 /** 317 * <p> 318 * searches the provided sessions for task iterations. If a task is 319 * iterated, it is added to the returned set. 320 * </p> 321 * 322 * @param the 323 * session to search for iterations in 324 * 325 * @return a set of tasks being iterated somewhere 326 */ 327 private Set<ITask> searchIteratedTasks(List<IUserSession> sessions) { 328 Set<ITask> iteratedTasks = new HashSet<ITask>(); 329 for (IUserSession session : sessions) { 330 for (int i = 0; i < (session.size() - 1); i++) { 331 // we prepared the task instances to refer to unique tasks, if 332 // they are treated 333 // as equal. Therefore, we just compare the identity of the 334 // tasks of the task 335 // instances 336 if (session.get(i).getTask() == session.get(i + 1).getTask()) { 337 iteratedTasks.add(session.get(i).getTask()); 338 } 339 } 340 } 341 342 return iteratedTasks; 343 } 344 345 /** 346 * <p> 347 * replaces all occurrences of all tasks provided in the set with iterations 348 * </p> 349 * 350 * @param iteratedTasks 351 * the tasks to be replaced with iterations 352 * @param sessions 353 * the sessions in which the tasks are to be replaced 354 * @param appData 355 * the rule application data combining all data used for applying 356 * this rule 357 */ 358 private void replaceIterationsOf(Set<ITask> iteratedTasks, 359 List<IUserSession> sessions, RuleApplicationData appData) { 360 Map<ITask, IIteration> iterations = new HashMap<ITask, IIteration>(); 361 Map<IIteration, List<IIterationInstance>> iterationInstances = new HashMap<IIteration, List<IIterationInstance>>(); 362 363 for (ITask iteratedTask : iteratedTasks) { 364 IIteration iteration = taskFactory.createNewIteration(); 365 iterations.put(iteratedTask, iteration); 366 iterationInstances.put(iteration, 367 new LinkedList<IIterationInstance>()); 368 } 369 370 IIterationInstance iterationInstance; 371 372 for (IUserSession session : sessions) { 373 int index = 0; 374 iterationInstance = null; 375 376 while (index < session.size()) { 377 // we prepared the task instances to refer to unique tasks, if 378 // they are treated 379 // as equal. Therefore, we just compare the identity of the 380 // tasks of the task 381 // instances 382 ITask currentTask = session.get(index).getTask(); 383 IIteration iteration = iterations.get(currentTask); 384 if (iteration != null) { 385 if ((iterationInstance == null) 386 || (iterationInstance.getTask() != iteration)) { 387 iterationInstance = taskFactory 388 .createNewTaskInstance(iteration); 389 iterationInstances.get(iteration) 390 .add(iterationInstance); 391 taskBuilder.addTaskInstance(session, index, 392 iterationInstance); 393 index++; 394 } 395 396 taskBuilder.addChild(iterationInstance, session.get(index)); 397 taskBuilder.removeTaskInstance(session, index); 398 } else { 399 if (iterationInstance != null) { 400 iterationInstance = null; 401 } 402 index++; 403 } 404 } 405 } 406 407 for (Map.Entry<IIteration, List<IIterationInstance>> entry : iterationInstances 408 .entrySet()) { 409 harmonizeIterationInstancesModel(entry.getKey(), entry.getValue()); 410 } 411 } 412 413 /** 414 * <p> 415 * TODO clarify why this is done 416 * </p> 417 */ 418 private void harmonizeIterationInstancesModel(IIteration iteration, 419 List<IIterationInstance> iterationInstances) { 420 List<ITask> iteratedTaskVariants = new LinkedList<ITask>(); 421 TaskInstanceComparator comparator = preparationTaskHandlingStrategy 422 .getTaskComparator(); 423 424 // merge the lexically different variants of iterated task to a unique 425 // list 426 for (IIterationInstance iterationInstance : iterationInstances) { 427 for (ITaskInstance executionVariant : iterationInstance) { 428 ITask candidate = executionVariant.getTask(); 429 430 boolean found = false; 431 for (ITask taskVariant : iteratedTaskVariants) { 432 if (comparator.areLexicallyEqual(taskVariant, candidate)) { 433 taskBuilder.setTask(executionVariant, taskVariant); 434 found = true; 435 break; 436 } 437 } 438 439 if (!found) { 440 iteratedTaskVariants.add(candidate); 441 } 442 } 443 } 444 445 // if there are more than one lexically different variant of iterated 446 // tasks, adapt the 447 // iteration model to be a selection of different variants. In this case 448 // also adapt 449 // the generated iteration instances to correctly contain selection 450 // instances. If there 451 // is only one variant of an iterated task, simply set this as the 452 // marked task of the 453 // iteration. In this case, the instances can be preserved as is 454 if (iteratedTaskVariants.size() > 1) { 455 ISelection selection = taskFactory.createNewSelection(); 456 457 for (ITask variant : iteratedTaskVariants) { 458 taskBuilder.addChild(selection, variant); 459 } 460 461 taskBuilder.setMarkedTask(iteration, selection); 462 463 for (IIterationInstance instance : iterationInstances) { 464 for (int i = 0; i < instance.size(); i++) { 465 ISelectionInstance selectionInstance = taskFactory 466 .createNewTaskInstance(selection); 467 taskBuilder.setChild(selectionInstance, instance.get(i)); 468 taskBuilder.setTaskInstance(instance, i, selectionInstance); 469 } 470 } 471 } else { 472 taskBuilder.setMarkedTask(iteration, iteratedTaskVariants.get(0)); 473 } 474 } 475 476 /** 477 * TODO go on commenting 478 * 479 * @param appData 480 * the rule application data combining all data used for applying 481 * this rule 482 */ 483 private void detectAndReplaceTasks(RuleApplicationData appData) { 484 Console.traceln(Level.FINE, "detecting and replacing tasks"); 485 appData.getStopWatch().start("detecting tasks"); 486 487 getSequencesOccuringMostOften(appData); 488 489 appData.getStopWatch().stop("detecting tasks"); 490 appData.getStopWatch().start("replacing tasks"); 491 492 replaceSequencesOccurringMostOften(appData); 493 494 appData.getStopWatch().stop("replacing tasks"); 495 Console.traceln(Level.INFO, "detected and replaced " 496 + appData.getLastFoundTasks().size() + " tasks occuring " 497 + appData.getLastFoundTasks().getOccurrenceCount() + " times"); 498 } 499 500 /** 501 * @param appData 502 * the rule application data combining all data used for applying 503 * this rule 504 */ 505 private void getSequencesOccuringMostOften(RuleApplicationData appData) { 506 Console.traceln(Level.FINE, "determining most prominent tasks"); 507 508 Tasks tasks; 509 boolean createNewTrie = (appData.getLastTrie() == null) 510 || appData.detectedAndReplacedTasks(); // tree has changed 511 512 do { 513 if (createNewTrie) { 514 createNewTrie(appData); 515 } 516 517 MaxCountAndLongestTasksFinder finder = new MaxCountAndLongestTasksFinder(); 518 appData.getLastTrie().process(finder); 519 520 tasks = finder.getFoundTasks(); 521 522 createNewTrie = false; 523 524 for (List<ITaskInstance> task : tasks) { 525 if (task.size() >= appData.getTrainedSequenceLength()) { 526 // Trie must be recreated with a longer sequence length to 527 // be sure that 528 // the found sequences occurring most often are found in 529 // their whole length 530 appData.setTrainedSequenceLength(appData 531 .getTrainedSequenceLength() + 1); 532 createNewTrie = true; 533 break; 534 } 535 } 536 } while (createNewTrie); 537 538 // create a normal trie for comparison 539 /* 540 * System.out.println("creating test trie for comparison"); 541 * 542 * appData.getStopWatch().start("testtrie"); Trie<ITaskInstance> trie = 543 * new Trie<ITaskInstance>(identityTaskComparator); 544 * 545 * for (IUserSession session : appData.getSessions()) { 546 * trie.train(session.getExecutedTasks(), 547 * appData.getTrainedSequenceLength()); } 548 * 549 * appData.getStopWatch().stop("testtrie"); 550 * 551 * MaxCountAndLongestTasksFinder finder = new 552 * MaxCountAndLongestTasksFinder(); trie.process(finder); 553 * 554 * boolean allTasksEqual = finder.getFoundTasks().size() == 555 * tasks.size(); 556 * 557 * allTasksEqual &= finder.getFoundTasks().occurrenceCount == 558 * tasks.occurrenceCount; 559 * 560 * for (List<ITaskInstance> task1 : finder.getFoundTasks()) { boolean 561 * foundTask = false; for (List<ITaskInstance> task2 : tasks) { boolean 562 * tasksEqual = false; if (task1.size() == task2.size()) { tasksEqual = 563 * true; for (int i = 0; i < task1.size(); i++) { if 564 * (!identityTaskComparator.equals(task1.get(i).getTask(), 565 * task2.get(i).getTask())) { tasksEqual = false; } } } 566 * 567 * if (tasksEqual) { foundTask = true; break; } } 568 * 569 * if (!foundTask) { System.out.println("different is " + task1); 570 * allTasksEqual = false; break; } } 571 * 572 * if (!allTasksEqual) { System.out.println(finder.getFoundTasks()); 573 * System.out.println(tasks); 574 * 575 * throw new 576 * IllegalArgumentException("both tries calculated different subsequences" 577 * ); } 578 * 579 * /*TrieStatisticsDumper dumper = new TrieStatisticsDumper(); 580 * appData.getLastTrie().process(dumper); dumper.dumpCounters(); 581 */ 582 583 appData.setLastFoundTasks(tasks); 584 585 Console.traceln(Level.FINE, "found " 586 + appData.getLastFoundTasks().size() + " tasks " + "occurring " 587 + appData.getLastFoundTasks().getOccurrenceCount() + " times"); 588 } 589 590 /** 591 * @param appData 592 * the rule application data combining all data used for applying 593 * this rule 594 */ 595 private void createNewTrie(RuleApplicationData appData) { 596 Console.traceln( 597 Level.FINER, 598 "training trie with a maximum sequence length of " 599 + appData.getTrainedSequenceLength()); 600 601 appData.getStopWatch().start("training trie"); 602 603 // we prepared the task instances to refer to unique tasks, if they are 604 // treated 605 // as equal. Therefore, we just compare the identity of the tasks of the 606 // task 607 // instances 608 appData.setLastTrie(new TaskInstanceTrie(identityTaskHandlingStrategy)); 609 610 appData.getLastTrie().trainSessions(appData.getSessions(), 611 appData.getTrainedSequenceLength()); 612 613 appData.getStopWatch().stop("training trie"); 614 } 615 616 /** 617 * @param appData 618 * the rule application data combining all data used for applying 619 * this rule 620 */ 621 private void replaceSequencesOccurringMostOften(RuleApplicationData appData) { 622 appData.detectedAndReplacedTasks(false); 623 624 if ((appData.getLastFoundTasks().size() > 0) 625 && (appData.getLastFoundTasks().getOccurrenceCount() > 1)) { 626 Console.traceln(Level.FINER, "replacing tasks occurrences"); 627 628 for (List<ITaskInstance> task : appData.getLastFoundTasks()) { 629 ISequence sequence = taskFactory.createNewSequence(); 630 631 Console.traceln(Level.FINEST, "replacing " + sequence.getId() 632 + ": " + task); 633 634 List<ISequenceInstance> sequenceInstances = replaceTaskOccurrences( 635 task, appData.getSessions(), sequence); 636 637 harmonizeSequenceInstancesModel(sequence, sequenceInstances, 638 task.size()); 639 appData.detectedAndReplacedTasks(appData 640 .detectedAndReplacedTasks() 641 || (sequenceInstances.size() > 0)); 642 643 if (sequenceInstances.size() < appData.getLastFoundTasks() 644 .getOccurrenceCount()) { 645 Console.traceln(Level.FINE, 646 sequence.getId() 647 + ": replaced task only " 648 + sequenceInstances.size() 649 + " times instead of expected " 650 + appData.getLastFoundTasks() 651 .getOccurrenceCount()); 652 } 653 } 654 } 655 656 } 657 658 /** 604 659 * 605 660 */ 606 private void harmonizeSequenceInstancesModel(ISequence sequence, 607 List<ISequenceInstance> sequenceInstances, 608 int sequenceLength) 609 { 610 TaskInstanceComparator comparator = preparationTaskHandlingStrategy.getTaskComparator(); 611 612 // ensure for each subtask that lexically different variants are preserved 613 for (int subTaskIndex = 0; subTaskIndex < sequenceLength; subTaskIndex++) { 614 List<ITask> subTaskVariants = new LinkedList<ITask>(); 615 616 for (ISequenceInstance sequenceInstance : sequenceInstances) { 617 ITask candidate = sequenceInstance.get(subTaskIndex).getTask(); 618 619 boolean found = false; 620 621 for (int i = 0; i < subTaskVariants.size(); i++) { 622 if (comparator.areLexicallyEqual(subTaskVariants.get(i), candidate)) { 623 taskBuilder.setTask 624 (sequenceInstance.get(subTaskIndex), subTaskVariants.get(i)); 625 626 found = true; 627 break; 628 } 629 } 630 631 if (!found) { 632 subTaskVariants.add(candidate); 633 } 634 } 635 636 // if there are more than one lexically different variant of the sub task at 637 // the considered position, adapt the sequence model at that position to have 638 // a selection of the different variants. In this case also adapt the 639 // generated sequence instances to correctly contain selection instances. If 640 // there is only one variant of sub tasks at the given position, simply set 641 // this variant as the sub task of the selection. In this case, the instances 642 // can be preserved as is 643 if (subTaskVariants.size() > 1) { 644 ISelection selection = taskFactory.createNewSelection(); 645 646 for (ITask variant : subTaskVariants) { 647 taskBuilder.addChild(selection, variant); 648 } 649 650 taskBuilder.addChild(sequence, selection); 651 652 for (ISequenceInstance instance : sequenceInstances) { 653 ISelectionInstance selectionInstance = 654 taskFactory.createNewTaskInstance(selection); 655 taskBuilder.setChild(selectionInstance, instance.get(subTaskIndex)); 656 taskBuilder.setTaskInstance(instance, subTaskIndex, selectionInstance); 657 } 658 } 659 else if (subTaskVariants.size() == 1) { 660 taskBuilder.addChild(sequence, subTaskVariants.get(0)); 661 } 662 } 663 } 664 665 /** 666 * @param tree 667 */ 668 private List<ISequenceInstance> replaceTaskOccurrences(List<ITaskInstance> task, 669 List<IUserSession> sessions, 670 ISequence temporalTaskModel) 671 { 672 List<ISequenceInstance> sequenceInstances = new LinkedList<ISequenceInstance>(); 673 674 for (IUserSession session : sessions) { 675 int index = -1; 676 677 do { 678 index = getSubListIndex(session, task, ++index); 679 680 if (index > -1) { 681 sequenceInstances.add 682 (RuleUtils.createNewSubSequenceInRange 683 (session, index, index + task.size() - 1, temporalTaskModel, 684 taskFactory, taskBuilder)); 685 } 686 } 687 while (index > -1); 688 } 689 690 return sequenceInstances; 691 } 692 693 /** 694 * @param trie 695 * @param object 696 * @return 697 */ 698 private int getSubListIndex(ITaskInstanceList list, 699 List<ITaskInstance> subList, 700 int startIndex) 701 { 702 boolean matchFound; 703 int result = -1; 704 705 for (int i = startIndex; i <= list.size() - subList.size(); i++) { 706 matchFound = true; 707 708 for (int j = 0; j < subList.size(); j++) { 709 // we prepared the task instances to refer to unique tasks, if they are treated 710 // as equal. Therefore, we just compare the identity of the tasks of the task 711 // instances 712 if (list.get(i + j).getTask() != subList.get(j).getTask()) { 713 matchFound = false; 714 break; 715 } 716 } 717 718 if (matchFound) { 719 result = i; 720 break; 721 } 722 } 723 724 return result; 725 } 726 727 /** 728 * @param trie 729 * @param object 730 * @return 731 */ 732 private int getSubListIndex(List<ITaskInstance> list, 733 List<ITaskInstance> subList, 734 int startIndex) 735 { 736 boolean matchFound; 737 int result = -1; 738 739 for (int i = startIndex; i <= list.size() - subList.size(); i++) { 740 matchFound = true; 741 742 for (int j = 0; j < subList.size(); j++) { 743 // we prepared the task instances to refer to unique tasks, if they are treated 744 // as equal. Therefore, we just compare the identity of the tasks of the task 745 // instances 746 if (list.get(i + j) != subList.get(j)) { 747 matchFound = false; 748 break; 749 } 750 } 751 752 if (matchFound) { 753 result = i; 754 break; 755 } 756 } 757 758 return result; 759 } 760 761 /** 762 * @author Patrick Harms 763 */ 764 private class MaxCountAndLongestTasksFinder implements TrieProcessor<ITaskInstance> { 765 766 /** 661 private void harmonizeSequenceInstancesModel(ISequence sequence, 662 List<ISequenceInstance> sequenceInstances, int sequenceLength) { 663 TaskInstanceComparator comparator = preparationTaskHandlingStrategy 664 .getTaskComparator(); 665 666 // ensure for each subtask that lexically different variants are 667 // preserved 668 for (int subTaskIndex = 0; subTaskIndex < sequenceLength; subTaskIndex++) { 669 List<ITask> subTaskVariants = new LinkedList<ITask>(); 670 671 for (ISequenceInstance sequenceInstance : sequenceInstances) { 672 ITask candidate = sequenceInstance.get(subTaskIndex).getTask(); 673 674 boolean found = false; 675 676 for (int i = 0; i < subTaskVariants.size(); i++) { 677 if (comparator.areLexicallyEqual(subTaskVariants.get(i), 678 candidate)) { 679 taskBuilder.setTask(sequenceInstance.get(subTaskIndex), 680 subTaskVariants.get(i)); 681 682 found = true; 683 break; 684 } 685 } 686 687 if (!found) { 688 subTaskVariants.add(candidate); 689 } 690 } 691 692 // if there are more than one lexically different variant of the sub 693 // task at 694 // the considered position, adapt the sequence model at that 695 // position to have 696 // a selection of the different variants. In this case also adapt 697 // the 698 // generated sequence instances to correctly contain selection 699 // instances. If 700 // there is only one variant of sub tasks at the given position, 701 // simply set 702 // this variant as the sub task of the selection. In this case, the 703 // instances 704 // can be preserved as is 705 if (subTaskVariants.size() > 1) { 706 ISelection selection = taskFactory.createNewSelection(); 707 708 for (ITask variant : subTaskVariants) { 709 taskBuilder.addChild(selection, variant); 710 } 711 712 taskBuilder.addChild(sequence, selection); 713 714 for (ISequenceInstance instance : sequenceInstances) { 715 ISelectionInstance selectionInstance = taskFactory 716 .createNewTaskInstance(selection); 717 taskBuilder.setChild(selectionInstance, 718 instance.get(subTaskIndex)); 719 taskBuilder.setTaskInstance(instance, subTaskIndex, 720 selectionInstance); 721 } 722 } else if (subTaskVariants.size() == 1) { 723 taskBuilder.addChild(sequence, subTaskVariants.get(0)); 724 } 725 } 726 } 727 728 /** 729 * @param tree 730 */ 731 private List<ISequenceInstance> replaceTaskOccurrences( 732 List<ITaskInstance> task, List<IUserSession> sessions, 733 ISequence temporalTaskModel) { 734 List<ISequenceInstance> sequenceInstances = new LinkedList<ISequenceInstance>(); 735 736 for (IUserSession session : sessions) { 737 int index = -1; 738 739 do { 740 index = getSubListIndex(session, task, ++index); 741 742 if (index > -1) { 743 sequenceInstances.add(RuleUtils 744 .createNewSubSequenceInRange(session, index, index 745 + task.size() - 1, temporalTaskModel, 746 taskFactory, taskBuilder)); 747 } 748 } while (index > -1); 749 } 750 751 return sequenceInstances; 752 } 753 754 /** 755 * @param trie 756 * @param object 757 * @return 758 */ 759 private int getSubListIndex(ITaskInstanceList list, 760 List<ITaskInstance> subList, int startIndex) { 761 boolean matchFound; 762 int result = -1; 763 764 for (int i = startIndex; i <= list.size() - subList.size(); i++) { 765 matchFound = true; 766 767 for (int j = 0; j < subList.size(); j++) { 768 // we prepared the task instances to refer to unique tasks, if 769 // they are treated 770 // as equal. Therefore, we just compare the identity of the 771 // tasks of the task 772 // instances 773 if (list.get(i + j).getTask() != subList.get(j).getTask()) { 774 matchFound = false; 775 break; 776 } 777 } 778 779 if (matchFound) { 780 result = i; 781 break; 782 } 783 } 784 785 return result; 786 } 787 788 /** 789 * @param trie 790 * @param object 791 * @return 792 */ 793 private int getSubListIndex(List<ITaskInstance> list, 794 List<ITaskInstance> subList, int startIndex) { 795 boolean matchFound; 796 int result = -1; 797 798 for (int i = startIndex; i <= list.size() - subList.size(); i++) { 799 matchFound = true; 800 801 for (int j = 0; j < subList.size(); j++) { 802 // we prepared the task instances to refer to unique tasks, if 803 // they are treated 804 // as equal. Therefore, we just compare the identity of the 805 // tasks of the task 806 // instances 807 if (list.get(i + j) != subList.get(j)) { 808 matchFound = false; 809 break; 810 } 811 } 812 813 if (matchFound) { 814 result = i; 815 break; 816 } 817 } 818 819 return result; 820 } 821 822 /** 823 * @author Patrick Harms 824 */ 825 private class MaxCountAndLongestTasksFinder implements 826 TrieProcessor<ITaskInstance> { 827 828 /** 767 829 * 768 830 */ 769 770 771 831 private int currentCount; 832 833 /** 772 834 * 773 835 */ 774 775 776 836 private List<List<ITaskInstance>> foundTasks = new LinkedList<List<ITaskInstance>>(); 837 838 /** 777 839 * 778 840 */ 779 public MaxCountAndLongestTasksFinder() { 780 super(); 781 this.currentCount = 0; 782 } 783 784 /* (non-Javadoc) 785 * @see de.ugoe.cs.autoquest.usageprofiles.TrieProcessor#process(java.util.List, int) 786 */ 787 @Override 788 public TrieProcessor.Result process(List<ITaskInstance> foundTask, int count) { 789 if (foundTask.size() < 2) { 790 // ignore single tasks 791 return TrieProcessor.Result.CONTINUE; 792 } 793 794 if (count < 2) { 795 // ignore singular occurrences 796 return TrieProcessor.Result.SKIP_NODE; 797 } 798 799 if (this.currentCount > count) { 800 // ignore this children of this task, as they may have only smaller counts than 801 // the already found tasks 802 return TrieProcessor.Result.SKIP_NODE; 803 } 804 805 if (this.currentCount < count) { 806 // the provided task occurs more often that all tasks found so far. 807 // clear all found tasks and use the new count as the one searched for 808 foundTasks.clear(); 809 this.currentCount = count; 810 } 811 812 if (this.currentCount == count) { 813 // the task is of interest. Sort it into the other found tasks so that 814 // the longest come first 815 boolean added = false; 816 for (int i = 0; i < foundTasks.size(); i++) { 817 if (foundTasks.get(i).size() < foundTask.size()) { 818 // defensive copy 819 foundTasks.add(i, new LinkedList<ITaskInstance>(foundTask)); // defensive copy 820 added = true; 821 break; 822 } 823 } 824 825 if (!added) { 826 foundTasks.add(new LinkedList<ITaskInstance>(foundTask)); // defensive copy 827 } 828 } 829 830 return TrieProcessor.Result.CONTINUE; 831 } 832 833 /** 834 * @return 835 */ 836 public Tasks getFoundTasks() { 837 removePermutationsOfShorterTasks(); 838 return new Tasks(currentCount, foundTasks); 839 } 840 841 /** 841 public MaxCountAndLongestTasksFinder() { 842 super(); 843 this.currentCount = 0; 844 } 845 846 /* 847 * (non-Javadoc) 848 * 849 * @see 850 * de.ugoe.cs.autoquest.usageprofiles.TrieProcessor#process(java.util 851 * .List, int) 852 */ 853 @Override 854 public TrieProcessor.Result process(List<ITaskInstance> foundTask, 855 int count) { 856 if (foundTask.size() < 2) { 857 // ignore single tasks 858 return TrieProcessor.Result.CONTINUE; 859 } 860 861 if (count < 2) { 862 // ignore singular occurrences 863 return TrieProcessor.Result.SKIP_NODE; 864 } 865 866 if (this.currentCount > count) { 867 // ignore this children of this task, as they may have only 868 // smaller counts than 869 // the already found tasks 870 return TrieProcessor.Result.SKIP_NODE; 871 } 872 873 if (this.currentCount < count) { 874 // the provided task occurs more often that all tasks found so 875 // far. 876 // clear all found tasks and use the new count as the one 877 // searched for 878 foundTasks.clear(); 879 this.currentCount = count; 880 } 881 882 if (this.currentCount == count) { 883 // the task is of interest. Sort it into the other found tasks 884 // so that 885 // the longest come first 886 boolean added = false; 887 for (int i = 0; i < foundTasks.size(); i++) { 888 if (foundTasks.get(i).size() < foundTask.size()) { 889 // defensive copy 890 foundTasks.add(i, new LinkedList<ITaskInstance>( 891 foundTask)); // defensive copy 892 added = true; 893 break; 894 } 895 } 896 897 if (!added) { 898 foundTasks.add(new LinkedList<ITaskInstance>(foundTask)); // defensive 899 // copy 900 } 901 } 902 903 return TrieProcessor.Result.CONTINUE; 904 } 905 906 /** 907 * @return 908 */ 909 public Tasks getFoundTasks() { 910 removePermutationsOfShorterTasks(); 911 return new Tasks(currentCount, foundTasks); 912 } 913 914 /** 842 915 * 843 916 */ 844 private void removePermutationsOfShorterTasks() { 845 // now iterate the sorted list and for each task remove all other tasks that are shorter 846 // (i.e. come later in the sorted list) and that represent a subpart of the task 847 for (int i = 0; i < foundTasks.size(); i++) { 848 for (int j = i + 1; j < foundTasks.size();) { 849 if (foundTasks.get(j).size() < foundTasks.get(i).size()) { 850 // found a task that is a potential subtask. Check for this and remove the 851 // subtask if needed 852 List<ITaskInstance> longTask = foundTasks.get(i); 853 List<ITaskInstance> shortTask = foundTasks.get(j); 854 855 if (getSubListIndex(longTask, shortTask, 0) > -1) { 856 foundTasks.remove(j); 857 } 858 else { 859 j++; 860 } 861 } 862 else { 863 j++; 864 } 865 } 866 } 867 } 868 869 } 870 871 // /** 872 // * @author Patrick Harms 873 // */ 874 // private class TrieStatisticsDumper implements TrieProcessor<ITaskInstance> { 875 // 876 // /** 877 // * 878 // */ 879 // private Map<Integer, Integer> counters = new HashMap<Integer, Integer>(); 880 // 881 // /* (non-Javadoc) 882 // * @see de.ugoe.cs.autoquest.usageprofiles.TrieProcessor#process(java.util.List, int) 883 // */ 884 // @Override 885 // public TrieProcessor.Result process(List<ITaskInstance> subsequence, int count) { 886 // if (subsequence.size() == 1) { 887 // Integer value = counters.get(count); 888 // 889 // if (value == null) { 890 // value = 0; 891 // } 892 // 893 // counters.put(count, value + 1); 894 // 895 // return TrieProcessor.Result.CONTINUE; 896 // } 897 // else { 898 // // ignore singular occurrences 899 // return TrieProcessor.Result.SKIP_NODE; 900 // } 901 // } 902 // 903 // /** 904 // * @return 905 // */ 906 // public void dumpCounters() { 907 // int dumpedCounters = 0; 908 // 909 // int count = 1; 910 // while (dumpedCounters < counters.size()) { 911 // Integer value = counters.get(count++); 912 // if (value != null) { 913 // System.out.println(value + " symbols occurred " + count + " times"); 914 // dumpedCounters++; 915 // } 916 // } 917 // } 918 // 919 // } 920 921 /** 917 private void removePermutationsOfShorterTasks() { 918 // now iterate the sorted list and for each task remove all other 919 // tasks that are shorter 920 // (i.e. come later in the sorted list) and that represent a subpart 921 // of the task 922 for (int i = 0; i < foundTasks.size(); i++) { 923 for (int j = i + 1; j < foundTasks.size();) { 924 if (foundTasks.get(j).size() < foundTasks.get(i).size()) { 925 // found a task that is a potential subtask. Check for 926 // this and remove the 927 // subtask if needed 928 List<ITaskInstance> longTask = foundTasks.get(i); 929 List<ITaskInstance> shortTask = foundTasks.get(j); 930 931 if (getSubListIndex(longTask, shortTask, 0) > -1) { 932 foundTasks.remove(j); 933 } else { 934 j++; 935 } 936 } else { 937 j++; 938 } 939 } 940 } 941 } 942 943 } 944 945 // /** 946 // * @author Patrick Harms 947 // */ 948 // private class TrieStatisticsDumper implements 949 // TrieProcessor<ITaskInstance> { 950 // 951 // /** 952 // * 953 // */ 954 // private Map<Integer, Integer> counters = new HashMap<Integer, Integer>(); 955 // 956 // /* (non-Javadoc) 957 // * @see 958 // de.ugoe.cs.autoquest.usageprofiles.TrieProcessor#process(java.util.List, 959 // int) 960 // */ 961 // @Override 962 // public TrieProcessor.Result process(List<ITaskInstance> subsequence, int 963 // count) { 964 // if (subsequence.size() == 1) { 965 // Integer value = counters.get(count); 966 // 967 // if (value == null) { 968 // value = 0; 969 // } 970 // 971 // counters.put(count, value + 1); 972 // 973 // return TrieProcessor.Result.CONTINUE; 974 // } 975 // else { 976 // // ignore singular occurrences 977 // return TrieProcessor.Result.SKIP_NODE; 978 // } 979 // } 980 // 981 // /** 982 // * @return 983 // */ 984 // public void dumpCounters() { 985 // int dumpedCounters = 0; 986 // 987 // int count = 1; 988 // while (dumpedCounters < counters.size()) { 989 // Integer value = counters.get(count++); 990 // if (value != null) { 991 // System.out.println(value + " symbols occurred " + count + " times"); 992 // dumpedCounters++; 993 // } 994 // } 995 // } 996 // 997 // } 998 999 /** 922 1000 * 923 1001 */ 924 925 926 1002 private static class RuleApplicationData { 1003 1004 /** 927 1005 * 928 1006 */ 929 930 931 1007 private List<IUserSession> sessions; 1008 1009 /** 932 1010 * 933 1011 */ 934 935 936 937 938 939 940 941 1012 private TaskInstanceTrie lastTrie; 1013 1014 /** 1015 * default and minimum trained sequence length is 3 1016 */ 1017 private int trainedSequenceLength = 3; 1018 1019 /** 942 1020 * 943 1021 */ 944 945 946 1022 private Tasks lastFoundTasks = new Tasks(Integer.MAX_VALUE, null); 1023 1024 /** 947 1025 * 948 1026 */ 949 950 951 1027 private boolean detectedAndReplacedTasks; 1028 1029 /** 952 1030 * 953 1031 */ 954 955 956 1032 private RuleApplicationResult result = new RuleApplicationResult(); 1033 1034 /** 957 1035 * 958 1036 */ 959 960 961 1037 private StopWatch stopWatch = new StopWatch(); 1038 1039 /** 962 1040 * 963 1041 */ 964 private RuleApplicationData(List<IUserSession> sessions) { 965 this.sessions = sessions; 966 } 967 968 /** 969 * @return the tree 970 */ 971 private List<IUserSession> getSessions() { 972 return sessions; 973 } 974 975 /** 976 * @param lastTrie the lastTrie to set 977 */ 978 private void setLastTrie(TaskInstanceTrie lastTrie) { 979 this.lastTrie = lastTrie; 980 } 981 982 /** 983 * @return the lastTrie 984 */ 985 private TaskInstanceTrie getLastTrie() { 986 return lastTrie; 987 } 988 989 /** 990 * @param trainedSequenceLength the trainedSequenceLength to set 991 */ 992 private void setTrainedSequenceLength(int trainedSequenceLength) { 993 this.trainedSequenceLength = trainedSequenceLength; 994 } 995 996 /** 997 * @return the trainedSequenceLength 998 */ 999 private int getTrainedSequenceLength() { 1000 return trainedSequenceLength; 1001 } 1002 1003 /** 1004 * @param lastFoundSequences the lastFoundSequences to set 1005 */ 1006 private void setLastFoundTasks(Tasks lastFoundSequences) { 1007 this.lastFoundTasks = lastFoundSequences; 1008 } 1009 1010 /** 1011 * @return the lastFoundSequences 1012 */ 1013 private Tasks getLastFoundTasks() { 1014 return lastFoundTasks; 1015 } 1016 1017 /** 1042 private RuleApplicationData(List<IUserSession> sessions) { 1043 this.sessions = sessions; 1044 } 1045 1046 /** 1047 * @return the tree 1048 */ 1049 private List<IUserSession> getSessions() { 1050 return sessions; 1051 } 1052 1053 /** 1054 * @param lastTrie 1055 * the lastTrie to set 1056 */ 1057 private void setLastTrie(TaskInstanceTrie lastTrie) { 1058 this.lastTrie = lastTrie; 1059 } 1060 1061 /** 1062 * @return the lastTrie 1063 */ 1064 private TaskInstanceTrie getLastTrie() { 1065 return lastTrie; 1066 } 1067 1068 /** 1069 * @param trainedSequenceLength 1070 * the trainedSequenceLength to set 1071 */ 1072 private void setTrainedSequenceLength(int trainedSequenceLength) { 1073 this.trainedSequenceLength = trainedSequenceLength; 1074 } 1075 1076 /** 1077 * @return the trainedSequenceLength 1078 */ 1079 private int getTrainedSequenceLength() { 1080 return trainedSequenceLength; 1081 } 1082 1083 /** 1084 * @param lastFoundSequences 1085 * the lastFoundSequences to set 1086 */ 1087 private void setLastFoundTasks(Tasks lastFoundSequences) { 1088 this.lastFoundTasks = lastFoundSequences; 1089 } 1090 1091 /** 1092 * @return the lastFoundSequences 1093 */ 1094 private Tasks getLastFoundTasks() { 1095 return lastFoundTasks; 1096 } 1097 1098 /** 1018 1099 * 1019 1100 */ 1020 1021 1022 1023 1024 1101 private void detectedAndReplacedTasks(boolean detectedAndReplacedTasks) { 1102 this.detectedAndReplacedTasks = detectedAndReplacedTasks; 1103 } 1104 1105 /** 1025 1106 * 1026 1107 */ 1027 private boolean detectedAndReplacedTasks() { 1028 return detectedAndReplacedTasks; 1029 } 1030 1031 /** 1032 * @return the result 1033 */ 1034 private RuleApplicationResult getResult() { 1035 return result; 1036 } 1037 1038 /** 1039 * @return the stopWatch 1040 */ 1041 private StopWatch getStopWatch() { 1042 return stopWatch; 1043 } 1044 1045 } 1046 1047 1048 /** 1049 * @author Patrick Harms 1050 */ 1051 private static class Tasks implements Iterable<List<ITaskInstance>> { 1052 1053 /** 1108 private boolean detectedAndReplacedTasks() { 1109 return detectedAndReplacedTasks; 1110 } 1111 1112 /** 1113 * @return the result 1114 */ 1115 private RuleApplicationResult getResult() { 1116 return result; 1117 } 1118 1119 /** 1120 * @return the stopWatch 1121 */ 1122 private StopWatch getStopWatch() { 1123 return stopWatch; 1124 } 1125 1126 } 1127 1128 /** 1129 * @author Patrick Harms 1130 */ 1131 private static class Tasks implements Iterable<List<ITaskInstance>> { 1132 1133 /** 1054 1134 * 1055 1135 */ 1056 1057 1058 1136 private int occurrenceCount; 1137 1138 /** 1059 1139 * 1060 1140 */ 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1141 private List<List<ITaskInstance>> sequences; 1142 1143 /** 1144 * @param occurrenceCount 1145 * @param sequences 1146 */ 1147 private Tasks(int occurrenceCount, List<List<ITaskInstance>> sequences) { 1148 super(); 1149 this.occurrenceCount = occurrenceCount; 1150 this.sequences = sequences; 1151 } 1152 1153 /** 1154 * @return 1155 */ 1156 private int getOccurrenceCount() { 1157 return occurrenceCount; 1158 } 1159 1160 /** 1161 * @return 1162 */ 1163 private int size() { 1164 return this.sequences.size(); 1165 } 1166 1167 /** 1088 1168 * 1089 1169 */ 1090 1170 1091 /* (non-Javadoc) 1092 * @see java.lang.Iterable#iterator() 1093 */ 1094 @Override 1095 public Iterator<List<ITaskInstance>> iterator() { 1096 return this.sequences.iterator(); 1097 } 1098 1099 /* (non-Javadoc) 1100 * @see java.lang.Object#toString() 1101 */ 1102 @Override 1103 public String toString() { 1104 StringBuffer result = new StringBuffer(); 1105 result.append(this.occurrenceCount); 1106 result.append(" occurrences:\n"); 1107 1108 for (List<ITaskInstance> task : sequences) { 1109 result.append(task); 1110 result.append("\n"); 1111 } 1112 1113 return result.toString(); 1114 } 1115 1116 } 1117 1118 // methods for internal testing 1119 // private void checkMatchingOfSessions(List<List<Event>> flattenedSessions, 1120 // List<IUserSession> sessions, 1121 // String when) 1122 // { 1123 // List<List<Event>> currentFlattenedSessions = flattenSessions(sessions); 1124 // if (flattenedSessions.size() != currentFlattenedSessions.size()) { 1125 // System.out.println("################## number of sessions changed after " + when); 1126 // } 1127 // else { 1128 // for (int i = 0; i < flattenedSessions.size(); i++) { 1129 // List<Event> expected = flattenedSessions.get(i); 1130 // List<Event> current = currentFlattenedSessions.get(i); 1131 // 1132 // if (expected.size() != current.size()) { 1133 // System.out.println 1134 // ("################## length of session " + i + " changed after " + when); 1135 // } 1136 // else { 1137 // for (int j = 0; j < expected.size(); j++) { 1138 // if (!expected.get(j).equals(current.get(j))) { 1139 // System.out.println("################## event " + j + " of session " + 1140 // i + " changed after " + when); 1141 // } 1142 // } 1143 // } 1144 // } 1145 // } 1146 // } 1147 // 1148 // private List<List<Event>> flattenSessions(List<IUserSession> sessions) { 1149 // List<List<Event>> flattenedSessions = new ArrayList<List<Event>>(); 1150 // for (IUserSession session : sessions) { 1151 // List<Event> flattenedUserSession = new ArrayList<Event>(); 1152 // flatten(session, flattenedUserSession); 1153 // flattenedSessions.add(flattenedUserSession); 1154 // } 1155 // 1156 // return flattenedSessions; 1157 // } 1158 // 1159 // private void flatten(IUserSession iUserSession, List<Event> flattenedUserSession) { 1160 // for (ITaskInstance instance : iUserSession) { 1161 // flatten(instance, flattenedUserSession); 1162 // } 1163 // } 1164 // 1165 // private void flatten(ITaskInstance instance, List<Event> flattenedUserSession) { 1166 // if (instance instanceof ITaskInstanceList) { 1167 // for (ITaskInstance child : (ITaskInstanceList) instance) { 1168 // flatten(child, flattenedUserSession); 1169 // } 1170 // } 1171 // else if (instance instanceof ISelectionInstance) { 1172 // flatten(((ISelectionInstance) instance).getChild(), flattenedUserSession); 1173 // } 1174 // else if (instance instanceof IOptionalInstance) { 1175 // flatten(((IOptionalInstance) instance).getChild(), flattenedUserSession); 1176 // } 1177 // else if (instance instanceof IEventTaskInstance) { 1178 // flattenedUserSession.add(((IEventTaskInstance) instance).getEvent()); 1179 // } 1180 // } 1171 /* 1172 * (non-Javadoc) 1173 * 1174 * @see java.lang.Iterable#iterator() 1175 */ 1176 @Override 1177 public Iterator<List<ITaskInstance>> iterator() { 1178 return this.sequences.iterator(); 1179 } 1180 1181 /* 1182 * (non-Javadoc) 1183 * 1184 * @see java.lang.Object#toString() 1185 */ 1186 @Override 1187 public String toString() { 1188 StringBuffer result = new StringBuffer(); 1189 result.append(this.occurrenceCount); 1190 result.append(" occurrences:\n"); 1191 1192 for (List<ITaskInstance> task : sequences) { 1193 result.append(task); 1194 result.append("\n"); 1195 } 1196 1197 return result.toString(); 1198 } 1199 1200 } 1201 1202 // methods for internal testing 1203 // private void checkMatchingOfSessions(List<List<Event>> flattenedSessions, 1204 // List<IUserSession> sessions, 1205 // String when) 1206 // { 1207 // List<List<Event>> currentFlattenedSessions = flattenSessions(sessions); 1208 // if (flattenedSessions.size() != currentFlattenedSessions.size()) { 1209 // System.out.println("################## number of sessions changed after " 1210 // + when); 1211 // } 1212 // else { 1213 // for (int i = 0; i < flattenedSessions.size(); i++) { 1214 // List<Event> expected = flattenedSessions.get(i); 1215 // List<Event> current = currentFlattenedSessions.get(i); 1216 // 1217 // if (expected.size() != current.size()) { 1218 // System.out.println 1219 // ("################## length of session " + i + " changed after " + when); 1220 // } 1221 // else { 1222 // for (int j = 0; j < expected.size(); j++) { 1223 // if (!expected.get(j).equals(current.get(j))) { 1224 // System.out.println("################## event " + j + " of session " + 1225 // i + " changed after " + when); 1226 // } 1227 // } 1228 // } 1229 // } 1230 // } 1231 // } 1232 // 1233 // private List<List<Event>> flattenSessions(List<IUserSession> sessions) { 1234 // List<List<Event>> flattenedSessions = new ArrayList<List<Event>>(); 1235 // for (IUserSession session : sessions) { 1236 // List<Event> flattenedUserSession = new ArrayList<Event>(); 1237 // flatten(session, flattenedUserSession); 1238 // flattenedSessions.add(flattenedUserSession); 1239 // } 1240 // 1241 // return flattenedSessions; 1242 // } 1243 // 1244 // private void flatten(IUserSession iUserSession, List<Event> 1245 // flattenedUserSession) { 1246 // for (ITaskInstance instance : iUserSession) { 1247 // flatten(instance, flattenedUserSession); 1248 // } 1249 // } 1250 // 1251 // private void flatten(ITaskInstance instance, List<Event> 1252 // flattenedUserSession) { 1253 // if (instance instanceof ITaskInstanceList) { 1254 // for (ITaskInstance child : (ITaskInstanceList) instance) { 1255 // flatten(child, flattenedUserSession); 1256 // } 1257 // } 1258 // else if (instance instanceof ISelectionInstance) { 1259 // flatten(((ISelectionInstance) instance).getChild(), 1260 // flattenedUserSession); 1261 // } 1262 // else if (instance instanceof IOptionalInstance) { 1263 // flatten(((IOptionalInstance) instance).getChild(), flattenedUserSession); 1264 // } 1265 // else if (instance instanceof IEventTaskInstance) { 1266 // flattenedUserSession.add(((IEventTaskInstance) instance).getEvent()); 1267 // } 1268 // } 1181 1269 1182 1270 }
Note: See TracChangeset
for help on using the changeset viewer.