Changeset 1855 for trunk/autoquest-core-tasktrees/src/main
- Timestamp:
- 12/23/14 11:49:50 (10 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/autoquest-core-tasktrees/src/main/java/de/ugoe/cs/autoquest/tasktrees/temporalrelation/SequenceForTaskDetectionRule.java
r1767 r1855 15 15 package de.ugoe.cs.autoquest.tasktrees.temporalrelation; 16 16 17 import java.util.ArrayList; 17 18 import java.util.HashMap; 18 19 import java.util.HashSet; 20 import java.util.IdentityHashMap; 19 21 import java.util.Iterator; 20 22 import java.util.LinkedList; 21 23 import java.util.List; 24 import java.util.ListIterator; 22 25 import java.util.Map; 23 26 import java.util.Set; … … 25 28 26 29 import de.ugoe.cs.autoquest.tasktrees.taskequality.TaskEquality; 30 import de.ugoe.cs.autoquest.tasktrees.temporalrelation.utils.DebuggingHelper; 27 31 import de.ugoe.cs.autoquest.tasktrees.treeifc.IIteration; 28 32 import de.ugoe.cs.autoquest.tasktrees.treeifc.IIterationInstance; … … 183 187 appData.getStopWatch().start("harmonizing event tasks"); 184 188 185 SymbolMap<ITaskInstance, ITask> uniqueTasks = 186 preparationTaskHandlingStrategy.createSymbolMap(); 187 TaskInstanceComparator comparator = preparationTaskHandlingStrategy.getTaskComparator(); 189 SymbolMap<ITask, ITask> uniqueTasks = preparationTaskHandlingStrategy.createSymbolMap(); 190 TaskComparator comparator = preparationTaskHandlingStrategy.getTaskComparator(); 188 191 189 192 int unifiedTasks = 0; … … 194 197 Console.traceln(Level.FINE, "handling " + (++sessionNo) + ". " + session); 195 198 for (ITaskInstance taskInstance : session) { 196 task = uniqueTasks.getValue(taskInstance );199 task = uniqueTasks.getValue(taskInstance.getTask()); 197 200 198 201 if (task == null) { 199 uniqueTasks.addSymbol(taskInstance , taskInstance.getTask());202 uniqueTasks.addSymbol(taskInstance.getTask(), taskInstance.getTask()); 200 203 } 201 204 else { … … 374 377 { 375 378 List<ITask> iteratedTaskVariants = new LinkedList<ITask>(); 376 Task InstanceComparator comparator = preparationTaskHandlingStrategy.getTaskComparator();379 TaskComparator comparator = preparationTaskHandlingStrategy.getTaskComparator(); 377 380 378 381 // merge the lexically different variants of iterated task to a unique list … … 432 435 appData.getStopWatch().start("detecting tasks"); 433 436 434 getS equencesOccuringMostOften(appData);435 437 getSubsequencesOccuringMostOften(appData); 438 436 439 appData.getStopWatch().stop("detecting tasks"); 440 appData.getStopWatch().start("sorting tasks"); 441 442 removeInterleavingTasks(appData); 443 444 appData.getStopWatch().stop("sorting tasks"); 437 445 appData.getStopWatch().start("replacing tasks"); 438 446 … … 440 448 441 449 appData.getStopWatch().stop("replacing tasks"); 442 Console.traceln(Level.INFO, "detected and replaced " + appData.getLastFound Tasks().size() +443 " tasks occuring " + appData.getLastFound Tasks().getOccurrenceCount() +450 Console.traceln(Level.INFO, "detected and replaced " + appData.getLastFoundSubsequences().size() + 451 " tasks occuring " + appData.getLastFoundSubsequences().getOccurrenceCount() + 444 452 " times"); 445 453 } … … 448 456 * @param appData the rule application data combining all data used for applying this rule 449 457 */ 450 private void getS equencesOccuringMostOften(RuleApplicationData appData) {451 Console.traceln(Level.FINE , "determining most prominent tasks");452 453 Tasks tasks;458 private void getSubsequencesOccuringMostOften(RuleApplicationData appData) { 459 Console.traceln(Level.FINER, "determining most prominent subsequences"); 460 461 Subsequences subsequences; 454 462 boolean createNewTrie = (appData.getLastTrie() == null) || 455 463 appData.detectedAndReplacedTasks(); // tree has changed … … 460 468 } 461 469 462 MaxCountAndLongest TasksFinder finder = new MaxCountAndLongestTasksFinder();470 MaxCountAndLongestSubsequencesFinder finder = new MaxCountAndLongestSubsequencesFinder(); 463 471 appData.getLastTrie().process(finder); 464 472 465 tasks = finder.getFoundTasks();473 subsequences = finder.getFoundSubsequences(); 466 474 467 475 createNewTrie = false; 468 476 469 for ( List<ITaskInstance> task : tasks) {470 if ( task.size() >= appData.getTrainedSequenceLength()) {477 for (Subsequence subsequence : subsequences) { 478 if (subsequence.size() >= appData.getTrainedSubsequenceLength()) { 471 479 // Trie must be recreated with a longer sequence length to be sure that 472 480 // the found sequences occurring most often are found in their whole length 473 appData.setTrainedS equenceLength(appData.getTrainedSequenceLength() + 1);481 appData.setTrainedSubsequenceLength(appData.getTrainedSubsequenceLength() + 1); 474 482 createNewTrie = true; 475 483 break; … … 536 544 dumper.dumpCounters();*/ 537 545 538 appData.setLastFoundTasks(tasks); 539 540 Console.traceln(Level.FINE, "found " + appData.getLastFoundTasks().size() + " tasks " + 541 "occurring " + appData.getLastFoundTasks().getOccurrenceCount() + " times"); 546 appData.setLastFoundSubsequences(subsequences); 547 548 Console.traceln(Level.FINE, "found " + appData.getLastFoundSubsequences().size() + 549 " tasks occurring " + 550 appData.getLastFoundSubsequences().getOccurrenceCount() + " times"); 542 551 } 543 552 … … 546 555 */ 547 556 private void createNewTrie(RuleApplicationData appData) { 548 Console.traceln(Level.FINE R, "training trie with a maximum sequence length of " +549 appData.getTrainedS equenceLength());557 Console.traceln(Level.FINEST, "training trie with a maximum sequence length of " + 558 appData.getTrainedSubsequenceLength()); 550 559 551 560 appData.getStopWatch().start("training trie"); … … 557 566 558 567 appData.getLastTrie().trainSessions 559 (appData.getSessions(), appData.getTrainedS equenceLength());568 (appData.getSessions(), appData.getTrainedSubsequenceLength()); 560 569 561 570 appData.getStopWatch().stop("training trie"); 571 } 572 573 /** 574 * from the last found tasks, sort out those that interleave with each other as for them always 575 * the same replacement order needs to be taken. 576 */ 577 private void removeInterleavingTasks(RuleApplicationData appData) { 578 // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 579 // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> TEST IMPLEMENTATION >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 580 // dumpSortedCollectionOfSubsequences 581 // ("found task", appData.getLastFoundSubsequences().subsequences); 582 // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< 583 // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< TEST IMPLEMENTATION <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< 584 585 List<InterleavingSubsequence> interleavings; 586 587 do { 588 interleavings = getInterleavings(appData.getLastFoundSubsequences(), appData); 589 590 if (interleavings.size() > 0) { 591 // dumpSorted(interleavings); 592 593 // Console.traceln(Level.FINEST, "found " + interleavings.size() + " subsequences " + 594 // "--> checking for most real interleavings"); 595 596 // we found interleaving subsequences. We need to decide for them, which to replace 597 // first. For this, we need to remove some of them from the list of detected 598 // subsequences in an ordered way to always have the same prioritization for 599 // replacements. The ones to be removed are those with most interleavings. 600 interleavings = getMostIntensiveInterleavings(interleavings); 601 602 //dumpSorted(interleavings); 603 604 if (interleavings.size() == 1) { 605 // Console.traceln(Level.FINEST, "found one most interleaving subsequence " + 606 // "--> removing it and checking for further interleavings"); 607 608 // we have exactly one most interleaving detected subsequence. In this case, 609 // we remove it from the list of found subsequences and check again, if their 610 // are remaining interleavings. If not, we have the final list of non 611 // interleaving subsequences to be replaced. The order or their replacement 612 // doesn't matter as they are not interleaving. 613 appData.getLastFoundSubsequences().remove 614 (interleavings.get(0).getSubsequence()); 615 616 continue; 617 } 618 else if (interleavings.size() == 0) { 619 // this should never happen 620 throw new RuntimeException("Implementation error: don't know how I got here"); 621 } 622 623 // Console.traceln(Level.FINEST, "found " + interleavings.size() + " most " + 624 // "interleaving subsequences --> checking which are most often a " + 625 // "successor"); 626 627 // there are several subsequences with the same amount of interleavings. 628 // Check which of them is the most often a successor. This should be removed. 629 interleavings = getMostInterleavingsAsSuccessor(interleavings); 630 631 // dumpSorted(interleavings); 632 633 if (interleavings.size() == 1) { 634 // Console.traceln(Level.FINEST, "found one interleaving subsequence being most " + 635 // "often a successor --> removing it and checking for further " + 636 // "interleavings"); 637 638 // we have exactly one interleaving subsequence that is most often a successor 639 // of the others. Remove it and try again to see if sufficient interleavings 640 // were cleared. 641 appData.getLastFoundSubsequences().remove 642 (interleavings.get(0).getSubsequence()); 643 644 continue; 645 } 646 else if (interleavings.size() == 0) { 647 // this should never happen 648 throw new RuntimeException("Implementation error: don't know how I got here"); 649 } 650 651 // Console.traceln(Level.FINEST, "found " + interleavings.size() + 652 // " most interleaving subsequences being most often a successor " + 653 // "--> checking which is most seldom a predecessor"); 654 655 // there are several subsequences with the same amount of interleavings being also 656 // the same times a successor of another subsequence. Hence, check which of them is 657 // the least often a predecessor. This should be removed. 658 interleavings = getLeastInterleavingsAsPredecessor(interleavings); 659 660 //dumpSorted(interleavings); 661 662 if (interleavings.size() == 1) { 663 // Console.traceln(Level.FINEST, "found one interleaving subsequence being most " + 664 // "often a successor and most seldom a predecessor --> " + 665 // "removing it and checking for further interleavings"); 666 667 // we have exactly one interleaving subsequence that is most often a successor 668 // and most seldom a predecessor of the others. Remove it and try again to see 669 // if sufficient interleavings were cleared. 670 appData.getLastFoundSubsequences().remove 671 (interleavings.get(0).getSubsequence()); 672 673 continue; 674 } 675 else if (interleavings.size() == 0) { 676 // this should never happen 677 throw new RuntimeException("Implementation error: don't know how I got here"); 678 } 679 680 // the remaining subsequences are interleaving the same amount of times and are 681 // used the same amount of times as successors and as predecessors by all other 682 // detected interleaving subsequences. Now lets check, which of them is mostly used 683 // as successor and most seldom used as predecessor only considering the remaining 684 // subsequences. If some of them do not interfere with the others, remove them and 685 // try again to see if sufficient interleavings were cleared. 686 687 // Console.traceln(Level.FINEST, "found " + interleavings.size() + 688 // " most interleaving subsequences being most often a successor " + 689 // "and most seldom a predecessor --> removing collision being not " + 690 // "between themselves"); 691 692 interleavings = removeCollisionsOfOtherSubsequences(interleavings); 693 694 // dumpSorted(interleavings); 695 696 // Console.traceln(Level.FINEST, "removed collisions of other subsequences not " + 697 // "belonging to the remaining interleaving subsequences --> " + 698 // "checking of the remaining interleaving are most often a " + 699 // "successor of another one"); 700 701 interleavings = getMostInterleavingsAsSuccessor(interleavings); 702 interleavings = removeCollisionsOfOtherSubsequences(interleavings); 703 704 // dumpSorted(interleavings); 705 706 if (interleavings.size() == 1) { 707 // Console.traceln(Level.FINEST, "found one interleaving subsequence being most " + 708 // "often a successor in comparison to the other remaining " + 709 // "interleavings --> removing it and checking for further " + 710 // "interleavings"); 711 712 appData.getLastFoundSubsequences().remove 713 (interleavings.get(0).getSubsequence()); 714 715 continue; 716 } 717 else if (interleavings.size() == 0) { 718 // this should never happen 719 throw new RuntimeException("Implementation error: don't know how I got here"); 720 } 721 722 // Console.traceln(Level.FINEST, "found " + interleavings.size() + 723 // " most interleaving subsequences being most often a successor in " + 724 // "comparison to the other remaining interleavings --> checking " + 725 // "which is most seldom a predecessor"); 726 727 interleavings = getLeastInterleavingsAsPredecessor(interleavings); 728 interleavings = removeCollisionsOfOtherSubsequences(interleavings); 729 730 // dumpSorted(interleavings); 731 732 if (interleavings.size() == 1) { 733 // Console.traceln(Level.FINEST, "found one interleaving subsequence being most " + 734 // "often a successor and most seldom a predecessor in " + 735 // "comparison to the other remaining interleavings --> " + 736 // "removing it and checking for further interleavings"); 737 738 appData.getLastFoundSubsequences().remove 739 (interleavings.get(0).getSubsequence()); 740 741 continue; 742 } 743 else if (interleavings.size() == 0) { 744 // this should never happen 745 throw new RuntimeException("Implementation error: don't know how I got here"); 746 } 747 748 // Console.traceln(Level.FINEST, "found " + interleavings.size() + 749 // " most interleaving subsequences being most often a successor " + 750 // "and most seldom a predecessor in comparison to the other " + 751 // "remaining interleavings --> this may happen if there are no " + 752 // "collisions between them anymore. If so, remove all of them at " + 753 // "once."); 754 755 int collisionCount = 0; 756 757 for (InterleavingSubsequence subsequence : interleavings) { 758 collisionCount += subsequence.getCollisionCounter(); 759 } 760 761 if (collisionCount == 0) { 762 // Console.traceln(Level.FINEST, "remaining interleaving subsequences have no " + 763 // "further collisions with each other --> removing all of them " + 764 // "and checking for further interleavings"); 765 766 for (InterleavingSubsequence subsequence : interleavings) { 767 appData.getLastFoundSubsequences().remove(subsequence.getSubsequence()); 768 } 769 770 continue; 771 } 772 773 // Console.traceln(Level.FINEST, "remaining interleaving subsequences still have " + 774 // "collisions with each other --> decide based on their occurrences" + 775 // " in the sessions (remove those, coming later in comparison to " + 776 // "the others)"); 777 778 // determine the predecessor collisions being the last in all sessions. Those 779 // collisions show the interleaving subsequence occurring last 780 Map<IUserSession, Collision> sessions = 781 new IdentityHashMap<IUserSession, Collision>(); 782 783 for (InterleavingSubsequence interleaving : interleavings) { 784 for (Collision coll : interleaving.getPredecessorCollisions()) { 785 Collision maxPosColl = sessions.get(coll.getLocation().getSession()); 786 787 if ((maxPosColl == null) || 788 (maxPosColl.getLocation().getIndex() < coll.getLocation().getIndex())) 789 { 790 sessions.put(coll.getLocation().getSession(), coll); 791 } 792 } 793 } 794 795 // determine, which of the subsequences occurs most often as the last one 796 // interleaving with another 797 Map<Subsequence, Integer> lastOccurrenceCounters = 798 new IdentityHashMap<Subsequence, Integer>(); 799 800 for (Collision coll : sessions.values()) { 801 Integer counter = lastOccurrenceCounters.get(coll.getSubsequence()); 802 803 if (counter == null) { 804 lastOccurrenceCounters.put(coll.getSubsequence(), 1); 805 } 806 else { 807 lastOccurrenceCounters.put(coll.getSubsequence(), counter + 1); 808 } 809 } 810 811 int maxCounter = 0; 812 Subsequence toRemove = null; 813 814 for (Map.Entry<Subsequence, Integer> entry : lastOccurrenceCounters.entrySet()) { 815 if (entry.getValue() > maxCounter) { 816 maxCounter = entry.getValue(); 817 toRemove = entry.getKey(); 818 } 819 else if (entry.getValue() == maxCounter) { 820 // we can not decide again 821 toRemove = null; 822 break; 823 } 824 } 825 826 if (toRemove != null) { 827 // Console.traceln(Level.FINEST, "one of the remaining interleaving subsequences" + 828 // " is most often the last to occur --> removing it and " + 829 // "checking for further interleavings"); 830 831 appData.getLastFoundSubsequences().remove(toRemove); 832 continue; 833 } 834 835 // checking now, if there is one sequence, having the lowest index for any of 836 // its collisions and preserve it. If there are several ones with the same minimum 837 // index, throw an exception 838 int minPosInAnySequence = Integer.MAX_VALUE; 839 InterleavingSubsequence subsequenceWithMinPos = null; 840 841 for (InterleavingSubsequence interleaving : interleavings) { 842 for (Collision collision : interleaving.getSuccessorCollisions()) { 843 if (minPosInAnySequence > collision.getLocation().getIndex()) { 844 minPosInAnySequence = collision.getLocation().getIndex(); 845 subsequenceWithMinPos = interleaving; 846 } 847 else if (minPosInAnySequence == collision.getLocation().getIndex()) { 848 // several have the same min pos --> undecidable which to prefer 849 subsequenceWithMinPos = null; 850 } 851 } 852 } 853 854 if (subsequenceWithMinPos != null) { 855 List<Subsequence> subsequencesToRemove = new LinkedList<Subsequence>(); 856 857 for (Subsequence candidate : appData.getLastFoundSubsequences()) { 858 if (candidate != subsequenceWithMinPos.getSubsequence()) { 859 subsequencesToRemove.add(candidate); 860 } 861 } 862 863 for (Subsequence candidate : subsequencesToRemove) { 864 appData.getLastFoundSubsequences().remove(candidate); 865 } 866 867 continue; 868 } 869 870 // At this point, we can not decide anymore. But it should also not 871 // happen. Even if two subsequences ab and ba one of them should be 872 // more often a successor or predecessor than the other if they 873 // directly follow each other. If not, it can not be decided, which of 874 // them to replace first. Perhaps the one occurring more often as 875 // the first in a session that the other. But this can be implemented 876 // later. 877 dumpSorted(interleavings, Level.SEVERE); 878 879 throw new RuntimeException 880 ("can not decide which detected subsequence to replace first."); 881 } 882 } 883 while (interleavings.size() > 0); 884 885 // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 886 // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> TEST IMPLEMENTATION >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 887 // dumpSortedCollectionOfSubsequences 888 // ("to replace", appData.getLastFoundSubsequences().subsequences); 889 // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< 890 // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< TEST IMPLEMENTATION <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< 891 } 892 893 /** 894 * 895 */ 896 private List<InterleavingSubsequence> getInterleavings(Subsequences subsequences, 897 RuleApplicationData appData) 898 { 899 List<InterleavingSubsequence> interleavings = new LinkedList<InterleavingSubsequence>(); 900 List<Subsequence> potentialPredecessors = new LinkedList<Subsequence>(); 901 List<Subsequence> potentialSuccessors = new LinkedList<Subsequence>(); 902 903 Map<Subsequence, List<SubsequenceLocation>> allLocations = 904 getLocations(subsequences, appData); 905 906 for (Subsequence subsequence : subsequences) { 907 // Console.traceln 908 // (Level.FINEST, "searching for interleavings of " + toPlainStr(subsequence)); 909 910 potentialPredecessors.clear(); 911 potentialSuccessors.clear(); 912 913 getInterleavingSubsequences 914 (subsequence, subsequences, potentialPredecessors, potentialSuccessors); 915 916 if ((potentialPredecessors.size() <= 0) && (potentialSuccessors.size() <= 0)) { 917 // subsequence is not interleaving with others. Check next one. 918 continue; 919 } 920 921 // subsequence is interleaving. First, determine its locations in the user sessions. 922 List<SubsequenceLocation> locations = allLocations.get(subsequence); 923 924 List<Collision> precedingCollisions = 925 getPrecedingCollisions(subsequence, locations, potentialPredecessors, appData); 926 927 List<Collision> succeedingCollisions = 928 getSucceedingCollisions(subsequence, locations, potentialSuccessors, appData); 929 930 if ((precedingCollisions.size() <= 0) && (succeedingCollisions.size() <= 0)) { 931 // subsequence is not interleaving with others. Check next one. 932 continue; 933 } 934 935 interleavings.add(new InterleavingSubsequence(subsequence, precedingCollisions, 936 succeedingCollisions)); 937 } 938 939 return interleavings; 940 } 941 942 /** 943 * 944 */ 945 private void getInterleavingSubsequences(Subsequence subsequence, 946 Subsequences allSubsequences, 947 List<Subsequence> potentialPredecessors, 948 List<Subsequence> potentialSuccessors) 949 { 950 TaskComparator comparator = identityTaskHandlingStrategy.getTaskComparator(); 951 952 for (Subsequence candidate : allSubsequences) { 953 if (comparator.equals(subsequence.get(subsequence.size() - 1), candidate.get(0))) { 954 potentialSuccessors.add(candidate); 955 } 956 957 if (comparator.equals(subsequence.get(0), candidate.get(candidate.size() - 1))) { 958 potentialPredecessors.add(candidate); 959 } 960 } 961 962 // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 963 // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> TEST IMPLEMENTATION >>>>>>>>>>>>>>>>>>>>>>>>>>>>> 964 // Console.traceln(Level.FINEST, " potential successors of " + toPlainStr(subsequence)); 965 // dumpSortedCollectionOfSubsequences(" ", potentialSuccessors); 966 967 // Console.traceln(Level.FINEST, " potential predecessors of " + toPlainStr(subsequence)); 968 // dumpSortedCollectionOfSubsequences(" ", potentialPredecessors); 969 // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< 970 // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< TEST IMPLEMENTATION <<<<<<<<<<<<<<<<<<<<<<<<<<<<< 971 } 972 973 /** 974 * 975 */ 976 private Map<Subsequence, List<SubsequenceLocation>> getLocations(Subsequences subsequences, 977 RuleApplicationData appData) 978 { 979 Map<Subsequence, List<SubsequenceLocation>> result = 980 new IdentityHashMap<Subsequence, List<SubsequenceLocation>>(); 981 982 // fill the map with empty locations 983 for (Subsequence subsequence : subsequences) { 984 result.put(subsequence, new LinkedList<SubsequenceLocation>()); 985 } 986 987 LinkedList<LinkedList<Subsequence>> candidates = new LinkedList<LinkedList<Subsequence>>(); 988 989 for (IUserSession session : appData.getSessions()) { 990 for (int i = 0; i < session.size(); i++) { 991 ITask currentTask = session.get(i).getTask(); 992 993 // create a list of candidates that may start here 994 LinkedList<Subsequence> candidatesToStartHere = new LinkedList<Subsequence>(); 995 996 for (Subsequence candidate : subsequences) { 997 if (candidate.get(0) == currentTask) { 998 candidatesToStartHere.add(candidate); 999 } 1000 } 1001 1002 candidates.addFirst(candidatesToStartHere); 1003 1004 // check if the other candidates continue here. 1005 ListIterator<LinkedList<Subsequence>> candidatesIt = candidates.listIterator(1); 1006 int index = 1; 1007 while (candidatesIt.hasNext()) { 1008 ListIterator<Subsequence> candidateIt = candidatesIt.next().listIterator(); 1009 while (candidateIt.hasNext()) { 1010 Subsequence candidate = candidateIt.next(); 1011 1012 if (candidate.get(index) == currentTask) { 1013 if (candidate.size() == (index + 1)) { 1014 // subsequence was fully matched --> store location 1015 result.get(candidate).add 1016 (new SubsequenceLocation(session, i - candidate.size() + 1)); 1017 candidateIt.remove(); 1018 } 1019 } 1020 else if (candidate.get(index) != currentTask) { 1021 // remove the candidate as it is not located here 1022 candidateIt.remove(); 1023 } 1024 } 1025 1026 index++; 1027 } 1028 1029 // remove potential continuation being empty 1030 while ((candidates.size() > 0) && (candidates.getLast().size() == 0)) { 1031 candidates.removeLast(); 1032 } 1033 } 1034 } 1035 1036 return result; 1037 } 1038 1039 /** 1040 * 1041 */ 1042 private List<Collision> getPrecedingCollisions(Subsequence subsequence, 1043 List<SubsequenceLocation> locations, 1044 List<Subsequence> potentialPredecessors, 1045 RuleApplicationData appData) 1046 { 1047 List<Collision> precedingCollisions = new LinkedList<Collision>(); 1048 int interleavingStartIndex; 1049 int interleavingEndIndex; 1050 1051 for (SubsequenceLocation location : locations) { 1052 for (Subsequence predecessor : potentialPredecessors) { 1053 // start where the interleaving would start 1054 interleavingStartIndex = location.getIndex() - predecessor.size() + 1; 1055 1056 if (interleavingStartIndex >= 0) { 1057 interleavingEndIndex = 1058 getSubListIndex(location.getSession(), predecessor, interleavingStartIndex); 1059 1060 if (interleavingStartIndex == interleavingEndIndex) { 1061 precedingCollisions.add(new Collision(location, subsequence, predecessor)); 1062 } 1063 } 1064 } 1065 } 1066 1067 return precedingCollisions; 1068 } 1069 1070 /** 1071 * 1072 */ 1073 private List<Collision> getSucceedingCollisions(Subsequence subsequence, 1074 List<SubsequenceLocation> locations, 1075 List<Subsequence> potentialPredecessors, 1076 RuleApplicationData appData) 1077 { 1078 List<Collision> succeedingCollisions = new LinkedList<Collision>(); 1079 int interleavingStartIndex; 1080 int interleavingEndIndex; 1081 1082 for (SubsequenceLocation location : locations) { 1083 for (Subsequence successor : potentialPredecessors) { 1084 interleavingStartIndex = location.getIndex() + subsequence.size() - 1; 1085 interleavingEndIndex = 1086 getSubListIndex(location.getSession(), successor, interleavingStartIndex); 1087 1088 if (interleavingStartIndex == interleavingEndIndex) { 1089 succeedingCollisions.add(new Collision(location, subsequence, successor)); 1090 } 1091 } 1092 } 1093 1094 return succeedingCollisions; 1095 } 1096 1097 /** 1098 * 1099 */ 1100 private List<InterleavingSubsequence> getMostIntensiveInterleavings 1101 (List<InterleavingSubsequence> interleavings) 1102 { 1103 List<InterleavingSubsequence> mostIntensiveInterleavings = 1104 new LinkedList<InterleavingSubsequence>(); 1105 1106 int collisionCounter = 0; 1107 1108 for (InterleavingSubsequence interleaving : interleavings) { 1109 if (interleaving.getCollisionCounter() > collisionCounter) { 1110 collisionCounter = interleaving.getCollisionCounter(); 1111 mostIntensiveInterleavings.clear(); 1112 } 1113 1114 if (interleaving.getCollisionCounter() == collisionCounter) { 1115 mostIntensiveInterleavings.add(interleaving); 1116 } 1117 } 1118 1119 return mostIntensiveInterleavings; 1120 } 1121 1122 /** 1123 * 1124 */ 1125 private List<InterleavingSubsequence> getLeastInterleavingsAsPredecessor 1126 (List<InterleavingSubsequence> interleavings) 1127 { 1128 List<InterleavingSubsequence> leastInterleavingsAsPredecessor = 1129 new LinkedList<InterleavingSubsequence>(); 1130 1131 int collisionCounter = Integer.MAX_VALUE; 1132 1133 for (InterleavingSubsequence interleaving : interleavings) { 1134 if (interleaving.getSuccessorCollisionCounter() < collisionCounter) { 1135 collisionCounter = interleaving.getSuccessorCollisionCounter(); 1136 leastInterleavingsAsPredecessor.clear(); 1137 } 1138 1139 if (interleaving.getSuccessorCollisionCounter() == collisionCounter) { 1140 leastInterleavingsAsPredecessor.add(interleaving); 1141 } 1142 } 1143 1144 return leastInterleavingsAsPredecessor; 1145 } 1146 1147 /** 1148 * 1149 */ 1150 private List<InterleavingSubsequence> getMostInterleavingsAsSuccessor 1151 (List<InterleavingSubsequence> interleavings) 1152 { 1153 List<InterleavingSubsequence> mostInterleavingsAsSuccessor = 1154 new LinkedList<InterleavingSubsequence>(); 1155 1156 int collisionCounter = 0; 1157 1158 for (InterleavingSubsequence interleaving : interleavings) { 1159 if (interleaving.getPredecessorCollisionCounter() > collisionCounter) { 1160 collisionCounter = interleaving.getPredecessorCollisionCounter(); 1161 mostInterleavingsAsSuccessor.clear(); 1162 } 1163 1164 if (interleaving.getPredecessorCollisionCounter() == collisionCounter) { 1165 mostInterleavingsAsSuccessor.add(interleaving); 1166 } 1167 } 1168 1169 return mostInterleavingsAsSuccessor; 1170 } 1171 1172 /** 1173 * 1174 */ 1175 private List<InterleavingSubsequence> removeCollisionsOfOtherSubsequences 1176 (List<InterleavingSubsequence> interleavings) 1177 { 1178 List<InterleavingSubsequence> subsequencesWithoutOtherCollisions = 1179 new LinkedList<InterleavingSubsequence>(); 1180 1181 for (InterleavingSubsequence interleaving : interleavings) { 1182 List<Collision> reducedPredecessorCollisions = new LinkedList<>(); 1183 1184 for (Collision collision : interleaving.getPredecessorCollisions()) { 1185 for (InterleavingSubsequence otherInterleaving : interleavings) { 1186 if (otherInterleaving.getSubsequence() == collision.getCollidingWith()) { 1187 reducedPredecessorCollisions.add(collision); 1188 break; 1189 } 1190 } 1191 } 1192 1193 List<Collision> reducedSuccessorCollisions = new LinkedList<>(); 1194 1195 for (Collision collision : interleaving.getSuccessorCollisions()) { 1196 for (InterleavingSubsequence otherInterleaving : interleavings) { 1197 if (otherInterleaving.getSubsequence() == collision.getCollidingWith()) { 1198 reducedSuccessorCollisions.add(collision); 1199 break; 1200 } 1201 } 1202 } 1203 1204 subsequencesWithoutOtherCollisions.add 1205 (new InterleavingSubsequence(interleaving.getSubsequence(), 1206 reducedPredecessorCollisions, 1207 reducedSuccessorCollisions)); 1208 } 1209 1210 return subsequencesWithoutOtherCollisions; 562 1211 } 563 1212 … … 568 1217 appData.detectedAndReplacedTasks(false); 569 1218 570 if ((appData.getLastFound Tasks().size() > 0) &&571 (appData.getLastFound Tasks().getOccurrenceCount() > 1))1219 if ((appData.getLastFoundSubsequences().size() > 0) && 1220 (appData.getLastFoundSubsequences().getOccurrenceCount() > 1)) 572 1221 { 573 1222 Console.traceln(Level.FINER, "replacing tasks occurrences"); 574 1223 575 for ( List<ITaskInstance> task : appData.getLastFoundTasks()) {1224 for (Subsequence subsequence : appData.getLastFoundSubsequences()) { 576 1225 ISequence sequence = taskFactory.createNewSequence(); 577 1226 578 Console.traceln(Level.FINEST, "replacing " + sequence.getId() + ": " + task);579 580 List<ISequenceInstance> sequenceInstances = 581 replaceTaskOccurrences(task, appData.getSessions(), sequence);582 583 harmonizeSequenceInstancesModel(sequence, sequenceInstances, task.size());1227 Console.traceln(Level.FINEST, "replacing " + sequence.getId() + ": " + subsequence); 1228 1229 List<ISequenceInstance> sequenceInstances = replaceSubsequenceOccurrences 1230 (subsequence, appData.getSessions(), sequence); 1231 1232 harmonizeSequenceInstancesModel(sequence, sequenceInstances, subsequence.size()); 584 1233 appData.detectedAndReplacedTasks 585 1234 (appData.detectedAndReplacedTasks() || (sequenceInstances.size() > 0)); 586 1235 587 if (sequenceInstances.size() < appData.getLastFound Tasks().getOccurrenceCount()) {1236 if (sequenceInstances.size() < appData.getLastFoundSubsequences().getOccurrenceCount()) { 588 1237 Console.traceln(Level.FINE, sequence.getId() + ": replaced task only " + 589 1238 sequenceInstances.size() + " times instead of expected " + 590 appData.getLastFoundTasks().getOccurrenceCount()); 591 } 592 } 593 } 594 1239 appData.getLastFoundSubsequences().getOccurrenceCount()); 1240 } 1241 } 1242 } 595 1243 } 596 1244 … … 602 1250 int sequenceLength) 603 1251 { 604 Task InstanceComparator comparator = preparationTaskHandlingStrategy.getTaskComparator();1252 TaskComparator comparator = preparationTaskHandlingStrategy.getTaskComparator(); 605 1253 606 1254 // ensure for each subtask that lexically different variants are preserved … … 660 1308 * @param tree 661 1309 */ 662 private List<ISequenceInstance> replace TaskOccurrences(List<ITaskInstance> task,663 List<IUserSession> sessions,664 ISequence temporalTaskModel)1310 private List<ISequenceInstance> replaceSubsequenceOccurrences(Subsequence subsequence, 1311 List<IUserSession> sessions, 1312 ISequence temporalTaskModel) 665 1313 { 666 1314 List<ISequenceInstance> sequenceInstances = new LinkedList<ISequenceInstance>(); … … 668 1316 for (IUserSession session : sessions) { 669 1317 int index = -1; 670 1318 671 1319 do { 672 index = getSubListIndex(session, task, ++index);1320 index = getSubListIndex(session, subsequence, ++index); 673 1321 674 1322 if (index > -1) { 1323 // subsequence is found --> perform replacement 675 1324 sequenceInstances.add 676 1325 (RuleUtils.createNewSubSequenceInRange 677 (session, index, index + task.size() - 1, temporalTaskModel,1326 (session, index, index + subsequence.size() - 1, temporalTaskModel, 678 1327 taskFactory, taskBuilder)); 679 1328 } … … 691 1340 */ 692 1341 private int getSubListIndex(ITaskInstanceList list, 693 List<ITaskInstance> subList,1342 Subsequence subsequence, 694 1343 int startIndex) 695 1344 { … … 697 1346 int result = -1; 698 1347 699 for (int i = startIndex; i <= list.size() - sub List.size(); i++) {1348 for (int i = startIndex; i <= list.size() - subsequence.size(); i++) { 700 1349 matchFound = true; 701 1350 702 for (int j = 0; j < sub List.size(); j++) {1351 for (int j = 0; j < subsequence.size(); j++) { 703 1352 // we prepared the task instances to refer to unique tasks, if they are treated 704 1353 // as equal. Therefore, we just compare the identity of the tasks of the task 705 1354 // instances 706 if (list.get(i + j).getTask() != sub List.get(j).getTask()) {1355 if (list.get(i + j).getTask() != subsequence.get(j)) { 707 1356 matchFound = false; 708 1357 break; … … 724 1373 * @return 725 1374 */ 726 private int getSubListIndex( List<ITaskInstance> list,727 List<ITaskInstance> subList,728 int 1375 private int getSubListIndex(Subsequence longerSubsequence, 1376 Subsequence shorterSubsequence, 1377 int startIndex) 729 1378 { 730 1379 boolean matchFound; 731 1380 int result = -1; 732 1381 733 for (int i = startIndex; i <= l ist.size() - subList.size(); i++) {1382 for (int i = startIndex; i <= longerSubsequence.size() - shorterSubsequence.size(); i++) { 734 1383 matchFound = true; 735 1384 736 for (int j = 0; j < s ubList.size(); j++) {1385 for (int j = 0; j < shorterSubsequence.size(); j++) { 737 1386 // we prepared the task instances to refer to unique tasks, if they are treated 738 1387 // as equal. Therefore, we just compare the identity of the tasks of the task 739 1388 // instances 740 if (l ist.get(i + j) != subList.get(j)) {1389 if (longerSubsequence.get(i + j) != shorterSubsequence.get(j)) { 741 1390 matchFound = false; 742 1391 break; … … 752 1401 return result; 753 1402 } 1403 1404 // /** 1405 // * 1406 // */ 1407 // private void dumpSorted(List<InterleavingSubsequence> interleavings) { 1408 // dumpSorted(interleavings, Level.FINEST); 1409 // } 1410 1411 /** 1412 * 1413 */ 1414 private void dumpSorted(List<InterleavingSubsequence> interleavings, Level level) { 1415 List<String> tmpList = new LinkedList<String>(); 1416 1417 for (InterleavingSubsequence interleaving : interleavings) { 1418 String taskStr = toPlainStr(interleaving); 1419 int index; 1420 for (index = 0; index < tmpList.size(); index++) { 1421 if (taskStr.compareTo(tmpList.get(index)) > 0) { 1422 break; 1423 } 1424 } 1425 1426 tmpList.add(index, taskStr); 1427 } 1428 1429 for (String task : tmpList) { 1430 Console.traceln(level, task); 1431 } 1432 } 1433 1434 // /** 1435 // * 1436 // */ 1437 // private void dumpSortedCollectionOfSubsequences(String prefix, 1438 // Collection<Subsequence> subsequences) 1439 // { 1440 // List<String> tmpList = new LinkedList<String>(); 1441 // 1442 // for (Subsequence subsequence : subsequences) { 1443 // String taskStr = toPlainStr(subsequence); 1444 // int index; 1445 // for (index = 0; index < tmpList.size(); index++) { 1446 // if (taskStr.compareTo(tmpList.get(index)) > 0) { 1447 // break; 1448 // } 1449 // } 1450 // 1451 // tmpList.add(index, taskStr); 1452 // } 1453 // 1454 // for (String task : tmpList) { 1455 // Console.traceln(Level.FINEST, prefix + " " + task); 1456 // } 1457 // } 1458 1459 /** 1460 * 1461 */ 1462 private String toPlainStr(InterleavingSubsequence interleaving) { 1463 StringBuffer result = new StringBuffer(); 1464 result.append("interleavings of "); 1465 result.append(toPlainStr(interleaving.getSubsequence())); 1466 result.append("\n predecessor collisions:\n"); 1467 1468 for (Collision collision : interleaving.getPredecessorCollisions()) { 1469 result.append(" "); 1470 result.append(toPlainStr(collision.getCollidingWith())); 1471 result.append(" ("); 1472 result.append(collision.getLocation()); 1473 result.append(")\n"); 1474 } 1475 1476 result.append(" successor collisions:\n"); 1477 1478 for (Collision collision : interleaving.getSuccessorCollisions()) { 1479 result.append(" "); 1480 result.append(toPlainStr(collision.getCollidingWith())); 1481 result.append(" ("); 1482 result.append(collision.getLocation()); 1483 result.append(")\n"); 1484 } 1485 1486 return result.toString(); 1487 } 1488 1489 /** 1490 * 1491 */ 1492 private String toPlainStr(Subsequence subsequence) { 1493 StringBuffer result = new StringBuffer(); 1494 result.append(subsequence.size()); 1495 result.append(": "); 1496 for (ITask task : subsequence) { 1497 DebuggingHelper.toPlainStr(task, result); 1498 result.append(" --> "); 1499 } 1500 1501 return result.toString(); 1502 } 754 1503 1504 755 1505 /** 756 1506 * @author Patrick Harms 757 1507 */ 758 private class MaxCountAndLongest TasksFinder implements TrieProcessor<ITaskInstance> {1508 private class MaxCountAndLongestSubsequencesFinder implements TrieProcessor<ITask> { 759 1509 760 1510 /** … … 766 1516 * 767 1517 */ 768 private Li st<List<ITaskInstance>> foundTasks = new LinkedList<List<ITaskInstance>>();1518 private LinkedList<Subsequence> foundSubsequences = new LinkedList<Subsequence>(); 769 1519 770 1520 /** 771 1521 * 772 1522 */ 773 public MaxCountAndLongest TasksFinder() {1523 public MaxCountAndLongestSubsequencesFinder() { 774 1524 super(); 775 1525 this.currentCount = 0; … … 780 1530 */ 781 1531 @Override 782 public TrieProcessor.Result process(List<ITask Instance> foundTask, int count) {1532 public TrieProcessor.Result process(List<ITask> foundTask, int count) { 783 1533 if (foundTask.size() < 2) { 784 1534 // ignore single tasks … … 800 1550 // the provided task occurs more often that all tasks found so far. 801 1551 // clear all found tasks and use the new count as the one searched for 802 found Tasks.clear();1552 foundSubsequences.clear(); 803 1553 this.currentCount = count; 804 1554 } … … 808 1558 // the longest come first 809 1559 boolean added = false; 810 for (int i = 0; i < foundTasks.size(); i++) { 811 if (foundTasks.get(i).size() < foundTask.size()) { 812 // defensive copy 813 foundTasks.add(i, new LinkedList<ITaskInstance>(foundTask)); // defensive copy 1560 for (int i = 0; i < foundSubsequences.size(); i++) { 1561 if (foundSubsequences.get(i).size() < foundTask.size()) { 1562 foundSubsequences.add(i, new Subsequence(currentCount, foundTask)); 814 1563 added = true; 815 1564 break; … … 818 1567 819 1568 if (!added) { 820 found Tasks.add(new LinkedList<ITaskInstance>(foundTask)); // defensive copy1569 foundSubsequences.add(new Subsequence(currentCount, foundTask)); 821 1570 } 822 1571 } … … 828 1577 * @return 829 1578 */ 830 p ublic Tasks getFoundTasks() {1579 private Subsequences getFoundSubsequences() { 831 1580 removePermutationsOfShorterTasks(); 832 return new Tasks(currentCount, foundTasks);1581 return new Subsequences(currentCount, foundSubsequences); 833 1582 } 834 1583 … … 839 1588 // now iterate the sorted list and for each task remove all other tasks that are shorter 840 1589 // (i.e. come later in the sorted list) and that represent a subpart of the task 841 for (int i = 0; i < foundTasks.size(); i++) { 842 for (int j = i + 1; j < foundTasks.size();) { 843 if (foundTasks.get(j).size() < foundTasks.get(i).size()) { 1590 1591 boolean removeI; 1592 1593 for (int i = 0; i < foundSubsequences.size();) { 1594 removeI = false; 1595 boolean removeJ; 1596 1597 for (int j = i + 1; j < foundSubsequences.size();) { 1598 removeJ = false; 1599 1600 if (foundSubsequences.get(j).size() < foundSubsequences.get(i).size()) { 844 1601 // found a task that is a potential subtask. Check for this and remove the 845 1602 // subtask if needed 846 List<ITaskInstance> longTask = foundTasks.get(i);847 List<ITaskInstance> shortTask = foundTasks.get(j);1603 Subsequence longTask = foundSubsequences.get(i); 1604 Subsequence shortTask = foundSubsequences.get(j); 848 1605 849 if (getSubListIndex(longTask, shortTask, 0) > -1) { 850 foundTasks.remove(j); 1606 int index = getSubListIndex(longTask, shortTask, 0); 1607 if (index > -1) { 1608 if (index == 0) { 1609 // check if the short task is included in the long task partially 1610 // a second time. If so, prefer the short task 1611 boolean secondInclude = true; 1612 for (int pos = shortTask.size(); pos < longTask.size(); pos++) { 1613 // we prepared the task instances to refer to unique tasks, if 1614 // they are treated as equal. Therefore, we just compare the 1615 // identity of the tasks of the task instances 1616 if (longTask.get(pos) != shortTask.get(pos % shortTask.size())) 1617 { 1618 secondInclude = false; 1619 break; 1620 } 1621 } 1622 1623 if (secondInclude) { 1624 // delete the long task 1625 // Console.traceln(Level.FINEST, "1: short task is contained several times in longer one --> removing it"); 1626 // Console.traceln(Level.FINEST, "short: " + toPlainStr(shortTask)); 1627 // Console.traceln(Level.FINEST, "long: " + toPlainStr(longTask)); 1628 removeI = true; 1629 } 1630 else { 1631 // Console.traceln(Level.FINEST, "2: short task is a part of a longer one --> removing it"); 1632 // Console.traceln(Level.FINEST, "short: " + toPlainStr(shortTask)); 1633 // Console.traceln(Level.FINEST, "long: " + toPlainStr(longTask)); 1634 removeJ = true; 1635 } 1636 } 1637 else { 1638 // Console.traceln(Level.FINEST, "3: short task is a part of a longer one --> removing it"); 1639 // Console.traceln(Level.FINEST, "short: " + toPlainStr(shortTask)); 1640 // Console.traceln(Level.FINEST, "long: " + toPlainStr(longTask)); 1641 removeJ = true; 1642 } 851 1643 } 852 else { 853 j++; 854 } 1644 } 1645 1646 if (removeJ) { 1647 foundSubsequences.remove(j); 855 1648 } 856 1649 else { … … 858 1651 } 859 1652 } 860 } 861 } 862 863 } 864 1653 1654 if (removeI) { 1655 foundSubsequences.remove(i); 1656 } 1657 else { 1658 i++; 1659 } 1660 } 1661 } 1662 1663 } 1664 865 1665 // /** 866 1666 // * @author Patrick Harms … … 929 1729 930 1730 /** 931 * default and minimum trained s equence length is 3932 */ 933 private int trainedS equenceLength = 3;1731 * default and minimum trained subsequence length is 3 1732 */ 1733 private int trainedSubsequenceLength = 3; 934 1734 935 1735 /** 936 1736 * 937 1737 */ 938 private Tasks lastFoundTasks = new Tasks(Integer.MAX_VALUE, null);1738 private Subsequences lastFoundSubsequences = new Subsequences(Integer.MAX_VALUE, null); 939 1739 940 1740 /** … … 982 1782 983 1783 /** 984 * @param trainedS equenceLength the trainedSequenceLength to set985 */ 986 private void setTrainedS equenceLength(int trainedSequenceLength) {987 this.trainedS equenceLength = trainedSequenceLength;988 } 989 990 /** 991 * @return the trainedS equenceLength992 */ 993 private int getTrainedS equenceLength() {994 return trainedS equenceLength;1784 * @param trainedSubsequenceLength the trainedSubsequenceLength to set 1785 */ 1786 private void setTrainedSubsequenceLength(int trainedSubsequenceLength) { 1787 this.trainedSubsequenceLength = trainedSubsequenceLength; 1788 } 1789 1790 /** 1791 * @return the trainedSubsequenceLength 1792 */ 1793 private int getTrainedSubsequenceLength() { 1794 return trainedSubsequenceLength; 995 1795 } 996 1796 … … 998 1798 * @param lastFoundSequences the lastFoundSequences to set 999 1799 */ 1000 private void setLastFound Tasks(Tasks lastFoundSequences) {1001 this.lastFound Tasks = lastFoundSequences;1800 private void setLastFoundSubsequences(Subsequences lastFoundSequences) { 1801 this.lastFoundSubsequences = lastFoundSequences; 1002 1802 } 1003 1803 … … 1005 1805 * @return the lastFoundSequences 1006 1806 */ 1007 private Tasks getLastFoundTasks() {1008 return lastFound Tasks;1807 private Subsequences getLastFoundSubsequences() { 1808 return lastFoundSubsequences; 1009 1809 } 1010 1810 … … 1039 1839 } 1040 1840 1041 1042 1841 /** 1043 1842 * @author Patrick Harms 1044 1843 */ 1045 private static class Tasks implements Iterable<List<ITaskInstance>> {1844 private static class Subsequence implements Iterable<ITask> { 1046 1845 1047 1846 /** … … 1049 1848 */ 1050 1849 private int occurrenceCount; 1051 1850 1052 1851 /** 1053 1852 * 1054 1853 */ 1055 private List<List<ITaskInstance>> sequences; 1854 private List<ITask> subsequence; 1855 1856 /** 1857 * @param occurrenceCount 1858 * @param subsequences 1859 */ 1860 private Subsequence(int occurrenceCount, List<ITask> subsequence) { 1861 super(); 1862 this.occurrenceCount = occurrenceCount; 1863 this.subsequence = new ArrayList<ITask>(subsequence); 1864 } 1865 1866 /** 1867 * @return 1868 */ 1869 private int size() { 1870 return this.subsequence.size(); 1871 } 1872 1873 /** 1874 * @return 1875 */ 1876 private ITask get(int index) { 1877 return this.subsequence.get(index); 1878 } 1879 1880 /* (non-Javadoc) 1881 * @see java.lang.Iterable#iterator() 1882 */ 1883 @Override 1884 public Iterator<ITask> iterator() { 1885 return this.subsequence.iterator(); 1886 } 1887 1888 /* (non-Javadoc) 1889 * @see java.lang.Object#toString() 1890 */ 1891 @Override 1892 public String toString() { 1893 return subsequence.toString() + " (" + occurrenceCount + ")"; 1894 } 1895 } 1896 1897 /** 1898 * @author Patrick Harms 1899 */ 1900 private static class Subsequences implements Iterable<Subsequence> { 1901 1902 /** 1903 * 1904 */ 1905 private int occurrenceCount; 1906 1907 /** 1908 * 1909 */ 1910 private LinkedList<Subsequence> subsequences; 1056 1911 1057 1912 /** … … 1059 1914 * @param sequences 1060 1915 */ 1061 private Tasks(int occurrenceCount, List<List<ITaskInstance>>sequences) {1916 private Subsequences(int occurrenceCount, LinkedList<Subsequence> subsequences) { 1062 1917 super(); 1063 1918 this.occurrenceCount = occurrenceCount; 1064 this.sequences = sequences; 1919 this.subsequences = subsequences; 1920 } 1921 1922 /** 1923 * 1924 */ 1925 private void remove(Subsequence subsequence) { 1926 ListIterator<Subsequence> it = subsequences.listIterator(); 1927 1928 while (it.hasNext()) { 1929 // reference comparison is sufficient 1930 if (it.next() == subsequence) { 1931 it.remove(); 1932 } 1933 } 1065 1934 } 1066 1935 … … 1076 1945 */ 1077 1946 private int size() { 1078 return this.sequences.size(); 1079 } 1080 1081 /** 1082 * 1083 */ 1947 return this.subsequences.size(); 1948 } 1084 1949 1085 1950 /* (non-Javadoc) … … 1087 1952 */ 1088 1953 @Override 1089 public Iterator< List<ITaskInstance>> iterator() {1090 return this.s equences.iterator();1954 public Iterator<Subsequence> iterator() { 1955 return this.subsequences.iterator(); 1091 1956 } 1092 1957 … … 1097 1962 public String toString() { 1098 1963 StringBuffer result = new StringBuffer(); 1964 result.append(" subsequences occuring "); 1099 1965 result.append(this.occurrenceCount); 1100 result.append(" occurrences:\n");1101 1102 for ( List<ITaskInstance> task :sequences) {1103 result.append( task);1966 result.append(" times:\n"); 1967 1968 for (Subsequence subsequence : subsequences) { 1969 result.append(subsequence); 1104 1970 result.append("\n"); 1105 1971 } … … 1107 1973 return result.toString(); 1108 1974 } 1109 1975 } 1976 1977 /** 1978 * @author Patrick Harms 1979 */ 1980 private static class InterleavingSubsequence { 1981 1982 /** */ 1983 private Subsequence subsequence; 1984 1985 /** */ 1986 private List<Collision> successorCollisions; 1987 1988 /** */ 1989 private List<Collision> predecessorCollisions; 1990 1991 /** 1992 * 1993 */ 1994 private InterleavingSubsequence(Subsequence subsequence, 1995 List<Collision> predecessorCollisions, 1996 List<Collision> successorCollisions) 1997 { 1998 super(); 1999 this.subsequence = subsequence; 2000 this.predecessorCollisions = predecessorCollisions; 2001 this.successorCollisions = successorCollisions; 2002 } 2003 2004 /** 2005 * 2006 */ 2007 private int getCollisionCounter() { 2008 return getSuccessorCollisionCounter() + getPredecessorCollisionCounter(); 2009 } 2010 2011 /** 2012 * 2013 */ 2014 private int getSuccessorCollisionCounter() { 2015 return successorCollisions.size(); 2016 } 2017 2018 /** 2019 * 2020 */ 2021 private List<Collision> getSuccessorCollisions() { 2022 return successorCollisions; 2023 } 2024 2025 /** 2026 * 2027 */ 2028 private int getPredecessorCollisionCounter() { 2029 return predecessorCollisions.size(); 2030 } 2031 2032 /** 2033 * 2034 */ 2035 private List<Collision> getPredecessorCollisions() { 2036 return predecessorCollisions; 2037 } 2038 2039 /** 2040 * 2041 */ 2042 private Subsequence getSubsequence() { 2043 return subsequence; 2044 } 2045 2046 /* (non-Javadoc) 2047 * @see java.lang.Object#toString() 2048 */ 2049 @Override 2050 public String toString() { 2051 return "interleaving subsequence " + subsequence.toString() + " (" + 2052 successorCollisions.size() + " successor, " + predecessorCollisions.size() + 2053 " predecessor)"; 2054 } 2055 } 2056 2057 /** 2058 * @author Patrick Harms 2059 */ 2060 private static class SubsequenceLocation { 2061 2062 /** */ 2063 private IUserSession session; 2064 2065 /** */ 2066 private int index; 2067 2068 /** 2069 * 2070 */ 2071 private SubsequenceLocation(IUserSession session, int index) { 2072 this.session = session; 2073 this.index = index; 2074 } 2075 2076 /** 2077 * @return the session 2078 */ 2079 private IUserSession getSession() { 2080 return session; 2081 } 2082 2083 /** 2084 * @return the index 2085 */ 2086 private int getIndex() { 2087 return index; 2088 } 2089 2090 /* (non-Javadoc) 2091 * @see java.lang.Object#toString() 2092 */ 2093 @Override 2094 public String toString() { 2095 return "location (" + session + ", " + index + ")"; 2096 } 2097 } 2098 2099 /** 2100 * @author Patrick Harms 2101 */ 2102 private static class Collision { 2103 2104 /** */ 2105 private SubsequenceLocation location; 2106 2107 /** */ 2108 private Subsequence subsequence; 2109 2110 /** */ 2111 private Subsequence collidingWith; 2112 2113 /** 2114 * 2115 */ 2116 private Collision(SubsequenceLocation location, 2117 Subsequence subsequence, 2118 Subsequence collidingWith) 2119 { 2120 this.location = location; 2121 this.subsequence = subsequence; 2122 this.collidingWith = collidingWith; 2123 } 2124 2125 /** 2126 * @return the collidingWith 2127 */ 2128 private Subsequence getCollidingWith() { 2129 return collidingWith; 2130 } 2131 2132 /** 2133 * @return the location 2134 */ 2135 private SubsequenceLocation getLocation() { 2136 return location; 2137 } 2138 2139 /** 2140 * @return the subsequence 2141 */ 2142 private Subsequence getSubsequence() { 2143 return subsequence; 2144 } 2145 2146 /* (non-Javadoc) 2147 * @see java.lang.Object#toString() 2148 */ 2149 @Override 2150 public String toString() { 2151 return "collision (" + location + " ," + subsequence + ", " + collidingWith + ")"; 2152 } 1110 2153 } 1111 2154
Note: See TracChangeset
for help on using the changeset viewer.