View Javadoc

1   package cz.cuni.amis.utils.astar;
2   
3   import java.util.ArrayList;
4   import java.util.Collection;
5   import java.util.HashMap;
6   import java.util.HashSet;
7   import java.util.List;
8   import java.util.Stack;
9   
10  /**
11   * This class is returned by AStar.aStar().
12   * It contains results from the search as well as method for
13   * finding
14   *  the path from the startNode to the goalNode.
15   * 
16   * It contains all data structures the AStar is using during the work.
17   * Everything is made public here so that AStar (during work) and you (for
18   * browsing the results) may use it.
19   */
20  public class AStarResult<NODE> {
21  	
22  	/**
23  	 * Used by getPath() and filled by A* algorithm (AStar.aStar()). 
24  	 * Keys are nodes and values are 'parent-nodes' (from where we've come to the key node
25  	 * on the path from startNode to key-node).
26  	 */
27  	public HashMap<NODE, NODE> previousNode = new HashMap<NODE, NODE>();
28  	
29  	/**
30  	 * List of nodes which is opened -> was touched by the algorithm and are
31  	 * subjects of examination.
32  	 * 
33  	 * Initialized by AStar.aStar()
34  	 */
35  	public Collection<NODE> openList;
36  	
37  	/**
38  	 * Nodes which were examined by the algoritm.
39  	 * At the end of work of AStar contains all the nodes which were examined.
40  	 * If AStar successful -> at least contains nodes on the shortest path from
41  	 * startNode to goalNode.
42  	 */
43  	public Collection<NODE> closeList = new HashSet<NODE>();
44  	
45  	/**
46  	 * Used and filled by A* algorithm (AStar.aStar()).
47  	 * Here we store the real cost from the startNode to the 'key'.
48  	 */
49  	public HashMap<NODE, Integer> pathCost = new HashMap<NODE, Integer>();
50  	
51  	/**
52  	 * Used and filled by A* alorithm (AStar.aStar()).
53  	 * Here we store estimated cost of the path from 'key' to the goal.
54  	 */
55  	public HashMap<NODE, Integer> estimatedCost = new HashMap<NODE, Integer>();
56  	
57  	/**
58  	 * Contains the number of iterations made by A* search.
59  	 * One iteration means evaluating of the one node ("touching" each of the neighbours)
60  	 * Is 0-based ... if startGoal == goalNode or startGoal then this will be 0. 
61  	 */
62  	public long interations = 0;
63  	
64  	/**
65  	 * Start node of the A*.
66  	 */
67  	public NODE startNode = null;
68  	
69  	/**
70  	 * Node which was marked as a goalNode by AStarMap. (Note that you theoreticaly may have many
71  	 * goal nodes but A* searches only for the first one.)
72  	 * It's filled only if A* found the goalNoda! (success == true) 
73  	 */
74  	public NODE goalNode = null;
75  	
76  	/**
77  	 * Whether goalNode was found during the A* run.
78  	 * If this is true then goalNode is not null.
79  	 */
80  	public boolean success = false;
81  	
82  	/**
83  	 * Used by getPath() to cache the path from startNode to goalNode once it has
84  	 * been found.
85  	 */
86  	private List<NODE> path = null;
87  	
88  	/**
89  	 * Used by getPath() method when creating a list of nodes (the path) from startNode
90  	 * to goalNode.
91  	 * @param node
92  	 * @return previous node of supplied node | null
93  	 */
94  	public NODE getPreviousNode(NODE node){
95  		if (previousNode.containsKey(node)) return previousNode.get(node);
96  		else                                return null;
97  	}	
98  	
99  	/**
100 	 * Assing 'previous' as an previous node for 'node' (the path from 'startNode' to 'node' goes across 'previous').
101 	 * @param node
102 	 * @param previous
103 	 */
104 	public void putPreviousNode(NODE node, NODE previous){
105 		previousNode.put(node, previous);
106 	}
107 	
108 	/**
109 	 * Returns cost of the path from startNode to node if the node was touched
110 	 * by A* algorithm (if A* was successful, then this always contains the goalNode
111 	 * and every node on the path).
112 	 * 
113 	 * If node wasn't touched by A* algorithm, then it returns -1.
114 	 * 
115 	 * @param node
116 	 * @return cost of the path from startNode to node
117 	 */
118 	public int getCostToNode(NODE node){
119 		if (pathCost.containsKey(node)) 
120 			return ((Integer)pathCost.get(node)).intValue();
121 		else                            
122 			return -1;
123 	}
124 	
125 	/**
126 	 * Assing cost of the path from startNode to node.
127 	 * @param node
128 	 * @param cost
129 	 */
130 	public void putCostToNode(NODE node, Integer cost){
131 		pathCost.put(node, cost);
132 	}
133 	
134 	/**
135 	 * Returns estimated cost of the path from startNode to goal through node.
136 	 * If the node was touched by A* algorithm then it has this value stored here
137 	 * (if A* was successful, then this always contains the goalNode
138 	 * and every node on the path).
139 	 * 
140 	 * If node wasn't touched by A* algorithm, then it returns -1.
141 	 * 
142 	 * @param node
143 	 * @return cost of the path from startNode to node
144 	 */
145 	public int getEstimatedCostToNode(NODE node){
146 		if (estimatedCost.containsKey(node)) 
147 			return estimatedCost.get(node);
148 		else                                 
149 			return -1;
150 	}
151 	
152 	/**
153 	 * Assing estimated cost of the path from startNode to goalNode through node.
154 	 * @param node
155 	 * @param cost
156 	 */
157 	public void putEstimatedCostToNode(NODE node, Integer cost){
158 		estimatedCost.put(node, cost);
159 	}
160 	
161 	/**
162 	 * Returns the path from startNode to goalNode. (Don't change it as it's cached,
163 	 * if you want to alter it - then copy it :-)
164 	 * 
165 	 * First item is startNode and the last item is goalNode.
166 	 * If startNode == goalNode then it contains only one item.
167 	 * For each index ... path[index] has neighbour path[index+1].
168 	 * 
169 	 * If the path doesn't exist - returns null.
170 	 */
171 	public List<NODE> getPath(){
172 		if (path != null) 
173 			return path;
174 		if (!success)
175 			return null;
176 		
177 		Stack<NODE> tempPath = new Stack<NODE>();		
178 		tempPath.push(goalNode);
179 		
180 		NODE node = goalNode;
181 		while (node != startNode){
182 			node = getPreviousNode(node);
183 			if (node == null)
184 				return null; // path doesn't exist
185 			tempPath.push(node);
186 		}
187 
188 		path = new ArrayList<NODE>();
189 		
190 		while (!tempPath.empty()){
191 			path.add(tempPath.pop());
192 		}
193 			
194 		return path;
195 	}
196 	
197 	/**
198 	 * If the AStar succeeded then it returns the distance to the goal.
199 	 * Returns -1 otherwise.
200 	 * @return distance | -1
201 	 */
202 	public int getDistanceToGoal(){
203 		if (!this.success) return -1;
204 		return ((Integer) this.pathCost.get(goalNode)).intValue();
205 	}
206 }