package de.ugoe.cs.autoquest.tasktrees.alignment.matrix; import java.io.Serializable; import java.util.HashMap; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; import java.util.HashSet; import java.util.Iterator; import java.util.LinkedList; import java.util.logging.Level; import de.ugoe.cs.autoquest.eventcore.guimodel.IGUIElement; import de.ugoe.cs.autoquest.tasktrees.alignment.algorithms.AlignmentHelpers; import de.ugoe.cs.autoquest.tasktrees.alignment.algorithms.Constants; import de.ugoe.cs.autoquest.tasktrees.treeifc.IEventTask; import de.ugoe.cs.autoquest.tasktrees.treeifc.IEventTaskInstance; import de.ugoe.cs.autoquest.tasktrees.treeifc.ITask; import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInstance; import de.ugoe.cs.util.console.Console; public class ObjectDistanceSubstitionMatrix implements SubstitutionMatrix,Serializable { /** * */ private static final long serialVersionUID = -4253258274617754083L; private HashMap idmapping; private ITriangleMatrix matrix; private HashSet uniqueTasks; private float gapPenalty; private int index = 0; private HashMap> etisOfTasks; private boolean calculateNonTaskInstances = true; private int firstRoundMaxIndex = 0; private double positiveThreshold; public ObjectDistanceSubstitionMatrix( float positiveThreshold, int gapPenalty, boolean calculateNonTaskInstances) { this.positiveThreshold = positiveThreshold; idmapping = new HashMap(); etisOfTasks = new HashMap>(); this.gapPenalty = gapPenalty; this.calculateNonTaskInstances = calculateNonTaskInstances; } public float getGapPenalty() { return gapPenalty; } public void setGapPenalty(float gapPenalty) { this.gapPenalty = gapPenalty; } //TODO: Merge this with updateEventTaskInstances private void searchEventTaskInstances() { for (Iterator it = uniqueTasks.iterator(); it.hasNext();) { ITask task = it.next(); if (!(task instanceof IEventTask)) { EventTaskInstancesListGenerator etlg = new EventTaskInstancesListGenerator(); task.accept(etlg); LinkedList eventTaskInstances = etlg .getEventlist(); etisOfTasks.put(task.getId(), eventTaskInstances); } } } public void updateEventTaskInstances(LinkedList newTasks){ for (Iterator it = newTasks.iterator();it.hasNext();) { ITask task = it.next(); if (!(task instanceof IEventTask)) { EventTaskInstancesListGenerator etlg = new EventTaskInstancesListGenerator(); task.accept(etlg); LinkedList eventTaskInstances = etlg .getEventlist(); etisOfTasks.put(task.getId(), eventTaskInstances); } } } //Just Calculate the distance between the new tasks and the matrix. public void update(LinkedList newTasks) { if (this.calculateNonTaskInstances) { try { matrix.increaseSize(newTasks.size()); System.out.println("Subsitution matrix size is now " + matrix.size()*(matrix.size()+1)/2); Console.traceln(Level.INFO, "searching EventTasks in Tasks"); } catch (Exception e) { Console.logException(e); } this.updateEventTaskInstances(newTasks); int nThreads = de.ugoe.cs.autoquest.tasktrees.temporalrelation.SequenceForTaskDetectionRuleAlignment.nThreads; ExecutorService executor = Executors.newFixedThreadPool(nThreads); int count=0; int size=uniqueTasks.size(); for(Iterator it = newTasks.iterator();it.hasNext();) { ITask task1 = it.next(); for (Iterator jt = uniqueTasks.iterator(); jt.hasNext();) { ITask task2 = jt.next(); Runnable worker = new DistanceCalculator(task1,task2); executor.execute(worker); } } executor.shutdown(); // Wait until all threads are finish try { executor.awaitTermination(60, TimeUnit.MINUTES); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("Finished all threads"); } } public void generate(HashSet uniqueTasks) { this.uniqueTasks = uniqueTasks; if (this.calculateNonTaskInstances) { matrix = new DynamicTriangleMatrix(uniqueTasks.size() + 1); Console.traceln(Level.INFO, "searching EventTasks in Tasks"); searchEventTaskInstances(); } else{ matrix = new StaticTriangleMatrix(uniqueTasks.size()+1); } matrix.initialize(0); int nThreads = de.ugoe.cs.autoquest.tasktrees.temporalrelation.SequenceForTaskDetectionRuleAlignment.nThreads; Console.traceln(Level.INFO, "calculating distances with " + nThreads + " threads"); ExecutorService executor = Executors.newFixedThreadPool(nThreads); int count=0; int size=uniqueTasks.size(); for (Iterator it = uniqueTasks.iterator(); it.hasNext();) { ITask task1 = it.next(); count++; if((size%count*100)==0) { Console.traceln(Level.INFO,(Math.round((float) count/size*100))+ "%"); } for (Iterator jt = uniqueTasks.iterator(); jt.hasNext();) { ITask task2 = jt.next(); Runnable worker = new DistanceCalculator(task1,task2); executor.execute(worker); } } executor.shutdown(); // Wait until all threads are finish try { executor.awaitTermination(60, TimeUnit.MINUTES); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("Finished all threads"); this.firstRoundMaxIndex=index; } private float distanceBetweenTaskAndInstance(ITask task1, IEventTaskInstance eti1) { if (this.calculateNonTaskInstances) { float tmpDistance = 0; //System.out.println(etisOfTasks); LinkedList eventTaskInstances = etisOfTasks .get(task1.getId()); for (Iterator it = eventTaskInstances .iterator(); it.hasNext();) { IEventTaskInstance eti2 = it.next(); //int taskId1 = eti1.getTask().getId(); //int taskId2 = eti2.getTask().getId(); //if (scoreExists(taskId1, taskId2)) { // tmpDistance += getScore(taskId1, taskId2); //} else { float dist = distanceBetweenInstances(eti1, eti2); matrix.set(getIndex(eti1), getIndex(eti2), dist); tmpDistance += dist; //} } return tmpDistance / eventTaskInstances.size(); } else { return 0; } } //public boolean scoreExists(int id, int id2) { //return idmapping.containsKey(id) && idmapping.containsKey(id2); // return false; //} private float distanceBetweenTasks(ITask task1, ITask task2) { if (this.calculateNonTaskInstances) { LinkedList eventTaskInstances = etisOfTasks .get(task1.getId()); float tmpDistance = 0; for (Iterator it = eventTaskInstances .iterator(); it.hasNext();) { IEventTaskInstance eti1 = it.next(); tmpDistance += distanceBetweenTaskAndInstance(task2, eti1); } return tmpDistance / eventTaskInstances.size(); } else { return 0; } } synchronized private int getIndex(ITask task) { int tempindex = -1; if (!idmapping.containsKey(task.getId())) { idmapping.put(task.getId(), index); tempindex = index; index++; } else { tempindex = idmapping.get(task.getId()); } return tempindex; } synchronized private int getIndex(IEventTaskInstance eti) { int tempindex = -1; if (!idmapping.containsKey(eti.getTask().getId())) { idmapping.put(eti.getTask().getId(), index); tempindex = index; index++; } else { tempindex = idmapping.get(eti.getTask().getId()); } return tempindex; }; private float distanceBetweenInstances(IEventTaskInstance eti1, IEventTaskInstance eti2) { IGUIElement first = (IGUIElement) eti1.getEvent().getTarget(); IGUIElement second = (IGUIElement) eti2.getEvent().getTarget(); float distance = -1 * AlignmentHelpers.distanceBetween(first, second); distance += positiveThreshold; return distance; } public String toString() { return matrix.toString(); } public float getScore(int taskId1, int taskId2) { if (taskId1 == Constants.GAP_SYMBOL || taskId1 == Constants.UNMATCHED_SYMBOL || taskId2 == Constants.GAP_SYMBOL || taskId2 == Constants.UNMATCHED_SYMBOL) { return 0; } else if(this.calculateNonTaskInstances==false && (taskId1>this.firstRoundMaxIndex || taskId2>this.firstRoundMaxIndex)) { return 0; } else { Integer first = idmapping.get(taskId1); Integer second = idmapping.get(taskId2); return matrix.get(first, second); } } private class DistanceCalculator implements Runnable { private ITask task1; private ITask task2; public DistanceCalculator(ITask task1, ITask task2){ this.task1 = task1; this.task2 = task2; } @Override public void run() { computeDistance(task1,task2); } private void computeDistance(ITask task1, ITask task2) { int index1 = -1; int index2 = -1; float distance = 0; ITaskInstance ti1 = null; ITaskInstance ti2 = null; // We just need to the first instance here if (task1.getInstances().size() > 0) { ti1 = (ITaskInstance) task1.getInstances().iterator() .next(); } if (task2.getInstances().size() > 0) { ti2 = (ITaskInstance) task2.getInstances().iterator() .next(); } IEventTaskInstance eti1 = null; IEventTaskInstance eti2 = null; if (ti1 instanceof IEventTaskInstance && ti2 instanceof IEventTaskInstance) { eti1 = (IEventTaskInstance) ti1; index1 = getIndex(eti1); eti2 = (IEventTaskInstance) ti2; index2 = getIndex(eti2); distance = distanceBetweenInstances(eti1, eti2); } else if (ti1 instanceof IEventTaskInstance && !(ti2 instanceof IEventTaskInstance)) { task1 = ((ITaskInstance) ti1).getTask(); index2 = getIndex(task2); eti1 = (IEventTaskInstance) ti1; index1 = getIndex(eti1); distance = distanceBetweenTaskAndInstance(task2, eti1); } else if (!(ti1 instanceof IEventTaskInstance) && ti2 instanceof IEventTaskInstance) { index1 = getIndex(task1); eti2 = (IEventTaskInstance) ti2; index2 = getIndex(eti2); distance = distanceBetweenTaskAndInstance(task1, eti2); } else if (!(ti1 instanceof IEventTaskInstance) && !(ti2 instanceof IEventTaskInstance)) { index1 = getIndex(task1); index2 = getIndex(task2); distance = distanceBetweenTasks(task1, task2); } else { System.out.println("Unknown error"); } matrix.set(index1, index2, distance); //return distance; } } }