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

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

Saving everything to file.

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