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

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