Changeset 1734 for branches/autoquest-core-tasktrees-alignment/src/main/java/de/ugoe/cs/autoquest/tasktrees/temporalrelation/SequenceForTaskDetectionRuleAlignment.java
- Timestamp:
- 09/05/14 20:20:29 (10 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/autoquest-core-tasktrees-alignment/src/main/java/de/ugoe/cs/autoquest/tasktrees/temporalrelation/SequenceForTaskDetectionRuleAlignment.java
r1733 r1734 15 15 package de.ugoe.cs.autoquest.tasktrees.temporalrelation; 16 16 17 import java.io.FileInputStream;18 import java.io.FileOutputStream;19 import java.io.IOException;20 import java.io.ObjectInputStream;21 import java.io.ObjectOutputStream;22 17 import java.io.Serializable; 23 18 import java.util.ArrayList; … … 36 31 import java.util.logging.Level; 37 32 38 import de.ugoe.cs.autoquest.CommandHelpers;39 33 import de.ugoe.cs.autoquest.tasktrees.alignment.algorithms.AlignmentAlgorithm; 40 34 import de.ugoe.cs.autoquest.tasktrees.alignment.algorithms.AlignmentAlgorithmFactory; … … 59 53 import de.ugoe.cs.util.StopWatch; 60 54 import de.ugoe.cs.util.console.Console; 61 import de.ugoe.cs.util.console.GlobalDataContainer; 55 62 56 63 57 /** … … 66 60 * of recorded user sessions. For this, it first harmonizes all tasks. This 67 61 * eases later comparison. Then it searches the sessions for iterations and 68 * replaces them accordingly. Then it searches for sub sequences being the69 * longest and occurring most often.For each found sub sequence, it replaces62 * replaces them accordingly. Then it searches for sub sequences using alignment algorithms 63 * For each found sub sequence, it replaces 70 64 * the occurrences by creating appropriate {@link ISequence}s. Afterwards, again 71 65 * searches for iterations and then again for sub sequences until no more … … 75 69 * 76 70 * 77 * @author Patrick Harms71 * @author Ralph Krimmel 78 72 */ 79 73 public class SequenceForTaskDetectionRuleAlignment implements ISessionScopeRule { 80 74 75 76 /** 77 * The Class RuleApplicationData. 78 */ 79 private static class RuleApplicationData implements Serializable { 80 81 /** The Constant serialVersionUID. */ 82 private static final long serialVersionUID = -7559657686755522960L; 83 84 /** The number2task HashMap. Since we align the tasks just by their integer id, 85 * we need this to convert them back to Tasks again*/ 86 private final HashMap<Integer, ITask> number2task; 87 88 89 /** The unique tasks, keeps track about all unique tasks 90 * TODO: We Actually just need number2task here, this structure can be 91 * removed in the future.*/ 92 private final HashSet<ITask> uniqueTasks; 93 94 /** The substitution matrix used by the alignment algorithm to be able to compare 95 * distances of tasks */ 96 private final ObjectDistanceSubstitionMatrix submat; 97 98 /** HashMap for keeping track in which sequence which replacement has been performed. 99 * Neccessary for updating the indices of other occurrences accordingly */ 100 public HashMap<Integer, List<MatchOccurence>> replacedOccurences; 101 102 /** The list of all found matches */ 103 public LinkedList<Match> matchseqs; 104 105 /** The generated NumberSequences. 106 * This is the integer representation of the user sessions */ 107 private ArrayList<NumberSequence> numberseqs; 108 109 /** The list of newly created tasks (of one iteration). */ 110 private final LinkedList<ITask> newTasks; 111 112 /** The user sessions containing all EventTasks/Instances */ 113 private final List<IUserSession> sessions; 114 115 /** True if we replaced something in the user sessions in one iteration. */ 116 private boolean detectedAndReplacedTasks; 117 118 /** The result we give autoquest back */ 119 private final RuleApplicationResult result; 120 121 /** Stop Watch to measure performance */ 122 private final StopWatch stopWatch; 123 124 /** 125 * Instantiates a new rule application data. 126 * 127 * @param sessions The user sessions 128 */ 129 private RuleApplicationData(List<IUserSession> sessions) { 130 this.sessions = sessions; 131 numberseqs = new ArrayList<NumberSequence>(); 132 uniqueTasks = new HashSet<ITask>(); 133 number2task = new HashMap<Integer, ITask>(); 134 stopWatch = new StopWatch(); 135 result = new RuleApplicationResult(); 136 submat = new ObjectDistanceSubstitionMatrix(6, -3, false); 137 newTasks = new LinkedList<ITask>(); 138 this.detectedAndReplacedTasks = true; 139 } 140 141 /** 142 * Detected and replaced tasks. 143 * 144 * @return true, if successful 145 */ 146 private boolean detectedAndReplacedTasks() { 147 return detectedAndReplacedTasks; 148 } 149 150 /** 151 * Gets the matchseqs. 152 * 153 * @return the matchseqs 154 */ 155 public LinkedList<Match> getMatchseqs() { 156 return matchseqs; 157 } 158 159 /** 160 * Gets the new tasks. 161 * 162 * @return the new tasks 163 */ 164 public LinkedList<ITask> getNewTasks() { 165 return newTasks; 166 } 167 168 /** 169 * Gets the number2task. 170 * 171 * @return the number2task HashMap 172 */ 173 private HashMap<Integer, ITask> getNumber2Task() { 174 return number2task; 175 } 176 177 /** 178 * Gets the number sequences. 179 * 180 * @return the number sequences 181 */ 182 private ArrayList<NumberSequence> getNumberSequences() { 183 return numberseqs; 184 } 185 186 /** 187 * Gets the replaced occurrences. 188 * 189 * @return the replaced occurences 190 */ 191 public HashMap<Integer, List<MatchOccurence>> getReplacedOccurrences() { 192 return replacedOccurences; 193 } 194 195 /** 196 * Gets the result. 197 * 198 * @return the result 199 */ 200 private RuleApplicationResult getResult() { 201 return result; 202 } 203 204 /** 205 * Gets the sessions. 206 * 207 * @return the UserSessions as List. 208 */ 209 private List<IUserSession> getSessions() { 210 return sessions; 211 } 212 213 /** 214 * Gets the stop watch. 215 * 216 * @return the stopWatch 217 */ 218 private StopWatch getStopWatch() { 219 return stopWatch; 220 } 221 222 /** 223 * Gets the submat. 224 * 225 * @return the submat 226 */ 227 private ObjectDistanceSubstitionMatrix getSubmat() { 228 return submat; 229 } 230 231 /** 232 * Gets the unique tasks. 233 * 234 * @return the unique tasks 235 */ 236 private HashSet<ITask> getUniqueTasks() { 237 return uniqueTasks; 238 } 239 240 /** 241 * New task created. 242 * 243 * @param task the task 244 */ 245 private void newTaskCreated(ITask task) { 246 number2task.put(task.getId(), task); 247 newTasks.add(task); 248 } 249 250 /** 251 * Reset newly created tasks. 252 */ 253 synchronized private void resetNewlyCreatedTasks() { 254 uniqueTasks.addAll(newTasks); 255 newTasks.clear(); 256 } 257 258 /** 259 * Sets the number sequences. 260 * 261 * @param numberseqs the new number sequences 262 */ 263 private void setNumberSequences(ArrayList<NumberSequence> numberseqs) { 264 this.numberseqs = numberseqs; 265 } 266 267 /** 268 * Sets the replaced occurences. 269 * 270 * @param replacedOccurences the replaced occurences 271 */ 272 public void setReplacedOccurences( 273 HashMap<Integer, List<MatchOccurence>> replacedOccurences) { 274 this.replacedOccurences = replacedOccurences; 275 } 276 277 /** 278 * Update substitution matrix. 279 */ 280 private void updateSubstitutionMatrix() { 281 submat.update(getNewTasks()); 282 resetNewlyCreatedTasks(); 283 } 284 285 } 286 287 /** The n threads. */ 288 public static int nThreads = Runtime.getRuntime().availableProcessors() - 1; 289 290 /** The iteration. */ 291 private int iteration = 0; 292 293 /** <p> the task factory to be used for creating substructures for the temporal relationships identified during rul application </p>. */ 294 private final ITaskFactory taskFactory; 295 296 /** <p> the task builder to be used for creating substructures for the temporal relationships identified during rule application </p>. */ 297 private final ITaskBuilder taskBuilder; 298 299 /** 300 * <p> 301 * the task handling strategy to be used for comparing tasks for 302 * preparation, i.e., before the tasks are harmonized 303 * </p> 304 */ 305 private final TaskHandlingStrategy preparationTaskHandlingStrategy; 306 307 /** 308 * <p> 309 * instantiates the rule and initializes it with a task equality to be 310 * considered when comparing tasks as well as a task factory and builder to 311 * be used for creating task structures. 312 * </p> 313 * 314 * @param minimalTaskEquality 315 * the task equality to be considered when comparing tasks 316 * @param taskFactory 317 * the task factory to be used for creating substructures 318 * @param taskBuilder 319 * the task builder to be used for creating substructures 320 */ 321 322 SequenceForTaskDetectionRuleAlignment(TaskEquality minimalTaskEquality, 323 ITaskFactory taskFactory, ITaskBuilder taskBuilder) { 324 this.taskFactory = taskFactory; 325 this.taskBuilder = taskBuilder; 326 327 this.preparationTaskHandlingStrategy = new TaskHandlingStrategy( 328 minimalTaskEquality); 329 } 330 331 /* 332 * (non-Javadoc) 333 * 334 * @see 335 * de.ugoe.cs.autoquest.tasktrees.temporalrelation.ISessionScopeRule#apply 336 * (java.util.List) 337 */ 338 @Override 339 public RuleApplicationResult apply(List<IUserSession> sessions) { 340 final RuleApplicationData appData = new RuleApplicationData(sessions); 341 342 harmonizeEventTaskInstancesModel(appData); 343 344 345 Console.traceln(Level.INFO, "generating substitution matrix from " 346 + appData.getUniqueTasks().size() + " unique tasks"); 347 appData.getStopWatch().start("substitution matrix"); 348 appData.getSubmat().generate(appData.getUniqueTasks()); 349 appData.getStopWatch().stop("substitution matrix"); 350 351 Console.traceln(Level.INFO, "Starting main loop"); 352 do { 353 Console.traceln(Level.INFO, "Iteration Number: " + iteration); 354 iteration++; 355 appData.detectedAndReplacedTasks = false; 356 appData.getStopWatch().start("whole loop"); 357 detectAndReplaceIterations(appData); 358 appData.getStopWatch().start("task replacement"); 359 appData.updateSubstitutionMatrix(); 360 detectAndReplaceTasks(appData); // 361 appData.getStopWatch().stop("task replacement"); 362 appData.getStopWatch().stop("whole loop"); 363 appData.getStopWatch().dumpStatistics(System.out); 364 appData.getStopWatch().reset(); 365 366 } while (appData.detectedAndReplacedTasks()); 367 368 Console.println("created " 369 + appData.getResult().getNewlyCreatedTasks().size() 370 + " new tasks and " 371 + appData.getResult().getNewlyCreatedTaskInstances().size() 372 + " appropriate instances\n"); 373 374 if ((appData.getResult().getNewlyCreatedTasks().size() > 0) 375 || (appData.getResult().getNewlyCreatedTaskInstances().size() > 0)) { 376 appData.getResult().setRuleApplicationStatus( 377 RuleApplicationStatus.FINISHED); 378 } 379 380 return appData.getResult(); 381 } 382 383 /** 384 * Creates the number sequences. 385 * 386 * @param appData the app data 387 * @return the array list 388 */ 389 private ArrayList<NumberSequence> createNumberSequences( 390 RuleApplicationData appData) { 391 final ArrayList<NumberSequence> result = new ArrayList<NumberSequence>(); 392 for (int i = 0; i < appData.getSessions().size(); i++) { 393 final IUserSession session = appData.getSessions().get(i); 394 final NumberSequence templist = new NumberSequence(session.size()); 395 for (int j = 0; j < session.size(); j++) { 396 final ITaskInstance taskInstance = session.get(j); 397 templist.getSequence()[j] = taskInstance.getTask().getId(); 398 } 399 // Each NumberSequence is identified by its id, beginning to count 400 // at zero 401 templist.setId(i); 402 result.add(templist); 403 } 404 return result; 405 } 406 407 /** 408 * <p> 409 * searches for direct iterations of single tasks in all sequences and 410 * replaces them with {@link IIteration}s, respectively appropriate 411 * instances. Also all single occurrences of a task that is iterated 412 * somewhen are replaced with iterations to have again an efficient way for 413 * task comparisons. 414 * </p> 415 * 416 * @param appData 417 * the rule application data combining all data used for applying 418 * this rule 419 */ 420 private void detectAndReplaceIterations(RuleApplicationData appData) { 421 Console.traceln(Level.FINE, "detecting iterations"); 422 appData.getStopWatch().start("detecting iterations"); 423 424 final List<IUserSession> sessions = appData.getSessions(); 425 426 final Set<ITask> iteratedTasks = searchIteratedTasks(sessions); 427 428 if (iteratedTasks.size() > 0) { 429 replaceIterationsOf(iteratedTasks, sessions, appData); 430 } 431 432 appData.getStopWatch().stop("detecting iterations"); 433 Console.traceln(Level.INFO, "replaced " + iteratedTasks.size() 434 + " iterated tasks"); 435 } 436 437 /** 438 * Detect and replace tasks. 439 * 440 * @param appData the rule application data combining all data used for applying 441 * this rule 442 */ 443 private void detectAndReplaceTasks(RuleApplicationData appData) { 444 Console.traceln(Level.FINE, "detecting and replacing tasks"); 445 appData.getStopWatch().start("detecting tasks"); 446 447 // Create NumberSequences 448 appData.setNumberSequences(this.createNumberSequences(appData)); 449 450 // Generate pairwise alignments 451 // appData.setMatchseqs(generatePairwiseAlignments(appData)); 452 generatePairwiseAlignments(appData); 453 454 // Searching each match in all other sessions, counting its occurences 455 searchMatchesInAllSessions(appData); 456 457 // Sort results to get the most occurring results 458 Console.traceln(Level.INFO, "sorting " + appData.getMatchseqs().size() 459 + " results"); 460 final Comparator<Match> comparator = new Comparator<Match>() { 461 @Override 462 public int compare(Match m1, Match m2) { 463 return m2.occurenceCount() - m1.occurenceCount(); 464 465 } 466 }; 467 Collections.sort(appData.getMatchseqs(), comparator); 468 appData.getStopWatch().stop("detecting tasks"); 469 470 // Replace matches in the sessions 471 Console.traceln(Level.INFO, "Replacing matches in sessions"); 472 appData.getStopWatch().start("replacing tasks"); 473 replaceMatches(appData); 474 appData.getStopWatch().stop("replacing tasks"); 475 } 476 477 478 /** 479 * Generate pairwise alignments. 480 * 481 * @param appData the app data 482 */ 483 private void generatePairwiseAlignments(RuleApplicationData appData) { 484 final int numberSeqSize = appData.getNumberSequences().size(); 485 appData.matchseqs = new LinkedList<Match>(); 486 Console.traceln(Level.INFO, "generating pairwise alignments from " 487 + numberSeqSize + " sessions with " + nThreads + " threads"); 488 489 int newThreads = nThreads; 490 if (numberSeqSize < nThreads) { 491 newThreads = numberSeqSize; 492 } 493 494 final ExecutorService executor = Executors 495 .newFixedThreadPool(newThreads); 496 final int interval = numberSeqSize / newThreads; 497 int rest = numberSeqSize % newThreads; 498 499 for (int i = 0; i < (numberSeqSize - interval); i += interval) { 500 int offset = 0; 501 if (rest != 0) { 502 offset = 1; 503 rest--; 504 } 505 final int from = i; 506 final int to = i + interval + offset; 507 System.out.println("Creating thread for sessions " + from 508 + " till " + to); 509 final ParallelPairwiseAligner aligner = new ParallelPairwiseAligner( 510 appData, from, to); 511 executor.execute(aligner); 512 } 513 executor.shutdown(); 514 try { 515 executor.awaitTermination(2, TimeUnit.HOURS); 516 } catch (final InterruptedException e) { 517 // TODO Auto-generated catch block 518 e.printStackTrace(); 519 } 520 } 521 522 /** 523 * <p> 524 * harmonizes the event task instances by unifying tasks. This is done, as 525 * initially the event tasks being equal with respect to the considered task 526 * equality are distinct objects. The comparison of these distinct objects 527 * is more time consuming than comparing the object references. 528 * </p> 529 * 530 * @param appData 531 * the rule application data combining all data used for applying 532 * this rule 533 * @return Returns the unique tasks symbol map 534 */ 535 private void harmonizeEventTaskInstancesModel(RuleApplicationData appData) { 536 Console.traceln(Level.INFO, 537 "harmonizing task model of event task instances"); 538 appData.getStopWatch().start("harmonizing event tasks"); 539 final SymbolMap<ITaskInstance, ITask> uniqueTasks = preparationTaskHandlingStrategy 540 .createSymbolMap(); 541 542 final TaskInstanceComparator comparator = preparationTaskHandlingStrategy 543 .getTaskComparator(); 544 545 int unifiedTasks = 0; 546 ITask task; 547 final List<IUserSession> sessions = appData.getSessions(); 548 for (int j = 0; j < sessions.size(); j++) { 549 final IUserSession session = sessions.get(j); 550 551 for (int i = 0; i < session.size(); i++) { 552 final ITaskInstance taskInstance = session.get(i); 553 task = uniqueTasks.getValue(taskInstance); 554 555 if (task == null) { 556 uniqueTasks.addSymbol(taskInstance, taskInstance.getTask()); 557 appData.getUniqueTasks().add(taskInstance.getTask()); 558 appData.getNumber2Task().put( 559 taskInstance.getTask().getId(), 560 taskInstance.getTask()); 561 } else { 562 taskBuilder.setTask(taskInstance, task); 563 unifiedTasks++; 564 } 565 } 566 comparator.clearBuffers(); 567 } 568 569 appData.getStopWatch().stop("harmonizing event tasks"); 570 Console.traceln(Level.INFO, "harmonized " + unifiedTasks 571 + " task occurrences (still " + appData.getUniqueTasks().size() 572 + " different tasks)"); 573 574 appData.getStopWatch().dumpStatistics(System.out); 575 appData.getStopWatch().reset(); 576 } 577 578 /** 579 * <p> 580 * TODO clarify why this is done 581 * </p>. 582 * 583 * @param iteration the iteration 584 * @param iterationInstances the iteration instances 585 */ 586 private void harmonizeIterationInstancesModel(IIteration iteration, 587 List<IIterationInstance> iterationInstances) { 588 final List<ITask> iteratedTaskVariants = new LinkedList<ITask>(); 589 final TaskInstanceComparator comparator = preparationTaskHandlingStrategy 590 .getTaskComparator(); 591 592 // merge the lexically different variants of iterated task to a unique 593 // list 594 for (final IIterationInstance iterationInstance : iterationInstances) { 595 for (final ITaskInstance executionVariant : iterationInstance) { 596 final ITask candidate = executionVariant.getTask(); 597 598 boolean found = false; 599 for (final ITask taskVariant : iteratedTaskVariants) { 600 if (comparator.areLexicallyEqual(taskVariant, candidate)) { 601 taskBuilder.setTask(executionVariant, taskVariant); 602 found = true; 603 break; 604 } 605 } 606 607 if (!found) { 608 iteratedTaskVariants.add(candidate); 609 } 610 } 611 } 612 613 // if there are more than one lexically different variant of iterated 614 // tasks, adapt the 615 // iteration model to be a selection of different variants. In this case 616 // also adapt 617 // the generated iteration instances to correctly contain selection 618 // instances. If there 619 // is only one variant of an iterated task, simply set this as the 620 // marked task of the 621 // iteration. In this case, the instances can be preserved as is 622 if (iteratedTaskVariants.size() > 1) { 623 final ISelection selection = taskFactory.createNewSelection(); 624 625 for (final ITask variant : iteratedTaskVariants) { 626 taskBuilder.addChild(selection, variant); 627 } 628 629 taskBuilder.setMarkedTask(iteration, selection); 630 631 for (final IIterationInstance instance : iterationInstances) { 632 for (int i = 0; i < instance.size(); i++) { 633 final ISelectionInstance selectionInstance = taskFactory 634 .createNewTaskInstance(selection); 635 taskBuilder.setChild(selectionInstance, instance.get(i)); 636 taskBuilder.setTaskInstance(instance, i, selectionInstance); 637 } 638 } 639 } else { 640 taskBuilder.setMarkedTask(iteration, iteratedTaskVariants.get(0)); 641 } 642 } 643 644 645 /** 646 * Match as sequence. 647 * 648 * @param appData , Ruleapplication Data needed to keep track of all created 649 * tasks 650 * @param m The match to be converted into a Task 651 * @return The task of the match with an ISequence as it's root 652 */ 653 synchronized public ISequence matchAsSequence(RuleApplicationData appData, 654 Match m) { 655 final ISequence sequence = taskFactory.createNewSequence(); 656 appData.newTaskCreated(sequence); 657 658 final int[] first = m.getFirstSequence().getSequence(); 659 final int[] second = m.getSecondSequence().getSequence(); 660 661 // Both sequences of a match are equally long 662 for (int i = 0; i < m.getFirstSequence().size(); i++) { 663 664 // Two gaps aligned to each other: Have not seen it happening so 665 // far, just to handle it 666 if ((first[i] == -1) && (second[i] == -1)) { 667 // Do nothing here. 668 } 669 // Both events are equal, we can simply add the task referring to 670 // the number 671 else if (first[i] == second[i]) { 672 taskBuilder.addChild(sequence, 673 appData.getNumber2Task().get(first[i])); 674 } 675 // We have a gap in the first sequence, we need to add the task of 676 // the second sequence as optional 677 else if ((first[i] == -1) && (second[i] != -1)) { 678 final IOptional optional = taskFactory.createNewOptional(); 679 appData.newTaskCreated(optional); 680 taskBuilder.setMarkedTask(optional, appData.getNumber2Task() 681 .get(second[i])); 682 taskBuilder.addChild(sequence, optional); 683 } 684 // We have a gap in the second sequence, we need to add the task of 685 // the first sequence as optional 686 else if ((first[i] != -1) && (second[i] == -1)) { 687 final IOptional optional = taskFactory.createNewOptional(); 688 appData.newTaskCreated(optional); 689 taskBuilder.setMarkedTask(optional, appData.getNumber2Task() 690 .get(first[i])); 691 taskBuilder.addChild(sequence, optional); 692 } 693 // Both tasks are not equal, we need to insert a selection here. 694 // Check if the next position is not a selection 695 else if (i < (first.length - 1)) { 696 697 if ((first[i] != second[i]) 698 && (((first[i + 1] == second[i + 1]) 699 || (first[i + 1] == -1) || (second[i + 1] == -1)))) { 700 701 final ISelection selection = taskFactory 702 .createNewSelection(); 703 appData.newTaskCreated(selection); 704 taskBuilder.addChild(selection, appData.getNumber2Task() 705 .get(first[i])); 706 taskBuilder.addChild(selection, appData.getNumber2Task() 707 .get(second[i])); 708 taskBuilder.addChild(sequence, selection); 709 } else { 710 boolean selectionfound = true; 711 final ISelection selection = taskFactory 712 .createNewSelection(); 713 appData.newTaskCreated(selection); 714 715 final ISequence subsequence1 = taskFactory 716 .createNewSequence(); 717 appData.newTaskCreated(subsequence1); 718 719 final ISequence subsequence2 = taskFactory 720 .createNewSequence(); 721 appData.newTaskCreated(subsequence2); 722 723 taskBuilder.addChild(selection, subsequence1); 724 taskBuilder.addChild(selection, subsequence2); 725 taskBuilder.addChild(sequence, selection); 726 while ((i < (first.length - 1)) && selectionfound) { 727 selectionfound = false; 728 taskBuilder.addChild(subsequence1, appData 729 .getNumber2Task().get(first[i])); 730 taskBuilder.addChild(subsequence2, appData 731 .getNumber2Task().get(second[i])); 732 if ((first[i + 1] != second[i + 1]) 733 && (first[i + 1] != -1) 734 && (second[i + 1] != -1)) { 735 selectionfound = true; 736 } else { 737 continue; 738 } 739 i++; 740 } 741 if ((i == (first.length - 1)) && selectionfound) { 742 taskBuilder.addChild(subsequence1, appData 743 .getNumber2Task().get(first[i])); 744 taskBuilder.addChild(subsequence2, appData 745 .getNumber2Task().get(second[i])); 746 } 747 } 748 } else { 749 if ((first[i] != second[i])) { 750 751 final ISelection selection = taskFactory 752 .createNewSelection(); 753 appData.newTaskCreated(selection); 754 taskBuilder.addChild(selection, appData.getNumber2Task() 755 .get(first[i])); 756 taskBuilder.addChild(selection, appData.getNumber2Task() 757 .get(second[i])); 758 taskBuilder.addChild(sequence, selection); 759 } 760 } 761 762 } 763 return sequence; 764 } 765 766 /** 767 * <p> 768 * replaces all occurrences of all tasks provided in the set with iterations 769 * </p>. 770 * 771 * @param iteratedTasks the tasks to be replaced with iterations 772 * @param sessions the sessions in which the tasks are to be replaced 773 * @param appData the rule application data combining all data used for applying 774 * this rule 775 */ 776 private void replaceIterationsOf(Set<ITask> iteratedTasks, 777 List<IUserSession> sessions, RuleApplicationData appData) { 778 final Map<ITask, IIteration> iterations = new HashMap<ITask, IIteration>(); 779 final Map<IIteration, List<IIterationInstance>> iterationInstances = new HashMap<IIteration, List<IIterationInstance>>(); 780 781 for (final ITask iteratedTask : iteratedTasks) { 782 783 final IIteration iteration = taskFactory.createNewIteration(); 784 appData.newTaskCreated(iteration); 785 iterations.put(iteratedTask, iteration); 786 iterationInstances.put(iteration, 787 new LinkedList<IIterationInstance>()); 788 } 789 790 IIterationInstance iterationInstance; 791 792 for (final IUserSession session : sessions) { 793 int index = 0; 794 iterationInstance = null; 795 796 while (index < session.size()) { 797 // we prepared the task instances to refer to unique tasks, if 798 // they are treated 799 // as equal. Therefore, we just compare the identity of the 800 // tasks of the task 801 // instances 802 final ITask currentTask = session.get(index).getTask(); 803 final IIteration iteration = iterations.get(currentTask); 804 if (iteration != null) { 805 if ((iterationInstance == null) 806 || (iterationInstance.getTask() != iteration)) { 807 iterationInstance = taskFactory 808 .createNewTaskInstance(iteration); 809 iterationInstances.get(iteration) 810 .add(iterationInstance);// TODO:: Don't create 811 // TaskInstances here, 812 // use a set of tasks 813 // instead 814 taskBuilder.addTaskInstance(session, index, 815 iterationInstance); 816 index++; 817 } 818 819 taskBuilder.addChild(iterationInstance, session.get(index)); 820 taskBuilder.removeTaskInstance(session, index); 821 } else { 822 if (iterationInstance != null) { 823 iterationInstance = null; 824 } 825 index++; 826 } 827 } 828 } 829 830 for (final Map.Entry<IIteration, List<IIterationInstance>> entry : iterationInstances 831 .entrySet()) { 832 harmonizeIterationInstancesModel(entry.getKey(), entry.getValue()); 833 } 834 } 835 836 /** 837 * Replace matches. 838 * 839 * @param appData the app data 840 */ 841 private void replaceMatches(RuleApplicationData appData) { 842 appData.replacedOccurences = new HashMap<Integer, List<MatchOccurence>>(); 843 844 final int matchSeqSize = appData.getMatchseqs().size(); 845 int newThreads = nThreads; 846 if (matchSeqSize < nThreads) { 847 newThreads = matchSeqSize; 848 } 849 final ExecutorService executor = Executors 850 .newFixedThreadPool(newThreads); 851 final int interval = matchSeqSize / newThreads; 852 int rest = matchSeqSize % newThreads; 853 854 for (int i = 0; i < (matchSeqSize - interval); i += interval) { 855 int offset = 0; 856 if (rest != 0) { 857 offset = 1; 858 rest--; 859 } 860 final int from = i; 861 final int to = i + interval + offset; 862 System.out 863 .println("Replacement: Creating thread with matches from " 864 + from + " to " + to); 865 // search each match in every other sequence 866 final ParallelMatchReplacer replacer = new ParallelMatchReplacer( 867 appData, from, to); 868 executor.execute(replacer); 869 } 870 executor.shutdown(); 871 try { 872 executor.awaitTermination(2, TimeUnit.HOURS); 873 } catch (final InterruptedException e) { 874 // TODO Auto-generated catch block 875 e.printStackTrace(); 876 } 877 } 878 879 880 /** 881 * <p> 882 * searches the provided sessions for task iterations. If a task is 883 * iterated, it is added to the returned set. 884 * </p> 885 * 886 * @param sessions the sessions 887 * @return a set of tasks being iterated somewhere 888 */ 889 private Set<ITask> searchIteratedTasks(List<IUserSession> sessions) { 890 final Set<ITask> iteratedTasks = new HashSet<ITask>(); 891 for (final IUserSession session : sessions) { 892 for (int i = 0; i < (session.size() - 1); i++) { 893 // we prepared the task instances to refer to unique tasks, if 894 // they are treated 895 // as equal. Therefore, we just compare the identity of the 896 // tasks of the task 897 // instances 898 if (session.get(i).getTask() == session.get(i + 1).getTask()) { 899 iteratedTasks.add(session.get(i).getTask()); 900 } 901 } 902 } 903 return iteratedTasks; 904 } 905 906 /** 907 * Search matches in all sessions. 908 * 909 * @param appData the app data 910 */ 911 private void searchMatchesInAllSessions(RuleApplicationData appData) { 912 Console.traceln(Level.INFO, 913 "searching for patterns occuring most with " + nThreads 914 + " threads"); 915 // Prepare parallel search of matchseqs 916 917 final int matchSeqSize = appData.getMatchseqs().size(); 918 int newThreads = nThreads; 919 if (matchSeqSize < nThreads) { 920 newThreads = matchSeqSize; 921 } 922 final int interval = matchSeqSize / newThreads; 923 int rest = matchSeqSize % newThreads; 924 final ExecutorService executor = Executors.newFixedThreadPool(nThreads); 925 926 for (int i = 0; i < (matchSeqSize - interval); i += interval) { 927 int offset = 0; 928 if (rest != 0) { 929 offset = 1; 930 rest--; 931 } 932 final int from = i; 933 final int to = i + interval + offset; 934 System.out 935 .println("Match finding: Creating thread with matches from " 936 + from + " to " + to); 937 // search each match in every other sequence 938 final ParallelMatchOcurrencesFinder finder = new ParallelMatchOcurrencesFinder( 939 appData, from, to); 940 executor.execute(finder); 941 } 942 executor.shutdown(); 943 try { 944 executor.awaitTermination(2, TimeUnit.HOURS); 945 } catch (final InterruptedException e) { 946 // TODO Auto-generated catch block 947 e.printStackTrace(); 948 } 949 950 } 951 952 /* 953 * (non-Javadoc) 954 * 955 * @see java.lang.Object#toString() 956 */ 957 @Override 958 public String toString() { 959 return "SequenceForTaskDetectionRuleAlignment"; 960 } 961 962 /** 963 * The Class ParallelMatchOcurrencesFinder. 964 */ 81 965 private class ParallelMatchOcurrencesFinder implements Runnable { 966 967 /** The app data. */ 82 968 private final RuleApplicationData appData; 969 970 /** The from. */ 83 971 private final int from; 972 973 /** The to. */ 84 974 private final int to; 85 975 976 /** 977 * Instantiates a new parallel match ocurrences finder. 978 * 979 * @param appData the app data 980 * @param from the from 981 * @param to the to 982 */ 86 983 ParallelMatchOcurrencesFinder(RuleApplicationData appData, int from, 87 984 int to) { … … 91 988 } 92 989 990 /* (non-Javadoc) 991 * @see java.lang.Runnable#run() 992 */ 93 993 @Override 94 994 public void run() { … … 129 1029 } 130 1030 1031 /** 1032 * The Class ParallelMatchReplacer. 1033 */ 131 1034 private class ParallelMatchReplacer implements Runnable { 132 1035 1036 /** The app data. */ 133 1037 private final RuleApplicationData appData; 1038 1039 /** The from. */ 134 1040 private final int from; 1041 1042 /** The to. */ 135 1043 private final int to; 136 1044 1045 /** 1046 * Instantiates a new parallel match replacer. 1047 * 1048 * @param appData the app data 1049 * @param from the from 1050 * @param to the to 1051 */ 137 1052 ParallelMatchReplacer(RuleApplicationData appData, int from, int to) { 138 1053 this.appData = appData; … … 141 1056 } 142 1057 1058 /* (non-Javadoc) 1059 * @see java.lang.Runnable#run() 1060 */ 143 1061 @Override 144 1062 public void run() { … … 164 1082 // want to replace now 165 1083 166 synchronized (appData.getReplacedOccur ences()) {167 if (appData.getReplacedOccur ences().get(1084 synchronized (appData.getReplacedOccurrences()) { 1085 if (appData.getReplacedOccurrences().get( 168 1086 oc.getSequenceId()) == null) { 169 appData.getReplacedOccur ences().put(1087 appData.getReplacedOccurrences().put( 170 1088 oc.getSequenceId(), 171 1089 new LinkedList<MatchOccurence>()); … … 186 1104 // harmonized. 187 1105 for (final Iterator<MatchOccurence> jt = appData 188 .getReplacedOccur ences()1106 .getReplacedOccurrences() 189 1107 .get(oc.getSequenceId()).iterator(); jt 190 1108 .hasNext();) { … … 239 1157 // instance. (OptionalInstances may be shorter) 240 1158 241 synchronized (appData.getReplacedOccur ences().get(1159 synchronized (appData.getReplacedOccurrences().get( 242 1160 oc.getSequenceId())) { 243 appData.getReplacedOccur ences()1161 appData.getReplacedOccurrences() 244 1162 .get(oc.getSequenceId()).add(oc); 245 1163 } … … 250 1168 } 251 1169 1170 /** 1171 * The Class ParallelPairwiseAligner. 1172 */ 252 1173 private class ParallelPairwiseAligner implements Runnable { 1174 1175 /** The app data. */ 253 1176 private final RuleApplicationData appData; 1177 1178 /** The from. */ 254 1179 private final int from; 1180 1181 /** The to. */ 255 1182 private final int to; 256 1183 1184 /** 1185 * Instantiates a new parallel pairwise aligner. 1186 * 1187 * @param appData the app data 1188 * @param from the from 1189 * @param to the to 1190 */ 257 1191 ParallelPairwiseAligner(RuleApplicationData appData, int from, int to) { 258 1192 this.appData = appData; … … 261 1195 } 262 1196 1197 /* (non-Javadoc) 1198 * @see java.lang.Runnable#run() 1199 */ 263 1200 @Override 264 1201 public void run() { … … 286 1223 } 287 1224 } 288 289 /** 290 * 291 */ 292 private static class RuleApplicationData implements Serializable { 293 294 /** 295 * 296 */ 297 private static final long serialVersionUID = -7559657686755522960L; 298 299 private final HashMap<Integer, ITask> number2task; 300 301 // TODO: We Actually just need number2task here, this structure can be 302 // removed in the future. 303 private final HashSet<ITask> uniqueTasks; 304 305 private final ObjectDistanceSubstitionMatrix submat; 306 307 public HashMap<Integer, List<MatchOccurence>> replacedOccurences; 308 309 public LinkedList<Match> matchseqs; 310 311 private ArrayList<NumberSequence> numberseqs; 312 313 private final LinkedList<ITask> newTasks; 314 315 /** 316 * 317 */ 318 private final List<IUserSession> sessions; 319 320 /** 321 * 322 */ 323 private boolean detectedAndReplacedTasks; 324 325 /** 326 * 327 */ 328 private final RuleApplicationResult result; 329 330 /** 331 * 332 */ 333 private final StopWatch stopWatch; 334 335 /** 336 * 337 */ 338 private RuleApplicationData(List<IUserSession> sessions) { 339 this.sessions = sessions; 340 numberseqs = new ArrayList<NumberSequence>(); 341 uniqueTasks = new HashSet<ITask>(); 342 number2task = new HashMap<Integer, ITask>(); 343 stopWatch = new StopWatch(); 344 result = new RuleApplicationResult(); 345 submat = new ObjectDistanceSubstitionMatrix(6, -3, false); 346 newTasks = new LinkedList<ITask>(); 347 this.detectedAndReplacedTasks = true; 348 } 349 350 /** 351 * 352 */ 353 private boolean detectedAndReplacedTasks() { 354 return detectedAndReplacedTasks; 355 } 356 357 public LinkedList<Match> getMatchseqs() { 358 return matchseqs; 359 } 360 361 public LinkedList<ITask> getNewTasks() { 362 return newTasks; 363 } 364 365 private HashMap<Integer, ITask> getNumber2Task() { 366 return number2task; 367 } 368 369 private ArrayList<NumberSequence> getNumberSequences() { 370 return numberseqs; 371 } 372 373 public HashMap<Integer, List<MatchOccurence>> getReplacedOccurences() { 374 return replacedOccurences; 375 } 376 377 /** 378 * @return the result 379 */ 380 private RuleApplicationResult getResult() { 381 return result; 382 } 383 384 /** 385 * @return the UserSessions as List. 386 */ 387 private List<IUserSession> getSessions() { 388 return sessions; 389 } 390 391 /** 392 * @return the stopWatch 393 */ 394 private StopWatch getStopWatch() { 395 return stopWatch; 396 } 397 398 private ObjectDistanceSubstitionMatrix getSubmat() { 399 return submat; 400 } 401 402 private HashSet<ITask> getUniqueTasks() { 403 return uniqueTasks; 404 } 405 406 private void newTaskCreated(ITask task) { 407 number2task.put(task.getId(), task); 408 newTasks.add(task); 409 } 410 411 synchronized private void resetNewlyCreatedTasks() { 412 uniqueTasks.addAll(newTasks); 413 newTasks.clear(); 414 } 415 416 private void setNumberSequences(ArrayList<NumberSequence> numberseqs) { 417 this.numberseqs = numberseqs; 418 } 419 420 public void setReplacedOccurences( 421 HashMap<Integer, List<MatchOccurence>> replacedOccurences) { 422 this.replacedOccurences = replacedOccurences; 423 } 424 425 private void updateSubstitutionMatrix() { 426 submat.update(getNewTasks()); 427 resetNewlyCreatedTasks(); 428 } 429 430 } 431 432 public static int nThreads = Runtime.getRuntime().availableProcessors() - 1; 433 434 private int iteration = 0; 435 436 /** 437 * <p> 438 * the task factory to be used for creating substructures for the temporal 439 * relationships identified during rul application 440 * </p> 441 */ 442 private final ITaskFactory taskFactory; 443 444 /** 445 * <p> 446 * the task builder to be used for creating substructures for the temporal 447 * relationships identified during rule application 448 * </p> 449 */ 450 private final ITaskBuilder taskBuilder; 451 452 /** 453 * <p> 454 * the task handling strategy to be used for comparing tasks for 455 * preparation, i.e., before the tasks are harmonized 456 * </p> 457 */ 458 private final TaskHandlingStrategy preparationTaskHandlingStrategy; 459 460 /** 461 * <p> 462 * instantiates the rule and initializes it with a task equality to be 463 * considered when comparing tasks as well as a task factory and builder to 464 * be used for creating task structures. 465 * </p> 466 * 467 * @param minimalTaskEquality 468 * the task equality to be considered when comparing tasks 469 * @param taskFactory 470 * the task factory to be used for creating substructures 471 * @param taskBuilder 472 * the task builder to be used for creating substructures 473 */ 474 475 SequenceForTaskDetectionRuleAlignment(TaskEquality minimalTaskEquality, 476 ITaskFactory taskFactory, ITaskBuilder taskBuilder) { 477 this.taskFactory = taskFactory; 478 this.taskBuilder = taskBuilder; 479 480 this.preparationTaskHandlingStrategy = new TaskHandlingStrategy( 481 minimalTaskEquality); 482 } 483 484 /* 485 * (non-Javadoc) 486 * 487 * @see 488 * de.ugoe.cs.autoquest.tasktrees.temporalrelation.ISessionScopeRule#apply 489 * (java.util.List) 490 */ 491 @Override 492 public RuleApplicationResult apply(List<IUserSession> sessions) { 493 final RuleApplicationData appData = new RuleApplicationData(sessions); 494 // File harmonized = new File("harmonized.dat"); 495 // if(harmonized.exists() && !harmonized.isDirectory()) { 496 // Console.traceln(Level.INFO,"loading harmonized sessions from file"); 497 // appData = loadAppData("harmonized"); 498 // } 499 // else { 500 // appData.getStopWatch().start("harmonization"); 501 harmonizeEventTaskInstancesModel(appData); 502 // appData.getStopWatch().stop("harmonization"); 503 GlobalDataContainer.getInstance().addData("harmonized", appData); 504 // Saving intermediate results to file 505 Console.traceln(Level.INFO, "saving substitution matrix to file"); 506 // saveAppData("harmonized"); 507 // } 508 509 // File substitution = new File("substitution.dat"); 510 // if(!(substitution.exists() && !substitution.isDirectory())) { 511 Console.traceln(Level.INFO, "generating substitution matrix from " 512 + appData.getUniqueTasks().size() + " unique tasks"); 513 appData.getStopWatch().start("substitution matrix"); 514 appData.getSubmat().generate(appData.getUniqueTasks()); 515 appData.getStopWatch().stop("substitution matrix"); 516 // GlobalDataContainer.getInstance().addData("substitution", appData); 517 // saveAppData("substitution"); 518 // } 519 // else { 520 // Console.traceln(Level.INFO,"loading substitution matrix from file"); 521 // appData = loadAppData("substitution"); 522 // } 523 524 Console.traceln(Level.INFO, "Starting main loop"); 525 do { 526 Console.traceln(Level.INFO, "Iteration Number: " + iteration); 527 iteration++; 528 appData.detectedAndReplacedTasks = false; 529 appData.getStopWatch().start("whole loop"); 530 detectAndReplaceIterations(appData); 531 appData.getStopWatch().start("task replacement"); 532 // appData.updateSubstitutionMatrix(); 533 detectAndReplaceTasks(appData); // 534 appData.getStopWatch().stop("task replacement"); 535 appData.getStopWatch().stop("whole loop"); 536 appData.getStopWatch().dumpStatistics(System.out); 537 appData.getStopWatch().reset(); 538 539 } while (appData.detectedAndReplacedTasks()); 540 541 Console.println("created " 542 + appData.getResult().getNewlyCreatedTasks().size() 543 + " new tasks and " 544 + appData.getResult().getNewlyCreatedTaskInstances().size() 545 + " appropriate instances\n"); 546 547 if ((appData.getResult().getNewlyCreatedTasks().size() > 0) 548 || (appData.getResult().getNewlyCreatedTaskInstances().size() > 0)) { 549 appData.getResult().setRuleApplicationStatus( 550 RuleApplicationStatus.FINISHED); 551 } 552 553 return appData.getResult(); 554 } 555 556 private ArrayList<NumberSequence> createNumberSequences( 557 RuleApplicationData appData) { 558 final ArrayList<NumberSequence> result = new ArrayList<NumberSequence>(); 559 for (int i = 0; i < appData.getSessions().size(); i++) { 560 final IUserSession session = appData.getSessions().get(i); 561 final NumberSequence templist = new NumberSequence(session.size()); 562 for (int j = 0; j < session.size(); j++) { 563 final ITaskInstance taskInstance = session.get(j); 564 templist.getSequence()[j] = taskInstance.getTask().getId(); 565 } 566 // Each NumberSequence is identified by its id, beginning to count 567 // at zero 568 templist.setId(i); 569 result.add(templist); 570 } 571 return result; 572 } 573 574 /** 575 * <p> 576 * searches for direct iterations of single tasks in all sequences and 577 * replaces them with {@link IIteration}s, respectively appropriate 578 * instances. Also all single occurrences of a task that is iterated 579 * somewhen are replaced with iterations to have again an efficient way for 580 * task comparisons. 581 * </p> 582 * 583 * @param appData 584 * the rule application data combining all data used for applying 585 * this rule 586 */ 587 private void detectAndReplaceIterations(RuleApplicationData appData) { 588 Console.traceln(Level.FINE, "detecting iterations"); 589 appData.getStopWatch().start("detecting iterations"); 590 591 final List<IUserSession> sessions = appData.getSessions(); 592 593 final Set<ITask> iteratedTasks = searchIteratedTasks(sessions); 594 595 if (iteratedTasks.size() > 0) { 596 replaceIterationsOf(iteratedTasks, sessions, appData); 597 } 598 599 appData.getStopWatch().stop("detecting iterations"); 600 Console.traceln(Level.INFO, "replaced " + iteratedTasks.size() 601 + " iterated tasks"); 602 } 603 604 /** 605 * 606 * @param appData 607 * the rule application data combining all data used for applying 608 * this rule 609 */ 610 private void detectAndReplaceTasks(RuleApplicationData appData) { 611 Console.traceln(Level.FINE, "detecting and replacing tasks"); 612 appData.getStopWatch().start("detecting tasks"); 613 614 // Create NumberSequences 615 appData.setNumberSequences(this.createNumberSequences(appData)); 616 617 // Generate pairwise alignments 618 // appData.setMatchseqs(generatePairwiseAlignments(appData)); 619 generatePairwiseAlignments(appData); 620 621 // Searching each match in all other sessions, counting its occurences 622 searchMatchesInAllSessions(appData); 623 624 // Sort results to get the most occurring results 625 Console.traceln(Level.INFO, "sorting " + appData.getMatchseqs().size() 626 + " results"); 627 final Comparator<Match> comparator = new Comparator<Match>() { 628 @Override 629 public int compare(Match m1, Match m2) { 630 return m2.occurenceCount() - m1.occurenceCount(); 631 632 } 633 }; 634 635 Collections.sort(appData.getMatchseqs(), comparator); 636 appData.getStopWatch().stop("detecting tasks"); 637 638 // Replace matches in the sessions 639 Console.traceln(Level.INFO, "Replacing matches in sessions"); 640 replaceMatches(appData); 641 appData.getStopWatch().start("replacing tasks"); 642 643 // appData.setMatchseqs(null); 644 appData.getStopWatch().stop("replacing tasks"); 645 } 646 647 // private LinkedList<Match> generatePairwiseAlignments(RuleApplicationData 648 // appData) { 649 private void generatePairwiseAlignments(RuleApplicationData appData) { 650 final int numberSeqSize = appData.getNumberSequences().size(); 651 appData.matchseqs = new LinkedList<Match>(); 652 Console.traceln(Level.INFO, "generating pairwise alignments from " 653 + numberSeqSize + " sessions with " + nThreads + " threads"); 654 655 int newThreads = nThreads; 656 if (numberSeqSize < nThreads) { 657 newThreads = numberSeqSize; 658 } 659 660 final ExecutorService executor = Executors 661 .newFixedThreadPool(newThreads); 662 final int interval = numberSeqSize / newThreads; 663 int rest = numberSeqSize % newThreads; 664 665 for (int i = 0; i < (numberSeqSize - interval); i += interval) { 666 int offset = 0; 667 if (rest != 0) { 668 offset = 1; 669 rest--; 670 } 671 final int from = i; 672 final int to = i + interval + offset; 673 System.out.println("Creating thread for sessions " + from 674 + " till " + to); 675 final ParallelPairwiseAligner aligner = new ParallelPairwiseAligner( 676 appData, from, to); 677 executor.execute(aligner); 678 } 679 executor.shutdown(); 680 try { 681 executor.awaitTermination(2, TimeUnit.HOURS); 682 } catch (final InterruptedException e) { 683 // TODO Auto-generated catch block 684 e.printStackTrace(); 685 } 686 } 687 688 /** 689 * <p> 690 * harmonizes the event task instances by unifying tasks. This is done, as 691 * initially the event tasks being equal with respect to the considered task 692 * equality are distinct objects. The comparison of these distinct objects 693 * is more time consuming than comparing the object references. 694 * </p> 695 * 696 * @param appData 697 * the rule application data combining all data used for applying 698 * this rule 699 * @return Returns the unique tasks symbol map 700 */ 701 private void harmonizeEventTaskInstancesModel(RuleApplicationData appData) { 702 Console.traceln(Level.INFO, 703 "harmonizing task model of event task instances"); 704 appData.getStopWatch().start("harmonizing event tasks"); 705 final SymbolMap<ITaskInstance, ITask> uniqueTasks = preparationTaskHandlingStrategy 706 .createSymbolMap(); 707 708 final TaskInstanceComparator comparator = preparationTaskHandlingStrategy 709 .getTaskComparator(); 710 711 int unifiedTasks = 0; 712 ITask task; 713 final List<IUserSession> sessions = appData.getSessions(); 714 for (int j = 0; j < sessions.size(); j++) { 715 final IUserSession session = sessions.get(j); 716 717 for (int i = 0; i < session.size(); i++) { 718 final ITaskInstance taskInstance = session.get(i); 719 task = uniqueTasks.getValue(taskInstance); 720 721 if (task == null) { 722 uniqueTasks.addSymbol(taskInstance, taskInstance.getTask()); 723 appData.getUniqueTasks().add(taskInstance.getTask()); 724 appData.getNumber2Task().put( 725 taskInstance.getTask().getId(), 726 taskInstance.getTask()); 727 } else { 728 taskBuilder.setTask(taskInstance, task); 729 unifiedTasks++; 730 } 731 } 732 comparator.clearBuffers(); 733 } 734 735 appData.getStopWatch().stop("harmonizing event tasks"); 736 Console.traceln(Level.INFO, "harmonized " + unifiedTasks 737 + " task occurrences (still " + appData.getUniqueTasks().size() 738 + " different tasks)"); 739 740 appData.getStopWatch().dumpStatistics(System.out); 741 appData.getStopWatch().reset(); 742 } 743 744 /** 745 * <p> 746 * TODO clarify why this is done 747 * </p> 748 */ 749 private void harmonizeIterationInstancesModel(IIteration iteration, 750 List<IIterationInstance> iterationInstances) { 751 final List<ITask> iteratedTaskVariants = new LinkedList<ITask>(); 752 final TaskInstanceComparator comparator = preparationTaskHandlingStrategy 753 .getTaskComparator(); 754 755 // merge the lexically different variants of iterated task to a unique 756 // list 757 for (final IIterationInstance iterationInstance : iterationInstances) { 758 for (final ITaskInstance executionVariant : iterationInstance) { 759 final ITask candidate = executionVariant.getTask(); 760 761 boolean found = false; 762 for (final ITask taskVariant : iteratedTaskVariants) { 763 if (comparator.areLexicallyEqual(taskVariant, candidate)) { 764 taskBuilder.setTask(executionVariant, taskVariant); 765 found = true; 766 break; 767 } 768 } 769 770 if (!found) { 771 iteratedTaskVariants.add(candidate); 772 } 773 } 774 } 775 776 // if there are more than one lexically different variant of iterated 777 // tasks, adapt the 778 // iteration model to be a selection of different variants. In this case 779 // also adapt 780 // the generated iteration instances to correctly contain selection 781 // instances. If there 782 // is only one variant of an iterated task, simply set this as the 783 // marked task of the 784 // iteration. In this case, the instances can be preserved as is 785 if (iteratedTaskVariants.size() > 1) { 786 final ISelection selection = taskFactory.createNewSelection(); 787 788 for (final ITask variant : iteratedTaskVariants) { 789 taskBuilder.addChild(selection, variant); 790 } 791 792 taskBuilder.setMarkedTask(iteration, selection); 793 794 for (final IIterationInstance instance : iterationInstances) { 795 for (int i = 0; i < instance.size(); i++) { 796 final ISelectionInstance selectionInstance = taskFactory 797 .createNewTaskInstance(selection); 798 taskBuilder.setChild(selectionInstance, instance.get(i)); 799 taskBuilder.setTaskInstance(instance, i, selectionInstance); 800 } 801 } 802 } else { 803 taskBuilder.setMarkedTask(iteration, iteratedTaskVariants.get(0)); 804 } 805 } 806 807 public RuleApplicationData loadAppData(String name) { 808 final String objectName = name; 809 final String filename = name + ".dat"; 810 811 Object data = null; 812 FileInputStream fis = null; 813 ObjectInputStream in = null; 814 try { 815 fis = new FileInputStream(filename); 816 in = new ObjectInputStream(fis); 817 data = in.readObject(); 818 in.close(); 819 } catch (final IOException ex) { 820 Console.logException(ex); 821 } catch (final ClassNotFoundException ex) { 822 Console.logException(ex); 823 } 824 if (GlobalDataContainer.getInstance().addData(objectName, data)) { 825 CommandHelpers.dataOverwritten(objectName); 826 } 827 return (RuleApplicationData) GlobalDataContainer.getInstance().getData( 828 name); 829 } 830 831 /** 832 * @param appData 833 * , Ruleapplication Data needed to keep track of all created 834 * tasks 835 * @param m 836 * The match to be converted into a Task 837 * @return The task of the match with an ISequence as it's root 838 */ 839 synchronized public ISequence matchAsSequence(RuleApplicationData appData, 840 Match m) { 841 final ISequence sequence = taskFactory.createNewSequence(); 842 appData.newTaskCreated(sequence); 843 844 final int[] first = m.getFirstSequence().getSequence(); 845 final int[] second = m.getSecondSequence().getSequence(); 846 847 // Both sequences of a match are equally long 848 for (int i = 0; i < m.getFirstSequence().size(); i++) { 849 850 // Two gaps aligned to each other: Have not seen it happening so 851 // far, just to handle it 852 if ((first[i] == -1) && (second[i] == -1)) { 853 // Do nothing here. 854 } 855 // Both events are equal, we can simply add the task referring to 856 // the number 857 else if (first[i] == second[i]) { 858 taskBuilder.addChild(sequence, 859 appData.getNumber2Task().get(first[i])); 860 } 861 // We have a gap in the first sequence, we need to add the task of 862 // the second sequence as optional 863 else if ((first[i] == -1) && (second[i] != -1)) { 864 final IOptional optional = taskFactory.createNewOptional(); 865 appData.newTaskCreated(optional); 866 taskBuilder.setMarkedTask(optional, appData.getNumber2Task() 867 .get(second[i])); 868 taskBuilder.addChild(sequence, optional); 869 } 870 // We have a gap in the second sequence, we need to add the task of 871 // the first sequence as optional 872 else if ((first[i] != -1) && (second[i] == -1)) { 873 final IOptional optional = taskFactory.createNewOptional(); 874 appData.newTaskCreated(optional); 875 taskBuilder.setMarkedTask(optional, appData.getNumber2Task() 876 .get(first[i])); 877 taskBuilder.addChild(sequence, optional); 878 } 879 // Both tasks are not equal, we need to insert a selection here. 880 // Check if the next position is not a selection 881 else if (i < (first.length - 1)) { 882 883 if ((first[i] != second[i]) 884 && (((first[i + 1] == second[i + 1]) 885 || (first[i + 1] == -1) || (second[i + 1] == -1)))) { 886 887 final ISelection selection = taskFactory 888 .createNewSelection(); 889 appData.newTaskCreated(selection); 890 taskBuilder.addChild(selection, appData.getNumber2Task() 891 .get(first[i])); 892 taskBuilder.addChild(selection, appData.getNumber2Task() 893 .get(second[i])); 894 taskBuilder.addChild(sequence, selection); 895 } else { 896 boolean selectionfound = true; 897 final ISelection selection = taskFactory 898 .createNewSelection(); 899 appData.newTaskCreated(selection); 900 901 final ISequence subsequence1 = taskFactory 902 .createNewSequence(); 903 appData.newTaskCreated(subsequence1); 904 905 final ISequence subsequence2 = taskFactory 906 .createNewSequence(); 907 appData.newTaskCreated(subsequence2); 908 909 taskBuilder.addChild(selection, subsequence1); 910 taskBuilder.addChild(selection, subsequence2); 911 taskBuilder.addChild(sequence, selection); 912 while ((i < (first.length - 1)) && selectionfound) { 913 selectionfound = false; 914 taskBuilder.addChild(subsequence1, appData 915 .getNumber2Task().get(first[i])); 916 taskBuilder.addChild(subsequence2, appData 917 .getNumber2Task().get(second[i])); 918 if ((first[i + 1] != second[i + 1]) 919 && (first[i + 1] != -1) 920 && (second[i + 1] != -1)) { 921 selectionfound = true; 922 } else { 923 continue; 924 } 925 i++; 926 } 927 if ((i == (first.length - 1)) && selectionfound) { 928 taskBuilder.addChild(subsequence1, appData 929 .getNumber2Task().get(first[i])); 930 taskBuilder.addChild(subsequence2, appData 931 .getNumber2Task().get(second[i])); 932 } 933 } 934 } else { 935 if ((first[i] != second[i])) { 936 937 final ISelection selection = taskFactory 938 .createNewSelection(); 939 appData.newTaskCreated(selection); 940 taskBuilder.addChild(selection, appData.getNumber2Task() 941 .get(first[i])); 942 taskBuilder.addChild(selection, appData.getNumber2Task() 943 .get(second[i])); 944 taskBuilder.addChild(sequence, selection); 945 } 946 } 947 948 } 949 return sequence; 950 } 951 952 /** 953 * <p> 954 * replaces all occurrences of all tasks provided in the set with iterations 955 * </p> 956 * 957 * @param iteratedTasks 958 * the tasks to be replaced with iterations 959 * @param sessions 960 * the sessions in which the tasks are to be replaced 961 * @param appData 962 * the rule application data combining all data used for applying 963 * this rule 964 */ 965 private void replaceIterationsOf(Set<ITask> iteratedTasks, 966 List<IUserSession> sessions, RuleApplicationData appData) { 967 final Map<ITask, IIteration> iterations = new HashMap<ITask, IIteration>(); 968 final Map<IIteration, List<IIterationInstance>> iterationInstances = new HashMap<IIteration, List<IIterationInstance>>(); 969 970 for (final ITask iteratedTask : iteratedTasks) { 971 972 final IIteration iteration = taskFactory.createNewIteration(); 973 appData.newTaskCreated(iteration); 974 iterations.put(iteratedTask, iteration); 975 iterationInstances.put(iteration, 976 new LinkedList<IIterationInstance>()); 977 } 978 979 IIterationInstance iterationInstance; 980 981 for (final IUserSession session : sessions) { 982 int index = 0; 983 iterationInstance = null; 984 985 while (index < session.size()) { 986 // we prepared the task instances to refer to unique tasks, if 987 // they are treated 988 // as equal. Therefore, we just compare the identity of the 989 // tasks of the task 990 // instances 991 final ITask currentTask = session.get(index).getTask(); 992 final IIteration iteration = iterations.get(currentTask); 993 if (iteration != null) { 994 if ((iterationInstance == null) 995 || (iterationInstance.getTask() != iteration)) { 996 iterationInstance = taskFactory 997 .createNewTaskInstance(iteration); 998 iterationInstances.get(iteration) 999 .add(iterationInstance);// TODO:: Don't create 1000 // TaskInstances here, 1001 // use a set of tasks 1002 // instead 1003 taskBuilder.addTaskInstance(session, index, 1004 iterationInstance); 1005 index++; 1006 } 1007 1008 taskBuilder.addChild(iterationInstance, session.get(index)); 1009 taskBuilder.removeTaskInstance(session, index); 1010 } else { 1011 if (iterationInstance != null) { 1012 iterationInstance = null; 1013 } 1014 index++; 1015 } 1016 } 1017 } 1018 1019 for (final Map.Entry<IIteration, List<IIterationInstance>> entry : iterationInstances 1020 .entrySet()) { 1021 harmonizeIterationInstancesModel(entry.getKey(), entry.getValue()); 1022 } 1023 } 1024 1025 private void replaceMatches(RuleApplicationData appData) { 1026 appData.replacedOccurences = new HashMap<Integer, List<MatchOccurence>>(); 1027 1028 final int matchSeqSize = appData.getMatchseqs().size(); 1029 int newThreads = nThreads; 1030 if (matchSeqSize < nThreads) { 1031 newThreads = matchSeqSize; 1032 } 1033 final ExecutorService executor = Executors 1034 .newFixedThreadPool(newThreads); 1035 final int interval = matchSeqSize / newThreads; 1036 int rest = matchSeqSize % newThreads; 1037 1038 for (int i = 0; i < (matchSeqSize - interval); i += interval) { 1039 int offset = 0; 1040 if (rest != 0) { 1041 offset = 1; 1042 rest--; 1043 } 1044 final int from = i; 1045 final int to = i + interval + offset; 1046 System.out 1047 .println("Replacement: Creating thread with matches from " 1048 + from + " to " + to); 1049 // search each match in every other sequence 1050 final ParallelMatchReplacer replacer = new ParallelMatchReplacer( 1051 appData, from, to); 1052 executor.execute(replacer); 1053 } 1054 executor.shutdown(); 1055 try { 1056 executor.awaitTermination(2, TimeUnit.HOURS); 1057 } catch (final InterruptedException e) { 1058 // TODO Auto-generated catch block 1059 e.printStackTrace(); 1060 } 1061 } 1062 1063 public void saveAppData(String name) { 1064 final String objectName = name; 1065 final String filename = name + ".dat"; 1066 final Object dataObject = GlobalDataContainer.getInstance().getData( 1067 objectName); 1068 if (dataObject == null) { 1069 CommandHelpers.objectNotFoundMessage(objectName); 1070 } 1071 FileOutputStream fos = null; 1072 ObjectOutputStream out = null; 1073 try { 1074 fos = new FileOutputStream(filename); 1075 out = new ObjectOutputStream(fos); 1076 out.writeObject(dataObject); 1077 out.close(); 1078 } catch (final IOException ex) { 1079 Console.logException(ex); 1080 } 1081 } 1082 1083 /** 1084 * <p> 1085 * searches the provided sessions for task iterations. If a task is 1086 * iterated, it is added to the returned set. 1087 * </p> 1088 * 1089 * @param the 1090 * session to search for iterations in 1091 * 1092 * @return a set of tasks being iterated somewhere 1093 */ 1094 private Set<ITask> searchIteratedTasks(List<IUserSession> sessions) { 1095 final Set<ITask> iteratedTasks = new HashSet<ITask>(); 1096 for (final IUserSession session : sessions) { 1097 for (int i = 0; i < (session.size() - 1); i++) { 1098 // we prepared the task instances to refer to unique tasks, if 1099 // they are treated 1100 // as equal. Therefore, we just compare the identity of the 1101 // tasks of the task 1102 // instances 1103 if (session.get(i).getTask() == session.get(i + 1).getTask()) { 1104 iteratedTasks.add(session.get(i).getTask()); 1105 } 1106 } 1107 } 1108 return iteratedTasks; 1109 } 1110 1111 private void searchMatchesInAllSessions(RuleApplicationData appData) { 1112 Console.traceln(Level.INFO, 1113 "searching for patterns occuring most with " + nThreads 1114 + " threads"); 1115 // Prepare parallel search of matchseqs 1116 1117 final int matchSeqSize = appData.getMatchseqs().size(); 1118 int newThreads = nThreads; 1119 if (matchSeqSize < nThreads) { 1120 newThreads = matchSeqSize; 1121 } 1122 final int interval = matchSeqSize / newThreads; 1123 int rest = matchSeqSize % newThreads; 1124 final ExecutorService executor = Executors.newFixedThreadPool(nThreads); 1125 1126 for (int i = 0; i < (matchSeqSize - interval); i += interval) { 1127 int offset = 0; 1128 if (rest != 0) { 1129 offset = 1; 1130 rest--; 1131 } 1132 final int from = i; 1133 final int to = i + interval + offset; 1134 System.out 1135 .println("Match finding: Creating thread with matches from " 1136 + from + " to " + to); 1137 // search each match in every other sequence 1138 final ParallelMatchOcurrencesFinder finder = new ParallelMatchOcurrencesFinder( 1139 appData, from, to); 1140 executor.execute(finder); 1141 } 1142 executor.shutdown(); 1143 try { 1144 executor.awaitTermination(2, TimeUnit.HOURS); 1145 } catch (final InterruptedException e) { 1146 // TODO Auto-generated catch block 1147 e.printStackTrace(); 1148 } 1149 1150 } 1151 1152 /* 1153 * (non-Javadoc) 1154 * 1155 * @see java.lang.Object#toString() 1156 */ 1157 @Override 1158 public String toString() { 1159 return "SequenceForTaskDetectionRuleAlignment"; 1160 } 1161 1225 1162 1226 }
Note: See TracChangeset
for help on using the changeset viewer.