From 7d1ee66d95063006f71c201627587bb917d72b5a Mon Sep 17 00:00:00 2001 From: mwever Date: Mon, 20 Aug 2018 08:57:09 +0200 Subject: [PATCH] Added config interface to HASCO * added renameAttribute to TaskChunk/Task --- .../src/jaicore/basic/chunks/Task.java | 217 ++++--- .../src/jaicore/basic/chunks/TaskChunk.java | 69 +- .../standard/core/ORGraphSearch.java | 611 ++++++++++-------- .../hasco/src/hasco/core/HASCO.java | 294 +++++---- 4 files changed, 661 insertions(+), 530 deletions(-) diff --git a/JAICore/jaicore-basic/src/jaicore/basic/chunks/Task.java b/JAICore/jaicore-basic/src/jaicore/basic/chunks/Task.java index 224ca24f22..fe2a6245cb 100644 --- a/JAICore/jaicore-basic/src/jaicore/basic/chunks/Task.java +++ b/JAICore/jaicore-basic/src/jaicore/basic/chunks/Task.java @@ -1,7 +1,5 @@ package jaicore.basic.chunks; -import jaicore.basic.kvstore.SimpleKVStore; - import java.util.Collection; import java.util.HashMap; import java.util.HashSet; @@ -9,109 +7,118 @@ import java.util.Map.Entry; import java.util.Set; +import jaicore.basic.kvstore.SimpleKVStore; + public class Task extends SimpleKVStore { - /** - * - */ - private static final long serialVersionUID = -8259795114344707332L; - - private static final String FIELD_TASKID = "taskID"; - private TaskChunk chunk; - - public Task() { - super(); - } - - public Task(final String stringRepresentation) { - super(stringRepresentation); - } - - public Task(final Task taskToCopy) { - super(new HashMap<>()); - this.chunk = taskToCopy.chunk; - for (Entry entry : taskToCopy.getAllKVEntries()) { - this.store(entry.getKey(), entry.getValue()); - } - } - - public Task(final Map keyValueMap) { - super(keyValueMap); - } - - @Override - public Task clone() { - Task t = new Task(); - t.getKeyValueMap().putAll(this.getKeyValueMap()); - return t; - } - - public void setChunk(final TaskChunk chunk) { - this.chunk = chunk; - } - - public TaskChunk getChunk() { - return this.chunk; - } - - public String getTaskID() { - return this.getValueAsString(FIELD_TASKID); - } - - public void setTaskID(final String taskID) { - this.store(FIELD_TASKID, taskID); - } - - public Collection storeEach(final String key, final Set values) { - return Task.storeEach(this, key, values); - } - - public static Collection storeEach(final Task task, final String key, final Set values) { - Collection allCombinations = new HashSet<>(); - for (String value : values) { - Task copy = new Task(task); - copy.store(key, value); - allCombinations.add(copy); - } - return allCombinations; - } - - @Override - public String toString() { - return super.toString(); - } - - public void implode(final String[] fieldKeys, final String separator, final String newKey) { - StringBuilder sb = new StringBuilder(); - boolean first = true; - for (String fieldKey : fieldKeys) { - if (first) { - first = false; - } else { - sb.append(separator); - } - sb.append(this.getValueAsString(fieldKey)); - this.getKeyValueMap().remove(fieldKey); - } - this.store(newKey, sb.toString()); - } - - public void prefixKeys(final String prefix) { - Set keySet = new HashSet<>(this.getKeyValueMap().keySet()); - for (String key : keySet) { - String value = this.getValueAsString(key); - this.getKeyValueMap().remove(key); - this.store(prefix + key, value); - } - } - - @Override - public boolean equals(final Object other) { - if (!(other instanceof Task)) { - return false; - } - - Task t = (Task) other; - return t.getKeyValueMap().equals(this.getKeyValueMap()); - } + /** + * + */ + private static final long serialVersionUID = -8259795114344707332L; + + private static final String FIELD_TASKID = "taskID"; + private TaskChunk chunk; + + public Task() { + super(); + } + + public Task(final String stringRepresentation) { + super(stringRepresentation); + } + + public Task(final Task taskToCopy) { + super(new HashMap<>()); + this.chunk = taskToCopy.chunk; + for (Entry entry : taskToCopy.getAllKVEntries()) { + this.store(entry.getKey(), entry.getValue()); + } + } + + public Task(final Map keyValueMap) { + super(keyValueMap); + } + + @Override + public Task clone() { + Task t = new Task(); + t.getKeyValueMap().putAll(this.getKeyValueMap()); + return t; + } + + public void setChunk(final TaskChunk chunk) { + this.chunk = chunk; + } + + public TaskChunk getChunk() { + return this.chunk; + } + + public String getTaskID() { + return this.getValueAsString(FIELD_TASKID); + } + + public void setTaskID(final String taskID) { + this.store(FIELD_TASKID, taskID); + } + + public Collection storeEach(final String key, final Set values) { + return Task.storeEach(this, key, values); + } + + public static Collection storeEach(final Task task, final String key, final Set values) { + Collection allCombinations = new HashSet<>(); + for (String value : values) { + Task copy = new Task(task); + copy.store(key, value); + allCombinations.add(copy); + } + return allCombinations; + } + + @Override + public String toString() { + return super.toString(); + } + + public void implode(final String[] fieldKeys, final String separator, final String newKey) { + StringBuilder sb = new StringBuilder(); + boolean first = true; + for (String fieldKey : fieldKeys) { + if (first) { + first = false; + } else { + sb.append(separator); + } + sb.append(this.getValueAsString(fieldKey)); + this.getKeyValueMap().remove(fieldKey); + } + this.store(newKey, sb.toString()); + } + + public void prefixKeys(final String prefix) { + Set keySet = new HashSet<>(this.getKeyValueMap().keySet()); + for (String key : keySet) { + String value = this.getValueAsString(key); + this.getKeyValueMap().remove(key); + this.store(prefix + key, value); + } + } + + public void renameAttribute(final String attributeName, final String replacement) { + if (this.containsKey(attributeName)) { + this.store(replacement, this.getValueAsString(attributeName)); + this.projectRemove(new String[] { attributeName }); + } + } + + @Override + public boolean equals(final Object other) { + if (!(other instanceof Task)) { + return false; + } + + Task t = (Task) other; + return t.getKeyValueMap().equals(this.getKeyValueMap()); + } } diff --git a/JAICore/jaicore-basic/src/jaicore/basic/chunks/TaskChunk.java b/JAICore/jaicore-basic/src/jaicore/basic/chunks/TaskChunk.java index a1b0782484..f1a3366195 100644 --- a/JAICore/jaicore-basic/src/jaicore/basic/chunks/TaskChunk.java +++ b/JAICore/jaicore-basic/src/jaicore/basic/chunks/TaskChunk.java @@ -259,30 +259,64 @@ public void removeAny(final String[] value, final boolean or) { public void removeAny(final Map condition, final boolean or) { if (or) { - taskList.removeIf(t -> { + this.taskList.removeIf(t -> { for (String key : condition.keySet()) { String val = t.getValueAsString(key); - if (val == null && condition.get(key) == null || val != null && val.equals(condition.get(key))) + if (val == null && condition.get(key) == null || val != null && val.equals(condition.get(key))) { return true; + } } return false; }); } else { - taskList.removeIf(t -> { + this.taskList.removeIf(t -> { for (String key : condition.keySet()) { - if (!t.getValueAsString(key).equals(condition.get(key))) + if (!t.getValueAsString(key).equals(condition.get(key))) { return false; + } } return true; }); } } - public void removeGroupsIfNotAtLeastWithSize(int size) { + public void removeGroupsIfNotAtLeastWithSize(final int size) { Map groupSizeCondition = new HashMap<>(); for (int i = 1; i < size; i++) { groupSizeCondition.put("GROUP_SIZE", "" + i); - removeAny(groupSizeCondition, true); + this.removeAny(groupSizeCondition, true); + } + } + + public void removeGroupsIfNotAtLeastWithSizeButOne(final int size, final String[] groupingKeys) { + + Map groupSizeCondition = new HashMap<>(); + for (int i = 1; i < size; i++) { + System.out.println("Remove any groups that dont have at least " + (i + 1) + " entries."); + + int currentMinLength = i; + TaskChunk group = new TaskChunk<>(this.getStringRepresentation()); + group.renameAttribute("GROUP_SIZE", "size"); + group = group.group(groupingKeys, new HashMap<>()); + + for (V t : group) { + List sizeList = t.getValueAsIntList("size", ",").stream().filter(x -> x > currentMinLength).collect(Collectors.toList()); + System.out.println(currentMinLength + " " + sizeList + " " + t.getValueAsIntList("size", ",")); + if (sizeList.size() > 0) { + for (String groupingKey : groupingKeys) { + groupSizeCondition.put(groupingKey, t.getValueAsString(groupingKey)); + } + groupSizeCondition.put("GROUP_SIZE", "" + i); + System.out.println(groupSizeCondition); + this.removeAny(groupSizeCondition, false); + } + } + } + } + + public void renameAttribute(final String attributeName, final String replacement) { + for (V t : this) { + t.renameAttribute(attributeName, replacement); } } @@ -492,8 +526,7 @@ public void mergeTasks(final Task other, final Map combineMap) { boolean equals = true; for (Entry combineEntry : combineMap.entrySet()) { - if (!t.containsKey(combineEntry.getKey()) || !other.containsKey(combineEntry.getValue()) - || !t.getValueAsString(combineEntry.getKey()).equals(other.getValueAsString(combineEntry.getValue()))) { + if (!t.containsKey(combineEntry.getKey()) || !other.containsKey(combineEntry.getValue()) || !t.getValueAsString(combineEntry.getKey()).equals(other.getValueAsString(combineEntry.getValue()))) { equals = false; break; } @@ -567,9 +600,9 @@ public void mannWhitneyU(final String keyFieldName, final String comparatorField } } - + public void best(final String keyFieldName, final String comparatorFieldName, final String valueFieldName) { - best (keyFieldName, comparatorFieldName, valueFieldName, "best"); + this.best(keyFieldName, comparatorFieldName, valueFieldName, "best"); } public void best(final String keyFieldName, final String comparatorFieldName, final String valueFieldName, final String outputFieldName) { @@ -610,23 +643,23 @@ public void best(final String keyFieldName, final String comparatorFieldName, fi } } - + public void singleBest(final String keyFieldName, final String comparatorFieldName, final String valueFieldName) { - singleBest(keyFieldName, comparatorFieldName, valueFieldName, "best"); + this.singleBest(keyFieldName, comparatorFieldName, valueFieldName, "best"); } public void singleBest(final String keyFieldName, final String comparatorFieldName, final String valueFieldName, final String outputFieldName) { - best(keyFieldName, comparatorFieldName, valueFieldName, outputFieldName); + this.best(keyFieldName, comparatorFieldName, valueFieldName, outputFieldName); List distinctTasks = new ArrayList<>(); Set consideredKeys = new HashSet<>(); - taskList.forEach(t -> { + this.taskList.forEach(t -> { String keyValue = t.getValueAsString(keyFieldName); if (!consideredKeys.contains(keyValue) && t.getValueAsBoolean(outputFieldName)) { consideredKeys.add(keyValue); distinctTasks.add(t); } }); - taskList = distinctTasks; + this.taskList = distinctTasks; } public void best(final String keyFieldName, final String comparatorFieldName, final String valueFieldName, final Set compareObjects) { @@ -784,9 +817,11 @@ public void tTest(final String keyFN, final String idFN, final String valueListF StatisticalSummaryValues summaryComp = new StatisticalSummaryValues(mean2, variance2, n2, max2, min2, sum2); try { - sig = test.tTest(summaryGT, summaryComp, 0.05); - } catch(NumberIsTooSmallException e) { + sig = test.tTest(summaryGT, summaryComp, 0.05); + } catch (NumberIsTooSmallException e) { System.out.println("Cannot apply ttest for dataset " + groundTruthEntry.getKey() + " and comparison of " + name1 + " and " + name2); + System.out.println(summaryGT); + System.out.println(summaryComp); throw e; } diff --git a/JAICore/jaicore-search/src/jaicore/search/algorithms/standard/core/ORGraphSearch.java b/JAICore/jaicore-search/src/jaicore/search/algorithms/standard/core/ORGraphSearch.java index 2225a3a8d2..7bb87187ae 100644 --- a/JAICore/jaicore-search/src/jaicore/search/algorithms/standard/core/ORGraphSearch.java +++ b/JAICore/jaicore-search/src/jaicore/search/algorithms/standard/core/ORGraphSearch.java @@ -52,8 +52,7 @@ import jaicore.search.structure.graphgenerator.SingleRootGenerator; import jaicore.search.structure.graphgenerator.SuccessorGenerator; -public class ORGraphSearch> - implements IObservableORGraphSearch, IIterableAlgorithm>>, Iterator>>, ILoggingCustomizable { +public class ORGraphSearch> implements IObservableORGraphSearch, IIterableAlgorithm>>, Iterator>>, ILoggingCustomizable { private Logger logger = LoggerFactory.getLogger(ORGraphSearch.class); @@ -110,7 +109,7 @@ private class NodeBuilder implements Runnable { private final Node expandedNodeInternal; private final NodeExpansionDescription successorDescription; - public NodeBuilder(Node expandedNodeInternal, NodeExpansionDescription successorDescription) { + public NodeBuilder(final Node expandedNodeInternal, final NodeExpansionDescription successorDescription) { super(); this.expandedNodeInternal = expandedNodeInternal; this.successorDescription = successorDescription; @@ -119,23 +118,24 @@ public NodeBuilder(Node expandedNodeInternal, NodeExpansionDescription newNode = newNode(expandedNodeInternal, successorDescription.getTo()); + Node newNode = ORGraphSearch.this.newNode(this.expandedNodeInternal, this.successorDescription.getTo()); /* update creation counter */ - createdCounter++; + ORGraphSearch.this.createdCounter++; /* set timeout on thread that interrupts it after the timeout */ int taskId = -1; - if (timeoutForComputationOfF > 0) { - if (timeoutSubmitter == null) { - timeoutSubmitter = TimeoutTimer.getInstance().getSubmitter(); + if (ORGraphSearch.this.timeoutForComputationOfF > 0) { + if (ORGraphSearch.this.timeoutSubmitter == null) { + ORGraphSearch.this.timeoutSubmitter = TimeoutTimer.getInstance().getSubmitter(); } - taskId = timeoutSubmitter.interruptMeAfterMS(timeoutForComputationOfF); + taskId = ORGraphSearch.this.timeoutSubmitter.interruptMeAfterMS(ORGraphSearch.this.timeoutForComputationOfF); } /* compute node label */ @@ -143,88 +143,92 @@ public void run() { boolean computationTimedout = false; long startComputation = System.currentTimeMillis(); try { - label = nodeEvaluator.f(newNode); + label = ORGraphSearch.this.nodeEvaluator.f(newNode); /* check whether the required time exceeded the timeout */ long fTime = System.currentTimeMillis() - startComputation; - if (timeoutForComputationOfF > 0 && fTime > timeoutForComputationOfF + 1000) - logger.warn("Computation of f for node {} took {}ms, which is more than the allowed {}ms", newNode, fTime, timeoutForComputationOfF); + if (ORGraphSearch.this.timeoutForComputationOfF > 0 && fTime > ORGraphSearch.this.timeoutForComputationOfF + 1000) { + ORGraphSearch.this.logger.warn("Computation of f for node {} took {}ms, which is more than the allowed {}ms", newNode, fTime, ORGraphSearch.this.timeoutForComputationOfF); + } } catch (InterruptedException e) { - logger.debug("Received interrupt during computation of f."); - graphEventBus.post(new NodeTypeSwitchEvent<>(newNode, "or_timedout")); + ORGraphSearch.this.logger.debug("Received interrupt during computation of f."); + ORGraphSearch.this.graphEventBus.post(new NodeTypeSwitchEvent<>(newNode, "or_timedout")); newNode.setAnnotation("fError", "Timeout"); computationTimedout = true; try { - label = timeoutNodeEvaluator != null ? timeoutNodeEvaluator.f(newNode) : null; + label = ORGraphSearch.this.timeoutNodeEvaluator != null ? ORGraphSearch.this.timeoutNodeEvaluator.f(newNode) : null; } catch (Throwable e2) { e2.printStackTrace(); } } catch (Throwable e) { - logger.error("Observed an execution during computation of f:\n{}", LoggerUtil.getExceptionInfo(e)); + ORGraphSearch.this.logger.error("Observed an exception during computation of f:\n{}", LoggerUtil.getExceptionInfo(e)); newNode.setAnnotation("fError", e); - graphEventBus.post(new NodeTypeSwitchEvent<>(newNode, "or_ffail")); + ORGraphSearch.this.graphEventBus.post(new NodeTypeSwitchEvent<>(newNode, "or_ffail")); } - if (taskId >= 0) - timeoutSubmitter.cancelTimeout(taskId); - + if (taskId >= 0) { + ORGraphSearch.this.timeoutSubmitter.cancelTimeout(taskId); + } + /* register time required to compute this node label */ long fTime = System.currentTimeMillis() - startComputation; newNode.setAnnotation("fTime", fTime); - + /* if no label was computed, prune the node and cancel the computation */ if (label == null) { - if (!computationTimedout) - logger.info("Not inserting node {} since its label is missing!", newNode); - else - logger.info("Not inserting node {} because computation of f-value timed out.", newNode); - if (!newNode.getAnnotations().containsKey("fError")) + if (!computationTimedout) { + ORGraphSearch.this.logger.info("Not inserting node {} since its label is missing!", newNode); + } else { + ORGraphSearch.this.logger.info("Not inserting node {} because computation of f-value timed out.", newNode); + } + if (!newNode.getAnnotations().containsKey("fError")) { newNode.setAnnotation("fError", "f-computer returned NULL"); - graphEventBus.post(new NodeTypeSwitchEvent<>(newNode, "or_pruned")); - if (pool != null) { - activeJobs.decrementAndGet(); - fComputationTickets.release(); + } + ORGraphSearch.this.graphEventBus.post(new NodeTypeSwitchEvent<>(newNode, "or_pruned")); + if (ORGraphSearch.this.pool != null) { + ORGraphSearch.this.activeJobs.decrementAndGet(); + ORGraphSearch.this.fComputationTickets.release(); } return; } newNode.setInternalLabel(label); - logger.info("Inserting successor {} of {} to OPEN. F-Value is {}", newNode, expandedNodeInternal, label); + ORGraphSearch.this.logger.info("Inserting successor {} of {} to OPEN. F-Value is {}", newNode, this.expandedNodeInternal, label); // assert !open.contains(newNode) && !expanded.contains(newNode.getPoint()) : "Inserted node is already in OPEN or even expanded!"; /* if we discard (either only on OPEN or on both OPEN and CLOSED) */ boolean nodeProcessed = false; - if (parentDiscarding != ParentDiscarding.NONE) { + if (ORGraphSearch.this.parentDiscarding != ParentDiscarding.NONE) { /* determine whether we already have the node AND it is worse than the one we want to insert */ - Optional> existingIdenticalNodeOnOpen = open.stream().filter(n -> n.getPoint().equals(newNode.getPoint())).findFirst(); + Optional> existingIdenticalNodeOnOpen = ORGraphSearch.this.open.stream().filter(n -> n.getPoint().equals(newNode.getPoint())).findFirst(); if (existingIdenticalNodeOnOpen.isPresent()) { Node existingNode = existingIdenticalNodeOnOpen.get(); if (newNode.compareTo(existingNode) < 0) { - graphEventBus.post(new NodeTypeSwitchEvent<>(newNode, "or_" + (newNode.isGoal() ? "solution" : "open"))); - graphEventBus.post(new NodeRemovedEvent<>(existingNode)); - open.remove(existingNode); - open.add(newNode); + ORGraphSearch.this.graphEventBus.post(new NodeTypeSwitchEvent<>(newNode, "or_" + (newNode.isGoal() ? "solution" : "open"))); + ORGraphSearch.this.graphEventBus.post(new NodeRemovedEvent<>(existingNode)); + ORGraphSearch.this.open.remove(existingNode); + ORGraphSearch.this.open.add(newNode); } else { - graphEventBus.post(new NodeRemovedEvent<>(newNode)); + ORGraphSearch.this.graphEventBus.post(new NodeRemovedEvent<>(newNode)); } nodeProcessed = true; } /* if parent discarding is not only for OPEN but also for CLOSE (and the node was not on OPEN), check the list of expanded nodes */ - else if (parentDiscarding == ParentDiscarding.ALL) { + else if (ORGraphSearch.this.parentDiscarding == ParentDiscarding.ALL) { /* reopening, if the node is already on CLOSED */ - Optional existingIdenticalNodeOnClosed = expanded.stream().filter(n -> n.equals(newNode.getPoint())).findFirst(); + Optional existingIdenticalNodeOnClosed = ORGraphSearch.this.expanded.stream().filter(n -> n.equals(newNode.getPoint())).findFirst(); if (existingIdenticalNodeOnClosed.isPresent()) { - Node node = ext2int.get(existingIdenticalNodeOnClosed.get()); + Node node = ORGraphSearch.this.ext2int.get(existingIdenticalNodeOnClosed.get()); if (newNode.compareTo(node) < 0) { node.setParent(newNode.getParent()); node.setInternalLabel(newNode.getInternalLabel()); - expanded.remove(node.getPoint()); - open.add(node); - graphEventBus.post(new NodeParentSwitchEvent>(node, node.getParent(), newNode.getParent())); + ORGraphSearch.this.expanded.remove(node.getPoint()); + ORGraphSearch.this.open.add(node); + ORGraphSearch.this.graphEventBus.post(new NodeParentSwitchEvent>(node, node.getParent(), newNode.getParent())); } - graphEventBus.post(new NodeRemovedEvent>(newNode)); + ORGraphSearch.this.graphEventBus.post(new NodeRemovedEvent>(newNode)); nodeProcessed = true; } } @@ -233,28 +237,29 @@ else if (parentDiscarding == ParentDiscarding.ALL) { /* if parent discarding is turned off OR if the node was node processed by a parent discarding rule, just insert it on OPEN */ if (!nodeProcessed) { - if (!newNode.isGoal()) - open.add(newNode); - graphEventBus.post(new NodeTypeSwitchEvent<>(newNode, "or_" + (newNode.isGoal() ? "solution" : "open"))); - createdCounter++; + if (!newNode.isGoal()) { + ORGraphSearch.this.open.add(newNode); + } + ORGraphSearch.this.graphEventBus.post(new NodeTypeSwitchEvent<>(newNode, "or_" + (newNode.isGoal() ? "solution" : "open"))); + ORGraphSearch.this.createdCounter++; } /* Recognize solution in cache together with annotation */ if (newNode.isGoal()) { - List solution = getTraversalPath(newNode); + List solution = ORGraphSearch.this.getTraversalPath(newNode); /* if the node evaluator has not reported the solution already anyway, register the solution and store its annotation */ - if (!solutionReportingNodeEvaluator && !solutions.contains(solution)) { - solutions.add(solution); - solutionAnnotations.put(solution, new HashMap<>()); - solutionAnnotations.get(solution).put("f", newNode.getInternalLabel()); + if (!ORGraphSearch.this.solutionReportingNodeEvaluator && !ORGraphSearch.this.solutions.contains(solution)) { + ORGraphSearch.this.solutions.add(solution); + ORGraphSearch.this.solutionAnnotations.put(solution, new HashMap<>()); + ORGraphSearch.this.solutionAnnotations.get(solution).put("f", newNode.getInternalLabel()); } } /* free resources if this is computed by helper threads */ - if (pool != null) { - activeJobs.decrementAndGet(); - fComputationTickets.release(); + if (ORGraphSearch.this.pool != null) { + ORGraphSearch.this.activeJobs.decrementAndGet(); + ORGraphSearch.this.fComputationTickets.release(); } } catch (Throwable e) { e.printStackTrace(); @@ -263,18 +268,18 @@ else if (parentDiscarding == ParentDiscarding.ALL) { } } - public ORGraphSearch(GraphGenerator graphGenerator, INodeEvaluator pNodeEvaluator) { + public ORGraphSearch(final GraphGenerator graphGenerator, final INodeEvaluator pNodeEvaluator) { this(graphGenerator, pNodeEvaluator, ParentDiscarding.NONE); } @SuppressWarnings("unchecked") - public ORGraphSearch(GraphGenerator graphGenerator, INodeEvaluator pNodeEvaluator, ParentDiscarding pd) { + public ORGraphSearch(final GraphGenerator graphGenerator, final INodeEvaluator pNodeEvaluator, final ParentDiscarding pd) { super(); this.graphGenerator = graphGenerator; this.rootGenerator = graphGenerator.getRootGenerator(); this.successorGenerator = graphGenerator.getSuccessorGenerator(); - checkGoalPropertyOnEntirePath = !(graphGenerator.getGoalTester() instanceof NodeGoalTester); - if (checkGoalPropertyOnEntirePath) { + this.checkGoalPropertyOnEntirePath = !(graphGenerator.getGoalTester() instanceof NodeGoalTester); + if (this.checkGoalPropertyOnEntirePath) { this.nodeGoalTester = null; this.pathGoalTester = (PathGoalTester) graphGenerator.getGoalTester(); ; @@ -284,7 +289,7 @@ public ORGraphSearch(GraphGenerator graphGenerator, INodeEvaluator p } /* set parent discarding */ - parentDiscarding = pd; + this.parentDiscarding = pd; // /*setting a priorityqueueopen As a default open collection*/ // @@ -295,28 +300,30 @@ public ORGraphSearch(GraphGenerator graphGenerator, INodeEvaluator p if (pNodeEvaluator instanceof DecoratingNodeEvaluator) { DecoratingNodeEvaluator castedEvaluator = (DecoratingNodeEvaluator) pNodeEvaluator; if (castedEvaluator.isGraphDependent()) { - logger.info("{} is a graph dependent node evaluator. Setting its graph generator now ...", castedEvaluator); + this.logger.info("{} is a graph dependent node evaluator. Setting its graph generator now ...", castedEvaluator); castedEvaluator.setGenerator(graphGenerator); } if (castedEvaluator.isSolutionReporter()) { - logger.info("{} is a solution reporter. Register the search algo in its event bus", castedEvaluator); + this.logger.info("{} is a solution reporter. Register the search algo in its event bus", castedEvaluator); castedEvaluator.registerSolutionListener(this); - solutionReportingNodeEvaluator = true; - } else - solutionReportingNodeEvaluator = false; + this.solutionReportingNodeEvaluator = true; + } else { + this.solutionReportingNodeEvaluator = false; + } } else { if (pNodeEvaluator instanceof IGraphDependentNodeEvaluator) { - logger.info("{} is a graph dependent node evaluator. Setting its graph generator now ...", pNodeEvaluator); + this.logger.info("{} is a graph dependent node evaluator. Setting its graph generator now ...", pNodeEvaluator); ((IGraphDependentNodeEvaluator) pNodeEvaluator).setGenerator(graphGenerator); } /* if the node evaluator is a solution reporter, register in his event bus */ if (pNodeEvaluator instanceof ISolutionReportingNodeEvaluator) { - logger.info("{} is a solution reporter. Register the search algo in its event bus", pNodeEvaluator); + this.logger.info("{} is a solution reporter. Register the search algo in its event bus", pNodeEvaluator); ((ISolutionReportingNodeEvaluator) pNodeEvaluator).registerSolutionListener(this); - solutionReportingNodeEvaluator = true; - } else - solutionReportingNodeEvaluator = false; + this.solutionReportingNodeEvaluator = true; + } else { + this.solutionReportingNodeEvaluator = false; + } } // /* if this is a decorator, go to the next one */ @@ -328,31 +335,31 @@ public ORGraphSearch(GraphGenerator graphGenerator, INodeEvaluator p // currentlyConsideredEvaluator = null; // } // while (currentlyConsideredEvaluator != null); - Runtime.getRuntime().addShutdownHook(shutdownHook); + Runtime.getRuntime().addShutdownHook(this.shutdownHook); } - private void labelNode(Node node) throws Throwable { - node.setInternalLabel(nodeEvaluator.f(node)); + private void labelNode(final Node node) throws Throwable { + node.setInternalLabel(this.nodeEvaluator.f(node)); } /** * This method setups the graph by inserting the root nodes. */ protected synchronized void initGraph() throws Throwable { - if (!initialized) { - initialized = true; - if (rootGenerator instanceof MultipleRootGenerator) { - Collection> roots = ((MultipleRootGenerator) rootGenerator).getRoots().stream().map(n -> newNode(null, n)).collect(Collectors.toList()); + if (!this.initialized) { + this.initialized = true; + if (this.rootGenerator instanceof MultipleRootGenerator) { + Collection> roots = ((MultipleRootGenerator) this.rootGenerator).getRoots().stream().map(n -> this.newNode(null, n)).collect(Collectors.toList()); for (Node root : roots) { - labelNode(root); - open.add(root); + this.labelNode(root); + this.open.add(root); root.setAnnotation("awa-level", 0); - logger.info("Labeled root with {}", root.getInternalLabel()); + this.logger.info("Labeled root with {}", root.getInternalLabel()); } } else { - Node root = newNode(null, ((SingleRootGenerator) rootGenerator).getRoot()); - labelNode(root); - open.add(root); + Node root = this.newNode(null, ((SingleRootGenerator) this.rootGenerator).getRoot()); + this.labelNode(root); + this.open.add(root); } // check if the equals method is explicitly implemented. @@ -373,17 +380,16 @@ public List nextSolutionThatDominatesOpen() { List currentlyBestSolution = null; V currentlyBestScore = null; do { - List solution = nextSolution(); - V scoreOfSolution = getFOfReturnedSolution(solution); + List solution = this.nextSolution(); + V scoreOfSolution = this.getFOfReturnedSolution(solution); if (currentlyBestScore == null || scoreOfSolution.compareTo(currentlyBestScore) < 0) { currentlyBestScore = scoreOfSolution; currentlyBestSolution = solution; } - } - while(open.peek().getInternalLabel().compareTo(currentlyBestScore) < 0); + } while (this.open.peek().getInternalLabel().compareTo(currentlyBestScore) < 0); return currentlyBestSolution; } - + /** * Find the shortest path to a goal starting from start. * @@ -391,59 +397,62 @@ public List nextSolutionThatDominatesOpen() { * The initial node. * @return A list of nodes from the initial point to a goal, null if a path doesn't exist. */ + @Override public List nextSolution() { /* check whether solution has been canceled */ - if (canceled) { + if (this.canceled) { throw new IllegalStateException("Search has been canceled, no more solutions can be requested."); } /* do preliminary stuff: init graph (only for first call) and return unreturned solutions first */ - logger.info("Starting search for next solution. Size of OPEN is {}", open.size()); + this.logger.info("Starting search for next solution. Size of OPEN is {}", this.open.size()); try { - initGraph(); + this.initGraph(); } catch (Throwable e) { e.printStackTrace(); return null; } - if (!solutions.isEmpty()) { - logger.debug("Still have solution in cache, return it."); - logger.info("Returning solution {} with score {}", solutions.peek(), getAnnotationsOfReturnedSolution(solutions.peek())); - return solutions.poll(); + if (!this.solutions.isEmpty()) { + this.logger.debug("Still have solution in cache, return it."); + this.logger.info("Returning solution {} with score {}", this.solutions.peek(), this.getAnnotationsOfReturnedSolution(this.solutions.peek())); + return this.solutions.poll(); } do { /* busy waiting for new nodes in OPEN */ - while (open.isEmpty() && activeJobs.get() > 0) { - logger.debug("Waiting 100ms, because OPEN size is {} and there are {} active jobs.", open.size(), activeJobs.get()); + while (this.open.isEmpty() && this.activeJobs.get() > 0) { + this.logger.debug("Waiting 100ms, because OPEN size is {} and there are {} active jobs.", this.open.size(), this.activeJobs.get()); try { Thread.sleep(100); } catch (InterruptedException e) { - logger.info("Received interrupt signal"); - interrupted = true; + this.logger.info("Received interrupt signal"); + this.interrupted = true; break; } } - if (open.isEmpty() || interrupted) { - logger.debug("OPEN has size {} and interrupted is {}", open.size(), interrupted); + if (this.open.isEmpty() || this.interrupted) { + this.logger.debug("OPEN has size {} and interrupted is {}", this.open.size(), this.interrupted); break; } - logger.debug("Iteration of main loop starts. Size of OPEN now {}. Now performing next expansion step.", open.size()); - step(); - if (!solutions.isEmpty()) { - List solution = solutions.poll(); - logger.debug("Iteration of main loop terminated. Found a solution to return. Size of OPEN now {}", open.size()); - logger.info("Returning solution {} with score {}", solution, getAnnotationsOfReturnedSolution(solution)); + this.logger.debug("Iteration of main loop starts. Size of OPEN now {}. Now performing next expansion step.", this.open.size()); + this.step(); + if (!this.solutions.isEmpty()) { + List solution = this.solutions.poll(); + this.logger.debug("Iteration of main loop terminated. Found a solution to return. Size of OPEN now {}", this.open.size()); + this.logger.info("Returning solution {} with score {}", solution, this.getAnnotationsOfReturnedSolution(solution)); return solution; } - logger.debug("Iteration of main loop terminated. Size of OPEN now {}. Number of active jobs: {}", open.size(), activeJobs.get()); - } while ((!open.isEmpty() || activeJobs.get() > 0) && !interrupted); - if (interrupted) - logger.info("Algorithm was interrupted"); - if (open.isEmpty()) - logger.info("OPEN is empty, terminating (possibly returning a solution)"); - return solutions.isEmpty() ? null : solutions.poll(); + this.logger.debug("Iteration of main loop terminated. Size of OPEN now {}. Number of active jobs: {}", this.open.size(), this.activeJobs.get()); + } while ((!this.open.isEmpty() || this.activeJobs.get() > 0) && !this.interrupted); + if (this.interrupted) { + this.logger.info("Algorithm was interrupted"); + } + if (this.open.isEmpty()) { + this.logger.info("OPEN is empty, terminating (possibly returning a solution)"); + } + return this.solutions.isEmpty() ? null : this.solutions.poll(); } protected boolean terminates() { @@ -452,155 +461,160 @@ protected boolean terminates() { /** * Makes a single expansion and returns solution paths. - * + * * @return The last found solution path. */ public List> nextExpansion() { if (!this.initialized) { try { - initGraph(); + this.initGraph(); } catch (Throwable e) { e.printStackTrace(); return null; } - return lastExpansion; - } else - step(); - return lastExpansion; + return this.lastExpansion; + } else { + this.step(); + } + return this.lastExpansion; } protected void step() { - if (beforeSelection()) { + if (this.beforeSelection()) { - Node nodeToExpand = open.peek(); - assert parentDiscarding == ParentDiscarding.ALL || !expanded.contains(nodeToExpand.getPoint()) : "Node " + nodeToExpand.getString() - + " has been selected for the second time for expansion."; - if (nodeToExpand == null) + Node nodeToExpand = this.open.peek(); + assert this.parentDiscarding == ParentDiscarding.ALL || !this.expanded.contains(nodeToExpand.getPoint()) : "Node " + nodeToExpand.getString() + " has been selected for the second time for expansion."; + if (nodeToExpand == null) { return; - afterSelection(nodeToExpand); - step(nodeToExpand); + } + this.afterSelection(nodeToExpand); + this.step(nodeToExpand); } } - public void step(Node nodeToExpand) { + public void step(final Node nodeToExpand) { // if (!(nodeEvaluator instanceof RandomizedDepthFirstEvaluator)) // System.out.println(nodeToExpand.getAnnotations()); /* if search has been interrupted, do not process next step */ - logger.debug("Step starts. Size of OPEN now {}", open.size()); + this.logger.debug("Step starts. Size of OPEN now {}", this.open.size()); if (Thread.interrupted()) { - logger.debug("Received interrupt signal before step."); - interrupted = true; + this.logger.debug("Received interrupt signal before step."); + this.interrupted = true; return; } - lastExpansion.clear(); - assert nodeToExpand == null || !expanded.contains(nodeToExpand.getPoint()) : "Node selected for expansion already has been expanded: " + nodeToExpand; - open.remove(nodeToExpand); - assert !open.contains(nodeToExpand) : "The selected node " + nodeToExpand + " was not really removed from OPEN!"; - logger.debug("Removed {} from OPEN for expansion. OPEN size now {}", nodeToExpand, open.size()); - assert ext2int.containsKey(nodeToExpand.getPoint()) : "Trying to expand a node whose point is not available in the ext2int map"; - beforeExpansion(nodeToExpand); - expandNode(nodeToExpand); - afterExpansion(nodeToExpand); + this.lastExpansion.clear(); + assert nodeToExpand == null || !this.expanded.contains(nodeToExpand.getPoint()) : "Node selected for expansion already has been expanded: " + nodeToExpand; + this.open.remove(nodeToExpand); + assert !this.open.contains(nodeToExpand) : "The selected node " + nodeToExpand + " was not really removed from OPEN!"; + this.logger.debug("Removed {} from OPEN for expansion. OPEN size now {}", nodeToExpand, this.open.size()); + assert this.ext2int.containsKey(nodeToExpand.getPoint()) : "Trying to expand a node whose point is not available in the ext2int map"; + this.beforeExpansion(nodeToExpand); + this.expandNode(nodeToExpand); + this.afterExpansion(nodeToExpand); if (Thread.interrupted()) { - logger.debug("Received interrupt signal during step."); - interrupted = true; + this.logger.debug("Received interrupt signal during step."); + this.interrupted = true; } - logger.debug("Step ends. Size of OPEN now {}", open.size()); + this.logger.debug("Step ends. Size of OPEN now {}", this.open.size()); } - private void expandNode(Node expandedNodeInternal) { - graphEventBus.post(new NodeTypeSwitchEvent>(expandedNodeInternal, "or_expanding")); - logger.info("Expanding node {} with f-value {}", expandedNodeInternal, expandedNodeInternal.getInternalLabel()); - assert !expanded.contains(expandedNodeInternal.getPoint()) : "Node " + expandedNodeInternal + " expanded twice!!"; - expanded.add(expandedNodeInternal.getPoint()); - assert expanded.contains(expandedNodeInternal.getPoint()) : "Expanded node " + expandedNodeInternal + " was not inserted into the set of expanded nodes!"; + private void expandNode(final Node expandedNodeInternal) { + this.graphEventBus.post(new NodeTypeSwitchEvent>(expandedNodeInternal, "or_expanding")); + this.logger.info("Expanding node {} with f-value {}", expandedNodeInternal, expandedNodeInternal.getInternalLabel()); + assert !this.expanded.contains(expandedNodeInternal.getPoint()) : "Node " + expandedNodeInternal + " expanded twice!!"; + this.expanded.add(expandedNodeInternal.getPoint()); + assert this.expanded.contains(expandedNodeInternal.getPoint()) : "Expanded node " + expandedNodeInternal + " was not inserted into the set of expanded nodes!"; /* compute successors */ - logger.debug("Start computation of successors"); + this.logger.debug("Start computation of successors"); final List> successorDescriptions = new ArrayList<>(); { Thread t = new Thread(new Runnable() { @Override public void run() { - if (ORGraphSearch.this.canceled || ORGraphSearch.this.interrupted) + if (ORGraphSearch.this.canceled || ORGraphSearch.this.interrupted) { return; + } int taskId = -1; - if (timeoutForComputationOfF > 0) { - if (timeoutSubmitter == null) { - timeoutSubmitter = TimeoutTimer.getInstance().getSubmitter(); + if (ORGraphSearch.this.timeoutForComputationOfF > 0) { + if (ORGraphSearch.this.timeoutSubmitter == null) { + ORGraphSearch.this.timeoutSubmitter = TimeoutTimer.getInstance().getSubmitter(); } - taskId = timeoutSubmitter.interruptMeAfterMS(timeoutForComputationOfF); + taskId = ORGraphSearch.this.timeoutSubmitter.interruptMeAfterMS(ORGraphSearch.this.timeoutForComputationOfF); + } + successorDescriptions.addAll(ORGraphSearch.this.successorGenerator.generateSuccessors(expandedNodeInternal.getPoint())); + if (taskId >= 0) { + ORGraphSearch.this.timeoutSubmitter.cancelTimeout(taskId); } - successorDescriptions.addAll(successorGenerator.generateSuccessors(expandedNodeInternal.getPoint())); - if (taskId >= 0) - timeoutSubmitter.cancelTimeout(taskId); } }, "Node Builder for some child of " + expandedNodeInternal); - logger.debug("Starting computation of successors in thread {}", t); + this.logger.debug("Starting computation of successors in thread {}", t); t.start(); try { t.join(); } catch (InterruptedException e) { - logger.debug("Search has been interrupted"); - interrupted = true; + this.logger.debug("Search has been interrupted"); + this.interrupted = true; return; } - logger.debug("Finished computation of successors"); + this.logger.debug("Finished computation of successors"); } - + /* send event that successor nodes have been computed */ - logger.debug("Sending SuccessorComputationCompletedEvent with {} successors for {}", successorDescriptions.size(), expandedNodeInternal); - graphEventBus.post(new SuccessorComputationCompletedEvent<>(expandedNodeInternal, successorDescriptions)); - + this.logger.debug("Sending SuccessorComputationCompletedEvent with {} successors for {}", successorDescriptions.size(), expandedNodeInternal); + this.graphEventBus.post(new SuccessorComputationCompletedEvent<>(expandedNodeInternal, successorDescriptions)); + /* attach successors to search graph */ -// System.out.println(expanded.contains(expandedNodeInternal.getPoint())); - if (additionalThreadsForExpansion < 1) { + // System.out.println(expanded.contains(expandedNodeInternal.getPoint())); + if (this.additionalThreadsForExpansion < 1) { successorDescriptions.stream().forEach(successorDescription -> { /* perform synchronized computation. The computation is outourced, because it may receive an interrupt-signal, and we do not want the main-thread to be interrupted */ Thread t = new Thread(new NodeBuilder(expandedNodeInternal, successorDescription), "Node Builder for some child of " + expandedNodeInternal); - logger.debug("Starting computation of successor in thread {}", t); + this.logger.debug("Starting computation of successor in thread {}", t); t.start(); try { t.join(); } catch (InterruptedException e) { - logger.debug("Search has been interrupted"); - interrupted = true; + this.logger.debug("Search has been interrupted"); + this.interrupted = true; return; } - logger.debug("Finished computation of successor", t); + this.logger.debug("Finished computation of successor", t); }); } else { successorDescriptions.stream().forEach(successorDescription -> { - if (interrupted) + if (this.interrupted) { return; + } try { - fComputationTickets.acquire(); + this.fComputationTickets.acquire(); } catch (InterruptedException e) { e.printStackTrace(); - interrupted = true; + this.interrupted = true; } - if (interrupted) + if (this.interrupted) { return; - activeJobs.incrementAndGet(); - pool.submit(new NodeBuilder(expandedNodeInternal, successorDescription)); + } + this.activeJobs.incrementAndGet(); + this.pool.submit(new NodeBuilder(expandedNodeInternal, successorDescription)); }); } - logger.debug("Finished expansion of node {}. Size of OPEN is now {}. Number of active jobs is {}", expandedNodeInternal, open.size(), activeJobs.get()); + this.logger.debug("Finished expansion of node {}. Size of OPEN is now {}. Number of active jobs is {}", expandedNodeInternal, this.open.size(), this.activeJobs.get()); /* update statistics, send closed notifications, and possibly return a solution */ - expandedCounter++; - graphEventBus.post(new NodeTypeSwitchEvent>(expandedNodeInternal, "or_closed")); + this.expandedCounter++; + this.graphEventBus.post(new NodeTypeSwitchEvent>(expandedNodeInternal, "or_closed")); } public GraphEventBus> getEventBus() { - return graphEventBus; + return this.graphEventBus; } - protected List getTraversalPath(Node n) { + protected List getTraversalPath(final Node n) { return n.path().stream().map(p -> p.getPoint()).collect(Collectors.toList()); } @@ -610,42 +624,47 @@ protected List getTraversalPath(Node n) { * @return A counter of how many times a node was expanded. */ public int getExpandedCounter() { - return expandedCounter; + return this.expandedCounter; } public int getCreatedCounter() { - return createdCounter; + return this.createdCounter; } - public V getFValue(T node) { - return getFValue(ext2int.get(node)); + @Override + public V getFValue(final T node) { + return this.getFValue(this.ext2int.get(node)); } - public V getFValue(Node node) { + @Override + public V getFValue(final Node node) { return node.getInternalLabel(); } - public Map getNodeAnnotations(T node) { - Node intNode = ext2int.get(node); + public Map getNodeAnnotations(final T node) { + Node intNode = this.ext2int.get(node); return intNode.getAnnotations(); } - public Object getNodeAnnotation(T node, String annotation) { - Node intNode = ext2int.get(node); + public Object getNodeAnnotation(final T node, final String annotation) { + Node intNode = this.ext2int.get(node); return intNode.getAnnotation(annotation); } - public Map getAnnotationsOfReturnedSolution(List solution) { - return solutionAnnotations.get(solution); + @Override + public Map getAnnotationsOfReturnedSolution(final List solution) { + return this.solutionAnnotations.get(solution); } - public Object getAnnotationOfReturnedSolution(List solution, String annotation) { - return solutionAnnotations.get(solution).get(annotation); + @Override + public Object getAnnotationOfReturnedSolution(final List solution, final String annotation) { + return this.solutionAnnotations.get(solution).get(annotation); } - public V getFOfReturnedSolution(List solution) { + @Override + public V getFOfReturnedSolution(final List solution) { @SuppressWarnings("unchecked") - V annotation = (V) getAnnotationOfReturnedSolution(solution, "f"); + V annotation = (V) this.getAnnotationOfReturnedSolution(solution, "f"); if (annotation == null) { throw new IllegalArgumentException( "There is no solution annotation for the given solution. Please check whether the solution was really produced by the algorithm. If so, please check that its annotation was added into the list of annotations before the solution itself was added to the solution set"); @@ -653,124 +672,137 @@ public V getFOfReturnedSolution(List solution) { return annotation; } + @Override public void cancel() { StringBuilder sb = new StringBuilder(); for (StackTraceElement ste : Thread.currentThread().getStackTrace()) { sb.append("\n" + ste.toString()); } - logger.info("Search has been canceled. Cancel came from: {}", sb.toString()); + this.logger.info("Search has been canceled. Cancel came from: {}", sb.toString()); this.canceled = true; this.interrupted = true; - if (this.pool != null) + if (this.pool != null) { this.pool.shutdownNow(); - if (nodeEvaluator instanceof ICancelableNodeEvaluator) { - logger.info("Canceling node evaluator."); - ((ICancelableNodeEvaluator) nodeEvaluator).cancel(); } - if (timeoutSubmitter != null) - timeoutSubmitter.close(); + if (this.nodeEvaluator instanceof ICancelableNodeEvaluator) { + this.logger.info("Canceling node evaluator."); + ((ICancelableNodeEvaluator) this.nodeEvaluator).cancel(); + } + if (this.timeoutSubmitter != null) { + this.timeoutSubmitter.close(); + } } public boolean isInterrupted() { return this.interrupted; } - public List getCurrentPathToNode(T node) { - return ext2int.get(node).externalPath(); + public List getCurrentPathToNode(final T node) { + return this.ext2int.get(node).externalPath(); } - public Node getInternalRepresentationOf(T node) { - return ext2int.get(node); + @Override + public Node getInternalRepresentationOf(final T node) { + return this.ext2int.get(node); } + @Override public List> getOpenSnapshot() { - return Collections.unmodifiableList(new ArrayList<>(open)); + return Collections.unmodifiableList(new ArrayList<>(this.open)); } - protected synchronized Node newNode(Node parent, T t2) { - return newNode(parent, t2, null); + protected synchronized Node newNode(final Node parent, final T t2) { + return this.newNode(parent, t2, null); } + @Override public INodeEvaluator getNodeEvaluator() { return this.nodeEvaluator; } - protected synchronized Node newNode(Node parent, T t2, V evaluation) { - assert parent == null || expanded.contains(parent.getPoint()) : "Generating successors of an unexpanded node " + parent + ". List of expanded nodes:\n" + expanded.stream().map(n -> "\n\t" + n.toString()).collect(Collectors.joining()); - assert !open.contains(parent) : "Parent node " + parent + " is still on OPEN, which must not be the case!"; + protected synchronized Node newNode(final Node parent, final T t2, final V evaluation) { + assert parent == null || this.expanded.contains(parent.getPoint()) : "Generating successors of an unexpanded node " + parent + ". List of expanded nodes:\n" + + this.expanded.stream().map(n -> "\n\t" + n.toString()).collect(Collectors.joining()); + assert !this.open.contains(parent) : "Parent node " + parent + " is still on OPEN, which must not be the case!"; /* create new node and check whether it is a goal */ Node newNode = new Node<>(parent, t2); - if (evaluation != null) + if (evaluation != null) { newNode.setInternalLabel(evaluation); + } /* check loop */ - assert parent == null || !parent.externalPath().contains(t2) : "There is a loop in the underlying graph. The following path contains the last node twice: " + newNode.externalPath().stream().map(n -> n.toString()).reduce("", (s,t) -> s + "\n\t\t" + t); - + assert parent == null || !parent.externalPath().contains(t2) : "There is a loop in the underlying graph. The following path contains the last node twice: " + + newNode.externalPath().stream().map(n -> n.toString()).reduce("", (s, t) -> s + "\n\t\t" + t); + /* currently, we only support tree search */ - assert !ext2int.containsKey(t2) : "Reached node " + t2 + " for the second time.\nt\tFirst path:" + ext2int.get(t2).externalPath().stream().map(n -> n.toString()).reduce("", (s,t) -> s + "\n\t\t" + t) - + "\n\tSecond Path:" + newNode.externalPath().stream().map(n -> n.toString()).reduce("", (s,t) -> s + "\n\t\t" + t); + assert !this.ext2int.containsKey(t2) : "Reached node " + t2 + " for the second time.\nt\tFirst path:" + this.ext2int.get(t2).externalPath().stream().map(n -> n.toString()).reduce("", (s, t) -> s + "\n\t\t" + t) + "\n\tSecond Path:" + + newNode.externalPath().stream().map(n -> n.toString()).reduce("", (s, t) -> s + "\n\t\t" + t); /* register node in map and create annotation object */ - ext2int.put(t2, newNode); + this.ext2int.put(t2, newNode); /* detect whether node is solution */ - if (checkGoalPropertyOnEntirePath ? pathGoalTester.isGoal(newNode.externalPath()) : nodeGoalTester.isGoal(newNode.getPoint())) + if (this.checkGoalPropertyOnEntirePath ? this.pathGoalTester.isGoal(newNode.externalPath()) : this.nodeGoalTester.isGoal(newNode.getPoint())) { newNode.setGoal(true); + } /* send events for this new node */ if (parent == null) { this.graphEventBus.post(new GraphInitializedEvent>(newNode)); } else { this.graphEventBus.post(new NodeReachedEvent>(parent, newNode, "or_" + (newNode.isGoal() ? "solution" : "created"))); - logger.debug("Sent message for creation of node {} as a successor of {}", newNode, parent); + this.logger.debug("Sent message for creation of node {} as a successor of {}", newNode, parent); } return newNode; } /** - * This method can be used to create an initial graph different from just root nodes. This can be interesting if the search is distributed and we want to search only an excerpt of the original - * one. + * This method can be used to create an initial graph different from just root nodes. This can be interesting if the search is distributed and we want to search only an excerpt of the original one. * * @param initialNodes */ - public void bootstrap(Collection> initialNodes) { + @Override + public void bootstrap(final Collection> initialNodes) { - if (initialized) + if (this.initialized) { throw new UnsupportedOperationException("Bootstrapping is only supported if the search has already been initialized."); + } /* now initialize the graph */ try { - initGraph(); + this.initGraph(); } catch (Throwable e) { e.printStackTrace(); return; } /* remove previous roots from open */ - open.clear(); + this.open.clear(); /* now insert new nodes, and the leaf ones in open */ for (Node node : initialNodes) { - insertNodeIntoLocalGraph(node); - open.add(getLocalVersionOfNode(node)); + this.insertNodeIntoLocalGraph(node); + this.open.add(this.getLocalVersionOfNode(node)); } } - protected void insertNodeIntoLocalGraph(Node node) { + protected void insertNodeIntoLocalGraph(final Node node) { Node localVersionOfParent = null; List> path = node.path(); Node leaf = path.get(path.size() - 1); for (Node nodeOnPath : path) { - if (!ext2int.containsKey(nodeOnPath.getPoint())) { + if (!this.ext2int.containsKey(nodeOnPath.getPoint())) { assert nodeOnPath.getParent() != null : "Want to insert a new node that has no parent. That must not be the case! Affected node is: " + nodeOnPath.getPoint(); - assert ext2int.containsKey(nodeOnPath.getParent().getPoint()) : "Want to insert a node whose parent is unknown locally"; - Node newNode = newNode(localVersionOfParent, nodeOnPath.getPoint(), nodeOnPath.getInternalLabel()); - if (!newNode.isGoal() && !newNode.getPoint().equals(leaf.getPoint())) + assert this.ext2int.containsKey(nodeOnPath.getParent().getPoint()) : "Want to insert a node whose parent is unknown locally"; + Node newNode = this.newNode(localVersionOfParent, nodeOnPath.getPoint(), nodeOnPath.getInternalLabel()); + if (!newNode.isGoal() && !newNode.getPoint().equals(leaf.getPoint())) { this.getEventBus().post(new NodeTypeSwitchEvent>(newNode, "or_closed")); + } localVersionOfParent = newNode; - } else - localVersionOfParent = getLocalVersionOfNode(nodeOnPath); + } else { + localVersionOfParent = this.getLocalVersionOfNode(nodeOnPath); + } } } @@ -780,8 +812,8 @@ protected void insertNodeIntoLocalGraph(Node node) { * @param node * @return */ - protected Node getLocalVersionOfNode(Node node) { - return ext2int.get(node.getPoint()); + protected Node getLocalVersionOfNode(final Node node) { + return this.ext2int.get(node.getPoint()); } /* hooks */ @@ -792,36 +824,38 @@ protected boolean beforeSelection() { return true; } - protected void afterSelection(Node node) { + protected void afterSelection(final Node node) { } - protected void beforeExpansion(Node node) { + protected void beforeExpansion(final Node node) { } - protected void afterExpansion(Node node) { + protected void afterExpansion(final Node node) { } @Override public boolean hasNext() { - if (!initialized) { + if (!this.initialized) { try { - initGraph(); + this.initGraph(); } catch (Throwable e) { e.printStackTrace(); return false; } - step(); - } else - step(); + this.step(); + } else { + this.step(); + } return !this.lastExpansion.isEmpty(); } @Override public List> next() { - if (hasNext()) + if (this.hasNext()) { return this.lastExpansion; - else + } else { return null; + } } @Override @@ -830,39 +864,42 @@ public Iterator>> iterator() { } @Subscribe - public void receiveSolutionEvent(SolutionFoundEvent solution) { + public void receiveSolutionEvent(final SolutionFoundEvent solution) { try { - logger.info("Received solution with f-value {}", solution.getF()); - if (solutionAnnotations.containsKey(solution.getSolution())) + this.logger.info("Received solution with f-value {}", solution.getF()); + if (this.solutionAnnotations.containsKey(solution.getSolution())) { throw new IllegalStateException("Solution is reported for the second time already!"); - solutionAnnotations.put(solution.getSolution(), new HashMap<>()); - solutionAnnotations.get(solution.getSolution()).put("f", solution.getF()); - solutions.add(solution.getSolution()); + } + this.solutionAnnotations.put(solution.getSolution(), new HashMap<>()); + this.solutionAnnotations.get(solution.getSolution()).put("f", solution.getF()); + this.solutions.add(solution.getSolution()); } catch (Throwable e) { e.printStackTrace(); } } @Subscribe - public void receiveSolutionAnnotationEvent(SolutionAnnotationEvent solution) { + public void receiveSolutionAnnotationEvent(final SolutionAnnotationEvent solution) { try { - logger.debug("Received solution annotation: {}", solution); - if (!solutionAnnotations.containsKey(solution.getSolution())) + this.logger.debug("Received solution annotation: {}", solution); + if (!this.solutionAnnotations.containsKey(solution.getSolution())) { throw new IllegalStateException("Solution annotation is reported for a solution that has not been reported previously!"); - solutionAnnotations.get(solution.getSolution()).put(solution.getAnnotationName(), solution.getAnnotationValue()); + } + this.solutionAnnotations.get(solution.getSolution()).put(solution.getAnnotationName(), solution.getAnnotationValue()); } catch (Throwable e) { e.printStackTrace(); } } @Subscribe - public void receiveNodeAnnotationEvent(NodeAnnotationEvent event) { + public void receiveNodeAnnotationEvent(final NodeAnnotationEvent event) { try { T nodeExt = event.getNode(); - logger.debug("Received annotation {} with value {} for node {}", event.getAnnotationName(), event.getAnnotationValue(), event.getNode()); - if (!ext2int.containsKey(nodeExt)) + this.logger.debug("Received annotation {} with value {} for node {}", event.getAnnotationName(), event.getAnnotationValue(), event.getNode()); + if (!this.ext2int.containsKey(nodeExt)) { throw new IllegalArgumentException("Received annotation for a node I don't know!"); - Node nodeInt = ext2int.get(nodeExt); + } + Node nodeInt = this.ext2int.get(nodeExt); nodeInt.setAnnotation(event.getAnnotationName(), event.getAnnotationValue()); } catch (Throwable e) { e.printStackTrace(); @@ -870,14 +907,16 @@ public void receiveNodeAnnotationEvent(NodeAnnotationEvent event) { } public int getAdditionalThreadsForExpansion() { - return additionalThreadsForExpansion; + return this.additionalThreadsForExpansion; } - public void parallelizeNodeExpansion(int threadsForExpansion) { - if (this.pool != null) + public void parallelizeNodeExpansion(final int threadsForExpansion) { + if (this.pool != null) { throw new UnsupportedOperationException("The number of additional threads can be only set once per search!"); - if (threadsForExpansion < 1) + } + if (threadsForExpansion < 1) { throw new IllegalArgumentException("Number of threads should be at least 1 for " + this.getClass().getName()); + } this.fComputationTickets = new Semaphore(threadsForExpansion); this.additionalThreadsForExpansion = threadsForExpansion; AtomicInteger counter = new AtomicInteger(0); @@ -889,10 +928,10 @@ public void parallelizeNodeExpansion(int threadsForExpansion) { } public int getTimeoutForComputationOfF() { - return timeoutForComputationOfF; + return this.timeoutForComputationOfF; } - public void setTimeoutForComputationOfF(int timeoutInMS, INodeEvaluator timeoutEvaluator) { + public void setTimeoutForComputationOfF(final int timeoutInMS, final INodeEvaluator timeoutEvaluator) { this.timeoutForComputationOfF = timeoutInMS; this.timeoutNodeEvaluator = timeoutEvaluator; } @@ -901,39 +940,39 @@ public void setTimeoutForComputationOfF(int timeoutInMS, INodeEvaluator ti * @return the openCollection */ public OpenCollection> getOpen() { - return open; + return this.open; } /** * @param open * the openCollection to set */ - public void setOpen(OpenCollection> collection) { + public void setOpen(final OpenCollection> collection) { collection.clear(); - collection.addAll(open); - open = collection; + collection.addAll(this.open); + this.open = collection; } @Override - public void setLoggerName(String name) { - logger.info("Switching logger from {} to {}", logger.getName(), name); - logger = LoggerFactory.getLogger(name); - logger.info("Activated logger {} with name {}", name, logger.getName()); + public void setLoggerName(final String name) { + this.logger.info("Switching logger from {} to {}", this.logger.getName(), name); + this.logger = LoggerFactory.getLogger(name); + this.logger.info("Activated logger {} with name {}", name, this.logger.getName()); } @Override public String getLoggerName() { - return logger.getName(); + return this.logger.getName(); } @Override - public void registerListener(Object listener) { + public void registerListener(final Object listener) { this.graphEventBus.register(listener); } @Override public GraphGenerator getGraphGenerator() { - return graphGenerator; + return this.graphGenerator; } } diff --git a/softwareconfiguration/hasco/src/hasco/core/HASCO.java b/softwareconfiguration/hasco/src/hasco/core/HASCO.java index 8cdd382215..1cb7ea5c67 100644 --- a/softwareconfiguration/hasco/src/hasco/core/HASCO.java +++ b/softwareconfiguration/hasco/src/hasco/core/HASCO.java @@ -7,6 +7,7 @@ import java.util.Map; import java.util.Random; +import org.aeonbits.owner.ConfigCache; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -47,63 +48,83 @@ * * @param */ -public class HASCO, R extends IPlanningSolution> - implements Iterable>, IObservableGraphAlgorithm, ILoggingCustomizable { +public class HASCO, R extends IPlanningSolution> implements Iterable>, IObservableGraphAlgorithm, ILoggingCustomizable { - /* domain description */ + /* Static parameters of HASCO */ + + /** Logger instance for controlled output. */ + private Logger logger = LoggerFactory.getLogger(HASCO.class); + + /** Name for the logger to facilitate output level configuration. */ + private String loggerName; + + /** Config object to store properties of HASCO. */ + private static final HASCOConfig CONFIG = ConfigCache.getOrCreate(HASCOConfig.class); + + /* Parameters concerning the software configuration problem + reduction to HTN planning */ + + /** Collection of components to be configured in HASCO. */ private final Collection components; + + /** Details for the refinement of single parameters. */ private final Map> paramRefinementConfig; - private Factory factory; - /* query */ - private final IObjectEvaluator benchmark; + /** Reduction turning the components description into an HTN planning problem. */ + private final HASCOProblemReduction reduction; + + /** The HTN planning problem. */ + private final CEOCIPSTNPlanningProblem problem; + + /** The planner to solve the HTN planning problem. */ + private IObservableGraphBasedHTNPlanningAlgorithm planner; - /* search algorithm configuration */ + /* Parameters for the search algorithm configuration */ + + /** Factory for producing planners solving the HTN planning problem. */ private final IObservableGraphBasedHTNPlanningAlgorithmFactory plannerFactory; private final IObservableORGraphSearchFactory searchFactory; private final IHASCOSearchSpaceUtilFactory searchSpaceUtilFactory; - private final RandomCompletionEvaluator randomCompletionEvaluator; + + /** The preferred node evaluator which is primarily called to assess a node's f-value. */ private INodeEvaluator preferredNodeEvaluator; - /* event buses for evaluation events */ - private final EventBus solutionEvaluationEventBus = new EventBus(); + /** The random completion evaluator sampling fully specified solutions at random. */ + private final RandomCompletionEvaluator randomCompletionEvaluator; - /* parameters relevant for functionality */ - private int timeout; - private int numberOfCPUs = 1; - private int randomSeed; + /** Factory to convert plans into objects as input for the benchmark. */ + private Factory factory; + + /** Object evaluator for assessing the quality of plans. */ + private IObjectEvaluator benchmark; - /* parameters for state of a single run */ private T bestRecognizedSolution; - private ComponentInstance compositionOfBestRecognizedSolution; + private V scoreOfBestRecognizedSolution; - /* logging */ - private Logger logger = LoggerFactory.getLogger(HASCO.class); - private String loggerName; - - /* run-specific options */ - private final HASCOProblemReduction reduction; - private final CEOCIPSTNPlanningProblem problem; - private IObservableGraphBasedHTNPlanningAlgorithm planner; - - + /* parameters for state of a single run */ + private ComponentInstance compositionOfBestRecognizedSolution; + + /* list of listeners */ + private final Collection listeners = new ArrayList<>(); + + /* event buses for evaluation events */ + + /** An EventBus for notifying listeners about the evaluation of solution nodes. */ + private final EventBus solutionEvaluationEventBus = new EventBus(); + private ISolutionEvaluator solutionEvaluator = new ISolutionEvaluator() { @Override public V evaluateSolution(final List solutionPath) throws Exception { List plan = HASCO.this.searchSpaceUtilFactory.getPathToPlanConverter().getPlan(solutionPath); - ComponentInstance composition = Util.getSolutionCompositionForPlan(HASCO.this.components, - reduction.getInitState(), plan); + ComponentInstance composition = Util.getSolutionCompositionForPlan(HASCO.this.components, HASCO.this.reduction.getInitState(), plan); T solution = HASCO.this.getObjectFromPlan(plan); V scoreOfSolution = HASCO.this.benchmark.evaluate(solution); - if (HASCO.this.scoreOfBestRecognizedSolution == null - || HASCO.this.scoreOfBestRecognizedSolution.compareTo(scoreOfSolution) > 0) { + if (HASCO.this.scoreOfBestRecognizedSolution == null || HASCO.this.scoreOfBestRecognizedSolution.compareTo(scoreOfSolution) > 0) { HASCO.this.bestRecognizedSolution = solution; HASCO.this.compositionOfBestRecognizedSolution = composition; HASCO.this.scoreOfBestRecognizedSolution = scoreOfSolution; } - HASCO.this.solutionEvaluationEventBus - .post(new HASCOSolutionEvaluationEvent<>(composition, solution, scoreOfSolution)); + HASCO.this.solutionEvaluationEventBus.post(new HASCOSolutionEvaluationEvent<>(composition, solution, scoreOfSolution)); return scoreOfSolution; } @@ -113,43 +134,38 @@ public boolean doesLastActionAffectScoreOfAnySubsequentSolution(final List pa } }; - /* list of listeners */ - private final Collection listeners = new ArrayList<>(); - public HASCO(final Collection components, final Map> paramRefinementConfig, final IObservableGraphBasedHTNPlanningAlgorithmFactory plannerFactory, - final IObservableORGraphSearchFactory searchFactory, - final IHASCOSearchSpaceUtilFactory searchSpaceUtilFactory, final Factory factory, - final String nameOfRequiredInterface, final IObjectEvaluator benchmark) { + final IObservableORGraphSearchFactory searchFactory, final IHASCOSearchSpaceUtilFactory searchSpaceUtilFactory, final Factory factory, final String nameOfRequiredInterface, + final IObjectEvaluator benchmark) { super(); - + /* set components and refinement configs */ this.components = components; this.paramRefinementConfig = paramRefinementConfig; - + /* define search relevant factories and evaluators */ this.plannerFactory = plannerFactory; this.searchFactory = searchFactory; - this.randomCompletionEvaluator = new RandomCompletionEvaluator<>(new Random(this.randomSeed), 3, - searchSpaceUtilFactory.getPathUnifier(), this.solutionEvaluator); + this.randomCompletionEvaluator = new RandomCompletionEvaluator<>(new Random(this.getConfig().randomSeed()), this.getConfig().randomCompletions(), searchSpaceUtilFactory.getPathUnifier(), this.solutionEvaluator); this.factory = factory; this.searchSpaceUtilFactory = searchSpaceUtilFactory; this.benchmark = benchmark; - + /* set run specific options */ - reduction = new HASCOProblemReduction(components, paramRefinementConfig, nameOfRequiredInterface, true); - this.problem = reduction.getPlanningProblem(); - if (logger.isDebugEnabled()) { + this.reduction = new HASCOProblemReduction(components, paramRefinementConfig, nameOfRequiredInterface, true); + this.problem = this.reduction.getPlanningProblem(); + if (this.logger.isDebugEnabled()) { StringBuilder opSB = new StringBuilder(); - for (Operation op : problem.getDomain().getOperations()) { + for (Operation op : this.problem.getDomain().getOperations()) { opSB.append("\n\t\t"); opSB.append(op); } StringBuilder methodSB = new StringBuilder(); - for (Method method : problem.getDomain().getMethods()) { + for (Method method : this.problem.getDomain().getMethods()) { methodSB.append("\n\t\t"); methodSB.append(method); } - logger.debug("The HTN problem created by HASCO is defined as follows:\n\tInit State: {}\n\tOperations:{}\n\tMethods:{}", reduction.getInitState(), opSB.toString(), methodSB.toString()); + this.logger.debug("The HTN problem created by HASCO is defined as follows:\n\tInit State: {}\n\tOperations:{}\n\tMethods:{}", this.reduction.getInitState(), opSB.toString(), methodSB.toString()); } } @@ -165,10 +181,6 @@ public void setNumberOfRandomCompletions(final int randomCompletions) { this.randomCompletionEvaluator.setNumberOfRandomCompletions(randomCompletions); } - public int getRandom() { - return this.randomSeed; - } - public class HASCOSolutionIterator implements Iterator> { private boolean isInitialized = false; @@ -176,51 +188,44 @@ public class HASCOSolutionIterator implements Iterator> { private boolean canceled = false; private HASCOSolutionIterator() { - /* set node evaluator based on the currently defined preferred node evaluator */ - INodeEvaluator nodeEvaluator = preferredNodeEvaluator == null ? randomCompletionEvaluator : new AlternativeNodeEvaluator<>(preferredNodeEvaluator, randomCompletionEvaluator); - HASCO.this.planner = HASCO.this.plannerFactory.newAlgorithm(HASCO.this.problem, HASCO.this.searchFactory, nodeEvaluator, HASCO.this.numberOfCPUs); - this.planIterator = planner.iterator(); + INodeEvaluator nodeEvaluator = HASCO.this.preferredNodeEvaluator == null ? HASCO.this.randomCompletionEvaluator : new AlternativeNodeEvaluator<>(HASCO.this.preferredNodeEvaluator, HASCO.this.randomCompletionEvaluator); + HASCO.this.planner = HASCO.this.plannerFactory.newAlgorithm(HASCO.this.problem, HASCO.this.searchFactory, nodeEvaluator, HASCO.this.getConfig().cpus()); + this.planIterator = HASCO.this.planner.iterator(); } @Override public boolean hasNext() { if (!this.isInitialized) { HASCO.this.logger.info("Starting HASCO run."); - + /* check whether there is a refinement config for each numeric parameter */ for (Component c : HASCO.this.components) { for (Parameter p : c.getParameters()) { - if (p.isNumeric() && (!HASCO.this.paramRefinementConfig.containsKey(c) - || !HASCO.this.paramRefinementConfig.get(c).containsKey(p))) { - throw new IllegalArgumentException( - "No refinement config was delivered for numeric parameter " + p.getName() - + " of component " + c.getName()); + if (p.isNumeric() && (!HASCO.this.paramRefinementConfig.containsKey(c) || !HASCO.this.paramRefinementConfig.get(c).containsKey(p))) { + throw new IllegalArgumentException("No refinement config was delivered for numeric parameter " + p.getName() + " of component " + c.getName()); } } } - + /* updating logger name of the planner */ - if (HASCO.this.loggerName != null && HASCO.this.loggerName.length() > 0 - && planner instanceof ILoggingCustomizable) { - logger.info("Setting logger name of {} to {}", planner, loggerName + ".planner"); - ((ILoggingCustomizable) planner).setLoggerName(loggerName + ".planner"); + if (HASCO.this.loggerName != null && HASCO.this.loggerName.length() > 0 && HASCO.this.planner instanceof ILoggingCustomizable) { + HASCO.this.logger.info("Setting logger name of {} to {}", HASCO.this.planner, HASCO.this.loggerName + ".planner"); + ((ILoggingCustomizable) HASCO.this.planner).setLoggerName(HASCO.this.loggerName + ".planner"); } /* register listeners */ - synchronized (listeners) { - listeners.forEach(l -> ((IObservableGraphAlgorithm) planner).registerListener(l)); + synchronized (HASCO.this.listeners) { + HASCO.this.listeners.forEach(l -> ((IObservableGraphAlgorithm) HASCO.this.planner).registerListener(l)); } - solutionEvaluationEventBus.post(new HASCORunStartedEvent<>(HASCO.this.randomSeed, - HASCO.this.timeout, HASCO.this.numberOfCPUs, HASCO.this.benchmark)); + HASCO.this.solutionEvaluationEventBus.post(new HASCORunStartedEvent<>(HASCO.this.getConfig().randomSeed(), HASCO.this.getConfig().timeout(), HASCO.this.getConfig().cpus(), HASCO.this.benchmark)); this.isInitialized = true; } if (this.canceled) { throw new IllegalStateException("HASCO has already been canceled. Cannot compute more solutions."); } - HASCO.this.logger.info("Now asking the planning algorithm iterator {} whether there is a next solution.", - this.planIterator.getClass().getName()); + HASCO.this.logger.info("Now asking the planning algorithm iterator {} whether there is a next solution.", this.planIterator.getClass().getName()); return this.planIterator.hasNext(); } @@ -229,43 +234,38 @@ public Solution next() { /* derive a map of ground components */ R plan = this.planIterator.next(); - Map solutionAnnotations = planner.getAnnotationsOfSolution(plan); - ComponentInstance objectInstance = Util.getSolutionCompositionForPlan(HASCO.this.components, - reduction.getInitState(), plan.getPlan()); + Map solutionAnnotations = HASCO.this.planner.getAnnotationsOfSolution(plan); + ComponentInstance objectInstance = Util.getSolutionCompositionForPlan(HASCO.this.components, HASCO.this.reduction.getInitState(), plan.getPlan()); @SuppressWarnings("unchecked") - Solution solution = new Solution<>(objectInstance, plan, - HASCO.this.getObjectFromPlan(plan.getPlan()), (V) solutionAnnotations.get("f"), + Solution solution = new Solution<>(objectInstance, plan, HASCO.this.getObjectFromPlan(plan.getPlan()), (V) solutionAnnotations.get("f"), solutionAnnotations.containsKey("fTime") ? (int) solutionAnnotations.get("fTime") : -1); return solution; } public Map getAnnotationsOfSolution(final Solution solution) { - return planner.getAnnotationsOfSolution(solution.getPlanningSolution()); + return HASCO.this.planner.getAnnotationsOfSolution(solution.getPlanningSolution()); } public void cancel() { this.canceled = true; - planner.cancel(); + HASCO.this.planner.cancel(); HASCO.this.triggerTerminationEvent(); } } private void triggerTerminationEvent() { - HASCO.this.solutionEvaluationEventBus - .post(new HASCORunTerminatedEvent<>(this.compositionOfBestRecognizedSolution, - this.bestRecognizedSolution, this.scoreOfBestRecognizedSolution)); + HASCO.this.solutionEvaluationEventBus.post(new HASCORunTerminatedEvent<>(this.compositionOfBestRecognizedSolution, this.bestRecognizedSolution, this.scoreOfBestRecognizedSolution)); } public T getObjectFromPlan(final List plan) { - Monom state = reduction.getInitState(); + Monom state = this.reduction.getInitState(); for (Action a : plan) { PlannerUtil.updateState(state, a); } try { return this.getObjectFromState(state); } catch (Exception e) { - this.logger.error("Could not retrieve target object from plan. Details:\n{}", - LoggerUtil.getExceptionInfo(e)); + this.logger.error("Could not retrieve target object from plan. Details:\n{}", LoggerUtil.getExceptionInfo(e)); return null; } } @@ -276,35 +276,30 @@ public T getObjectFromState(final Monom state) throws Exception { return object; } - - protected void afterSearch() { } - public int getTimeout() { - return this.timeout; - } - - public void setTimeout(final int timeout) { - this.timeout = timeout; - } - - public void setRandom(final int randomSeed) { - this.randomSeed = randomSeed; - } - - public int getNumberOfCPUs() { - return this.numberOfCPUs; + /** + * @return The config object defining the properties. + */ + public HASCOConfig getConfig() { + return CONFIG; } + /** + * Set the number of CPUs to be used by HASCO. + * + * @param numberOfCPUs + * The number of cpus to be used. + */ public void setNumberOfCPUs(final int numberOfCPUs) { - this.numberOfCPUs = numberOfCPUs; + this.getConfig().setProperty(HASCOConfig.K_CPUS, numberOfCPUs + ""); } public Collection getComponents() { return this.components; } - + public Factory getFactory() { return this.factory; } @@ -317,13 +312,15 @@ public IObjectEvaluator getBenchmark() { return this.benchmark; } + public void setBenchmark(final IObjectEvaluator benchmark) { + this.benchmark = benchmark; + } + @Override public HASCOSolutionIterator iterator() { return new HASCOSolutionIterator(); } - - @Override public void registerListener(final Object listener) { synchronized (this.listeners) { @@ -334,12 +331,30 @@ public void registerListener(final Object listener) { public void registerListenerForSolutionEvaluations(final Object listener) { this.solutionEvaluationEventBus.register(listener); } - + public GraphGenerator getGraphGenerator() { - if (planner != null) - return planner.getGraphGenerator(); - else - return plannerFactory.newAlgorithm(problem, numberOfCPUs).getGraphGenerator(); + if (this.planner != null) { + return this.planner.getGraphGenerator(); + } else { + return this.plannerFactory.newAlgorithm(this.problem, this.getConfig().cpus()).getGraphGenerator(); + } + } + + public INodeEvaluator getPreferredNodeEvaluator() { + return this.preferredNodeEvaluator; + } + + public void setPreferredNodeEvaluator(final INodeEvaluator preferredNodeEvaluator) { + this.preferredNodeEvaluator = preferredNodeEvaluator; + } + + public void setNumberOfSamplesOfRandomCompletion(final int numSamples) { + this.randomCompletionEvaluator.setNumberOfRandomCompletions(numSamples); + } + + @Override + public String getLoggerName() { + return this.loggerName; } @Override @@ -350,20 +365,55 @@ public void setLoggerName(final String name) { this.logger.info("Activated logger {} with name {}", name, this.logger.getName()); } - @Override - public String getLoggerName() { - return this.loggerName; + /** + * @return The timeout for gathering solutions. + */ + public int getTimeout() { + return this.getConfig().timeout(); } - public INodeEvaluator getPreferredNodeEvaluator() { - return preferredNodeEvaluator; + /** + * @param timeout + * Timeout for gathering solutions. + */ + public void setTimeout(final int timeout) { + this.getConfig().setProperty(HASCOConfig.K_TIMEOUT, timeout + ""); } - public void setPreferredNodeEvaluator(INodeEvaluator preferredNodeEvaluator) { - this.preferredNodeEvaluator = preferredNodeEvaluator; + /** + * @return The seed for the random number generator. + */ + public int getRandom() { + return this.getConfig().randomSeed(); + } + + /** + * @param randomSeed + * The random seed to initialize the random number generator. + */ + public void setRandom(final int randomSeed) { + this.getConfig().setProperty(HASCOConfig.K_RANDOM_SEED, randomSeed + ""); } - - public void setNumberOfSamplesOfRandomCompletion(int numSamples) { - randomCompletionEvaluator.setNumberOfRandomCompletions(numSamples); + + /** + * @return Returns the number of CPUs that is to be used by HASCO. + */ + public int getNumberOfCPUs() { + return this.getConfig().cpus(); + } + + /** + * @return The name of the interface which is requested. + */ + public String getRequestedInterface() { + return this.getConfig().requestedInterface(); + } + + /** + * @param requestedInterface + * The name of the interface which is requested. + */ + public void setRequestedInterface(final String requestedInterface) { + this.getConfig().setProperty(HASCOConfig.K_REQUESTED_INTERFACE, requestedInterface); } }