Ignore:
Timestamp:
04/04/13 16:06:07 (11 years ago)
Author:
pharms
Message:
  • complete refactoring of task tree model with a separation of task models and task instances
  • appropriate adaptation of task tree generation process
  • appropriate adaptation of commands and task tree visualization
File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/autoquest-core-tasktrees/src/main/java/de/ugoe/cs/autoquest/tasktrees/temporalrelation/SequenceForTaskDetectionRule.java

    r1133 r1146  
    1515package de.ugoe.cs.autoquest.tasktrees.temporalrelation; 
    1616 
     17import java.util.HashMap; 
    1718import java.util.Iterator; 
    1819import java.util.LinkedList; 
    1920import java.util.List; 
    2021 
    21 import de.ugoe.cs.autoquest.tasktrees.nodeequality.NodeEquality; 
    22 import de.ugoe.cs.autoquest.tasktrees.nodeequality.NodeEqualityRuleManager; 
     22import de.ugoe.cs.autoquest.tasktrees.taskequality.TaskEquality; 
     23import de.ugoe.cs.autoquest.tasktrees.taskequality.TaskEqualityRuleManager; 
     24import de.ugoe.cs.autoquest.tasktrees.treeifc.IEventTask; 
    2325import de.ugoe.cs.autoquest.tasktrees.treeifc.IIteration; 
    2426import de.ugoe.cs.autoquest.tasktrees.treeifc.ISelection; 
    2527import de.ugoe.cs.autoquest.tasktrees.treeifc.ISequence; 
    26 import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskTreeBuilder; 
    27 import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskTreeNode; 
    28 import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskTreeNodeFactory; 
     28import de.ugoe.cs.autoquest.tasktrees.treeifc.ITask; 
     29import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskBuilder; 
     30import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskFactory; 
     31import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInstance; 
     32import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInstanceList; 
     33import de.ugoe.cs.autoquest.tasktrees.treeifc.IUserSession; 
     34import de.ugoe.cs.autoquest.usageprofiles.SymbolComparator; 
    2935import de.ugoe.cs.autoquest.usageprofiles.Trie; 
    3036import de.ugoe.cs.autoquest.usageprofiles.TrieProcessor; 
    3137import de.ugoe.cs.util.StopWatch; 
    32 import de.ugoe.cs.util.console.Console; 
    3338 
    3439/** 
     
    3944 * @author Patrick Harms 
    4045 */ 
    41 class SequenceForTaskDetectionRule implements TemporalRelationshipRule { 
     46class SequenceForTaskDetectionRule implements ISessionScopeRule { 
    4247     
    4348    /** 
    4449     * <p> 
    45      * the task tree node factory to be used for creating substructures for the temporal 
     50     * the task factory to be used for creating substructures for the temporal 
    4651     * relationships identified during rule 
    4752     * </p> 
    4853     */ 
    49     private ITaskTreeNodeFactory taskTreeNodeFactory; 
     54    private ITaskFactory taskFactory; 
    5055    /** 
    5156     * <p> 
    52      * the task tree builder to be used for creating substructures for the temporal relationships 
     57     * the task builder to be used for creating substructures for the temporal relationships 
    5358     * identified during rule application 
    5459     * </p> 
    5560     */ 
    56     private ITaskTreeBuilder taskTreeBuilder; 
     61    private ITaskBuilder taskBuilder; 
    5762 
    5863    /** 
    5964     * <p> 
    60      * the node comparator to be used for comparing task tree nodes 
     65     * the task comparator to be used for comparing tasks 
    6166     * </p> 
    6267     */ 
    63     private TaskTreeNodeComparator nodeComparator; 
     68    private TaskComparator taskComparator; 
    6469 
    6570    /** 
    6671     * <p> 
    67      * instantiates the rule and initializes it with a node equality rule manager and the minimal 
    68      * node equality identified sublist must have to consider them as iterated. 
     72     * instantiates the rule and initializes it with a task equality rule manager and the minimal 
     73     * task equality identified sublist must have to consider them as iterated. 
    6974     * </p> 
    7075     */ 
    71     SequenceForTaskDetectionRule(NodeEqualityRuleManager nodeEqualityRuleManager, 
    72                                  NodeEquality            minimalNodeEquality, 
    73                                  ITaskTreeNodeFactory    taskTreeNodeFactory, 
    74                                  ITaskTreeBuilder        taskTreeBuilder) 
     76    SequenceForTaskDetectionRule(TaskEqualityRuleManager taskEqualityRuleManager, 
     77                                 TaskEquality            minimalTaskEquality, 
     78                                 ITaskFactory            taskFactory, 
     79                                 ITaskBuilder            taskBuilder) 
    7580    { 
    76         this.taskTreeNodeFactory = taskTreeNodeFactory; 
    77         this.taskTreeBuilder = taskTreeBuilder; 
    78          
    79         this.nodeComparator = 
    80             new TaskTreeNodeComparator(nodeEqualityRuleManager, minimalNodeEquality); 
     81        this.taskFactory = taskFactory; 
     82        this.taskBuilder = taskBuilder; 
     83         
     84        this.taskComparator = new TaskComparator(taskEqualityRuleManager, minimalTaskEquality); 
    8185    } 
    8286 
     
    8993    } 
    9094 
    91     /* 
    92      * (non-Javadoc) 
    93      *  
    94      * @see de.ugoe.cs.tasktree.temporalrelation.TemporalRelationshipRule#apply(TaskTreeNode, 
    95      * boolean) 
     95    /* (non-Javadoc) 
     96     * @see de.ugoe.cs.autoquest.tasktrees.temporalrelation.ISessionScopeRule#apply(java.util.List) 
    9697     */ 
    9798    @Override 
    98     public RuleApplicationResult apply(ITaskTreeNode parent, boolean finalize) { 
    99         if (!(parent instanceof ISequence)) { 
    100             return null; 
    101         } 
    102  
    103         if (!finalize) { 
    104             // the rule is always feasible as tasks may occur at any time 
    105             RuleApplicationResult result = new RuleApplicationResult(); 
    106             result.setRuleApplicationStatus(RuleApplicationStatus.FEASIBLE); 
    107             return result; 
    108         } 
    109  
    110         List<ITaskTreeNode> children = parent.getChildren(); 
    111         List<ISequence> sessions = new LinkedList<ISequence>(); 
    112          
    113         for (ITaskTreeNode child : children) { 
    114             if (child instanceof ISequence) { 
    115                 sessions.add((ISequence) child); 
    116             } 
    117             else { 
    118                 Console.println("provided parent is no parent of sessions"); 
    119                 return null; 
    120             } 
    121         } 
    122          
     99    public RuleApplicationResult apply(List<IUserSession> sessions) { 
    123100        RuleApplicationData appData = new RuleApplicationData(sessions); 
    124101 
    125         boolean finished = false; 
    126          
    127102        // this is the real rule application. Loop while something is replaced. 
    128103        do { 
     
    137112            appData.getStopWatch().stop("whole loop"); 
    138113             
    139             //((TaskTreeNodeComparator) nodeComparator).getStopWatch().dumpStatistics(System.out); 
    140             //((TaskTreeNodeComparator) nodeComparator).getStopWatch().reset(); 
     114            //((TaskTreeNodeComparator) taskComparator).getStopWatch().dumpStatistics(System.out); 
     115            //((TaskTreeNodeComparator) taskComparator).getStopWatch().reset(); 
    141116             
    142117            appData.getStopWatch().dumpStatistics(System.out); 
    143118            appData.getStopWatch().reset(); 
    144119             
    145             finished = (appData.getReplacementCounter() == 0); 
    146         } 
    147         while (!finished); 
    148          
    149         System.out.println("created " + appData.getResult().getNewlyCreatedParentNodes().size() + 
    150                            " new parent nodes\n"); 
    151          
    152         if (appData.getResult().getNewlyCreatedParentNodes().size() > 0) { 
     120        } 
     121        while (appData.detectedAndReplacedTasks()); 
     122         
     123        System.out.println 
     124            ("created " + appData.getResult().getNewlyCreatedTasks().size() + 
     125             " new tasks and " + appData.getResult().getNewlyCreatedTaskInstances().size() + 
     126             " appropriate instances\n"); 
     127         
     128        if ((appData.getResult().getNewlyCreatedTasks().size() > 0) || 
     129            (appData.getResult().getNewlyCreatedTaskInstances().size() > 0)) 
     130        { 
    153131            appData.getResult().setRuleApplicationStatus(RuleApplicationStatus.FINISHED); 
    154132        } 
     
    164142        appData.getStopWatch().start("detecting iterations"); 
    165143         
    166         List<ISequence> sessions = appData.getSessions(); 
    167         int foundIterations = 0; 
    168          
    169         for (ISequence session : sessions) { 
    170             foundIterations += detectAndReplaceIterations(session, appData); 
    171         } 
     144        List<IUserSession> sessions = appData.getSessions(); 
     145        int iteratedTasks = 0; 
     146         
     147        ITask iteratedTask = null; 
     148         
     149        do { 
     150            iteratedTask = searchIteratedTask(sessions); 
     151             
     152            if (iteratedTask != null) { 
     153                replaceIterationsOf(iteratedTask, sessions, appData); 
     154                iteratedTasks++; 
     155            } 
     156        } 
     157        while (iteratedTask != null); 
    172158         
    173159        appData.getStopWatch().stop("detecting iterations"); 
    174         System.out.println(" --> found " + foundIterations); 
    175     } 
    176  
    177     /** 
    178      * @param appData 
    179      */ 
    180     private int detectAndReplaceIterations(ISequence           session, 
    181                                            RuleApplicationData appData) 
     160        System.out.println(" --> found " + iteratedTasks + " iterated tasks"); 
     161    } 
     162 
     163    /** 
     164     * 
     165     */ 
     166    private ITask searchIteratedTask(List<IUserSession> sessions) { 
     167        for (IUserSession session : sessions) { 
     168            for (int i = 0; i < (session.size() - 1); i++) { 
     169                if (taskComparator.equals(session.get(i).getTask(), session.get(i + 1).getTask())) { 
     170                    return session.get(i).getTask(); 
     171                } 
     172            } 
     173        } 
     174         
     175        return null; 
     176    } 
     177 
     178    /** 
     179     * 
     180     */ 
     181    private void replaceIterationsOf(ITask               iteratedTask, 
     182                                     List<IUserSession>  sessions, 
     183                                     RuleApplicationData appData) 
    182184    { 
    183         int count = 0; 
    184          
    185         TemporalRelationshipRule rule = new SimpleIterationDetectionRule 
    186             (nodeComparator, taskTreeNodeFactory, taskTreeBuilder); 
    187  
    188         RuleApplicationResult result = rule.apply(session, true); 
    189              
    190         if ((result != null) && (result.getNewlyCreatedParentNodes() != null)) { 
    191             for (ITaskTreeNode newParent : result.getNewlyCreatedParentNodes()) { 
    192                 appData.getResult().addNewlyCreatedParentNode(newParent); 
    193                 if (newParent instanceof IIteration) { 
    194                     count++; 
    195                 } 
    196             } 
    197         } 
    198          
    199         return count; 
     185        IIteration iteration = taskFactory.createNewIteration(); 
     186        ITaskInstance iterationInstance = null; 
     187         
     188        List<ITaskInstance> iterationInstances = new LinkedList<ITaskInstance>(); 
     189         
     190        for (IUserSession session : sessions) { 
     191            int index = 0; 
     192            while (index < session.size()) { 
     193                if (taskComparator.equals(iteratedTask, session.get(index).getTask())) { 
     194                    if (iterationInstance == null) { 
     195                        iterationInstance = taskFactory.createNewTaskInstance(iteration); 
     196                        iterationInstances.add(iterationInstance); 
     197                        taskBuilder.addTaskInstance(session, index, iterationInstance); 
     198                        index++; 
     199                    } 
     200                     
     201                    taskBuilder.addChild(iterationInstance, session.get(index)); 
     202                    taskBuilder.removeTaskInstance(session, index); 
     203                } 
     204                else { 
     205                    if (iterationInstance != null) { 
     206                        iterationInstance = null; 
     207                    } 
     208                    index++; 
     209                } 
     210            } 
     211        } 
     212         
     213        harmonizeIterationInstancesModel(iteration, iterationInstances); 
     214    } 
     215 
     216    /** 
     217     * <p> 
     218     * TODO: comment 
     219     * </p> 
     220     * 
     221     * @param iteratedTaskVariants 
     222     */ 
     223    private void harmonizeIterationInstancesModel(IIteration          iteration, 
     224                                                  List<ITaskInstance> iterationInstances) 
     225    { 
     226        List<ITask> iteratedTaskVariants = new LinkedList<ITask>(); 
     227         
     228        // merge the lexically different variants of iterated task to a unique list  
     229        for (ITaskInstance iterationInstance : iterationInstances) { 
     230            for (ITaskInstance executionVariant : iterationInstance) { 
     231                ITask candidate = executionVariant.getTask(); 
     232             
     233                boolean found = false; 
     234                for (ITask taskVariant : iteratedTaskVariants) { 
     235                    if (taskComparator.areLexicallyEqual(taskVariant, candidate)) { 
     236                        taskBuilder.setTask(executionVariant, taskVariant); 
     237                        found = true; 
     238                        break; 
     239                    } 
     240                } 
     241                 
     242                if (!found) { 
     243                    iteratedTaskVariants.add(candidate); 
     244                } 
     245            } 
     246        } 
     247         
     248        // if there are more than one lexically different variant of iterated tasks, adapt the 
     249        // iteration model to be a selection of different variants. In this case also adapt 
     250        // the generated iteration instances to correctly contain selection instances. If there 
     251        // is only one variant of an iterated task, simply set this as the marked task of the 
     252        // iteration. In this case, the instances can be preserved as is 
     253        if (iteratedTaskVariants.size() > 1) { 
     254            ISelection selection = taskFactory.createNewSelection(); 
     255             
     256            for (ITask variant : iteratedTaskVariants) { 
     257                taskBuilder.addChild(selection, variant); 
     258            } 
     259             
     260            taskBuilder.setMarkedTask(iteration, selection); 
     261             
     262            for (ITaskInstance instance : iterationInstances) { 
     263                for (int i = 0; i < instance.size(); i++) { 
     264                    ITaskInstance selectionInstance = taskFactory.createNewTaskInstance(selection); 
     265                    taskBuilder.addChild(selectionInstance, instance.get(i)); 
     266                    taskBuilder.setTaskInstance(instance, i, selectionInstance); 
     267                } 
     268            } 
     269        } 
     270        else { 
     271            taskBuilder.setMarkedTask(iteration, iteratedTaskVariants.get(0)); 
     272        } 
    200273    } 
    201274 
     
    226299        Tasks tasks; 
    227300        boolean createNewTrie = (appData.getLastTrie() == null) || 
    228             appData.getReplacementCounter() > 0; // tree has changed 
     301            appData.detectedAndReplacedTasks(); // tree has changed 
    229302         
    230303        do { 
     
    240313            createNewTrie = false; 
    241314             
    242             for (List<ITaskTreeNode> task : tasks) { 
     315            for (List<ITaskInstance> task : tasks) { 
    243316                if (task.size() >= appData.getTrainedSequenceLength()) { 
    244317                    // Trie must be recreated with a longer sequence length to be sure that 
     
    267340 
    268341        appData.getStopWatch().start("training trie"); 
    269         appData.setLastTrie(new Trie<ITaskTreeNode>(nodeComparator)); 
     342        appData.setLastTrie(new Trie<ITaskInstance>(taskComparator)); 
    270343     
    271         List<ISequence> sessions = appData.getSessions(); 
    272          
    273         for (ISequence session : sessions) { 
     344        List<IUserSession> sessions = appData.getSessions(); 
     345         
     346        for (IUserSession session : sessions) { 
    274347            trainTrie(session, appData); 
    275348        } 
     
    282355     * @param parent 
    283356     */ 
    284     private void trainTrie(ISequence session, RuleApplicationData appData) { 
    285         List<ITaskTreeNode> children = session.getChildren(); 
     357    private void trainTrie(IUserSession session, RuleApplicationData appData) { 
     358        List<ITaskInstance> children = session.getExecutedTasks(); 
    286359         
    287360        if ((children != null) && (children.size() > 0)) { 
     
    294367     */ 
    295368    private void replaceSequencesOccurringMostOften(RuleApplicationData appData) { 
    296         appData.resetReplacementCounter(); 
     369        appData.detectedAndReplacedTasks(false); 
    297370 
    298371        if ((appData.getLastFoundTasks().size() > 0) && 
    299372            (appData.getLastFoundTasks().getOccurrenceCount() > 1)) 
    300373        { 
    301             System.out.println("replacing tasks occurrences with merged variants of all versions"); 
    302  
    303             for (List<ITaskTreeNode> task : appData.getLastFoundTasks()) { 
    304                 String taskId = "task " + RuleUtils.getNewId(); 
    305                 System.out.println("replacing " + taskId + ": " + task); 
    306  
    307                 appData.clearTaskOccurrences(); 
    308                 determineVariantsOfTaskOccurrences(task, appData.getSessions(), appData); 
    309                  
    310                 appData.getStopWatch().start("merging task nodes"); 
    311                 ITaskTreeNode taskReplacement = mergeVariantsOfTaskOccurrence(taskId, appData); 
    312                 appData.getStopWatch().stop("merging task nodes"); 
    313  
    314                 appData.resetReplacementCounter(); 
    315                 replaceTaskOccurrences(task, taskReplacement, appData.getSessions(), appData); 
    316  
    317                 if (appData.getReplacementCounter() > 0) { 
    318                     appData.getResult().addNewlyCreatedParentNode(taskReplacement); 
    319                 } 
    320  
    321                 if (appData.getReplacementCounter() < 
    322                     appData.getLastFoundTasks().getOccurrenceCount()) 
    323                 { 
    324                     System.out.println(taskId + ": replaced task only " + 
    325                                        appData.getReplacementCounter() + 
    326                                        " times instead of expected " + 
     374            System.out.println("replacing tasks occurrences"); 
     375 
     376            for (List<ITaskInstance> task : appData.getLastFoundTasks()) { 
     377                ISequence sequence = taskFactory.createNewSequence(); 
     378                 
     379                System.out.println("replacing " + sequence.getId() + ": " + task); 
     380 
     381                List<ITaskInstance> sequenceInstances = 
     382                    replaceTaskOccurrences(task, appData.getSessions(), sequence); 
     383                 
     384                harmonizeSequenceInstancesModel(sequence, sequenceInstances,task.size()); 
     385                appData.detectedAndReplacedTasks(sequenceInstances.size() > 0); 
     386 
     387                if (sequenceInstances.size() < appData.getLastFoundTasks().getOccurrenceCount()) { 
     388                    System.out.println(sequence.getId() + ": replaced task only " + 
     389                                       sequenceInstances.size() + " times instead of expected " + 
    327390                                       appData.getLastFoundTasks().getOccurrenceCount()); 
    328391                } 
     
    333396 
    334397    /** 
    335      * @param tree 
    336      */ 
    337     private void determineVariantsOfTaskOccurrences(List<ITaskTreeNode> task, 
    338                                                     List<ISequence>     sessions, 
    339                                                     RuleApplicationData appData) 
     398     * 
     399     */ 
     400    private void harmonizeSequenceInstancesModel(ISequence           sequence, 
     401                                                 List<ITaskInstance> sequenceInstances, 
     402                                                 int                 sequenceLength) 
    340403    { 
    341         for (ISequence session : sessions) { 
    342             int index = -1; 
    343                  
    344             List<ITaskTreeNode> children = session.getChildren(); 
    345  
    346             do { 
    347                 index = getSubListIndex(children, task, ++index); 
    348  
    349                 if (index > -1) { 
    350                     ISequence taskOccurrence = RuleUtils.getSubSequenceInRange 
    351                             (session, index, index + task.size() - 1, null, 
    352                              taskTreeNodeFactory, taskTreeBuilder); 
    353  
    354                     appData.addTaskOccurrence(taskOccurrence); 
    355  
    356                     // let the index point to the last element the belongs the identified occurrence 
    357                     index += task.size() - 1; 
    358                 } 
    359             } 
    360             while (index > -1); 
    361         } 
    362     } 
    363  
    364     /** 
    365      * @param appData 
    366      * @return 
    367      */ 
    368     private ITaskTreeNode mergeVariantsOfTaskOccurrence(String              taskId, 
    369                                                         RuleApplicationData appData) 
    370     { 
    371         return mergeVariantsOfTasks(taskId, appData.getTaskOccurrences()); 
    372     } 
    373  
    374     /** 
    375      * @param appData 
    376      * @return 
    377      */ 
    378     private ITaskTreeNode mergeVariantsOfTasks(String description, List<ITaskTreeNode> variants) { 
    379         // merge but preserve lexically distinct variants 
    380         TaskTreeNodeMerger merger = new TaskTreeNodeMerger 
    381             (taskTreeNodeFactory, taskTreeBuilder, nodeComparator); 
    382          
    383         merger.mergeTaskNodes(variants); 
    384          
    385         if (variants.size() == 1) { 
    386             ITaskTreeNode replacement = variants.get(0); 
    387             taskTreeBuilder.setDescription(replacement, description); 
    388             return replacement; 
    389         } 
    390         else { 
    391             ISelection selection = taskTreeNodeFactory.createNewSelection(); 
    392             taskTreeBuilder.setDescription(selection, "variants of task " + description); 
    393              
    394             for (ITaskTreeNode variant : variants) { 
    395                 taskTreeBuilder.addChild(selection, variant); 
    396             } 
    397              
    398             return selection; 
    399         } 
    400     } 
    401  
    402     /** 
    403      * @param task 
    404      * @param parent 
    405      * @param treeBuilder 
    406      * @param nodeFactory 
    407      * @param result 
    408      */ 
    409     private void replaceTaskOccurrences(List<ITaskTreeNode> task, 
    410                                         ITaskTreeNode       replacement, 
    411                                         List<ISequence>     sessions, 
    412                                         RuleApplicationData appData) 
    413     { 
    414         // now check the children themselves for an occurrence of the task 
    415         for (int i = 0; i < sessions.size(); i++) { 
    416             ISequence session = sessions.get(i); 
    417              
    418             int index = -1; 
    419          
    420             List<ITaskTreeNode> children = session.getChildren(); 
    421  
    422             do { 
    423                 index = getSubListIndex(children, task, ++index); 
    424  
    425                 if (index > -1) { 
    426                     if ((!(replacement instanceof ISequence)) || 
    427                         (task.size() < children.size())) 
    428                     { 
    429                         for (int j = index; j < index + task.size(); j++) { 
    430                             taskTreeBuilder.removeChild(session, index); 
    431                         } 
    432  
    433                         taskTreeBuilder.addChild(session, index, replacement); 
    434                         appData.incrementReplacementCounter(); 
    435  
    436                         children = session.getChildren(); 
    437                     } 
    438                     else { 
    439                         // the whole list of children is an occurrence of this task. So ask the 
    440                         // caller of the method to replace the whole node 
    441                         sessions.set(i, (ISequence) replacement); 
    442                         appData.incrementReplacementCounter(); 
     404         
     405        // ensure for each subtask that lexically different variants are preserved 
     406        for (int subTaskIndex = 0; subTaskIndex < sequenceLength; subTaskIndex++) { 
     407            List<ITask> subTaskVariants = new LinkedList<ITask>(); 
     408             
     409            for (ITaskInstance sequenceInstance : sequenceInstances) { 
     410                ITask candidate = sequenceInstance.get(subTaskIndex).getTask(); 
     411                 
     412                boolean found = false; 
     413                 
     414                for (int i = 0; i < subTaskVariants.size(); i++) { 
     415                    if (taskComparator.areLexicallyEqual(subTaskVariants.get(i), candidate)) { 
     416                        taskBuilder.setTask 
     417                            (sequenceInstance.get(subTaskIndex), subTaskVariants.get(i)); 
     418                         
     419                        found = true; 
    443420                        break; 
    444421                    } 
    445422                } 
     423                 
     424                if (!found) { 
     425                    subTaskVariants.add(candidate); 
     426                } 
     427            } 
     428             
     429            // if there are more than one lexically different variant of the sub task at 
     430            // the considered position, adapt the sequence model at that position to have 
     431            // a selection of the different variants. In this case also adapt the 
     432            // generated sequence instances to correctly contain selection instances. If 
     433            // there is only one variant of sub tasks at the given position, simply set 
     434            // this variant as the sub task of the selection. In this case, the instances 
     435            // can be preserved as is 
     436            if (subTaskVariants.size() > 1) { 
     437                ISelection selection = taskFactory.createNewSelection(); 
     438                 
     439                for (ITask variant : subTaskVariants) { 
     440                    taskBuilder.addChild(selection, variant); 
     441                } 
     442                 
     443                taskBuilder.addChild(sequence, selection); 
     444                 
     445                for (ITaskInstance instance : sequenceInstances) { 
     446                    ITaskInstance selectionInstance = 
     447                        taskFactory.createNewTaskInstance(selection); 
     448                    taskBuilder.addChild(selectionInstance, instance.get(subTaskIndex)); 
     449                    taskBuilder.setTaskInstance(instance, subTaskIndex, selectionInstance); 
     450                } 
     451            } 
     452            else if (subTaskVariants.size() == 1) { 
     453                taskBuilder.addChild(sequence, subTaskVariants.get(0)); 
     454            } 
     455        } 
     456    } 
     457 
     458    /** 
     459     * @param tree 
     460     */ 
     461    private List<ITaskInstance> replaceTaskOccurrences(List<ITaskInstance> task, 
     462                                                       List<IUserSession>  sessions, 
     463                                                       ISequence           temporalTaskModel) 
     464    { 
     465        List<ITaskInstance> sequenceInstances = new LinkedList<ITaskInstance>(); 
     466         
     467        for (IUserSession session : sessions) { 
     468            int index = -1; 
     469                 
     470            do { 
     471                index = getSubListIndex(session, task, ++index); 
     472 
     473                if (index > -1) { 
     474                    sequenceInstances.add 
     475                        (RuleUtils.createNewSubSequenceInRange 
     476                             (session, index, index + task.size() - 1, temporalTaskModel, 
     477                              taskFactory, taskBuilder)); 
     478                } 
    446479            } 
    447480            while (index > -1); 
    448481        } 
     482         
     483        return sequenceInstances; 
    449484    } 
    450485 
     
    454489     * @return 
    455490     */ 
    456     private int getSubListIndex(List<ITaskTreeNode> list, 
    457                                 List<ITaskTreeNode> subList, 
     491    private int getSubListIndex(ITaskInstanceList  list, 
     492                                List<ITaskInstance> subList, 
    458493                                int                 startIndex) 
    459494    { 
     
    465500             
    466501            for (int j = 0; j < subList.size(); j++) { 
    467                 if (!nodeComparator.equals(list.get(i + j), subList.get(j))) { 
     502                if (!taskComparator.equals(list.get(i + j), subList.get(j))) { 
    468503                    matchFound = false; 
    469504                    break; 
     
    479514        return result; 
    480515    } 
     516 
     517    /** 
     518     * @param trie 
     519     * @param object 
     520     * @return 
     521     */ 
     522    private int getSubListIndex(List<ITaskInstance> list, 
     523                                List<ITaskInstance> subList, 
     524                                int                 startIndex) 
     525    { 
     526        boolean matchFound; 
     527        int result = -1; 
     528         
     529        for (int i = startIndex; i <= list.size() - subList.size(); i++) { 
     530            matchFound = true; 
     531             
     532            for (int j = 0; j < subList.size(); j++) { 
     533                if (!taskComparator.equals(list.get(i + j), subList.get(j))) { 
     534                    matchFound = false; 
     535                    break; 
     536                } 
     537            } 
     538             
     539            if (matchFound) { 
     540                result = i; 
     541                break; 
     542            } 
     543        } 
     544         
     545        return result; 
     546    } 
    481547     
    482548    /** 
    483549     * @author Patrick Harms 
    484550     */ 
    485     private class MaxCountAndLongestTasksFinder implements TrieProcessor<ITaskTreeNode> { 
     551    private class MaxCountAndLongestTasksFinder implements TrieProcessor<ITaskInstance> { 
    486552         
    487553        /** 
     
    493559         *  
    494560         */ 
    495         private List<List<ITaskTreeNode>> foundTasks = new LinkedList<List<ITaskTreeNode>>(); 
     561        private List<List<ITaskInstance>> foundTasks = new LinkedList<List<ITaskInstance>>(); 
    496562 
    497563        /** 
     
    507573         */ 
    508574        @Override 
    509         public TrieProcessor.Result process(List<ITaskTreeNode> task, int count) { 
    510             if (task.size() < 2) { 
    511                 // ignore single nodes 
     575        public TrieProcessor.Result process(List<ITaskInstance> foundTask, int count) { 
     576            if (foundTask.size() < 2) { 
     577                // ignore single tasks 
    512578                return TrieProcessor.Result.CONTINUE; 
    513579            } 
     
    519585 
    520586            if (this.currentCount > count) { 
    521                 // ignore this children of this node, as they may have only smaller counts than 
     587                // ignore this children of this task, as they may have only smaller counts than 
    522588                // the already found tasks 
    523589                return TrieProcessor.Result.SKIP_NODE; 
     
    536602                boolean added = false; 
    537603                for (int i = 0; i < foundTasks.size(); i++) { 
    538                     if (foundTasks.get(i).size() < task.size()) { 
     604                    if (foundTasks.get(i).size() < foundTask.size()) { 
    539605                        // defensive copy 
    540                         foundTasks.add(i, new LinkedList<ITaskTreeNode>(task)); // defensive copy 
     606                        foundTasks.add(i, new LinkedList<ITaskInstance>(foundTask)); // defensive copy 
    541607                        added = true; 
    542608                        break; 
     
    545611                 
    546612                if (!added) { 
    547                     foundTasks.add(new LinkedList<ITaskTreeNode>(task)); // defensive copy 
     613                    foundTasks.add(new LinkedList<ITaskInstance>(foundTask)); // defensive copy 
    548614                } 
    549615            } 
     
    571637                        // found a task that is a potential subtask. Check for this and remove the 
    572638                        // subtask if needed 
    573                         List<ITaskTreeNode> longTask = foundTasks.get(i); 
    574                         List<ITaskTreeNode> shortTask = foundTasks.get(j); 
     639                        List<ITaskInstance> longTask = foundTasks.get(i); 
     640                        List<ITaskInstance> shortTask = foundTasks.get(j); 
    575641                         
    576642                        if (getSubListIndex(longTask, shortTask, 0) > -1) { 
     
    598664         *  
    599665         */ 
    600         private List<ISequence> sessions; 
    601          
    602         /** 
    603          *  
    604          */ 
    605         private Trie<ITaskTreeNode> lastTrie; 
     666        private List<IUserSession> sessions; 
     667         
     668        /** 
     669         *  
     670         */ 
     671        private Trie<ITaskInstance> lastTrie; 
    606672         
    607673        /** 
     
    618684         *  
    619685         */ 
    620         private List<ITaskTreeNode> taskOccurrences = new LinkedList<ITaskTreeNode>(); 
    621          
    622         /** 
    623          *  
    624          */ 
    625         private int replacementCounter; 
     686        private boolean detectedAndReplacedTasks; 
    626687         
    627688        /** 
     
    638699         *  
    639700         */ 
    640         private RuleApplicationData(List<ISequence> sessions) { 
     701        private RuleApplicationData(List<IUserSession> sessions) { 
    641702            this.sessions = sessions; 
    642703        } 
     
    645706         * @return the tree 
    646707         */ 
    647         private List<ISequence> getSessions() { 
     708        private List<IUserSession> getSessions() { 
    648709            return sessions; 
    649710        } 
     
    652713         * @param lastTrie the lastTrie to set 
    653714         */ 
    654         private void setLastTrie(Trie<ITaskTreeNode> lastTrie) { 
     715        private void setLastTrie(Trie<ITaskInstance> lastTrie) { 
    655716            this.lastTrie = lastTrie; 
    656717        } 
     
    659720         * @return the lastTrie 
    660721         */ 
    661         private Trie<ITaskTreeNode> getLastTrie() { 
     722        private Trie<ITaskInstance> getLastTrie() { 
    662723            return lastTrie; 
    663724        } 
     
    692753 
    693754        /** 
    694          * @return the taskOccurrences 
    695          */ 
    696         private void clearTaskOccurrences() { 
    697             taskOccurrences.clear(); 
    698         } 
    699  
    700         /** 
    701          * @return the taskOccurrences 
    702          */ 
    703         private void addTaskOccurrence(ITaskTreeNode taskOccurrence) { 
    704             taskOccurrences.add(taskOccurrence); 
    705         } 
    706  
    707         /** 
    708          * @return the taskOccurrences 
    709          */ 
    710         private List<ITaskTreeNode> getTaskOccurrences() { 
    711             return taskOccurrences; 
    712         } 
    713  
    714         /** 
    715755         * 
    716756         */ 
    717         private void resetReplacementCounter() { 
    718             replacementCounter = 0; 
     757        private void detectedAndReplacedTasks(boolean detectedAndReplacedTasks) { 
     758            this.detectedAndReplacedTasks = detectedAndReplacedTasks; 
    719759        } 
    720760 
     
    722762         * 
    723763         */ 
    724         private void incrementReplacementCounter() { 
    725             replacementCounter++; 
    726         } 
    727  
    728         /** 
    729          * 
    730          */ 
    731         private int getReplacementCounter() { 
    732             return replacementCounter; 
     764        private boolean detectedAndReplacedTasks() { 
     765            return detectedAndReplacedTasks; 
    733766        } 
    734767         
     
    753786     * @author Patrick Harms 
    754787     */ 
    755     private static class Tasks implements Iterable<List<ITaskTreeNode>> { 
     788    private static class Tasks implements Iterable<List<ITaskInstance>> { 
    756789         
    757790        /** 
     
    763796         *  
    764797         */ 
    765         private List<List<ITaskTreeNode>> sequences; 
     798        private List<List<ITaskInstance>> sequences; 
    766799 
    767800        /** 
     
    769802         * @param sequences 
    770803         */ 
    771         private Tasks(int occurrenceCount, List<List<ITaskTreeNode>> sequences) { 
     804        private Tasks(int occurrenceCount, List<List<ITaskInstance>> sequences) { 
    772805            super(); 
    773806            this.occurrenceCount = occurrenceCount; 
     
    797830         */ 
    798831        @Override 
    799         public Iterator<List<ITaskTreeNode>> iterator() { 
     832        public Iterator<List<ITaskInstance>> iterator() { 
    800833            return this.sequences.iterator(); 
    801834        } 
     
    803836    } 
    804837 
     838    /** 
     839     * 
     840     */ 
     841    private class TaskComparator implements SymbolComparator<ITaskInstance> { 
     842 
     843        /** */ 
     844        private Comparer comparer; 
     845 
     846        /** */ 
     847        private Comparer lexicalComparer; 
     848 
     849        /** */ 
     850        private HashMap<Long, Boolean> equalityBuffer = new HashMap<Long, Boolean>(); 
     851 
     852        /** */ 
     853        private HashMap<Long, Boolean> lexicalEqualityBuffer; 
     854 
     855        /** 
     856         * 
     857         */ 
     858        public TaskComparator(TaskEqualityRuleManager taskEqualityRuleManager, 
     859                              TaskEquality            minimalNodeEquality) 
     860        { 
     861            super(); 
     862             
     863            if (minimalNodeEquality == TaskEquality.LEXICALLY_EQUAL) { 
     864                comparer = new LexicalComparer(taskEqualityRuleManager); 
     865            } 
     866            else if (minimalNodeEquality == TaskEquality.SYNTACTICALLY_EQUAL) { 
     867                comparer = new SyntacticalComparer(taskEqualityRuleManager); 
     868            } 
     869            else if (minimalNodeEquality == TaskEquality.SEMANTICALLY_EQUAL) { 
     870                comparer = new SemanticalComparer(taskEqualityRuleManager); 
     871            } 
     872            else { 
     873                comparer = new DefaultComparer(taskEqualityRuleManager, minimalNodeEquality); 
     874            } 
     875             
     876            if (minimalNodeEquality == TaskEquality.LEXICALLY_EQUAL) { 
     877                lexicalComparer = comparer; 
     878                lexicalEqualityBuffer = equalityBuffer; 
     879            } 
     880            else { 
     881                lexicalComparer = new LexicalComparer(taskEqualityRuleManager); 
     882                lexicalEqualityBuffer = new HashMap<Long, Boolean>(); 
     883            } 
     884        } 
     885 
     886        /* (non-Javadoc) 
     887         * @see de.ugoe.cs.autoquest.tasktrees.temporalrelation.SymbolComparator#equals(java.lang.Object, java.lang.Object) 
     888         */ 
     889        @Override 
     890        public boolean equals(ITaskInstance taskInstance1, ITaskInstance taskInstance2) { 
     891            return equals(taskInstance1.getTask(), taskInstance2.getTask()); 
     892        }         
     893 
     894        /** 
     895         *  
     896         */ 
     897        public boolean equals(ITask task1, ITask task2) { 
     898            Boolean result; 
     899             
     900            if (task1 != task2) { 
     901                if ((task1 instanceof IEventTask) && (task2 instanceof IEventTask)) { 
     902                    long key = ((long) System.identityHashCode(task1)) << 32; 
     903                    key += System.identityHashCode(task2); 
     904                 
     905                    result = equalityBuffer.get(key); 
     906                 
     907                    if (result == null) { 
     908                        result = comparer.compare(task1, task2); 
     909                        equalityBuffer.put(key, result); 
     910                    } 
     911                } 
     912                else { 
     913                    result = false; 
     914                } 
     915            } 
     916            else { 
     917                result = true; 
     918            } 
     919             
     920            return result; 
     921        } 
     922 
     923        /** 
     924         * 
     925         */ 
     926        public boolean areLexicallyEqual(ITask task1, ITask task2) { 
     927            Boolean result; 
     928             
     929            if (task1 != task2) { 
     930                long key = ((long) System.identityHashCode(task1)) << 32; 
     931                key += System.identityHashCode(task2); 
     932                 
     933                result = lexicalEqualityBuffer.get(key); 
     934                 
     935                if (result == null) { 
     936                    result = lexicalComparer.compare(task1, task2); 
     937                    lexicalEqualityBuffer.put(key, result); 
     938                } 
     939            } 
     940            else { 
     941                result = true; 
     942            } 
     943             
     944            return result; 
     945        } 
     946    } 
     947 
     948    /** 
     949     *  
     950     */ 
     951    private interface Comparer { 
     952         
     953        /** 
     954         *  
     955         */ 
     956        boolean compare(ITask task1, ITask task2); 
     957    } 
     958 
     959    /** 
     960     *  
     961     */ 
     962    private class LexicalComparer implements Comparer { 
     963         
     964        /** 
     965         * <p> 
     966         * the task equality manager needed for comparing tasks with each other 
     967         * </p> 
     968         */ 
     969        private TaskEqualityRuleManager taskEqualityRuleManager; 
     970         
     971        /** 
     972         * 
     973         */ 
     974        public LexicalComparer(TaskEqualityRuleManager taskEqualityRuleManager) { 
     975           this.taskEqualityRuleManager = taskEqualityRuleManager; 
     976        } 
     977         
     978        /** 
     979         *  
     980         */ 
     981        public boolean compare(ITask task1, ITask task2) { 
     982            return taskEqualityRuleManager.areLexicallyEqual(task1, task2); 
     983        } 
     984    } 
     985 
     986    /** 
     987     *  
     988     */ 
     989    private class SyntacticalComparer implements Comparer { 
     990         
     991        /** 
     992         * <p> 
     993         * the task equality manager needed for comparing tasks with each other 
     994         * </p> 
     995         */ 
     996        private TaskEqualityRuleManager taskEqualityRuleManager; 
     997         
     998        /** 
     999         * 
     1000         */ 
     1001        public SyntacticalComparer(TaskEqualityRuleManager taskEqualityRuleManager) { 
     1002           this.taskEqualityRuleManager = taskEqualityRuleManager; 
     1003        } 
     1004         
     1005        /** 
     1006         *  
     1007         */ 
     1008        public boolean compare(ITask task1, ITask task2) { 
     1009            return taskEqualityRuleManager.areSyntacticallyEqual(task1, task2); 
     1010        } 
     1011    } 
     1012 
     1013    /** 
     1014     *  
     1015     */ 
     1016    private class SemanticalComparer implements Comparer { 
     1017         
     1018        /** 
     1019         * <p> 
     1020         * the task equality manager needed for comparing tasks with each other 
     1021         * </p> 
     1022         */ 
     1023        private TaskEqualityRuleManager taskEqualityRuleManager; 
     1024         
     1025        /** 
     1026         * 
     1027         */ 
     1028        public SemanticalComparer(TaskEqualityRuleManager taskEqualityRuleManager) { 
     1029           this.taskEqualityRuleManager = taskEqualityRuleManager; 
     1030        } 
     1031         
     1032        /** 
     1033         *  
     1034         */ 
     1035        public boolean compare(ITask task1, ITask task2) { 
     1036            return taskEqualityRuleManager.areSemanticallyEqual(task1, task2); 
     1037        } 
     1038    } 
     1039 
     1040    /** 
     1041     *  
     1042     */ 
     1043    private class DefaultComparer implements Comparer { 
     1044         
     1045        /** 
     1046         * <p> 
     1047         * the task equality manager needed for comparing tasks with each other 
     1048         * </p> 
     1049         */ 
     1050        private TaskEqualityRuleManager taskEqualityRuleManager; 
     1051 
     1052        /** 
     1053         * <p> 
     1054         * the minimal task equality two identified sublists need to have to consider them as equal 
     1055         * </p> 
     1056         */ 
     1057        private TaskEquality minimalNodeEquality; 
     1058         
     1059        /** 
     1060         * 
     1061         */ 
     1062        public DefaultComparer(TaskEqualityRuleManager taskEqualityRuleManager, 
     1063                               TaskEquality            minimalNodeEquality) 
     1064        { 
     1065           this.taskEqualityRuleManager = taskEqualityRuleManager; 
     1066           this.minimalNodeEquality = minimalNodeEquality; 
     1067        } 
     1068         
     1069        /** 
     1070         *  
     1071         */ 
     1072        public boolean compare(ITask task1, ITask task2) { 
     1073            return taskEqualityRuleManager.areAtLeastEqual(task1, task2, minimalNodeEquality); 
     1074        } 
     1075    } 
    8051076} 
Note: See TracChangeset for help on using the changeset viewer.