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

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