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
RevLine 
[1113]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
[1107]15package de.ugoe.cs.autoquest.tasktrees.temporalrelation;
16
17import java.util.Iterator;
18import java.util.LinkedList;
19import java.util.List;
20
[1146]21import de.ugoe.cs.autoquest.tasktrees.taskequality.TaskEquality;
[1127]22import de.ugoe.cs.autoquest.tasktrees.treeifc.IIteration;
23import de.ugoe.cs.autoquest.tasktrees.treeifc.ISelection;
[1107]24import de.ugoe.cs.autoquest.tasktrees.treeifc.ISequence;
[1146]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;
[1256]31import de.ugoe.cs.autoquest.usageprofiles.SymbolMap;
[1119]32import de.ugoe.cs.autoquest.usageprofiles.TrieProcessor;
[1129]33import de.ugoe.cs.util.StopWatch;
[1107]34
35/**
36 * <p>
37 * TODO comment
38 * </p>
39 *
40 * @author Patrick Harms
41 */
[1146]42class SequenceForTaskDetectionRule implements ISessionScopeRule {
[1107]43   
44    /**
45     * <p>
[1146]46     * the task factory to be used for creating substructures for the temporal
[1107]47     * relationships identified during rule
48     * </p>
49     */
[1146]50    private ITaskFactory taskFactory;
[1107]51    /**
52     * <p>
[1146]53     * the task builder to be used for creating substructures for the temporal relationships
[1107]54     * identified during rule application
55     * </p>
56     */
[1146]57    private ITaskBuilder taskBuilder;
[1107]58
59    /**
60     * <p>
[1146]61     * the task comparator to be used for comparing tasks
[1107]62     * </p>
63     */
[1146]64    private TaskComparator taskComparator;
[1107]65
66    /**
67     * <p>
[1146]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.
[1107]70     * </p>
71     */
[1189]72    SequenceForTaskDetectionRule(TaskEquality minimalTaskEquality,
73                                 ITaskFactory taskFactory,
74                                 ITaskBuilder taskBuilder)
[1107]75    {
[1146]76        this.taskFactory = taskFactory;
77        this.taskBuilder = taskBuilder;
[1107]78       
[1189]79        this.taskComparator = new TaskComparator(minimalTaskEquality);
[1107]80    }
81
[1119]82    /* (non-Javadoc)
83     * @see java.lang.Object#toString()
84     */
85    @Override
86    public String toString() {
[1127]87        return "SequenceForTaskDetectionRule";
[1119]88    }
89
[1146]90    /* (non-Javadoc)
91     * @see de.ugoe.cs.autoquest.tasktrees.temporalrelation.ISessionScopeRule#apply(java.util.List)
[1107]92     */
93    @Override
[1146]94    public RuleApplicationResult apply(List<IUserSession> sessions) {
[1127]95        RuleApplicationData appData = new RuleApplicationData(sessions);
96
97        // this is the real rule application. Loop while something is replaced.
[1256]98        harmonizeEventTaskInstancesModel(appData);
[1107]99        do {
[1127]100            System.out.println();
[1107]101           
[1127]102            appData.getStopWatch().start("whole loop");
103            detectAndReplaceIterations(appData);
[1133]104
[1127]105            appData.getStopWatch().start("task replacement");
106            detectAndReplaceTasks(appData);
107            appData.getStopWatch().stop("task replacement");
108            appData.getStopWatch().stop("whole loop");
[1107]109           
[1146]110            //((TaskTreeNodeComparator) taskComparator).getStopWatch().dumpStatistics(System.out);
111            //((TaskTreeNodeComparator) taskComparator).getStopWatch().reset();
[1127]112           
113            appData.getStopWatch().dumpStatistics(System.out);
114            appData.getStopWatch().reset();
115           
[1107]116        }
[1146]117        while (appData.detectedAndReplacedTasks());
[1107]118       
[1146]119        System.out.println
120            ("created " + appData.getResult().getNewlyCreatedTasks().size() +
121             " new tasks and " + appData.getResult().getNewlyCreatedTaskInstances().size() +
122             " appropriate instances\n");
[1107]123       
[1146]124        if ((appData.getResult().getNewlyCreatedTasks().size() > 0) ||
125            (appData.getResult().getNewlyCreatedTaskInstances().size() > 0))
126        {
[1127]127            appData.getResult().setRuleApplicationStatus(RuleApplicationStatus.FINISHED);
[1119]128        }
129       
[1127]130        return appData.getResult();
131    }
132
133    /**
[1256]134     * <p>
135     * TODO: comment
136     * </p>
137     *
[1127]138     * @param appData
139     */
[1256]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     */
[1127]175    private void detectAndReplaceIterations(RuleApplicationData appData) {
176        System.out.print("detecting iterations");
177        appData.getStopWatch().start("detecting iterations");
[1119]178       
[1146]179        List<IUserSession> sessions = appData.getSessions();
180        int iteratedTasks = 0;
[1127]181       
[1146]182        ITask iteratedTask = null;
183       
184        do {
185            iteratedTask = searchIteratedTask(sessions);
186           
187            if (iteratedTask != null) {
188                replaceIterationsOf(iteratedTask, sessions, appData);
189                iteratedTasks++;
190            }
[1127]191        }
[1146]192        while (iteratedTask != null);
[1127]193       
194        appData.getStopWatch().stop("detecting iterations");
[1146]195        System.out.println(" --> found " + iteratedTasks + " iterated tasks");
[1127]196    }
197
198    /**
[1146]199     *
[1127]200     */
[1146]201    private ITask searchIteratedTask(List<IUserSession> sessions) {
202        for (IUserSession session : sessions) {
203            for (int i = 0; i < (session.size() - 1); i++) {
[1155]204                if (taskComparator.equals(session.get(i), session.get(i + 1))) {
[1146]205                    return session.get(i).getTask();
206                }
207            }
208        }
209       
210        return null;
211    }
212
213    /**
214     *
215     */
[1155]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     */
[1146]267    private void replaceIterationsOf(ITask               iteratedTask,
268                                     List<IUserSession>  sessions,
269                                     RuleApplicationData appData)
[1127]270    {
[1146]271        IIteration iteration = taskFactory.createNewIteration();
272        ITaskInstance iterationInstance = null;
[1127]273       
[1146]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    }
[1127]301
[1146]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();
[1127]314           
[1146]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                    }
[1127]322                }
[1146]323               
324                if (!found) {
325                    iteratedTaskVariants.add(candidate);
326                }
[1107]327            }
328        }
329       
[1146]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        }
[1107]355    }
356
357    /**
[1127]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    /**
[1119]376     * @return
[1107]377     */
[1127]378    private void getSequencesOccuringMostOften(RuleApplicationData appData) {
379        System.out.println("determining most prominent tasks");
[1119]380
[1127]381        Tasks tasks;
[1119]382        boolean createNewTrie = (appData.getLastTrie() == null) ||
[1146]383            appData.detectedAndReplacedTasks(); // tree has changed
[1107]384       
[1119]385        do {
386            if (createNewTrie) {
387                createNewTrie(appData);
388            }
[1107]389           
[1127]390            MaxCountAndLongestTasksFinder finder = new MaxCountAndLongestTasksFinder();
[1119]391            appData.getLastTrie().process(finder);
392       
[1127]393            tasks = finder.getFoundTasks();
[1119]394           
395            createNewTrie = false;
396           
[1146]397            for (List<ITaskInstance> task : tasks) {
[1119]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                }
[1107]405            }
406        }
[1119]407        while (createNewTrie);
408       
[1256]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       
[1127]466        appData.setLastFoundTasks(tasks);
467
468        System.out.println("found " + appData.getLastFoundTasks().size() + " tasks occurring " +
469                           appData.getLastFoundTasks().getOccurrenceCount() + " times");
[1107]470    }
471
472    /**
[1119]473     * @param parent
474     * @return
[1107]475     */
[1127]476    private void createNewTrie(RuleApplicationData appData) {
[1119]477        System.out.println("training trie with a maximum sequence length of " +
478                           appData.getTrainedSequenceLength());
479
480        appData.getStopWatch().start("training trie");
[1256]481        appData.setLastTrie(new TaskInstanceTrie(taskComparator));
[1119]482   
[1256]483        appData.getLastTrie().trainSessions
484            (appData.getSessions(), appData.getTrainedSequenceLength());
[1127]485       
[1119]486        appData.getStopWatch().stop("training trie");
487    }
488
489    /**
[1127]490     * @param appData
491     */
492    private void replaceSequencesOccurringMostOften(RuleApplicationData appData) {
[1146]493        appData.detectedAndReplacedTasks(false);
[1127]494
495        if ((appData.getLastFoundTasks().size() > 0) &&
496            (appData.getLastFoundTasks().getOccurrenceCount() > 1))
497        {
[1146]498            System.out.println("replacing tasks occurrences");
[1127]499
[1146]500            for (List<ITaskInstance> task : appData.getLastFoundTasks()) {
501                ISequence sequence = taskFactory.createNewSequence();
502               
503                System.out.println("replacing " + sequence.getId() + ": " + task);
[1127]504
[1146]505                List<ITaskInstance> sequenceInstances =
506                    replaceTaskOccurrences(task, appData.getSessions(), sequence);
[1119]507               
[1146]508                harmonizeSequenceInstancesModel(sequence, sequenceInstances,task.size());
509                appData.detectedAndReplacedTasks(sequenceInstances.size() > 0);
[1127]510
[1146]511                if (sequenceInstances.size() < appData.getLastFoundTasks().getOccurrenceCount()) {
512                    System.out.println(sequence.getId() + ": replaced task only " +
513                                       sequenceInstances.size() + " times instead of expected " +
[1127]514                                       appData.getLastFoundTasks().getOccurrenceCount());
515                }
516            }
517        }
518       
519    }
520
521    /**
[1146]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    /**
[1127]583     * @param tree
584     */
[1146]585    private List<ITaskInstance> replaceTaskOccurrences(List<ITaskInstance> task,
586                                                       List<IUserSession>  sessions,
587                                                       ISequence           temporalTaskModel)
[1127]588    {
[1146]589        List<ITaskInstance> sequenceInstances = new LinkedList<ITaskInstance>();
590       
591        for (IUserSession session : sessions) {
[1127]592            int index = -1;
[1119]593               
[1127]594            do {
[1146]595                index = getSubListIndex(session, task, ++index);
[1127]596
597                if (index > -1) {
[1146]598                    sequenceInstances.add
599                        (RuleUtils.createNewSubSequenceInRange
600                             (session, index, index + task.size() - 1, temporalTaskModel,
601                              taskFactory, taskBuilder));
[1107]602                }
603            }
[1127]604            while (index > -1);
[1107]605        }
[1146]606       
607        return sequenceInstances;
[1107]608    }
609
610    /**
[1146]611     * @param trie
612     * @param object
[1127]613     * @return
614     */
[1146]615    private int getSubListIndex(ITaskInstanceList   list,
616                                List<ITaskInstance> subList,
617                                int                 startIndex)
[1127]618    {
[1146]619        boolean matchFound;
620        int result = -1;
[1127]621       
[1146]622        for (int i = startIndex; i <= list.size() - subList.size(); i++) {
623            matchFound = true;
[1127]624           
[1146]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                }
[1127]630            }
631           
[1146]632            if (matchFound) {
633                result = i;
634                break;
635            }
[1127]636        }
[1107]637       
[1146]638        return result;
[1107]639    }
640
641    /**
642     * @param trie
643     * @param object
644     * @return
645     */
[1146]646    private int getSubListIndex(List<ITaskInstance> list,
647                                List<ITaskInstance> subList,
[1107]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++) {
[1146]657                if (!taskComparator.equals(list.get(i + j), subList.get(j))) {
[1107]658                    matchFound = false;
659                    break;
660                }
661            }
662           
663            if (matchFound) {
664                result = i;
665                break;
666            }
667        }
668       
669        return result;
670    }
671   
[1119]672    /**
673     * @author Patrick Harms
674     */
[1146]675    private class MaxCountAndLongestTasksFinder implements TrieProcessor<ITaskInstance> {
[1119]676       
677        /**
678         *
679         */
680        private int currentCount;
681       
682        /**
683         *
684         */
[1146]685        private List<List<ITaskInstance>> foundTasks = new LinkedList<List<ITaskInstance>>();
[1119]686
687        /**
688         *
689         */
[1127]690        public MaxCountAndLongestTasksFinder() {
[1119]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
[1146]699        public TrieProcessor.Result process(List<ITaskInstance> foundTask, int count) {
700            if (foundTask.size() < 2) {
701                // ignore single tasks
[1119]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) {
[1146]711                // ignore this children of this task, as they may have only smaller counts than
[1127]712                // the already found tasks
[1119]713                return TrieProcessor.Result.SKIP_NODE;
714            }
715           
716            if (this.currentCount < count) {
[1127]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();
[1119]720                this.currentCount = count;
721            }
722           
723            if (this.currentCount == count) {
[1127]724                // the task is of interest. Sort it into the other found tasks so that
[1119]725                // the longest come first
726                boolean added = false;
[1127]727                for (int i = 0; i < foundTasks.size(); i++) {
[1146]728                    if (foundTasks.get(i).size() < foundTask.size()) {
[1119]729                        // defensive copy
[1146]730                        foundTasks.add(i, new LinkedList<ITaskInstance>(foundTask)); // defensive copy
[1119]731                        added = true;
732                        break;
733                    }
734                }
735               
736                if (!added) {
[1146]737                    foundTasks.add(new LinkedList<ITaskInstance>(foundTask)); // defensive copy
[1119]738                }
739            }
740           
741            return TrieProcessor.Result.CONTINUE;
742        }
743
744        /**
[1133]745         *  @return
[1119]746         */
[1127]747        public Tasks getFoundTasks() {
[1119]748            removePermutationsOfShorterTasks();
[1127]749            return new Tasks(currentCount, foundTasks);
[1119]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
[1127]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()) {
[1119]761                        // found a task that is a potential subtask. Check for this and remove the
762                        // subtask if needed
[1146]763                        List<ITaskInstance> longTask = foundTasks.get(i);
764                        List<ITaskInstance> shortTask = foundTasks.get(j);
[1119]765                       
766                        if (getSubListIndex(longTask, shortTask, 0) > -1) {
[1127]767                            foundTasks.remove(j);
[1119]768                        }
769                        else {
770                            j++;
771                        }
772                    }
773                    else {
774                        j++;
775                    }
776                }
777            }
778        }
779
780    }
781   
[1256]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   
[1119]832    /**
833     *
834     */
[1133]835    private static class RuleApplicationData {
[1119]836       
837        /**
838         *
839         */
[1146]840        private List<IUserSession> sessions;
[1119]841       
842        /**
843         *
844         */
[1256]845        private TaskInstanceTrie lastTrie;
[1119]846       
847        /**
[1127]848         * default and minimum trained sequence length is 3
[1119]849         */
[1127]850        private int trainedSequenceLength = 3;
[1119]851       
852        /**
853         *
854         */
[1127]855        private Tasks lastFoundTasks = new Tasks(Integer.MAX_VALUE, null);
[1119]856       
857        /**
[1127]858         *
[1119]859         */
[1146]860        private boolean detectedAndReplacedTasks;
[1119]861       
862        /**
863         *
864         */
[1127]865        private RuleApplicationResult result = new RuleApplicationResult();
866       
867        /**
868         *
869         */
[1119]870        private StopWatch stopWatch = new StopWatch();
871       
872        /**
873         *
874         */
[1146]875        private RuleApplicationData(List<IUserSession> sessions) {
[1127]876            this.sessions = sessions;
[1119]877        }
878
879        /**
[1127]880         * @return the tree
[1119]881         */
[1146]882        private List<IUserSession> getSessions() {
[1127]883            return sessions;
[1119]884        }
885
886        /**
[1127]887         * @param lastTrie the lastTrie to set
[1119]888         */
[1256]889        private void setLastTrie(TaskInstanceTrie lastTrie) {
[1127]890            this.lastTrie = lastTrie;
[1119]891        }
892
893        /**
894         * @return the lastTrie
895         */
[1256]896        private TaskInstanceTrie getLastTrie() {
[1119]897            return lastTrie;
898        }
899
900        /**
[1127]901         * @param trainedSequenceLength the trainedSequenceLength to set
902         */
903        private void setTrainedSequenceLength(int trainedSequenceLength) {
904            this.trainedSequenceLength = trainedSequenceLength;
905        }
906
907        /**
[1119]908         * @return the trainedSequenceLength
909         */
910        private int getTrainedSequenceLength() {
911            return trainedSequenceLength;
912        }
913
914        /**
[1127]915         * @param lastFoundSequences the lastFoundSequences to set
[1119]916         */
[1127]917        private void setLastFoundTasks(Tasks lastFoundSequences) {
918            this.lastFoundTasks = lastFoundSequences;
[1119]919        }
920
921        /**
[1127]922         * @return the lastFoundSequences
[1119]923         */
[1127]924        private Tasks getLastFoundTasks() {
925            return lastFoundTasks;
[1119]926        }
927
928        /**
929         *
930         */
[1146]931        private void detectedAndReplacedTasks(boolean detectedAndReplacedTasks) {
932            this.detectedAndReplacedTasks = detectedAndReplacedTasks;
[1119]933        }
934
935        /**
936         *
937         */
[1146]938        private boolean detectedAndReplacedTasks() {
939            return detectedAndReplacedTasks;
[1119]940        }
[1127]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
[1119]956    }
957   
958
959    /**
960     * @author Patrick Harms
961     */
[1146]962    private static class Tasks implements Iterable<List<ITaskInstance>> {
[1119]963       
964        /**
965         *
966         */
967        private int occurrenceCount;
968       
969        /**
970         *
971         */
[1146]972        private List<List<ITaskInstance>> sequences;
[1119]973
974        /**
975         * @param occurrenceCount
976         * @param sequences
977         */
[1146]978        private Tasks(int occurrenceCount, List<List<ITaskInstance>> sequences) {
[1119]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
[1146]1006        public Iterator<List<ITaskInstance>> iterator() {
[1119]1007            return this.sequences.iterator();
1008        }
1009
[1146]1010        /* (non-Javadoc)
[1256]1011         * @see java.lang.Object#toString()
[1146]1012         */
1013        @Override
[1256]1014        public String toString() {
1015            StringBuffer result = new StringBuffer();
1016            result.append(this.occurrenceCount);
1017            result.append(" occurrences:\n");
[1146]1018           
[1256]1019            for (List<ITaskInstance> task : sequences) {
1020                result.append(task);
1021                result.append("\n");
[1146]1022            }
1023           
[1256]1024            return result.toString();
[1146]1025        }
1026
1027    }
[1107]1028}
Note: See TracBrowser for help on using the repository browser.