From 6ef9863e921d293c05b19e71749dc35265eca1c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pablo=20Rodr=C3=ADguez=20Mier?= Date: Fri, 19 Apr 2013 19:04:10 +0200 Subject: [PATCH] Multiple changes to adapt all algorithms to the new Operable interface. Fix #42 #43 --- .../citius/lab/hipster/algorithm/ADStar.java | 5 +-- .../lab/hipster/algorithm/BellmanFord.java | 34 ++++++++++--------- .../lab/hipster/node/adstar/ADStarNode.java | 11 +++++- .../hipster/node/astar/CostNodeFactory.java | 13 +++++++ .../node/astar/InformedNodeFactory.java | 21 ++++++++++++ .../hipster/algorithm/BellmanFordTest.java | 29 +++++++++------- .../lab/hipster/algorithm/BenchmarkTest.java | 2 +- .../AlgorithmIteratorFromMazeCreator.java | 8 ++--- .../lab/hipster/testutils/MazeSearch.java | 11 +++--- 9 files changed, 93 insertions(+), 41 deletions(-) create mode 100644 src/main/java/es/usc/citius/lab/hipster/node/astar/CostNodeFactory.java diff --git a/src/main/java/es/usc/citius/lab/hipster/algorithm/ADStar.java b/src/main/java/es/usc/citius/lab/hipster/algorithm/ADStar.java index e483a1b..77a938d 100644 --- a/src/main/java/es/usc/citius/lab/hipster/algorithm/ADStar.java +++ b/src/main/java/es/usc/citius/lab/hipster/algorithm/ADStar.java @@ -3,6 +3,7 @@ import es.usc.citius.lab.hipster.function.TransitionFunction; import es.usc.citius.lab.hipster.node.adstar.ADStarNode; import es.usc.citius.lab.hipster.node.adstar.ADStarNodeUpdater; +import es.usc.citius.lab.hipster.node.informed.HeuristicNode; import es.usc.citius.lab.hipster.node.Node; import es.usc.citius.lab.hipster.node.NodeFactory; import es.usc.citius.lab.hipster.node.Transition; @@ -22,7 +23,7 @@ * @since 26-03-2013 * @version 1.0 */ -public class ADStar> implements Iterator> { +public class ADStar> implements Iterator> { private final ADStarNode beginNode; private final ADStarNode goalNode; @@ -136,7 +137,7 @@ public boolean hasNext() { return takePromising() != null; } - public Node next() { + public HeuristicNode next() { //First node in OPEN retrieved, not removed ADStarNode current = takePromising(); S state = current.transition().to(); diff --git a/src/main/java/es/usc/citius/lab/hipster/algorithm/BellmanFord.java b/src/main/java/es/usc/citius/lab/hipster/algorithm/BellmanFord.java index ec4cfde..b9d4d10 100644 --- a/src/main/java/es/usc/citius/lab/hipster/algorithm/BellmanFord.java +++ b/src/main/java/es/usc/citius/lab/hipster/algorithm/BellmanFord.java @@ -26,10 +26,11 @@ import java.util.Set; import es.usc.citius.lab.hipster.function.TransitionFunction; -import es.usc.citius.lab.hipster.node.HeuristicNode; import es.usc.citius.lab.hipster.node.Node; import es.usc.citius.lab.hipster.node.NodeFactory; import es.usc.citius.lab.hipster.node.Transition; +import es.usc.citius.lab.hipster.node.informed.CostNode; +import es.usc.citius.lab.hipster.util.Operable; /** * Bellman Ford (BF) algorithm is a label correcting method that computes @@ -40,13 +41,13 @@ * * @param */ -public class BellmanFord implements Iterator> { +public class BellmanFord> implements Iterator> { private TransitionFunction transition; - private NodeFactory> builder; + private NodeFactory> factory; private Queue queue; - private Map> explored; - //private Comparator> comparator; + private Map> explored; + //private Comparator> comparator; // Create a queue based on LinkedHashSet private class HashQueue extends AbstractQueue{ @@ -91,13 +92,13 @@ public boolean contains(Object o) { } - public BellmanFord(S initialState, TransitionFunction transition, NodeFactory> builder, Comparator> comparator){ - this.builder = builder; + public BellmanFord(S initialState, TransitionFunction transition, NodeFactory> builder){ + this.factory = builder; this.transition = transition; //this.queue = new LinkedList(); this.queue = new HashQueue(); - this.explored = new HashMap>(); - HeuristicNode initialNode = builder.node(null, new Transition(initialState)); + this.explored = new HashMap>(); + CostNode initialNode = builder.node(null, new Transition(initialState)); this.queue.add(initialState); this.explored.put(initialState, initialNode); } @@ -106,7 +107,7 @@ public boolean hasNext() { return !this.queue.isEmpty(); } - private void enqueue(HeuristicNode node){ + private void enqueue(CostNode node){ S state = node.transition().to(); if (!this.queue.contains(state)){ this.queue.add(state); @@ -114,27 +115,28 @@ private void enqueue(HeuristicNode node){ this.explored.put(state, node); } - private HeuristicNode dequeue(){ + private CostNode dequeue(){ S state = this.queue.poll(); return this.explored.get(state); } - public Node next() { + public CostNode next() { // Take the next node - HeuristicNode current = dequeue(); + CostNode current = dequeue(); // Calculate distances to each neighbor S currentState = current.transition().to(); for(Transition successor : this.transition.from(currentState)){ // Create the successor node - HeuristicNode successorNode = this.builder.node(current, successor); + CostNode successorNode = this.factory.node(current, successor); // Check if there is any improvement in the old cost - HeuristicNode previousNode = this.explored.get(successor.to()); + CostNode previousNode = this.explored.get(successor.to()); if (previousNode != null){ // Check both paths. If the new path is better than the previous // path, update and enqueue. Else, discard this node. //if (comparator.compare(successorNode, previousNode) <= 0){ - if (successorNode.compareByCost(previousNode) < 0){ + if (successorNode.getCost().compareTo(previousNode.getCost())<0){ + //if (successorNode.compareByCost(previousNode) < 0){ // Replace the worst version and re-enqueue (if not in queue) enqueue(successorNode); } diff --git a/src/main/java/es/usc/citius/lab/hipster/node/adstar/ADStarNode.java b/src/main/java/es/usc/citius/lab/hipster/node/adstar/ADStarNode.java index 866bbd9..4fb69dc 100644 --- a/src/main/java/es/usc/citius/lab/hipster/node/adstar/ADStarNode.java +++ b/src/main/java/es/usc/citius/lab/hipster/node/adstar/ADStarNode.java @@ -19,6 +19,7 @@ import es.usc.citius.lab.hipster.node.AbstractNode; import es.usc.citius.lab.hipster.node.Node; import es.usc.citius.lab.hipster.node.Transition; +import es.usc.citius.lab.hipster.node.informed.HeuristicNode; import es.usc.citius.lab.hipster.util.Scalable; /** @@ -28,7 +29,7 @@ * @since 16-04-2013 * @version 1.0 */ -public class ADStarNode> extends AbstractNode implements Comparable> { +public class ADStarNode> extends AbstractNode implements Comparable>, HeuristicNode { protected T g; protected T v; @@ -131,4 +132,12 @@ public int compareTo(Key o) { } } } + + public T getCost() { + return this.g; + } + + public T getScore() { + return this.v; + } } diff --git a/src/main/java/es/usc/citius/lab/hipster/node/astar/CostNodeFactory.java b/src/main/java/es/usc/citius/lab/hipster/node/astar/CostNodeFactory.java new file mode 100644 index 0000000..c2885ad --- /dev/null +++ b/src/main/java/es/usc/citius/lab/hipster/node/astar/CostNodeFactory.java @@ -0,0 +1,13 @@ +package es.usc.citius.lab.hipster.node.astar; + +public class CostNodeFactory { + + /** + * @param args + */ + public static void main(String[] args) { + // TODO Auto-generated method stub + + } + +} diff --git a/src/main/java/es/usc/citius/lab/hipster/node/astar/InformedNodeFactory.java b/src/main/java/es/usc/citius/lab/hipster/node/astar/InformedNodeFactory.java index 87f7a75..98f1d0d 100644 --- a/src/main/java/es/usc/citius/lab/hipster/node/astar/InformedNodeFactory.java +++ b/src/main/java/es/usc/citius/lab/hipster/node/astar/InformedNodeFactory.java @@ -4,6 +4,7 @@ import es.usc.citius.lab.hipster.function.HeuristicFunction; import es.usc.citius.lab.hipster.node.NodeFactory; import es.usc.citius.lab.hipster.node.Transition; +import es.usc.citius.lab.hipster.node.informed.CostNode; import es.usc.citius.lab.hipster.node.informed.HeuristicNode; import es.usc.citius.lab.hipster.node.informed.InformedNode; import es.usc.citius.lab.hipster.util.Operable; @@ -21,6 +22,16 @@ public InformedNodeFactory(CostFunction costFunction, HeuristicFunction costFunction, final T defaultValue){ + this.gf = costFunction; + this.hf = new HeuristicFunction() { + public T estimate(S state) { + return defaultValue; + } + }; + this.defaultValue = defaultValue; + } + public HeuristicNode node(HeuristicNode from, Transition transition) { T newCost, newScore; @@ -34,5 +45,15 @@ public HeuristicNode node(HeuristicNode from, } return new InformedNode(transition, from, newCost, newCost.add(newScore)); } + + public NodeFactory> toCostNodeFactory(){ + final NodeFactory> factory = this; + return new NodeFactory>() { + public CostNode node(CostNode from, + Transition transition) { + return factory.node((HeuristicNode) from, transition); + } + }; + } } diff --git a/src/test/java/es/usc/citius/lab/hipster/algorithm/BellmanFordTest.java b/src/test/java/es/usc/citius/lab/hipster/algorithm/BellmanFordTest.java index 9662e5a..3f57274 100644 --- a/src/test/java/es/usc/citius/lab/hipster/algorithm/BellmanFordTest.java +++ b/src/test/java/es/usc/citius/lab/hipster/algorithm/BellmanFordTest.java @@ -34,10 +34,13 @@ import es.usc.citius.lab.hipster.node.Transition; import es.usc.citius.lab.hipster.node.astar.HeuristicNumericNode; import es.usc.citius.lab.hipster.node.astar.HeuristicNumericNodeBuilder; +import es.usc.citius.lab.hipster.node.astar.InformedNodeFactory; +import es.usc.citius.lab.hipster.node.informed.CostNode; import es.usc.citius.lab.hipster.testutils.AlgorithmIteratorFromMazeCreator; import es.usc.citius.lab.hipster.testutils.JungDirectedGraphFromMazeCreator; import es.usc.citius.lab.hipster.testutils.JungEdge; import es.usc.citius.lab.hipster.testutils.MazeSearch; +import es.usc.citius.lab.hipster.util.DoubleOperable; import es.usc.citius.lab.hipster.util.maze.Maze2D; /** @@ -115,18 +118,20 @@ public Iterable> from(String current) { } }; - NodeFactory> builder = new HeuristicNumericNodeBuilder( - new CostFunction() { - public Double evaluate( - Transition transition) { - if (transition.from()==null){ - return 0d; - } - return graph.findEdge(transition.from(), transition.to()).getCost(); - } - }); + NodeFactory> factory = new InformedNodeFactory(new CostFunction() { + public DoubleOperable evaluate(Transition transition) { + if (transition.from()==null){ + return DoubleOperable.MIN; + } + return new DoubleOperable(graph.findEdge(transition.from(), transition.to()).getCost()); + } + + + }, DoubleOperable.MIN).toCostNodeFactory(); + + - BellmanFord it = new BellmanFord("A", transition, builder, null); + BellmanFord it = new BellmanFord("A", transition, factory); while(it.hasNext()){ Node edgeNode = it.next(); System.out.println("Exploring " + edgeNode.transition().from() + "->" + edgeNode.transition().to()); @@ -150,7 +155,7 @@ public Double evaluate( private void execute(Maze2D maze, boolean heuristic) throws InterruptedException { - BellmanFord it = AlgorithmIteratorFromMazeCreator.bellmanFord( + BellmanFord it = AlgorithmIteratorFromMazeCreator.bellmanFord( maze, heuristic); DirectedGraph> graph = JungDirectedGraphFromMazeCreator .create(maze); diff --git a/src/test/java/es/usc/citius/lab/hipster/algorithm/BenchmarkTest.java b/src/test/java/es/usc/citius/lab/hipster/algorithm/BenchmarkTest.java index 787c181..7f6fa00 100644 --- a/src/test/java/es/usc/citius/lab/hipster/algorithm/BenchmarkTest.java +++ b/src/test/java/es/usc/citius/lab/hipster/algorithm/BenchmarkTest.java @@ -133,7 +133,7 @@ public Result evaluate() { // Bellman-Ford bench.add("Hipster-Bellman-Ford", new Algorithm() { - BellmanFord it; Maze2D maze; + BellmanFord it; Maze2D maze; public void initialize(Maze2D maze) { it= AlgorithmIteratorFromMazeCreator.bellmanFord(maze, false); this.maze = maze; diff --git a/src/test/java/es/usc/citius/lab/hipster/testutils/AlgorithmIteratorFromMazeCreator.java b/src/test/java/es/usc/citius/lab/hipster/testutils/AlgorithmIteratorFromMazeCreator.java index 72122c2..dc8893e 100644 --- a/src/test/java/es/usc/citius/lab/hipster/testutils/AlgorithmIteratorFromMazeCreator.java +++ b/src/test/java/es/usc/citius/lab/hipster/testutils/AlgorithmIteratorFromMazeCreator.java @@ -27,6 +27,7 @@ import es.usc.citius.lab.hipster.node.adstar.ADStarNodeBuilder; import es.usc.citius.lab.hipster.node.Transition; import es.usc.citius.lab.hipster.node.astar.HeuristicNumericNodeBuilder; +import es.usc.citius.lab.hipster.node.astar.InformedNodeFactory; import es.usc.citius.lab.hipster.util.DoubleOperable; import es.usc.citius.lab.hipster.util.maze.Maze2D; import java.awt.Point; @@ -94,15 +95,14 @@ public static ADStar adstar(final Maze2D maze) { return adstar(maze, false); } - public static BellmanFord bellmanFord(final Maze2D maze, boolean useHeuristic) { + public static BellmanFord bellmanFord(final Maze2D maze, boolean useHeuristic) { CostFunction cost = defaultCostFunction(); TransitionFunction transition = defaultTransitionFunction(maze); - BellmanFord it; + BellmanFord it; - //it = new BellmanFord(maze.getInitialLoc(), transition, new HeuristicNumericNodeBuilder(cost), null); - it = null; + it = new BellmanFord(maze.getInitialLoc(), transition, new InformedNodeFactory(cost, DoubleOperable.MIN).toCostNodeFactory()); return it; } diff --git a/src/test/java/es/usc/citius/lab/hipster/testutils/MazeSearch.java b/src/test/java/es/usc/citius/lab/hipster/testutils/MazeSearch.java index 05fb533..2e26a1a 100644 --- a/src/test/java/es/usc/citius/lab/hipster/testutils/MazeSearch.java +++ b/src/test/java/es/usc/citius/lab/hipster/testutils/MazeSearch.java @@ -33,6 +33,7 @@ import edu.uci.ics.jung.algorithms.shortestpath.DijkstraShortestPath; import edu.uci.ics.jung.graph.DirectedGraph; import es.usc.citius.lab.hipster.node.Node; +import es.usc.citius.lab.hipster.node.informed.CostNode; import es.usc.citius.lab.hipster.node.informed.HeuristicNode; import es.usc.citius.lab.hipster.util.DoubleCostEvaluator; import es.usc.citius.lab.hipster.util.DoubleOperable; @@ -170,16 +171,16 @@ public boolean equals(Object obj) { } //public static Result executePrintIteratorSearch(AStar it, StringMaze maze) throws InterruptedException { - public static Result executePrintIteratorSearch(Iterator> it, Maze2D maze) throws InterruptedException { + public static Result executePrintIteratorSearch(Iterator> it, Maze2D maze) throws InterruptedException { return executePrintIteratorSearch(it, maze, true); } - public static Result executePrintIteratorSearch(Iterator> it, Maze2D maze, boolean exitWhenGoalReached) throws InterruptedException { + public static Result executePrintIteratorSearch(Iterator> it, Maze2D maze, boolean exitWhenGoalReached) throws InterruptedException { int steps = 0; Result r = null; Collection explored = new HashSet(); while (it.hasNext()) { - HeuristicNode currentNode = it.next(); + CostNode currentNode = it.next(); explored.add(currentNode.transition().to()); steps++; List> nodePath = currentNode.path(); @@ -228,10 +229,10 @@ public static String getMazeStringSolution(Maze2D maze, Collection explor //public static Result executeIteratorSearch(AStar it, StringMaze maze) { - public static Result executeIteratorSearch(Iterator> it, Maze2D maze) { + public static Result executeIteratorSearch(Iterator> it, Maze2D maze) { int steps = 0; while (it.hasNext()) { - HeuristicNode currentNode = it.next(); + CostNode currentNode = it.next(); steps++; if (currentNode.transition().to().equals(maze.getGoalLoc())) { List> nodePath = currentNode.path();