source: branches/autoquest-core-tasktrees-alignment/src/main/java/de/ugoe/cs/autoquest/tasktrees/temporalrelation/SequenceForTaskDetectionRuleAlignment.java @ 1707

Last change on this file since 1707 was 1707, checked in by rkrimmel, 10 years ago

Possibility to save intermediate results

File size: 28.8 KB
Line 
1//   Copyright 2012 Georg-August-Universität Göttingen, Germany
2//
3//   Licensed under the Apache License, Version 2.0 (the "License");
4//   you may not use this file except in compliance with the License.
5//   You may obtain a copy of the License at
6//
7//       http://www.apache.org/licenses/LICENSE-2.0
8//
9//   Unless required by applicable law or agreed to in writing, software
10//   distributed under the License is distributed on an "AS IS" BASIS,
11//   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12//   See the License for the specific language governing permissions and
13//   limitations under the License.
14
15package de.ugoe.cs.autoquest.tasktrees.temporalrelation;
16
17import java.io.FileInputStream;
18import java.io.FileOutputStream;
19import java.io.IOException;
20import java.io.ObjectInputStream;
21import java.io.ObjectOutputStream;
22import java.io.Serializable;
23import java.util.ArrayList;
24import java.util.Collections;
25import java.util.Comparator;
26import java.util.HashMap;
27import java.util.HashSet;
28import java.util.Iterator;
29import java.util.LinkedList;
30import java.util.List;
31import java.util.Map;
32import java.util.Set;
33import java.util.logging.Level;
34
35import de.ugoe.cs.autoquest.CommandHelpers;
36import de.ugoe.cs.autoquest.tasktrees.alignment.algorithms.Match;
37import de.ugoe.cs.autoquest.tasktrees.alignment.algorithms.MatchOccurence;
38import de.ugoe.cs.autoquest.tasktrees.alignment.algorithms.NumberSequence;
39import de.ugoe.cs.autoquest.tasktrees.alignment.matrix.PairwiseAlignmentGenerator;
40import de.ugoe.cs.autoquest.tasktrees.alignment.matrix.PairwiseAlignmentStorage;
41import de.ugoe.cs.autoquest.tasktrees.alignment.matrix.ObjectDistanceSubstitionMatrix;
42import de.ugoe.cs.autoquest.tasktrees.taskequality.TaskEquality;
43import de.ugoe.cs.autoquest.tasktrees.treeifc.IIteration;
44import de.ugoe.cs.autoquest.tasktrees.treeifc.IIterationInstance;
45import de.ugoe.cs.autoquest.tasktrees.treeifc.IOptional;
46import de.ugoe.cs.autoquest.tasktrees.treeifc.ISelection;
47import de.ugoe.cs.autoquest.tasktrees.treeifc.ISelectionInstance;
48import de.ugoe.cs.autoquest.tasktrees.treeifc.ISequence;
49import de.ugoe.cs.autoquest.tasktrees.treeifc.ISequenceInstance;
50import de.ugoe.cs.autoquest.tasktrees.treeifc.ITask;
51import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskBuilder;
52import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskFactory;
53import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInstance;
54import de.ugoe.cs.autoquest.tasktrees.treeifc.IUserSession;
55import de.ugoe.cs.autoquest.usageprofiles.SymbolMap;
56import de.ugoe.cs.util.StopWatch;
57import de.ugoe.cs.util.console.Console;
58import de.ugoe.cs.util.console.GlobalDataContainer;
59
60/**
61 * <p>
62 * This class implements the major rule for creating task trees based on a set
63 * of recorded user sessions. For this, it first harmonizes all tasks. This
64 * eases later comparison. Then it searches the sessions for iterations and
65 * replaces them accordingly. Then it searches for sub sequences being the
66 * longest and occurring most often. For each found sub sequence, it replaces
67 * the occurrences by creating appropriate {@link ISequence}s. Afterwards, again
68 * searches for iterations and then again for sub sequences until no more
69 * replacements are done.
70 * </p>
71 * <p>
72 *
73 *
74 * @author Patrick Harms
75 */
76public class SequenceForTaskDetectionRuleAlignment implements ISessionScopeRule {
77       
78       
79        public static int nThreads;
80        public static boolean harmonizeSequences;
81       
82
83        private int iteration = 0;
84        /**
85         * <p>
86         * the task factory to be used for creating substructures for the temporal
87         * relationships identified during rul application
88         * </p>
89         */
90        private ITaskFactory taskFactory;
91        /**
92         * <p>
93         * the task builder to be used for creating substructures for the temporal
94         * relationships identified during rule application
95         * </p>
96         */
97        private ITaskBuilder taskBuilder;
98
99        /**
100         * <p>
101         * the task handling strategy to be used for comparing tasks for
102         * preparation, i.e., before the tasks are harmonized
103         * </p>
104         */
105        private TaskHandlingStrategy preparationTaskHandlingStrategy;
106
107        /**
108         * <p>
109         * instantiates the rule and initializes it with a task equality to be
110         * considered when comparing tasks as well as a task factory and builder to
111         * be used for creating task structures.
112         * </p>
113         *
114         * @param minimalTaskEquality
115         *            the task equality to be considered when comparing tasks
116         * @param taskFactory
117         *            the task factory to be used for creating substructures
118         * @param taskBuilder
119         *            the task builder to be used for creating substructures
120         */
121
122        SequenceForTaskDetectionRuleAlignment(TaskEquality minimalTaskEquality,
123                        ITaskFactory taskFactory, ITaskBuilder taskBuilder) {
124                this.taskFactory = taskFactory;
125                this.taskBuilder = taskBuilder;
126
127                this.preparationTaskHandlingStrategy = new TaskHandlingStrategy(
128                                minimalTaskEquality);
129
130        }
131
132        /*
133         * (non-Javadoc)
134         *
135         * @see java.lang.Object#toString()
136         */
137        @Override
138        public String toString() {
139                return "SequenceForTaskDetectionRuleAlignment";
140        }
141
142        /*
143         * (non-Javadoc)
144         *
145         * @see
146         * de.ugoe.cs.autoquest.tasktrees.temporalrelation.ISessionScopeRule#apply
147         * (java.util.List)
148         */
149        @Override
150        public RuleApplicationResult apply(List<IUserSession> sessions) {
151                RuleApplicationData appData = new RuleApplicationData(sessions);
152                if(SequenceForTaskDetectionRuleAlignment.harmonizeSequences) {
153                        harmonizeEventTaskInstancesModel(appData);
154                        Console.traceln(Level.INFO, "generating substitution matrix from " + appData.getUniqueTasks().size() + " unique tasks");
155                        appData.getSubmat().generate(appData.getUniqueTasks());
156                        appData.getStopWatch().stop("substitution matrix");
157                        GlobalDataContainer.getInstance().addData("appData", appData);
158                        //Saving intermediate results to file
159                        Console.traceln(Level.INFO,"saving substitution matrix to file");
160                        String objectName = "appData";
161                        String filename = "appData.dat";
162                        Object dataObject = GlobalDataContainer.getInstance().getData(
163                                        objectName);
164                        if (dataObject == null) {
165                                CommandHelpers.objectNotFoundMessage(objectName);
166                        }
167                        FileOutputStream fos = null;
168                        ObjectOutputStream out = null;
169                        try {
170                                fos = new FileOutputStream(filename);
171                                out = new ObjectOutputStream(fos);
172                                out.writeObject(dataObject);
173                                out.close();
174                        } catch (IOException ex) {
175                                Console.logException(ex);
176                        }
177                }
178                else {
179                        Console.traceln(Level.INFO,"loading substitution matrix from file");
180                        String objectName = "appData";
181                        String filename = "appData.dat";
182                        Object data = null;
183                        FileInputStream fis = null;
184                        ObjectInputStream in = null;
185                        try {
186                                fis = new FileInputStream(filename);
187                                in = new ObjectInputStream(fis);
188                                data = in.readObject();
189                                in.close();
190                        } catch (IOException ex) {
191                                Console.logException(ex);
192                        } catch (ClassNotFoundException ex) {
193                                Console.logException(ex);
194                        }
195                        if (GlobalDataContainer.getInstance().addData(objectName, data)) {
196                                CommandHelpers.dataOverwritten(objectName);
197                        }
198                        appData = (RuleApplicationData) GlobalDataContainer.getInstance().getData("appData");
199                }
200               
201               
202                Console.traceln(Level.INFO, "Starting main loop");
203                do {
204                        Console.traceln(Level.INFO, "Iteration Number: " + iteration);
205                        iteration++;
206                       
207                        appData.detectedAndReplacedTasks = false;
208                        appData.getStopWatch().start("whole loop");
209                        detectAndReplaceIterations(appData);
210                        appData.getStopWatch().start("task replacement");
211                        appData.updateSubstitutionMatrix();
212                        detectAndReplaceTasks(appData); //
213                        appData.getStopWatch().stop("task replacement");
214                        appData.getStopWatch().stop("whole loop");
215                        appData.getStopWatch().dumpStatistics(System.out);
216                        appData.getStopWatch().reset();
217
218                } while (appData.detectedAndReplacedTasks());
219
220                Console.println("created "
221                                + appData.getResult().getNewlyCreatedTasks().size()
222                                + " new tasks and "
223                                + appData.getResult().getNewlyCreatedTaskInstances().size()
224                                + " appropriate instances\n");
225
226                if ((appData.getResult().getNewlyCreatedTasks().size() > 0)
227                                || (appData.getResult().getNewlyCreatedTaskInstances().size() > 0)) {
228                        appData.getResult().setRuleApplicationStatus(
229                                        RuleApplicationStatus.FINISHED);
230                }
231
232                return appData.getResult();
233        }
234
235
236        private ArrayList<NumberSequence> createNumberSequences(
237                        RuleApplicationData appData) {
238                ArrayList<NumberSequence> result = new ArrayList<NumberSequence>();
239                for (int i = 0; i < appData.getSessions().size(); i++) {
240                        IUserSession session = appData.getSessions().get(i);
241                        NumberSequence templist = new NumberSequence(session.size());
242                        for (int j = 0; j < session.size(); j++) {
243                                ITaskInstance taskInstance = session.get(j);
244                                templist.getSequence()[j] = taskInstance.getTask().getId();
245                        }
246                        // Each NumberSequence is identified by its id, beginning to count
247                        // at zero
248                        templist.setId(i);
249                        result.add(templist);
250                }
251                return result;
252        }
253
254        /**
255         * <p>
256         * harmonizes the event task instances by unifying tasks. This is done, as
257         * initially the event tasks being equal with respect to the considered task
258         * equality are distinct objects. The comparison of these distinct objects
259         * is more time consuming than comparing the object references.
260         * </p>
261         *
262         * @param appData
263         *            the rule application data combining all data used for applying
264         *            this rule
265         * @return Returns the unique tasks symbol map
266         */
267        private void harmonizeEventTaskInstancesModel(RuleApplicationData appData) {
268                Console.traceln(Level.INFO,
269                                "harmonizing task model of event task instances");
270                appData.getStopWatch().start("harmonizing event tasks");
271                SymbolMap<ITaskInstance, ITask> uniqueTasks = preparationTaskHandlingStrategy
272                                .createSymbolMap();
273
274                TaskInstanceComparator comparator = preparationTaskHandlingStrategy
275                                .getTaskComparator();
276
277                int unifiedTasks = 0;
278                ITask task;
279                List<IUserSession> sessions = appData.getSessions();
280                for (int j = 0; j < sessions.size(); j++) {
281                        IUserSession session = sessions.get(j);
282
283                        for (int i = 0; i < session.size(); i++) {
284                                ITaskInstance taskInstance = session.get(i);
285                                task = uniqueTasks.getValue(taskInstance);
286
287                                if (task == null) {
288                                        uniqueTasks.addSymbol(taskInstance, taskInstance.getTask());
289                                        appData.getUniqueTasks().add(taskInstance.getTask());
290                                        appData.getNumber2Task().put(
291                                                        taskInstance.getTask().getId(),
292                                                        taskInstance.getTask());
293                                } else {
294                                        taskBuilder.setTask(taskInstance, task);
295                                        unifiedTasks++;
296                                }
297                        }
298                        comparator.clearBuffers();
299                }
300
301                appData.getStopWatch().stop("harmonizing event tasks");
302                Console.traceln(Level.INFO, "harmonized " + unifiedTasks
303                                + " task occurrences (still " + appData.getUniqueTasks().size()
304                                + " different tasks)");
305
306                appData.getStopWatch().dumpStatistics(System.out);
307                appData.getStopWatch().reset();
308        }
309
310        /**
311         * <p>
312         * searches for direct iterations of single tasks in all sequences and
313         * replaces them with {@link IIteration}s, respectively appropriate
314         * instances. Also all single occurrences of a task that is iterated
315         * somewhen are replaced with iterations to have again an efficient way for
316         * task comparisons.
317         * </p>
318         *
319         * @param appData
320         *            the rule application data combining all data used for applying
321         *            this rule
322         */
323        private void detectAndReplaceIterations(RuleApplicationData appData) {
324                Console.traceln(Level.FINE, "detecting iterations");
325                appData.getStopWatch().start("detecting iterations");
326
327                List<IUserSession> sessions = appData.getSessions();
328
329                Set<ITask> iteratedTasks = searchIteratedTasks(sessions);
330
331                if (iteratedTasks.size() > 0) {
332                        replaceIterationsOf(iteratedTasks, sessions, appData);
333                }
334
335                appData.getStopWatch().stop("detecting iterations");
336                Console.traceln(Level.INFO, "replaced " + iteratedTasks.size()
337                                + " iterated tasks");
338        }
339
340        /**
341         * <p>
342         * searches the provided sessions for task iterations. If a task is
343         * iterated, it is added to the returned set.
344         * </p>
345         *
346         * @param the
347         *            session to search for iterations in
348         *
349         * @return a set of tasks being iterated somewhere
350         */
351        private Set<ITask> searchIteratedTasks(List<IUserSession> sessions) {
352                Set<ITask> iteratedTasks = new HashSet<ITask>();
353                for (IUserSession session : sessions) {
354                        for (int i = 0; i < (session.size() - 1); i++) {
355                                // we prepared the task instances to refer to unique tasks, if
356                                // they are treated
357                                // as equal. Therefore, we just compare the identity of the
358                                // tasks of the task
359                                // instances
360                                if (session.get(i).getTask() == session.get(i + 1).getTask()) {
361                                        iteratedTasks.add(session.get(i).getTask());
362                                }
363                        }
364                }
365                return iteratedTasks;
366        }
367
368        /**
369         * <p>
370         * replaces all occurrences of all tasks provided in the set with iterations
371         * </p>
372         *
373         * @param iteratedTasks
374         *            the tasks to be replaced with iterations
375         * @param sessions
376         *            the sessions in which the tasks are to be replaced
377         * @param appData
378         *            the rule application data combining all data used for applying
379         *            this rule
380         */
381        private void replaceIterationsOf(Set<ITask> iteratedTasks,
382                        List<IUserSession> sessions, RuleApplicationData appData) {
383                Map<ITask, IIteration> iterations = new HashMap<ITask, IIteration>();
384                Map<IIteration, List<IIterationInstance>> iterationInstances = new HashMap<IIteration, List<IIterationInstance>>();
385
386                for (ITask iteratedTask : iteratedTasks) {
387
388                        IIteration iteration = taskFactory.createNewIteration();
389                        appData.newTaskCreated(iteration);
390                        iterations.put(iteratedTask, iteration);
391                        iterationInstances.put(iteration,
392                                        new LinkedList<IIterationInstance>());
393                }
394
395                IIterationInstance iterationInstance;
396
397                for (IUserSession session : sessions) {
398                        int index = 0;
399                        iterationInstance = null;
400
401                        while (index < session.size()) {
402                                // we prepared the task instances to refer to unique tasks, if
403                                // they are treated
404                                // as equal. Therefore, we just compare the identity of the
405                                // tasks of the task
406                                // instances
407                                ITask currentTask = session.get(index).getTask();
408                                IIteration iteration = iterations.get(currentTask);
409                                if (iteration != null) {
410                                        if ((iterationInstance == null)
411                                                        || (iterationInstance.getTask() != iteration)) {
412                                                iterationInstance = taskFactory
413                                                                .createNewTaskInstance(iteration);
414                                                iterationInstances.get(iteration)
415                                                                .add(iterationInstance);// TODO:: Don't create
416                                                                                                                // TaskInstances here,
417                                                                                                                // use a set of tasks
418                                                                                                                // instead
419                                                taskBuilder.addTaskInstance(session, index,
420                                                                iterationInstance);
421                                                index++;
422                                        }
423
424                                        taskBuilder.addChild(iterationInstance, session.get(index));
425                                        taskBuilder.removeTaskInstance(session, index);
426                                } else {
427                                        if (iterationInstance != null) {
428                                                iterationInstance = null;
429                                        }
430                                        index++;
431                                }
432                        }
433                }
434
435                for (Map.Entry<IIteration, List<IIterationInstance>> entry : iterationInstances
436                                .entrySet()) {
437                        harmonizeIterationInstancesModel(entry.getKey(), entry.getValue());
438                }
439        }
440
441        /**
442         * <p>
443         * TODO clarify why this is done
444         * </p>
445         */
446        private void harmonizeIterationInstancesModel(IIteration iteration,
447                        List<IIterationInstance> iterationInstances) {
448                List<ITask> iteratedTaskVariants = new LinkedList<ITask>();
449                TaskInstanceComparator comparator = preparationTaskHandlingStrategy
450                                .getTaskComparator();
451
452                // merge the lexically different variants of iterated task to a unique
453                // list
454                for (IIterationInstance iterationInstance : iterationInstances) {
455                        for (ITaskInstance executionVariant : iterationInstance) {
456                                ITask candidate = executionVariant.getTask();
457
458                                boolean found = false;
459                                for (ITask taskVariant : iteratedTaskVariants) {
460                                        if (comparator.areLexicallyEqual(taskVariant, candidate)) {
461                                                taskBuilder.setTask(executionVariant, taskVariant);
462                                                found = true;
463                                                break;
464                                        }
465                                }
466
467                                if (!found) {
468                                        iteratedTaskVariants.add(candidate);
469                                }
470                        }
471                }
472
473                // if there are more than one lexically different variant of iterated
474                // tasks, adapt the
475                // iteration model to be a selection of different variants. In this case
476                // also adapt
477                // the generated iteration instances to correctly contain selection
478                // instances. If there
479                // is only one variant of an iterated task, simply set this as the
480                // marked task of the
481                // iteration. In this case, the instances can be preserved as is
482                if (iteratedTaskVariants.size() > 1) {
483                        ISelection selection = taskFactory.createNewSelection();
484
485                        for (ITask variant : iteratedTaskVariants) {
486                                taskBuilder.addChild(selection, variant);
487                        }
488
489                        taskBuilder.setMarkedTask(iteration, selection);
490
491                        for (IIterationInstance instance : iterationInstances) {
492                                for (int i = 0; i < instance.size(); i++) {
493                                        ISelectionInstance selectionInstance = taskFactory
494                                                        .createNewTaskInstance(selection);
495                                        taskBuilder.setChild(selectionInstance, instance.get(i));
496                                        taskBuilder.setTaskInstance(instance, i, selectionInstance);
497                                }
498                        }
499                } else {
500                        taskBuilder.setMarkedTask(iteration, iteratedTaskVariants.get(0));
501                }
502        }
503
504        /**
505         * @param appData
506         * @param m
507         * @return
508         */
509        public ISequence matchAsSequence(RuleApplicationData appData, Match m) {       
510                ISequence sequence = taskFactory.createNewSequence();
511                appData.newTaskCreated(sequence);
512
513                int[] first = m.getFirstSequence().getSequence();
514                int[] second = m.getSecondSequence().getSequence();
515
516                // Both sequences of a match are equally long
517                for (int i = 0; i < m.getFirstSequence().size(); i++) {
518
519                        // Two gaps aligned to each other: Have not seen it happening so
520                        // far, just to handle it
521                        if (first[i] == -1 && second[i] == -1) {
522                                // Do nothing here.
523                        }
524                        // Both events are equal, we can simply add the task referring to
525                        // the number
526                        else if (first[i] == second[i]) {
527                                taskBuilder.addChild(sequence,
528                                                appData.getNumber2Task().get(first[i]));
529                        }
530                        // We have a gap in the first sequence, we need to add the task of
531                        // the second sequence as optional
532                        else if (first[i] == -1 && second[i] != -1) {
533                                IOptional optional = taskFactory.createNewOptional();
534                                appData.newTaskCreated(optional);
535                                taskBuilder.setMarkedTask(optional, appData.getNumber2Task()
536                                                .get(second[i]));
537                                taskBuilder.addChild(sequence, optional);
538                        }
539                        // We have a gap in the second sequence, we need to add the task of
540                        // the first sequence as optional
541                        else if (first[i] != -1 && second[i] == -1) {
542                                IOptional optional = taskFactory.createNewOptional();
543                                appData.newTaskCreated(optional);
544                                taskBuilder.setMarkedTask(optional, appData.getNumber2Task()
545                                                .get(first[i]));
546                                taskBuilder.addChild(sequence, optional);
547                        }
548                        // Both tasks are not equal, we need to insert a selection here.
549                        // Check if the next position is not a selection
550                        else if (i < first.length - 1) {
551
552                                if ((first[i] != second[i])
553                                                && ((first[i + 1] == second[i + 1]
554                                                                || first[i + 1] == -1 || second[i + 1] == -1))) {
555
556                                        ISelection selection = taskFactory.createNewSelection();
557                                        appData.newTaskCreated(selection);
558                                        taskBuilder.addChild(selection, appData.getNumber2Task()
559                                                        .get(first[i]));
560                                        taskBuilder.addChild(selection, appData.getNumber2Task()
561                                                        .get(second[i]));
562                                        taskBuilder.addChild(sequence, selection);
563                                } else {
564                                        boolean selectionfound = true;
565                                        ISelection selection = taskFactory.createNewSelection();
566                                        appData.newTaskCreated(selection);
567
568                                        ISequence subsequence1 = taskFactory.createNewSequence();
569                                        appData.newTaskCreated(subsequence1);
570
571                                        ISequence subsequence2 = taskFactory.createNewSequence();
572                                        appData.newTaskCreated(subsequence2);
573
574                                        taskBuilder.addChild(selection, subsequence1);
575                                        taskBuilder.addChild(selection, subsequence2);
576                                        taskBuilder.addChild(sequence,selection);
577                                        while (i < first.length - 1 && selectionfound) {
578                                                selectionfound = false;
579                                                taskBuilder.addChild(subsequence1, appData
580                                                                .getNumber2Task().get(first[i]));
581                                                taskBuilder.addChild(subsequence2, appData
582                                                                .getNumber2Task().get(second[i]));
583                                                if (first[i + 1] != second[i + 1] && first[i + 1] != -1
584                                                                && second[i + 1] != -1) {
585                                                        selectionfound = true;
586                                                }
587                                                else{
588                                                        continue;
589                                                }
590                                                i++;
591                                        }
592                                        if(i==first.length-1 && selectionfound) {
593                                                taskBuilder.addChild(subsequence1, appData
594                                                                .getNumber2Task().get(first[i]));
595                                                taskBuilder.addChild(subsequence2, appData
596                                                                .getNumber2Task().get(second[i]));
597                                        }
598                                }
599                        }
600                        else {
601                                if ((first[i] != second[i])) {
602
603                                        ISelection selection = taskFactory.createNewSelection();
604                                        appData.newTaskCreated(selection);
605                                        taskBuilder.addChild(selection, appData.getNumber2Task()
606                                                        .get(first[i]));
607                                        taskBuilder.addChild(selection, appData.getNumber2Task()
608                                                        .get(second[i]));
609                                        taskBuilder.addChild(sequence, selection);
610                                }
611                        }
612
613                }
614                return sequence;
615        }
616
617        /**
618         *
619         * @param appData
620         *            the rule application data combining all data used for applying
621         *            this rule
622         */
623        private void detectAndReplaceTasks(RuleApplicationData appData) {
624                Console.traceln(Level.FINE, "detecting and replacing tasks");
625                appData.getStopWatch().start("detecting tasks");
626
627                // Create NumberSequences
628                appData.setNumberSequences(this.createNumberSequences(appData));
629               
630                // Generate pairwise alignments
631                Console.traceln(Level.INFO, "generating pairwise alignments");
632                LinkedList<Match> matchseqs = new LinkedList<Match>();
633                PairwiseAlignmentStorage alignments = PairwiseAlignmentGenerator
634                                .generate(appData.getNumberSequences(), appData.getSubmat(), 9);
635
636                // Retrieve all matches reached a specific threshold
637                Console.traceln(Level.INFO, "retrieving significant sequence pieces");
638                for (int i = 0; i < appData.getNumberSequences().size(); i++) {
639                        for (int j = 0; j < appData.getNumberSequences().size(); j++) {
640                                if (i != j) {
641                                        matchseqs.addAll(alignments.get(i, j).getMatches());
642                                }
643                        }
644                }
645
646
647                Console.traceln(Level.INFO, "searching for patterns occuring most");
648
649                // search each match in every other sequence
650                for (Iterator<Match> it = matchseqs.iterator(); it.hasNext();) {
651                        Match pattern = it.next();
652
653                        // Skip sequences with more 0 events (scrolls) than other events.
654                        // Both of the pattern sequences are equally long, so the zero
655                        // counts just need to be smaller than the length of one sequence
656                        if (pattern.getFirstSequence().eventCount(0)
657                                        + pattern.getSecondSequence().eventCount(0) + 1 > pattern
658                                        .getFirstSequence().size())
659                                continue;
660
661                        for (int j = 0; j < appData.getNumberSequences().size(); j++) {
662                                LinkedList<Integer> startpositions = appData
663                                                .getNumberSequences().get(j).containsPattern(pattern);
664                                if (startpositions.size() > 0) {
665                                        for (Iterator<Integer> jt = startpositions.iterator(); jt
666                                                        .hasNext();) {
667                                                int start = jt.next();
668                                                pattern.addOccurence(new MatchOccurence(start, start
669                                                                + pattern.size(), j));
670                                        }
671
672                                }
673                        }
674                }
675
676                Console.traceln(Level.INFO, "sorting results");
677                // Sort results to get the most occurring results
678                Comparator<Match> comparator = new Comparator<Match>() {
679                        public int compare(Match m1, Match m2) {
680                                return m2.occurenceCount() - m1.occurenceCount();
681
682                        }
683                };
684                Collections.sort(matchseqs, comparator);
685                appData.getStopWatch().stop("detecting tasks");
686
687                appData.getStopWatch().start("replacing tasks");
688                HashMap<Integer, List<MatchOccurence>> replacedOccurences = new HashMap<Integer, List<MatchOccurence>>();
689                // Replace matches in the sessions
690                for (int i = 0; i < matchseqs.size(); i++) {
691                        // Every pattern consists of 2 sequences, therefore the minimum
692                        // occurrences here is 2.
693                        // We just need the sequences also occurring in other sequences as
694                        // well
695                        if (matchseqs.get(i).occurenceCount() > 2) {
696
697                                appData.detectedAndReplacedTasks = true;
698                                ISequence task = matchAsSequence(appData, matchseqs.get(i));
699                                invalidOccurence: for (Iterator<MatchOccurence> it = matchseqs
700                                                .get(i).getOccurences().iterator(); it.hasNext();) {
701                                        MatchOccurence oc = it.next();
702                                       
703                                        /*
704                                        if (iteration > 1) {
705                                         
706                                        System.out.println("Trying to replace sequence: ");
707                                        matchseqs.get(i).getFirstSequence().printSequence();
708                                        matchseqs.get(i).getSecondSequence().printSequence();
709                                        System.out.println(" in session number: "
710                                                        + (oc.getSequenceId() + 1) + " at position "
711                                                        + (oc.getStartindex()) + "-" + oc.getEndindex());
712                                        System.out.println();
713
714                                        System.out.println("Printing session: ");
715                                        for (int j = 0; j < appData.getSessions()
716                                                        .get(oc.getSequenceId()).size(); j++) {
717                                                System.out.println(j
718                                                                + ": "
719                                                                + appData.getSessions().get(oc.getSequenceId())
720                                                                                .get(j));
721                                        }
722                                        }*/
723                                       
724                                        // Check if nothing has been replaced in the sequence we
725                                        // want to replace
726                                        if (replacedOccurences.get(oc.getSequenceId()) == null) {
727                                                replacedOccurences.put(oc.getSequenceId(),
728                                                                new LinkedList<MatchOccurence>());
729                                        } else {
730                                                // check if we have any replaced occurence with indexes
731                                                // smaller than ours. If so, we need to adjust our start
732                                                // and endpoints
733                                                // of the replacement.
734                                                // Also do a check if we have replaced this specific
735                                                // MatchOccurence in this sequence already. Jump to the
736                                                // next occurence if this is the case.
737                                                // This is no more neccessary once the matches are
738                                                // harmonized.
739                                                for (Iterator<MatchOccurence> jt = replacedOccurences
740                                                                .get(oc.getSequenceId()).iterator(); jt
741                                                                .hasNext();) {
742                                                        MatchOccurence tmpOC = jt.next();
743
744                                                        if (oc.getStartindex() >= tmpOC.getStartindex()
745                                                                        && oc.getStartindex() <= tmpOC
746                                                                                        .getEndindex()) {
747                                                                continue invalidOccurence;
748                                                        }
749                                                        if (oc.getEndindex() >= tmpOC.getStartindex()) {
750                                                                continue invalidOccurence;
751
752                                                        } else if (oc.getStartindex() > tmpOC.getEndindex()) {
753                                                                int diff = tmpOC.getEndindex()
754                                                                                - tmpOC.getStartindex();
755                                                                // Just to be sure.
756                                                                if (diff > 0) {
757                                                                        oc.setStartindex(oc.getStartindex() - diff
758                                                                                        + 1);
759                                                                        oc.setEndindex(oc.getEndindex() - diff + 1);
760                                                                } else {
761                                                                        Console.traceln(Level.WARNING,
762                                                                                        "End index of a Match before start. This should never happen");
763                                                                }
764                                                        }
765                                                }
766                                        }
767                                        ISequenceInstance sequenceInstances = RuleUtils
768                                                        .createNewSubSequenceInRange(appData.getSessions()
769                                                                        .get(oc.getSequenceId()), oc
770                                                                        .getStartindex(), oc.getEndindex(), task,
771                                                                        taskFactory, taskBuilder);
772                                        // Adjust the length of the match regarding to the length of
773                                        // instance. (OptionalInstances may be shorter)
774                                        oc.setEndindex(oc.getStartindex()
775                                                        + sequenceInstances.size()
776                                                        - RuleUtils.missedOptionals);
777                                        replacedOccurences.get(oc.getSequenceId()).add(oc);
778                                }
779                        }
780                }
781
782                alignments = null;
783                matchseqs = null;
784                appData.getStopWatch().stop("replacing tasks");
785        }
786
787        /**
788     *
789     */
790        private static class RuleApplicationData implements Serializable {
791
792                /**
793                 *
794                 */
795                private static final long serialVersionUID = -7559657686755522960L;
796
797                private HashMap<Integer, ITask> number2task;
798
799                // TODO: We Actually just need number2task here, this structure can be removed in the future.
800                private HashSet<ITask> uniqueTasks;
801               
802                ObjectDistanceSubstitionMatrix submat;
803
804       
805                private ArrayList<NumberSequence> numberseqs;
806
807                private LinkedList<ITask> newTasks;
808               
809                /**
810         *
811         */
812                private List<IUserSession> sessions;
813
814                /**
815         *
816         */
817                private boolean detectedAndReplacedTasks;
818
819                /**
820         *
821         */
822                private RuleApplicationResult result;
823
824                /**
825         *
826         */
827                private StopWatch stopWatch;
828
829                /**
830         *
831         */
832                private RuleApplicationData(List<IUserSession> sessions) {
833                        this.sessions = sessions;
834                        numberseqs = new ArrayList<NumberSequence>();
835                        uniqueTasks = new HashSet<ITask>();
836                        number2task = new HashMap<Integer, ITask>();
837                        stopWatch = new StopWatch();
838                        result = new RuleApplicationResult();
839                        submat= new ObjectDistanceSubstitionMatrix(6,-3,false);
840                        newTasks = new LinkedList<ITask>();
841                }
842
843                private ObjectDistanceSubstitionMatrix getSubmat() {
844                        return submat;
845                }
846               
847                private void resetNewlyCreatedTasks() {
848                        uniqueTasks.addAll(newTasks);
849                        newTasks.clear();
850                }
851               
852                private void newTaskCreated(ITask task) {
853                        number2task.put(task.getId(), task);
854                        newTasks.add(task);
855                }
856
857                /**
858                 * @return the UserSessions as List.
859                 */
860                private List<IUserSession> getSessions() {
861                        return sessions;
862                }
863
864                private HashSet<ITask> getUniqueTasks() {
865                        return uniqueTasks;
866                }
867
868                private void setNumberSequences(ArrayList<NumberSequence> numberseqs) {
869                        this.numberseqs = numberseqs;
870                }
871
872                private ArrayList<NumberSequence> getNumberSequences() {
873                        return numberseqs;
874                }
875
876                private void updateSubstitutionMatrix() {
877                        submat.update(getNewTasks());
878                        resetNewlyCreatedTasks();
879                }
880
881               
882                /**
883         *
884         */
885                private boolean detectedAndReplacedTasks() {
886                        return detectedAndReplacedTasks;
887                }
888
889                /**
890                 * @return the result
891                 */
892                private RuleApplicationResult getResult() {
893                        return result;
894                }
895
896                public LinkedList<ITask> getNewTasks() {
897                        return newTasks;
898                }
899               
900                /**
901                 * @return the stopWatch
902                 */
903                private StopWatch getStopWatch() {
904                        return stopWatch;
905                }
906
907                private HashMap<Integer, ITask> getNumber2Task() {
908                        return number2task;
909                }
910
911        }
912
913}
Note: See TracBrowser for help on using the repository browser.