source: trunk/autoquest-ui-core/src/main/java/de/ugoe/cs/autoquest/commands/usability/CMDgetTaskModelSimilarity.java @ 1919

Last change on this file since 1919 was 1919, checked in by pharms, 9 years ago
  • extended comparison for case study of INTERACT 2015 paper
File size: 35.0 KB
Line 
1//   Copyright 2012 Georg-August-Universität Göttingen, Germany
2//
3//   Licensed under the Apache License, Version 2.0 (the "License");
4//   you may not use this file except in compliance with the License.
5//   You may obtain a copy of the License at
6//
7//       http://www.apache.org/licenses/LICENSE-2.0
8//
9//   Unless required by applicable law or agreed to in writing, software
10//   distributed under the License is distributed on an "AS IS" BASIS,
11//   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12//   See the License for the specific language governing permissions and
13//   limitations under the License.
14
15package de.ugoe.cs.autoquest.commands.usability;
16
17import java.text.DecimalFormat;
18import java.util.ArrayList;
19import java.util.Collections;
20import java.util.HashMap;
21import java.util.IdentityHashMap;
22import java.util.LinkedList;
23import java.util.List;
24import java.util.Map;
25import java.util.logging.Level;
26
27import de.ugoe.cs.autoquest.CommandHelpers;
28import de.ugoe.cs.autoquest.eventcore.IEventTarget;
29import de.ugoe.cs.autoquest.tasktrees.taskequality.TaskEquality;
30import de.ugoe.cs.autoquest.tasktrees.taskequality.TaskEqualityRuleManager;
31import de.ugoe.cs.autoquest.tasktrees.temporalrelation.TaskComparator;
32import de.ugoe.cs.autoquest.tasktrees.temporalrelation.utils.SimilarTasks;
33import de.ugoe.cs.autoquest.tasktrees.treeifc.DefaultTaskTraversingVisitor;
34import de.ugoe.cs.autoquest.tasktrees.treeifc.IEventTask;
35import de.ugoe.cs.autoquest.tasktrees.treeifc.IEventTaskInstance;
36import de.ugoe.cs.autoquest.tasktrees.treeifc.ISelection;
37import de.ugoe.cs.autoquest.tasktrees.treeifc.ISequence;
38import de.ugoe.cs.autoquest.tasktrees.treeifc.ITask;
39import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskModel;
40import de.ugoe.cs.autoquest.tasktrees.treeifc.TaskMetric;
41import de.ugoe.cs.util.StopWatch;
42import de.ugoe.cs.util.console.Command;
43import de.ugoe.cs.util.console.Console;
44import de.ugoe.cs.util.console.GlobalDataContainer;
45
46/**
47 * <p>
48 * compares a set of task models with each other and drops their similarity as results
49 * </p>
50 *
51 * @author Patrick Harms
52 * @version 1.0
53 */
54public class CMDgetTaskModelSimilarity implements Command {
55
56    /*
57     * (non-Javadoc)
58     *
59     * @see de.ugoe.cs.util.console.Command#help()
60     */
61    @Override
62    public String help() {
63        return "getTaskModelSimilarity <tasktree1> <tasktree2> ...";
64    }
65
66    /*
67     * (non-Javadoc)
68     *
69     * @see de.ugoe.cs.util.console.Command#run(java.util.List)
70     */
71    @Override
72    public void run(List<Object> parameters) {
73        List<String> inputTaskTreeNames = new LinkedList<>();
74       
75        try {
76            for (Object param : parameters) {
77                inputTaskTreeNames.add((String) param);
78            }
79        }
80        catch (Exception e) {
81            throw new IllegalArgumentException("must provide valid input task tree names");
82        }
83
84        Map<ITaskModel, List<ISequence>> inputTaskModels = new IdentityHashMap<>();
85       
86        ITaskModel firstModel = null;
87       
88        for (String inputTaskTreeName : inputTaskTreeNames) {
89            Object dataObject = GlobalDataContainer.getInstance().getData(inputTaskTreeName);
90            if (dataObject == null) {
91                CommandHelpers.objectNotFoundMessage(inputTaskTreeName);
92                return;
93            }
94            if (!(dataObject instanceof ITaskModel)) {
95                CommandHelpers.objectNotType(inputTaskTreeName, "ITaskModel");
96                return;
97            }
98           
99            List<ISequence> tasksToCompare = new LinkedList<>();
100           
101            for (ITask task : ((ITaskModel) dataObject).getTasks()) {
102                if (task instanceof ISequence) {
103                    tasksToCompare.add((ISequence) task);
104                }
105            }
106           
107            inputTaskModels.put((ITaskModel) dataObject, tasksToCompare);
108           
109            if (firstModel == null) {
110                firstModel = (ITaskModel) dataObject;
111            }
112        }
113       
114        getTaskModelSimilarity(firstModel, inputTaskModels);
115    }
116
117    /**
118     *
119     */
120    private void getTaskModelSimilarity(ITaskModel                       modelToCompare,
121                                        Map<ITaskModel, List<ISequence>> inputTaskModels)
122    {
123        // create the indexes to not do too many comparisons
124        Map<ITaskModel, Map<Integer, Map<IEventTarget, List<ISequence>>>> index1 =
125            new IdentityHashMap<>();
126       
127        Map<ISequence, Integer> index2 = new HashMap<>();
128        Map<ISequence, IEventTarget> index3 = new HashMap<>();
129       
130        final List<IEventTask> terminalNodes = new ArrayList<>();
131        final List<ISelection> selections = new ArrayList<>();
132       
133        for (Map.Entry<ITaskModel, List<ISequence>> entry : inputTaskModels.entrySet()) {
134            for (ISequence sequence : entry.getValue()) {
135                terminalNodes.clear();
136                selections.clear();
137               
138                sequence.accept(new DefaultTaskTraversingVisitor() {
139                    @Override
140                    public void visit(IEventTask eventTask) {
141                        terminalNodes.add(eventTask);
142                    }
143                    @Override
144                    public void visit(ISelection selection) {
145                        selections.add(selection);
146                        // no need to traverse children as a sequences containing a selection
147                        // will be handled differently
148                    }
149                });
150               
151                int length = terminalNodes.size();
152                IEventTarget firstTarget = ((IEventTaskInstance) terminalNodes.get(0).getInstances()
153                    .iterator().next()).getEvent().getTarget();
154               
155                if (selections.size() > 0) {
156                    length = -1;
157                    firstTarget = null;
158                }
159
160                Map<Integer, Map<IEventTarget, List<ISequence>>> lengthMap =
161                    index1.get(entry.getKey());
162               
163                if (lengthMap == null) {
164                    lengthMap = new HashMap<>();
165                    index1.put(entry.getKey(), lengthMap);
166                }
167               
168                Map<IEventTarget, List<ISequence>> firstTaskMap = lengthMap.get(length);
169               
170                if (firstTaskMap == null) {
171                    firstTaskMap = new HashMap<>();
172                    lengthMap.put(length, firstTaskMap);
173                }
174               
175                List<ISequence> compareList = firstTaskMap.get(firstTarget);
176               
177                if (compareList == null) {
178                    compareList = new LinkedList<ISequence>();
179                    firstTaskMap.put(firstTarget, compareList);
180                }
181               
182                compareList.add(sequence);
183                index2.put(sequence, length);
184                index3.put(sequence, firstTarget);
185            }
186        }
187       
188        // create the comparison runnables
189        List<ComparisonRunnable> runnables = new LinkedList<>();
190       
191        for (Map.Entry<ITaskModel, List<ISequence>> model2 : inputTaskModels.entrySet()) {
192            if (modelToCompare != model2.getKey()) {
193                runnables.add(new ComparisonRunnable(modelToCompare,
194                                                     inputTaskModels.get(modelToCompare),
195                                                     model2.getKey(), model2.getValue(),
196                                                     Collections.unmodifiableMap
197                                                         (index1.get(model2.getKey())),
198                                                     Collections.unmodifiableMap(index2),
199                                                     Collections.unmodifiableMap(index3),
200                                                     runnables));
201            }
202        }
203       
204        // execute the threads
205        Console.traceln(Level.FINE, "scheduling " + runnables.size() + " comparison threads");
206       
207        synchronized (runnables) {
208            int startedRunnables = 0;
209            for (ComparisonRunnable runnable : runnables) {
210                while (startedRunnables >= Math.max(1, Runtime.getRuntime().availableProcessors()))
211                {
212                    try {
213                        Console.traceln(Level.FINER, "waiting for next thread to finish");
214                        runnables.wait();
215                        startedRunnables--;
216                        Console.traceln(Level.FINER, "thread finished");
217                    }
218                    catch (InterruptedException e) {
219                        // should not happen
220                        Console.logException(e);
221                    }
222                }
223           
224                Console.traceln(Level.FINER, "starting next thread");
225                startedRunnables++;
226                Console.traceln(Level.FINE, "comparing " + runnable.tasks1.size()
227                                + " tasks of model " + runnable.model1 + " with " +
228                                runnable.tasks2.size() + " tasks of model " + runnable.model2);
229             
230                new Thread(runnable).start();
231                Console.traceln(Level.FINER, "started next thread " + runnable);
232            }
233           
234            while (startedRunnables > 0) {
235                try {
236                    Console.traceln(Level.FINER, "waiting for next thread to finish");
237                    runnables.wait();
238                    startedRunnables--;
239                    Console.traceln(Level.FINER, "thread finished");
240                }
241                catch (InterruptedException e) {
242                    // should not happen
243                    Console.logException(e);
244                }
245            }
246        }
247
248        // merge the results
249        Console.traceln(Level.FINER, "all threads finished, mergin results");
250       
251        for (ComparisonRunnable runnable : runnables) {
252            Console.println("\nsimilarity statistics of comparison between " + runnable.model1 +
253                            " (" + runnable.tasks1.size() + " tasks) and " + runnable.model2 +
254                            " (" + runnable.tasks2.size() + " tasks)");
255            runnable.getStatistics().dump();
256        }
257    }
258
259    /**
260     *
261     */
262    private static class SimilarityStatistics {
263       
264        /**  */
265        private int taskCounter1 = 0;
266       
267        /** */
268        private int maxCoverage1 = 0;
269       
270        /** */
271        private ITaskModel model1 = null;
272       
273        /**  */
274        private Map<Integer, Integer> coverageCounters1 = new HashMap<>();
275       
276        /**  */
277        private int taskCounter2 = 0;
278       
279        /** */
280        private int maxCoverage2 = 0;
281       
282        /** */
283        private ITaskModel model2 = null;
284       
285        /**  */
286        private Map<Integer, Integer> coverageCounters2 = new HashMap<>();
287       
288        /**  */
289        private Map<Integer, Map<Integer, Map<TaskEquality, Integer>>> equalityCounters =
290            new HashMap<>();
291           
292        /**
293         *
294         */
295        private void addCoverageCounter(ITask task, ITaskModel model) {
296            if (model1 == null) {
297                model1 = model;
298            }
299            else if (model2 == null) {
300                model2 = model;
301            }
302           
303            int coverageRatio = model.getTaskInfo(task).getMeasureValue(TaskMetric.EVENT_COVERAGE);
304           
305            if (model == model1) {
306                addToMaps(coverageCounters1, coverageRatio, 1);
307                taskCounter1++;
308                maxCoverage1 = Math.max(maxCoverage1, coverageRatio);
309            }
310            else {
311                addToMaps(coverageCounters2, coverageRatio, 1);
312                taskCounter2++;
313                maxCoverage2 = Math.max(maxCoverage2, coverageRatio);
314            }
315        }
316       
317        /**
318         *
319         */
320        private void store(ITask        task,
321                           ITaskModel   model,
322                           ITask        other,
323                           ITaskModel   otherModel,
324                           TaskEquality equality)
325        {
326            int coverageRatio1 = model.getTaskInfo(task).getMeasureValue(TaskMetric.EVENT_COVERAGE);
327            int coverageRatio2 =
328                otherModel.getTaskInfo(other).getMeasureValue(TaskMetric.EVENT_COVERAGE);
329           
330            addToMaps(coverageRatio1, coverageRatio2, equality, 1);
331        }
332       
333        /**
334         *
335         */
336        private void store(ITask task, ITaskModel model) {
337            int coverageRatio1 = model.getTaskInfo(task).getMeasureValue(TaskMetric.EVENT_COVERAGE);
338           
339            addToMaps(coverageRatio1, 0, TaskEquality.UNEQUAL, 1);
340        }
341
342        /**
343         *
344         */
345        private void addToMaps(Map<Integer, Integer> coverageCounters, int ratio, int increment) {
346            Integer counter = coverageCounters.get(ratio);
347
348            if (counter == null) {
349                coverageCounters.put(ratio, increment);
350            }
351            else {
352                coverageCounters.put(ratio, counter + increment);
353            }
354        }
355       
356        /**
357         *
358         */
359        private void addToMaps(Integer ratio1, Integer ratio2, TaskEquality equality, int value) {
360            Map<Integer, Map<TaskEquality, Integer>> counters1 = equalityCounters.get(ratio1);
361               
362            if (counters1 == null) {
363                counters1 = new HashMap<>();
364                equalityCounters.put(ratio1, counters1);
365            }
366
367            Map<TaskEquality, Integer> counters2 = counters1.get(ratio2);
368
369            if (counters2 == null) {
370                counters2 = new HashMap<>();
371                counters1.put(ratio2, counters2);
372            }
373
374            Integer counter = counters2.get(equality);
375
376            if (counter == null) {
377                counters2.put(equality, value);
378            }
379            else {
380                counters2.put(equality, counter + value);
381            }
382        }
383
384        /**
385         *
386         */
387        private void dump() {
388            Console.println("Statistics of Similarity");
389            Console.println("========================");
390           
391            int[][] bins1 = getBinsOfAlmostEqualSize(coverageCounters1, taskCounter1, maxCoverage1);
392            int[][] bins2 = getBinsOfAlmostEqualSize(coverageCounters2, taskCounter2, maxCoverage2);
393            int lowerBorder1;
394            int higherBorder1;
395            int lowerBorder2;
396            int higherBorder2;
397            int lexicalEqualitiesOfBin = 0;
398            int syntacticalEqualitiesOfBin = 0;
399            int semanticalEqualitiesOfBin = 0;
400            int similaritiesOfBin = 0;
401            int allEqualities = 0;
402           
403            String[][] outputs = new String[(bins1.length * (bins2.length + 3)) + 1][];
404            int outputIndex = 0;
405           
406            DecimalFormat percentFormat = new DecimalFormat("##0.0%");
407            StringBuffer csvData = new StringBuffer();
408            csvData.append(taskCounter1);
409            csvData.append(';');
410            csvData.append(taskCounter2);
411           
412            for (int i = bins1.length - 1; i >= 0 ; i--) {
413                if (i <= 0) {
414                    lowerBorder1 = 0;
415                }
416                else {
417                    lowerBorder1 = bins1[i - 1][0] + 1;
418                }
419               
420                higherBorder1 = bins1[i][0];
421               
422                int allInBin1 = countAllInBin(lowerBorder1, higherBorder1);
423                csvData.append(';');
424                csvData.append(allInBin1);
425               
426                lexicalEqualitiesOfBin = 0;
427                syntacticalEqualitiesOfBin = 0;
428                semanticalEqualitiesOfBin = 0;
429                similaritiesOfBin = 0;
430               
431                outputs[outputIndex++] = new String[]
432                        { "similarities of " + bins1[i][1] + " tasks with " + lowerBorder1 +
433                          " to " + higherBorder1 + " covered events", "LEX", "SYN", "SEM",
434                          "ALL EQUAL", "SIM", "ALL" };
435               
436                for (int j = bins2.length - 1; j >= 0; j--) {
437                    if (j <= 0) {
438                        lowerBorder2 = 0;
439                    }
440                    else {
441                        lowerBorder2 = bins2[j - 1][0] + 1;
442                    }
443                   
444                    higherBorder2 = bins2[j][0];
445                   
446                    int allInBin2 = countAllInBin(lowerBorder2, higherBorder2);
447                    csvData.append(';');
448                    csvData.append(allInBin2);
449
450                    int count1 = countEqualities(lowerBorder1, higherBorder1, lowerBorder2,
451                                                 higherBorder2, TaskEquality.LEXICALLY_EQUAL);
452
453                    int count2 = countEqualities(lowerBorder1, higherBorder1, lowerBorder2,
454                                                 higherBorder2, TaskEquality.SYNTACTICALLY_EQUAL);
455
456                    int count3 = countEqualities(lowerBorder1, higherBorder1, lowerBorder2,
457                                                 higherBorder2, TaskEquality.SEMANTICALLY_EQUAL);
458                   
459                    int count4 = countEqualities(lowerBorder1, higherBorder1, lowerBorder2,
460                                                 higherBorder2, null);
461                   
462                    outputs[outputIndex++] = new String[]
463                            { "--> to " + allInBin2 + " tasks with " + lowerBorder2 +
464                              " to " + higherBorder2 + " covered events", format(count1, allInBin1),
465                              format(count2, allInBin1), format(count3, allInBin1),
466                              format(count1 + count2 + count3, allInBin1), format(count4, allInBin1),
467                              format(count1 + count2 + count3 + count4, allInBin1)
468                            };
469                   
470                    lexicalEqualitiesOfBin += count1;
471                    syntacticalEqualitiesOfBin += count2;
472                    semanticalEqualitiesOfBin += count3;
473                    similaritiesOfBin += count4;
474
475                    csvData.append(';');
476                    csvData.append(percentFormat.format((double) count1 / allInBin1));
477                    csvData.append(';');
478                    csvData.append(percentFormat.format((double) count2 / allInBin1));
479                    csvData.append(';');
480                    csvData.append(percentFormat.format((double) count3 / allInBin1));
481                    csvData.append(';');
482                    csvData.append(percentFormat.format
483                                       ((double) (count1 + count2 + count3) / allInBin1));
484                    csvData.append(';');
485                    csvData.append(percentFormat.format((double) count4 / allInBin1));
486                    csvData.append(';');
487                    csvData.append(percentFormat.format
488                                       ((double) (count1 + count2 + count3 + count4) / allInBin1));
489                }
490               
491                outputs[outputIndex++] = new String[]
492                        { "--> all recalls", format(lexicalEqualitiesOfBin, allInBin1),
493                          format(syntacticalEqualitiesOfBin, allInBin1),
494                          format(semanticalEqualitiesOfBin, allInBin1),
495                          format(lexicalEqualitiesOfBin + syntacticalEqualitiesOfBin +
496                                 semanticalEqualitiesOfBin, allInBin1),
497                          format(similaritiesOfBin, allInBin1),
498                          format(lexicalEqualitiesOfBin + syntacticalEqualitiesOfBin +
499                                 semanticalEqualitiesOfBin + similaritiesOfBin, allInBin1)
500                        };
501               
502
503                csvData.append(';');
504                csvData.append(percentFormat.format((double) lexicalEqualitiesOfBin / allInBin1));
505                csvData.append(';');
506                csvData.append(percentFormat.format((double) syntacticalEqualitiesOfBin / allInBin1));
507                csvData.append(';');
508                csvData.append(percentFormat.format((double) semanticalEqualitiesOfBin / allInBin1));
509                csvData.append(';');
510                csvData.append(percentFormat.format
511                                   ((double) (lexicalEqualitiesOfBin + syntacticalEqualitiesOfBin +
512                                              semanticalEqualitiesOfBin) / allInBin1));
513                csvData.append(';');
514                csvData.append(percentFormat.format((double) similaritiesOfBin / allInBin1));
515                csvData.append(';');
516                csvData.append(percentFormat.format
517                                   ((double) (lexicalEqualitiesOfBin + syntacticalEqualitiesOfBin +
518                                              semanticalEqualitiesOfBin + similaritiesOfBin) /
519                                              allInBin1));
520               
521                allEqualities += lexicalEqualitiesOfBin + syntacticalEqualitiesOfBin +
522                    semanticalEqualitiesOfBin + similaritiesOfBin;
523               
524                outputIndex++;
525            }
526           
527            outputs[outputIndex++] = new String[]
528                    { "complete recall is", null, null, null, null, null,
529                      format(allEqualities, taskCounter1)
530                    };
531           
532            csvData.append(';');
533            csvData.append(percentFormat.format((double) allEqualities / taskCounter1));
534           
535            dump(outputs);
536            Console.println("\nCSV: " + csvData);
537        }
538
539        /**
540         *
541         */
542        private void dump(String[][] outputs) {
543            int[] lengths = new int[outputs[0].length];
544           
545            for (String[] line : outputs) {
546                if (line != null) {
547                    for (int i = 0; i < line.length; i++) {
548                        if (line[i] != null) {
549                            lengths[i] = Math.max(lengths[i], line[i].length());
550                        }
551                    }
552                }
553            }
554           
555            for (String[] line : outputs) {
556                StringBuffer toWrite = new StringBuffer();
557               
558                if (line != null) {
559                    for (int i = 0; i < line.length; i++) {
560                        if (i > 0) {
561                            toWrite.append(" | ");
562                        }
563                   
564                        String text = line[i];
565                   
566                        if (text == null) {
567                            text = "";
568                        }
569                   
570                        for (int j = 0; j < (lengths[i] - text.length()); j++) {
571                            toWrite.append(' ');
572                        }
573                     
574                        toWrite.append(text);
575                    }
576                }
577               
578                Console.println(toWrite.toString());
579            }
580        }
581
582        /**
583         *
584         */
585        private int[][] getBinsOfAlmostEqualSize(Map<Integer, Integer> coverageCounters,
586                                                 int                   taskCounter,
587                                                 int                   maxCoverage)
588        {
589            int[][] result = new int[5][];
590           
591            for (int i = 0; i < result.length; i++) {
592                result[i] = new int[2];
593            }
594           
595            int averageBinSize = taskCounter / result.length;
596            int aimedBinSize = averageBinSize;
597           
598            int index = 0;
599           
600            for (int i = 0; i < maxCoverage; i++) {
601                if (result[index][1] > aimedBinSize) {
602                    // try to compensate, if the previous bin was a little too large
603                    aimedBinSize = averageBinSize + averageBinSize - result[index][1];
604                    index++;
605                }
606
607                Integer value = coverageCounters.get(i);
608               
609                if (value != null) {
610                    result[index][0] = i;
611                    result[index][1] += value;
612                }
613            }
614           
615            return result;
616        }
617
618        /**
619         *
620         */
621        private String format(int noOfEqualTasks, int noOfAllTasks) {
622            StringBuffer result = new StringBuffer();
623            if (noOfAllTasks > 0) {
624                double value = ((double) (noOfEqualTasks * 100)) / noOfAllTasks;
625                result.append(noOfEqualTasks);
626                result.append(" (");
627                result.append(new DecimalFormat("##0.0").format(value));
628                result.append("%)");
629            }
630            else {
631                result.append("n.a.");
632            }
633           
634            return result.toString();
635        }
636
637        /**
638         *
639         */
640        private int countEqualities(int          lowerBorder1,
641                                    int          higherBorder1,
642                                    int          lowerBorder2,
643                                    int          higherBorder2,
644                                    TaskEquality equality)
645        {
646            int counter = 0;
647           
648            for (int i = lowerBorder1; i <= higherBorder1; i++) {
649                Map<Integer, Map<TaskEquality, Integer>> counters1 = equalityCounters.get(i);
650
651                if (counters1 != null) {
652                    for (int j = lowerBorder2; j <= higherBorder2; j++) {
653                        Map<TaskEquality, Integer> counters2 = counters1.get(j);
654               
655                        if (counters2 != null) {
656                            Integer counterObj = counters2.get(equality);
657                   
658                            if (counterObj != null) {
659                                counter += counterObj;
660                            }
661                        }
662                    }
663                }
664            }
665           
666            return counter;
667        }
668
669        /**
670         *
671         */
672        private int countAllInBin(int lowerBorder, int higherBorder) {
673            int coverageCounter = 0;
674           
675            for (int i = lowerBorder; i <= higherBorder; i++) {
676                Integer value = coverageCounters1.get(i);
677               
678                if (value != null) {
679                    coverageCounter += value;
680                }
681            }
682           
683            return coverageCounter;
684        }
685    }
686
687    /**
688     *
689     */
690    private static class ComparisonRunnable implements Runnable {
691       
692        /** */
693        private ITaskModel model1;
694       
695        /** */
696        private ITaskModel model2;
697       
698        /** */
699        private List<ISequence> tasks1;
700       
701        /** */
702        private List<ISequence> tasks2;
703       
704        /** */
705        private Map<Integer, Map<IEventTarget, List<ISequence>>> lengthIndex1;
706       
707        /** */
708        private Map<ISequence, Integer> lengthIndex2;
709       
710        /** */
711        private Map<ISequence, IEventTarget> firstTargetIndex;
712
713        /** */
714        private Object semaphore;
715       
716        /** */
717        private SimilarityStatistics statistics = new SimilarityStatistics();
718       
719        /**
720         *
721         */
722        private ComparisonRunnable(ITaskModel                                       model1,
723                                   List<ISequence>                                  tasks1,
724                                   ITaskModel                                       model2,
725                                   List<ISequence>                                  tasks2,
726                                   Map<Integer, Map<IEventTarget, List<ISequence>>> lengthIndex1,
727                                   Map<ISequence, Integer>                          lengthIndex2,
728                                   Map<ISequence, IEventTarget>                     firstTargetIndex,
729                                   Object                                           semaphore)
730        {
731            this.model1 = model1;
732            this.tasks1 = tasks1;
733            this.model2 = model2;
734            this.tasks2 = tasks2;
735            this.lengthIndex1 = lengthIndex1;
736            this.lengthIndex2 = lengthIndex2;
737            this.firstTargetIndex = firstTargetIndex;
738            this.semaphore = semaphore;
739        }
740
741        /* (non-Javadoc)
742         * @see java.lang.Runnable#run()
743         */
744        @Override
745        public void run() {
746            TaskEqualityRuleManager equalityRuleManager = TaskEqualityRuleManager.getInstance();
747            TaskComparator comparator = new TaskComparator(TaskEquality.SEMANTICALLY_EQUAL);
748            TaskEquality mostCommonEquality;
749            ITask mostSimilarTask;
750            TaskEquality equality;
751            SimilarTasks similarity;
752
753            // store coverage infos for models
754            for (ISequence task : tasks1) {
755                statistics.addCoverageCounter(task, model1);
756            }
757           
758            for (ISequence task : tasks2) {
759                statistics.addCoverageCounter(task, model2);
760            }
761           
762            List<ISequence> tasksToCompareWith = new ArrayList<ISequence>();
763            StopWatch watch = new StopWatch();
764            watch.start("all comparisons ");
765            int count = 0;
766            for (ISequence task : tasks1) {
767                int length = lengthIndex2.get(task);
768                IEventTarget firstTarget = firstTargetIndex.get(task);
769                tasksToCompareWith.clear();
770               
771                // add tasks with same length
772                Map<IEventTarget, List<ISequence>> eventTaskMap = lengthIndex1.get(length);
773                List<ISequence> toCompare;
774               
775                if (eventTaskMap != null) {
776                    toCompare = eventTaskMap.get(firstTarget);
777               
778                    if (toCompare != null) {
779                        tasksToCompareWith.addAll(toCompare);
780                    }
781                }
782               
783                // add tasks containing selections
784                eventTaskMap = lengthIndex1.get(-1);
785               
786                if (eventTaskMap != null) {
787                    toCompare = eventTaskMap.get(firstTarget);
788               
789                    if (toCompare != null) {
790                        tasksToCompareWith.addAll(toCompare);
791                    }
792                }
793               
794                mostCommonEquality = null;
795                mostSimilarTask = null;
796               
797                for (ITask taskToCompare : tasksToCompareWith) {
798                    count++;
799                    watch.start("normal comparison");
800                    equality = equalityRuleManager.compare(task, taskToCompare);
801                    watch.stop("normal comparison");
802                   
803                    if ((equality != TaskEquality.UNEQUAL) &&
804                        ((mostCommonEquality == null) || (equality.isAtLeast(mostCommonEquality))))
805                    {
806                        // >>>>>>>>>>>>>>>>>>>>>> TEST IMPLEMENTATION >>>>>>>>>>>>>>>>>>>>>>>>>>>
807                        // synchronized (System.out) {
808                        //     System.out.println("found equal tasks: " + equality);
809                        //     new TaskTreeEncoder().encode(task, System.out);
810                        //     new TaskTreeEncoder().encode(taskToCompare, System.out);
811                        // }
812                        // <<<<<<<<<<<<<<<<<<<<<< TEST IMPLEMENTATION <<<<<<<<<<<<<<<<<<<<<<<<<<<
813
814                        mostCommonEquality = equality;
815                        mostSimilarTask = taskToCompare;
816                       
817                        if (mostCommonEquality.isAtLeast(TaskEquality.LEXICALLY_EQUAL)) {
818                            // we found a lexically equal match, the most concrete that
819                            // we can find. We can break up here
820                            break;
821                        }
822                    }
823                }
824               
825                if (mostCommonEquality != null) {
826                    statistics.store(task, model1, mostSimilarTask, model2, mostCommonEquality);
827                }
828                else {
829                    int lowestDiffLevel = Integer.MAX_VALUE;
830                    for (ITask taskToCompare : tasksToCompareWith) {
831                        count++;
832                        watch.start("similarity comparison");
833                        similarity = SimilarTasks.compareTasks(task, taskToCompare, comparator);
834                        watch.stop("similarity comparison");
835                       
836                        if (similarity.getDiffLevel() < lowestDiffLevel) {
837                            lowestDiffLevel = similarity.getDiffLevel();
838                            mostSimilarTask = taskToCompare;
839                           
840                            if (lowestDiffLevel <= 0) {
841                                // >>>>>>>>>>>>>>>>>>>>>> TEST IMPLEMENTATION >>>>>>>>>>>>>>>>>>>>>
842                                // synchronized (System.out) {
843                                //     System.out.println("found similar tasks");
844                                //     similarity.dump(System.out);
845                                // }
846                                // <<<<<<<<<<<<<<<<<<<<<< TEST IMPLEMENTATION <<<<<<<<<<<<<<<<<<<<<
847
848                                // we found a fully similar task. We will not find any more
849                                // similar, hence we break
850                                break;
851                            }
852                        }
853                    }
854                   
855                    if (lowestDiffLevel <= 0) {
856                        statistics.store(task, model1, mostSimilarTask, model2, null);
857                    }
858                    else {
859                        statistics.store(task, model1);
860                    }
861                }
862            }
863           
864            System.out.println("performed " + count + " comparisons");
865           
866            watch.stop("all comparisons ");
867            watch.dumpStatistics(System.out);
868           
869            synchronized (semaphore) {
870                semaphore.notify();
871            }
872        }
873
874        /**
875         * @return the statistics
876         */
877        private SimilarityStatistics getStatistics() {
878            return statistics;
879        }
880       
881    }
882}
Note: See TracBrowser for help on using the repository browser.