source: trunk/autoquest-core-tasktrees/src/main/java/de/ugoe/cs/autoquest/tasktrees/temporalrelation/SequenceForTaskDetectionRule.java @ 1189

Last change on this file since 1189 was 1189, checked in by pharms, 11 years ago
  • remove a find bugs warning
File size: 34.8 KB
Line 
1//   Copyright 2012 Georg-August-Universität Göttingen, Germany
2//
3//   Licensed under the Apache License, Version 2.0 (the "License");
4//   you may not use this file except in compliance with the License.
5//   You may obtain a copy of the License at
6//
7//       http://www.apache.org/licenses/LICENSE-2.0
8//
9//   Unless required by applicable law or agreed to in writing, software
10//   distributed under the License is distributed on an "AS IS" BASIS,
11//   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12//   See the License for the specific language governing permissions and
13//   limitations under the License.
14
15package de.ugoe.cs.autoquest.tasktrees.temporalrelation;
16
17import java.io.IOException;
18import java.io.ObjectInputStream;
19import java.util.HashMap;
20import java.util.Iterator;
21import java.util.LinkedList;
22import java.util.List;
23
24import de.ugoe.cs.autoquest.tasktrees.taskequality.TaskEquality;
25import de.ugoe.cs.autoquest.tasktrees.taskequality.TaskEqualityRuleManager;
26import de.ugoe.cs.autoquest.tasktrees.treeifc.IEventTask;
27import de.ugoe.cs.autoquest.tasktrees.treeifc.IIteration;
28import de.ugoe.cs.autoquest.tasktrees.treeifc.ISelection;
29import de.ugoe.cs.autoquest.tasktrees.treeifc.ISequence;
30import de.ugoe.cs.autoquest.tasktrees.treeifc.ITask;
31import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskBuilder;
32import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskFactory;
33import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInstance;
34import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInstanceList;
35import de.ugoe.cs.autoquest.tasktrees.treeifc.IUserSession;
36import de.ugoe.cs.autoquest.usageprofiles.SymbolComparator;
37import de.ugoe.cs.autoquest.usageprofiles.Trie;
38import de.ugoe.cs.autoquest.usageprofiles.TrieProcessor;
39import de.ugoe.cs.util.StopWatch;
40
41/**
42 * <p>
43 * TODO comment
44 * </p>
45 *
46 * @author Patrick Harms
47 */
48class SequenceForTaskDetectionRule implements ISessionScopeRule {
49   
50    /**
51     * <p>
52     * the task factory to be used for creating substructures for the temporal
53     * relationships identified during rule
54     * </p>
55     */
56    private ITaskFactory taskFactory;
57    /**
58     * <p>
59     * the task builder to be used for creating substructures for the temporal relationships
60     * identified during rule application
61     * </p>
62     */
63    private ITaskBuilder taskBuilder;
64
65    /**
66     * <p>
67     * the task comparator to be used for comparing tasks
68     * </p>
69     */
70    private TaskComparator taskComparator;
71
72    /**
73     * <p>
74     * instantiates the rule and initializes it with a task equality rule manager and the minimal
75     * task equality identified sublist must have to consider them as iterated.
76     * </p>
77     */
78    SequenceForTaskDetectionRule(TaskEquality minimalTaskEquality,
79                                 ITaskFactory taskFactory,
80                                 ITaskBuilder taskBuilder)
81    {
82        this.taskFactory = taskFactory;
83        this.taskBuilder = taskBuilder;
84       
85        this.taskComparator = new TaskComparator(minimalTaskEquality);
86    }
87
88    /* (non-Javadoc)
89     * @see java.lang.Object#toString()
90     */
91    @Override
92    public String toString() {
93        return "SequenceForTaskDetectionRule";
94    }
95
96    /* (non-Javadoc)
97     * @see de.ugoe.cs.autoquest.tasktrees.temporalrelation.ISessionScopeRule#apply(java.util.List)
98     */
99    @Override
100    public RuleApplicationResult apply(List<IUserSession> sessions) {
101        RuleApplicationData appData = new RuleApplicationData(sessions);
102
103        // this is the real rule application. Loop while something is replaced.
104        do {
105            System.out.println();
106           
107            appData.getStopWatch().start("whole loop");
108            detectAndReplaceIterations(appData);
109
110            appData.getStopWatch().start("task replacement");
111            detectAndReplaceTasks(appData);
112            appData.getStopWatch().stop("task replacement");
113            appData.getStopWatch().stop("whole loop");
114           
115            //((TaskTreeNodeComparator) taskComparator).getStopWatch().dumpStatistics(System.out);
116            //((TaskTreeNodeComparator) taskComparator).getStopWatch().reset();
117           
118            appData.getStopWatch().dumpStatistics(System.out);
119            appData.getStopWatch().reset();
120           
121        }
122        while (appData.detectedAndReplacedTasks());
123       
124        System.out.println
125            ("created " + appData.getResult().getNewlyCreatedTasks().size() +
126             " new tasks and " + appData.getResult().getNewlyCreatedTaskInstances().size() +
127             " appropriate instances\n");
128       
129        if ((appData.getResult().getNewlyCreatedTasks().size() > 0) ||
130            (appData.getResult().getNewlyCreatedTaskInstances().size() > 0))
131        {
132            appData.getResult().setRuleApplicationStatus(RuleApplicationStatus.FINISHED);
133        }
134       
135        return appData.getResult();
136    }
137
138    /**
139     * @param appData
140     */
141    private void detectAndReplaceIterations(RuleApplicationData appData) {
142        System.out.print("detecting iterations");
143        appData.getStopWatch().start("detecting iterations");
144       
145        List<IUserSession> sessions = appData.getSessions();
146        int iteratedTasks = 0;
147       
148        ITask iteratedTask = null;
149       
150        do {
151            iteratedTask = searchIteratedTask(sessions);
152           
153            if (iteratedTask != null) {
154                replaceIterationsOf(iteratedTask, sessions, appData);
155                iteratedTasks++;
156            }
157        }
158        while (iteratedTask != null);
159       
160        appData.getStopWatch().stop("detecting iterations");
161        System.out.println(" --> found " + iteratedTasks + " iterated tasks");
162    }
163
164    /**
165     *
166     */
167    private ITask searchIteratedTask(List<IUserSession> sessions) {
168        for (IUserSession session : sessions) {
169            for (int i = 0; i < (session.size() - 1); i++) {
170                if (taskComparator.equals(session.get(i), session.get(i + 1))) {
171                    return session.get(i).getTask();
172                }
173            }
174        }
175       
176        return null;
177    }
178
179    /**
180     *
181     */
182/*    private ITask searchIteratedTask(List<IUserSession> sessions) {
183        int minNoOfRepetitions = 2;
184        int minNoOfIterationOccurrences = 1;
185       
186        Map<ITask, Integer> iterationsCounter = new HashMap<ITask, Integer>();
187       
188        for (IUserSession session : sessions) {
189            for (int i = 0; i < (session.size() - minNoOfRepetitions + 1); i++) {
190                ITask task = session.get(i).getTask();
191
192                // check if the task is iterated
193                boolean isIterated = true;
194                for (int j = i + 1; j < i + minNoOfRepetitions; j++) {
195                    if (!taskComparator.equals(task, session.get(j).getTask())) {
196                        isIterated = false;
197                        break;
198                    }
199                }
200               
201                if (isIterated) {
202                    Integer currentCounter = null;
203                   
204                    for (Map.Entry<ITask, Integer> entry : iterationsCounter.entrySet()) {
205                        if (taskComparator.equals(task, entry.getKey())) {
206                            currentCounter = entry.getValue();
207                            break;
208                        }
209                    }
210                   
211                    if (currentCounter == null) {
212                        currentCounter = 1;
213                        iterationsCounter.put(task, currentCounter);
214                    }
215                    else {
216                        currentCounter++;
217                        iterationsCounter.put(task, currentCounter);
218                    }
219                   
220                    if (currentCounter >= minNoOfIterationOccurrences) {
221                        return task;
222                    }
223                }
224            }
225        }
226       
227        return null;
228    }*/
229
230    /**
231     *
232     */
233    private void replaceIterationsOf(ITask               iteratedTask,
234                                     List<IUserSession>  sessions,
235                                     RuleApplicationData appData)
236    {
237        IIteration iteration = taskFactory.createNewIteration();
238        ITaskInstance iterationInstance = null;
239       
240        List<ITaskInstance> iterationInstances = new LinkedList<ITaskInstance>();
241       
242        for (IUserSession session : sessions) {
243            int index = 0;
244            while (index < session.size()) {
245                if (taskComparator.equals(iteratedTask, session.get(index).getTask())) {
246                    if (iterationInstance == null) {
247                        iterationInstance = taskFactory.createNewTaskInstance(iteration);
248                        iterationInstances.add(iterationInstance);
249                        taskBuilder.addTaskInstance(session, index, iterationInstance);
250                        index++;
251                    }
252                   
253                    taskBuilder.addChild(iterationInstance, session.get(index));
254                    taskBuilder.removeTaskInstance(session, index);
255                }
256                else {
257                    if (iterationInstance != null) {
258                        iterationInstance = null;
259                    }
260                    index++;
261                }
262            }
263        }
264       
265        harmonizeIterationInstancesModel(iteration, iterationInstances);
266    }
267
268    /**
269     *
270     */
271    private void harmonizeIterationInstancesModel(IIteration          iteration,
272                                                  List<ITaskInstance> iterationInstances)
273    {
274        List<ITask> iteratedTaskVariants = new LinkedList<ITask>();
275       
276        // merge the lexically different variants of iterated task to a unique list
277        for (ITaskInstance iterationInstance : iterationInstances) {
278            for (ITaskInstance executionVariant : iterationInstance) {
279                ITask candidate = executionVariant.getTask();
280           
281                boolean found = false;
282                for (ITask taskVariant : iteratedTaskVariants) {
283                    if (taskComparator.areLexicallyEqual(taskVariant, candidate)) {
284                        taskBuilder.setTask(executionVariant, taskVariant);
285                        found = true;
286                        break;
287                    }
288                }
289               
290                if (!found) {
291                    iteratedTaskVariants.add(candidate);
292                }
293            }
294        }
295       
296        // if there are more than one lexically different variant of iterated tasks, adapt the
297        // iteration model to be a selection of different variants. In this case also adapt
298        // the generated iteration instances to correctly contain selection instances. If there
299        // is only one variant of an iterated task, simply set this as the marked task of the
300        // iteration. In this case, the instances can be preserved as is
301        if (iteratedTaskVariants.size() > 1) {
302            ISelection selection = taskFactory.createNewSelection();
303           
304            for (ITask variant : iteratedTaskVariants) {
305                taskBuilder.addChild(selection, variant);
306            }
307           
308            taskBuilder.setMarkedTask(iteration, selection);
309           
310            for (ITaskInstance instance : iterationInstances) {
311                for (int i = 0; i < instance.size(); i++) {
312                    ITaskInstance selectionInstance = taskFactory.createNewTaskInstance(selection);
313                    taskBuilder.addChild(selectionInstance, instance.get(i));
314                    taskBuilder.setTaskInstance(instance, i, selectionInstance);
315                }
316            }
317        }
318        else {
319            taskBuilder.setMarkedTask(iteration, iteratedTaskVariants.get(0));
320        }
321    }
322
323    /**
324     * @param appData
325     */
326    private void detectAndReplaceTasks(RuleApplicationData appData) {
327        System.out.println("detecting and replacing tasks");
328        appData.getStopWatch().start("detecting tasks");
329       
330        getSequencesOccuringMostOften(appData);
331
332        appData.getStopWatch().stop("detecting tasks");
333        appData.getStopWatch().start("replacing tasks");
334       
335        replaceSequencesOccurringMostOften(appData);
336       
337        appData.getStopWatch().stop("replacing tasks");
338        System.out.println("detected and replaced " + appData.getLastFoundTasks().size() + " tasks");
339    }
340
341    /**
342     * @return
343     */
344    private void getSequencesOccuringMostOften(RuleApplicationData appData) {
345        System.out.println("determining most prominent tasks");
346
347        Tasks tasks;
348        boolean createNewTrie = (appData.getLastTrie() == null) ||
349            appData.detectedAndReplacedTasks(); // tree has changed
350       
351        do {
352            if (createNewTrie) {
353                createNewTrie(appData);
354            }
355           
356            MaxCountAndLongestTasksFinder finder = new MaxCountAndLongestTasksFinder();
357            appData.getLastTrie().process(finder);
358       
359            tasks = finder.getFoundTasks();
360           
361            createNewTrie = false;
362           
363            for (List<ITaskInstance> task : tasks) {
364                if (task.size() >= appData.getTrainedSequenceLength()) {
365                    // Trie must be recreated with a longer sequence length to be sure that
366                    // the found sequences occurring most often are found in their whole length
367                    appData.setTrainedSequenceLength(appData.getTrainedSequenceLength() + 1);
368                    createNewTrie = true;
369                    break;
370                }
371            }
372        }
373        while (createNewTrie);
374       
375        appData.setLastFoundTasks(tasks);
376
377        System.out.println("found " + appData.getLastFoundTasks().size() + " tasks occurring " +
378                           appData.getLastFoundTasks().getOccurrenceCount() + " times");
379    }
380
381    /**
382     * @param parent
383     * @return
384     */
385    private void createNewTrie(RuleApplicationData appData) {
386        System.out.println("training trie with a maximum sequence length of " +
387                           appData.getTrainedSequenceLength());
388
389        appData.getStopWatch().start("training trie");
390        appData.setLastTrie(new Trie<ITaskInstance>(taskComparator));
391   
392        List<IUserSession> sessions = appData.getSessions();
393       
394        for (IUserSession session : sessions) {
395            trainTrie(session, appData);
396        }
397       
398        appData.getStopWatch().stop("training trie");
399    }
400
401    /**
402     * @param trie
403     * @param parent
404     */
405    private void trainTrie(IUserSession session, RuleApplicationData appData) {
406        List<ITaskInstance> children = session.getExecutedTasks();
407       
408        if ((children != null) && (children.size() > 0)) {
409            appData.getLastTrie().train(children, appData.getTrainedSequenceLength());
410        }
411    }
412
413    /**
414     * @param appData
415     */
416    private void replaceSequencesOccurringMostOften(RuleApplicationData appData) {
417        appData.detectedAndReplacedTasks(false);
418
419        if ((appData.getLastFoundTasks().size() > 0) &&
420            (appData.getLastFoundTasks().getOccurrenceCount() > 1))
421        {
422            System.out.println("replacing tasks occurrences");
423
424            for (List<ITaskInstance> task : appData.getLastFoundTasks()) {
425                ISequence sequence = taskFactory.createNewSequence();
426               
427                System.out.println("replacing " + sequence.getId() + ": " + task);
428
429                List<ITaskInstance> sequenceInstances =
430                    replaceTaskOccurrences(task, appData.getSessions(), sequence);
431               
432                harmonizeSequenceInstancesModel(sequence, sequenceInstances,task.size());
433                appData.detectedAndReplacedTasks(sequenceInstances.size() > 0);
434
435                if (sequenceInstances.size() < appData.getLastFoundTasks().getOccurrenceCount()) {
436                    System.out.println(sequence.getId() + ": replaced task only " +
437                                       sequenceInstances.size() + " times instead of expected " +
438                                       appData.getLastFoundTasks().getOccurrenceCount());
439                }
440            }
441        }
442       
443    }
444
445    /**
446     *
447     */
448    private void harmonizeSequenceInstancesModel(ISequence           sequence,
449                                                 List<ITaskInstance> sequenceInstances,
450                                                 int                 sequenceLength)
451    {
452       
453        // ensure for each subtask that lexically different variants are preserved
454        for (int subTaskIndex = 0; subTaskIndex < sequenceLength; subTaskIndex++) {
455            List<ITask> subTaskVariants = new LinkedList<ITask>();
456           
457            for (ITaskInstance sequenceInstance : sequenceInstances) {
458                ITask candidate = sequenceInstance.get(subTaskIndex).getTask();
459               
460                boolean found = false;
461               
462                for (int i = 0; i < subTaskVariants.size(); i++) {
463                    if (taskComparator.areLexicallyEqual(subTaskVariants.get(i), candidate)) {
464                        taskBuilder.setTask
465                            (sequenceInstance.get(subTaskIndex), subTaskVariants.get(i));
466                       
467                        found = true;
468                        break;
469                    }
470                }
471               
472                if (!found) {
473                    subTaskVariants.add(candidate);
474                }
475            }
476           
477            // if there are more than one lexically different variant of the sub task at
478            // the considered position, adapt the sequence model at that position to have
479            // a selection of the different variants. In this case also adapt the
480            // generated sequence instances to correctly contain selection instances. If
481            // there is only one variant of sub tasks at the given position, simply set
482            // this variant as the sub task of the selection. In this case, the instances
483            // can be preserved as is
484            if (subTaskVariants.size() > 1) {
485                ISelection selection = taskFactory.createNewSelection();
486               
487                for (ITask variant : subTaskVariants) {
488                    taskBuilder.addChild(selection, variant);
489                }
490               
491                taskBuilder.addChild(sequence, selection);
492               
493                for (ITaskInstance instance : sequenceInstances) {
494                    ITaskInstance selectionInstance =
495                        taskFactory.createNewTaskInstance(selection);
496                    taskBuilder.addChild(selectionInstance, instance.get(subTaskIndex));
497                    taskBuilder.setTaskInstance(instance, subTaskIndex, selectionInstance);
498                }
499            }
500            else if (subTaskVariants.size() == 1) {
501                taskBuilder.addChild(sequence, subTaskVariants.get(0));
502            }
503        }
504    }
505
506    /**
507     * @param tree
508     */
509    private List<ITaskInstance> replaceTaskOccurrences(List<ITaskInstance> task,
510                                                       List<IUserSession>  sessions,
511                                                       ISequence           temporalTaskModel)
512    {
513        List<ITaskInstance> sequenceInstances = new LinkedList<ITaskInstance>();
514       
515        for (IUserSession session : sessions) {
516            int index = -1;
517               
518            do {
519                index = getSubListIndex(session, task, ++index);
520
521                if (index > -1) {
522                    sequenceInstances.add
523                        (RuleUtils.createNewSubSequenceInRange
524                             (session, index, index + task.size() - 1, temporalTaskModel,
525                              taskFactory, taskBuilder));
526                }
527            }
528            while (index > -1);
529        }
530       
531        return sequenceInstances;
532    }
533
534    /**
535     * @param trie
536     * @param object
537     * @return
538     */
539    private int getSubListIndex(ITaskInstanceList   list,
540                                List<ITaskInstance> subList,
541                                int                 startIndex)
542    {
543        boolean matchFound;
544        int result = -1;
545       
546        for (int i = startIndex; i <= list.size() - subList.size(); i++) {
547            matchFound = true;
548           
549            for (int j = 0; j < subList.size(); j++) {
550                if (!taskComparator.equals(list.get(i + j), subList.get(j))) {
551                    matchFound = false;
552                    break;
553                }
554            }
555           
556            if (matchFound) {
557                result = i;
558                break;
559            }
560        }
561       
562        return result;
563    }
564
565    /**
566     * @param trie
567     * @param object
568     * @return
569     */
570    private int getSubListIndex(List<ITaskInstance> list,
571                                List<ITaskInstance> subList,
572                                int                 startIndex)
573    {
574        boolean matchFound;
575        int result = -1;
576       
577        for (int i = startIndex; i <= list.size() - subList.size(); i++) {
578            matchFound = true;
579           
580            for (int j = 0; j < subList.size(); j++) {
581                if (!taskComparator.equals(list.get(i + j), subList.get(j))) {
582                    matchFound = false;
583                    break;
584                }
585            }
586           
587            if (matchFound) {
588                result = i;
589                break;
590            }
591        }
592       
593        return result;
594    }
595   
596    /**
597     * @author Patrick Harms
598     */
599    private class MaxCountAndLongestTasksFinder implements TrieProcessor<ITaskInstance> {
600       
601        /**
602         *
603         */
604        private int currentCount;
605       
606        /**
607         *
608         */
609        private List<List<ITaskInstance>> foundTasks = new LinkedList<List<ITaskInstance>>();
610
611        /**
612         *
613         */
614        public MaxCountAndLongestTasksFinder() {
615            super();
616            this.currentCount = 0;
617        }
618
619        /* (non-Javadoc)
620         * @see de.ugoe.cs.autoquest.usageprofiles.TrieProcessor#process(java.util.List, int)
621         */
622        @Override
623        public TrieProcessor.Result process(List<ITaskInstance> foundTask, int count) {
624            if (foundTask.size() < 2) {
625                // ignore single tasks
626                return TrieProcessor.Result.CONTINUE;
627            }
628           
629            if (count < 2) {
630                // ignore singular occurrences
631                return TrieProcessor.Result.SKIP_NODE;
632            }
633
634            if (this.currentCount > count) {
635                // ignore this children of this task, as they may have only smaller counts than
636                // the already found tasks
637                return TrieProcessor.Result.SKIP_NODE;
638            }
639           
640            if (this.currentCount < count) {
641                // the provided task occurs more often that all tasks found so far.
642                // clear all found tasks and use the new count as the one searched for
643                foundTasks.clear();
644                this.currentCount = count;
645            }
646           
647            if (this.currentCount == count) {
648                // the task is of interest. Sort it into the other found tasks so that
649                // the longest come first
650                boolean added = false;
651                for (int i = 0; i < foundTasks.size(); i++) {
652                    if (foundTasks.get(i).size() < foundTask.size()) {
653                        // defensive copy
654                        foundTasks.add(i, new LinkedList<ITaskInstance>(foundTask)); // defensive copy
655                        added = true;
656                        break;
657                    }
658                }
659               
660                if (!added) {
661                    foundTasks.add(new LinkedList<ITaskInstance>(foundTask)); // defensive copy
662                }
663            }
664           
665            return TrieProcessor.Result.CONTINUE;
666        }
667
668        /**
669         *  @return
670         */
671        public Tasks getFoundTasks() {
672            removePermutationsOfShorterTasks();
673            return new Tasks(currentCount, foundTasks);
674        }
675
676        /**
677         *
678         */
679        private void removePermutationsOfShorterTasks() {
680            // now iterate the sorted list and for each task remove all other tasks that are shorter
681            // (i.e. come later in the sorted list) and that represent a subpart of the task
682            for (int i = 0; i < foundTasks.size(); i++) {
683                for (int j = i + 1; j < foundTasks.size();) {
684                    if (foundTasks.get(j).size() < foundTasks.get(i).size()) {
685                        // found a task that is a potential subtask. Check for this and remove the
686                        // subtask if needed
687                        List<ITaskInstance> longTask = foundTasks.get(i);
688                        List<ITaskInstance> shortTask = foundTasks.get(j);
689                       
690                        if (getSubListIndex(longTask, shortTask, 0) > -1) {
691                            foundTasks.remove(j);
692                        }
693                        else {
694                            j++;
695                        }
696                    }
697                    else {
698                        j++;
699                    }
700                }
701            }
702        }
703
704    }
705   
706    /**
707     *
708     */
709    private static class RuleApplicationData {
710       
711        /**
712         *
713         */
714        private List<IUserSession> sessions;
715       
716        /**
717         *
718         */
719        private Trie<ITaskInstance> lastTrie;
720       
721        /**
722         * default and minimum trained sequence length is 3
723         */
724        private int trainedSequenceLength = 3;
725       
726        /**
727         *
728         */
729        private Tasks lastFoundTasks = new Tasks(Integer.MAX_VALUE, null);
730       
731        /**
732         *
733         */
734        private boolean detectedAndReplacedTasks;
735       
736        /**
737         *
738         */
739        private RuleApplicationResult result = new RuleApplicationResult();
740       
741        /**
742         *
743         */
744        private StopWatch stopWatch = new StopWatch();
745       
746        /**
747         *
748         */
749        private RuleApplicationData(List<IUserSession> sessions) {
750            this.sessions = sessions;
751        }
752
753        /**
754         * @return the tree
755         */
756        private List<IUserSession> getSessions() {
757            return sessions;
758        }
759
760        /**
761         * @param lastTrie the lastTrie to set
762         */
763        private void setLastTrie(Trie<ITaskInstance> lastTrie) {
764            this.lastTrie = lastTrie;
765        }
766
767        /**
768         * @return the lastTrie
769         */
770        private Trie<ITaskInstance> getLastTrie() {
771            return lastTrie;
772        }
773
774        /**
775         * @param trainedSequenceLength the trainedSequenceLength to set
776         */
777        private void setTrainedSequenceLength(int trainedSequenceLength) {
778            this.trainedSequenceLength = trainedSequenceLength;
779        }
780
781        /**
782         * @return the trainedSequenceLength
783         */
784        private int getTrainedSequenceLength() {
785            return trainedSequenceLength;
786        }
787
788        /**
789         * @param lastFoundSequences the lastFoundSequences to set
790         */
791        private void setLastFoundTasks(Tasks lastFoundSequences) {
792            this.lastFoundTasks = lastFoundSequences;
793        }
794
795        /**
796         * @return the lastFoundSequences
797         */
798        private Tasks getLastFoundTasks() {
799            return lastFoundTasks;
800        }
801
802        /**
803         *
804         */
805        private void detectedAndReplacedTasks(boolean detectedAndReplacedTasks) {
806            this.detectedAndReplacedTasks = detectedAndReplacedTasks;
807        }
808
809        /**
810         *
811         */
812        private boolean detectedAndReplacedTasks() {
813            return detectedAndReplacedTasks;
814        }
815       
816        /**
817         * @return the result
818         */
819        private RuleApplicationResult getResult() {
820            return result;
821        }
822
823        /**
824         * @return the stopWatch
825         */
826        private StopWatch getStopWatch() {
827            return stopWatch;
828        }
829
830    }
831   
832
833    /**
834     * @author Patrick Harms
835     */
836    private static class Tasks implements Iterable<List<ITaskInstance>> {
837       
838        /**
839         *
840         */
841        private int occurrenceCount;
842       
843        /**
844         *
845         */
846        private List<List<ITaskInstance>> sequences;
847
848        /**
849         * @param occurrenceCount
850         * @param sequences
851         */
852        private Tasks(int occurrenceCount, List<List<ITaskInstance>> sequences) {
853            super();
854            this.occurrenceCount = occurrenceCount;
855            this.sequences = sequences;
856        }
857
858        /**
859         * @return
860         */
861        private int getOccurrenceCount() {
862            return occurrenceCount;
863        }
864
865        /**
866         * @return
867         */
868        private int size() {
869            return this.sequences.size();
870        }
871
872        /**
873         *
874         */
875
876        /* (non-Javadoc)
877         * @see java.lang.Iterable#iterator()
878         */
879        @Override
880        public Iterator<List<ITaskInstance>> iterator() {
881            return this.sequences.iterator();
882        }
883
884    }
885
886    /**
887     *
888     */
889    private static class TaskComparator implements SymbolComparator<ITaskInstance> {
890       
891        /** */
892        private TaskEquality minimalNodeEquality;
893
894        /** */
895        private transient Comparer comparer;
896
897        /** */
898        private transient Comparer lexicalComparer;
899
900        /** */
901        private transient HashMap<Long, Boolean> equalityBuffer = new HashMap<Long, Boolean>();
902
903        /** */
904        private transient HashMap<Long, Boolean> lexicalEqualityBuffer;
905
906        /**
907         *
908         */
909        public TaskComparator(TaskEquality minimalNodeEquality) {
910            this.minimalNodeEquality = minimalNodeEquality;
911            init();
912        }
913
914        /* (non-Javadoc)
915         * @see de.ugoe.cs.autoquest.tasktrees.temporalrelation.SymbolComparator#equals(java.lang.Object, java.lang.Object)
916         */
917        @Override
918        public boolean equals(ITaskInstance taskInstance1, ITaskInstance taskInstance2) {
919            return equals(taskInstance1.getTask(), taskInstance2.getTask());
920        }       
921
922        /**
923         *
924         */
925        public boolean equals(ITask task1, ITask task2) {
926            Boolean result;
927           
928            if (task1 != task2) {
929                if ((task1 instanceof IEventTask) && (task2 instanceof IEventTask)) {
930                    long key = ((long) System.identityHashCode(task1)) << 32;
931                    key += System.identityHashCode(task2);
932               
933                    result = equalityBuffer.get(key);
934               
935                    if (result == null) {
936                        result = comparer.compare(task1, task2);
937                        equalityBuffer.put(key, result);
938                    }
939                }
940                else {
941                    result = false;
942                }
943            }
944            else {
945                result = true;
946            }
947           
948            return result;
949        }
950
951        /**
952         *
953         */
954        public boolean areLexicallyEqual(ITask task1, ITask task2) {
955            Boolean result;
956           
957            if (task1 != task2) {
958                long key = ((long) System.identityHashCode(task1)) << 32;
959                key += System.identityHashCode(task2);
960               
961                result = lexicalEqualityBuffer.get(key);
962               
963                if (result == null) {
964                    result = lexicalComparer.compare(task1, task2);
965                    lexicalEqualityBuffer.put(key, result);
966                }
967            }
968            else {
969                result = true;
970            }
971           
972            return result;
973        }
974       
975        /**
976         *
977         */
978        private void init() {
979            if (minimalNodeEquality == TaskEquality.LEXICALLY_EQUAL) {
980                comparer = new LexicalComparer();
981            }
982            else if (minimalNodeEquality == TaskEquality.SYNTACTICALLY_EQUAL) {
983                comparer = new SyntacticalComparer();
984            }
985            else if (minimalNodeEquality == TaskEquality.SEMANTICALLY_EQUAL) {
986                comparer = new SemanticalComparer();
987            }
988            else {
989                comparer = new DefaultComparer(this.minimalNodeEquality);
990            }
991           
992            if (minimalNodeEquality == TaskEquality.LEXICALLY_EQUAL) {
993                lexicalComparer = comparer;
994                lexicalEqualityBuffer = equalityBuffer;
995            }
996            else {
997                lexicalComparer = new LexicalComparer();
998                lexicalEqualityBuffer = new HashMap<Long, Boolean>();
999            }
1000        }
1001       
1002        /**
1003         * <p>
1004         * deserialize this object and reinitialize the buffers
1005         * </p>
1006         */
1007        private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
1008            in.defaultReadObject();
1009            init();
1010        }
1011    }
1012
1013    /**
1014     *
1015     */
1016    private static interface Comparer {
1017       
1018        /**
1019         *
1020         */
1021        boolean compare(ITask task1, ITask task2);
1022    }
1023
1024    /**
1025     *
1026     */
1027    private static class LexicalComparer implements Comparer {
1028       
1029        /**
1030         *
1031         */
1032        public boolean compare(ITask task1, ITask task2) {
1033            return TaskEqualityRuleManager.getInstance().areLexicallyEqual(task1, task2);
1034        }
1035    }
1036
1037    /**
1038     *
1039     */
1040    private static class SyntacticalComparer implements Comparer {
1041       
1042        /**
1043         *
1044         */
1045        public boolean compare(ITask task1, ITask task2) {
1046            return TaskEqualityRuleManager.getInstance().areSyntacticallyEqual(task1, task2);
1047        }
1048    }
1049
1050    /**
1051     *
1052     */
1053    private static class SemanticalComparer implements Comparer {
1054       
1055        /**
1056         *
1057         */
1058        public boolean compare(ITask task1, ITask task2) {
1059            return TaskEqualityRuleManager.getInstance().areSemanticallyEqual(task1, task2);
1060        }
1061    }
1062
1063    /**
1064     *
1065     */
1066    private static class DefaultComparer implements Comparer {
1067       
1068        /**
1069         * <p>
1070         * the minimal task equality two identified sublists need to have to consider them as equal
1071         * </p>
1072         */
1073        private TaskEquality minimalNodeEquality;
1074       
1075        /**
1076         *
1077         */
1078        public DefaultComparer(TaskEquality minimalNodeEquality) {
1079           this.minimalNodeEquality = minimalNodeEquality;
1080        }
1081       
1082        /**
1083         *
1084         */
1085        public boolean compare(ITask task1, ITask task2) {
1086            return TaskEqualityRuleManager.getInstance().areAtLeastEqual
1087                (task1, task2, minimalNodeEquality);
1088        }
1089    }
1090}
Note: See TracBrowser for help on using the repository browser.