2 import java
.io
.IOException
;
4 import java
.util
.LinkedList
;
5 import java
.util
.PriorityQueue
;
6 import java
.util
.Enumeration
;
10 * Denna klass implementerar olika sökalgoritmer för att hitta vägar
11 * mellan två platser på en karta.
13 * @author "Anton Johansson" <anton.johansson@gmail.com>
14 * @author "Victor Zamanian" <victor.zamanian@gmail.com>
17 public class MySearcher
extends MapSearcher
{
23 * Skapar en ny MySearcher-instans.
25 public MySearcher () {
31 * Specificerar kartan utifrån en fil i XML-format. The xml-file
34 * <?xml version='1.0' encoding='ISO-8859-1' ?>
36 * <node id="Teg" x="1720099" y="7072732">
37 * <road to="Rondellen" speed="50" />
38 * <road to="Tegsbron" speed="110" />
43 * @param mapFile a File containing the xml representation of the
46 public void setMap(File mapFile
) {
48 List
<Element
> cityElements
;
50 doc
= loadXmlMap(mapFile
);
51 cityElements
= doc
.getRootElement().getChildren();
52 map
= new Graph(cityElements
.size(), 5);
54 // Iterate through cityElements
55 for (Element cityElement
: cityElements
) {
56 map
.insertNode(cityElement
.getAttributeValue("id"),
57 Integer
.parseInt(cityElement
.getAttributeValue("x")),
58 Integer
.parseInt(cityElement
.getAttributeValue("y")));
61 // Iterate through cityElements once more to add roads
62 for (Element cityElement
: cityElements
) {
63 GraphNode cityNode
= map
.getNode(cityElement
.getAttributeValue("id"));
65 // Iterate through roadElements in this cityElement
66 List
<Element
> roadElements
= cityElement
.getChildren();
67 for (Element roadElement
: roadElements
) {
68 GraphNode nodeAtEndOfRoad
= map
.getNode(roadElement
.getAttributeValue("to"));
69 Double distance
= Math
.hypot((cityNode
.getX() - nodeAtEndOfRoad
.getX()),
70 (cityNode
.getY() - nodeAtEndOfRoad
.getY()));
73 new Road(Integer
.parseInt(roadElement
.getAttributeValue("speed")),
75 if (road
.getSpeed() > topSpeed
) {
76 topSpeed
= road
.getSpeed();
78 map
.insertEdge(cityNode
.getName(),
79 nodeAtEndOfRoad
.getName(),
84 catch (IOException e
) {
85 System
.err
.println ("Could not read/find file.");
88 catch (JDOMException e
) {
89 System
.err
.println (e
.getMessage());
92 catch (NumberFormatException e
) {
93 System
.err
.println ("Coordinates cannot be parsed. Check XML-file for errors.");
99 * Utför sökning med Greedy Search.
101 * @param from Den plats sökningen börjar från.
102 * @param to Den plats sökningen avslutas på.
103 * @return En text-representation som innhåller sökvägen till
104 * målet. Ex: nod1, nod2, nod3, mål
106 public String
greedySearch (String from
, String to
) {
107 String pathToGoal
= "",
109 // 1. Set N to be a sorted list of initial nodes;
110 PriorityQueue
<GraphNode
> queue
=
111 new PriorityQueue
<GraphNode
>(this.map
.size());
112 // Set fromNodes distance to 0.0
113 map
.getNode(from
).setDistanceTraveled(0.0);
114 queue
.add(map
.getNode(from
));
116 while (!queue
.isEmpty()) { // 2. If N is empty,
117 // 3. set n to be the first node in N, and remove n from N;
120 expandedNodes
+= n
.getName() + (n
== map
.getNode(to
) ?
"" : ", ");
122 // 4. If n is the goal node, exit and signal success;
123 if (n
== this.map
.getNode(to
)) {
124 pathToGoal
= n
.getName(); // Goal
127 while (n
!= map
.getNode(from
)) {
128 pathToGoal
= n
.getName() + ", " + pathToGoal
;
131 pathToGoal
= n
.getName() + ", " + pathToGoal
; // Beginning
132 System
.out
.println("\nAll expanded nodes:\n" + expandedNodes
+ "\n\n");
135 // 5. Otherwise add the children of n to N,
137 for (Enumeration
<GraphNode
> e
= n
.getNeighbours();
138 e
.hasMoreElements();) {
139 neighbour
= e
.nextElement();
140 neighbour
.setEvalFuncVal(neighbour
.getDistanceToNode(map
.getNode(to
)));
141 if (!neighbour
.isVisited() && !queue
.contains(neighbour
)) {
142 neighbour
.setParent(n
);
143 queue
.add(neighbour
);
145 // and return to step 2. (end of loop)
148 // 2. ... exit and signal failure
149 return "Goal not found!\n";
153 * Utför sökning med A*.
155 * @param from Den plats sökningen börjar från.
156 * @param to Den plats sökningen avslutas på.
157 * @param fastest Om <code>true</code>, hitta snabbaste vägen,
158 * annars den kortaste.
159 * @return En text-representation som innhåller sökvägen till
160 * målet. Ex: nod1, nod2, nod3, mål
162 public String
aStar (String from
, String to
, boolean fastest
) {
163 String pathToGoal
= "",
166 // 1. Set N to be a sorted list of initial nodes;
167 PriorityQueue
<GraphNode
> queue
=
168 new PriorityQueue
<GraphNode
>(this.map
.size());
169 // Set fromNodes distance to 0.0
170 map
.getNode(from
).setDistanceTraveled(0.0);
171 queue
.add(map
.getNode(from
));
174 while (!queue
.isEmpty()) { // 2. If N is empty,
175 // 3. set n to be the first node in N, and remove n from N;
178 expandedNodes
+= n
.getName() + (n
== map
.getNode(to
) ?
"" : ", ");
180 // 4. If n is the goal node, exit and signal success;
181 if (n
== this.map
.getNode(to
)) {
182 pathToGoal
= n
.getName(); // Goal
185 while (n
!= map
.getNode(from
)) {
186 pathToGoal
= n
.getName() + ", " + pathToGoal
;
189 pathToGoal
= n
.getName() + ", " + pathToGoal
; // Beginning
190 System
.out
.println("\n All expanded nodes:\n " + expandedNodes
+ "\n\n");
194 // 5. Otherwise add the children of n to N,
196 for (Enumeration
<GraphNode
> e
= n
.getNeighbours();
197 e
.hasMoreElements();) {
198 neighbour
= e
.nextElement();
200 if (!neighbour
.isVisited()) {
201 Double evalFunctionValue
;
204 evalFunctionValue
= n
.getDistanceTraveled()
205 + ((Road
) n
.getEdge(neighbour
)).getTravelTime()
206 + neighbour
.getDistanceToNode(map
.getNode(to
)) / topSpeed
;
210 evalFunctionValue
= n
.getDistanceTraveled()
211 + ((Road
) n
.getEdge(neighbour
)).getDistance()
212 + neighbour
.getDistanceToNode(map
.getNode(to
));
215 if (queue
.contains(neighbour
)
216 && evalFunctionValue
>= neighbour
.getEvalFuncVal()) {
217 // Queue already contains a better way to this
218 // node, break the for-loop here and continue.
223 neighbour
.setDistanceTraveled(n
.getDistanceTraveled()
224 + ((Road
) n
.getEdge(neighbour
)).getTravelTime());
227 neighbour
.setDistanceTraveled(n
.getDistanceTraveled()
228 + ((Road
) n
.getEdge(neighbour
)).getDistance());
231 neighbour
.setEvalFuncVal(evalFunctionValue
);
232 neighbour
.setParent(n
);
234 if (!queue
.contains(neighbour
)) {
235 queue
.add(neighbour
);
240 System
.out
.println();
241 // 2. ... exit and signal failure
242 return "Goal not found!\n";
246 * Utför bredden-förstsökning.
248 * @param from Den plats sökningen börjar från.
249 * @param to Den plats sökningen avslutas på.
250 * @return En text-representation som innhåller sökvägen till
251 * målet. Ex: nod1, nod2, nod3, mål
253 public String
breadthFirst (String from
, String to
) {
255 * Comments fetched from
256 * http://en.wikipedia.org/wiki/Breadth-first_search
257 * at Tue Oct 14 12:57:18 2008
259 LinkedList
<GraphNode
> queue
= new LinkedList
<GraphNode
>();
260 String expandedNodes
= "";
261 String pathToGoal
= "";
262 // 1. Put the root node on the queue.
263 queue
.add(map
.getNode(from
));
264 while (!queue
.isEmpty()) {
265 // 2. Pull a node from the beginning of the queue and examine it.
266 GraphNode n
= queue
.removeFirst();
268 expandedNodes
+= n
.getName() + (n
== map
.getNode(to
) ?
"" : ", ");
270 // * If the searched element is found in this node, quit
271 // * the search and return a result.
272 if (n
.getName().equals(to
)) {
273 pathToGoal
= n
.getName(); // Goal
276 while (n
!= map
.getNode(from
)) {
277 pathToGoal
= n
.getName() + ", " + pathToGoal
;
280 pathToGoal
= n
.getName() + ", " + pathToGoal
; // Beginning
281 System
.out
.println("\nAll expanded nodes:\n" + expandedNodes
+ "\n\n");
284 // * Otherwise push all the (so-far-unexamined) successors
285 // * (the direct child nodes) of this node into the end of
286 // * the queue, if there are any.
288 for (Enumeration
<GraphNode
> e
= n
.getNeighbours(); e
.hasMoreElements();) {
289 GraphNode neighbour
= e
.nextElement();
290 if (!neighbour
.isVisited() && !queue
.contains(neighbour
)) {
291 neighbour
.setParent(n
);
292 queue
.add(neighbour
);
297 return "Goal not found!\n";
301 * Utför djupet-förstsökning.
303 * @param from Den plats sökningen börjar från.
304 * @param to Den plats sökningen avslutas på.
305 * @return En text-representation som innhåller sökvägen till
306 * målet. Ex: nod1, nod2, nod3, mål
308 public String
depthFirst (String from
, String to
) {
309 LinkedList
<GraphNode
> stack
= new LinkedList
<GraphNode
>();
310 String expandedNodes
= "";
311 String pathToGoal
= "";
312 // 1. Push the root node onto the stack.
313 stack
.add(map
.getNode(from
));
314 while (!stack
.isEmpty()) {
315 // 2. Pop a node from the stack
316 GraphNode n
= stack
.removeLast();
317 // * Mark this node as visited
319 // * If the searched element is found in this node, quit
320 // * the search and return a result.
321 if (n
.getName().equals(to
)) {
322 expandedNodes
+= n
.getName();
323 pathToGoal
= n
.getName(); // Goal
326 while (n
!= map
.getNode(from
)) {
327 pathToGoal
= n
.getName() + ", " + pathToGoal
;
330 pathToGoal
= n
.getName() + ", " + pathToGoal
; // Beginning
331 System
.out
.println("\nAll expanded nodes:\n" + expandedNodes
+ "\n\n");
334 // * Otherwise push all the unvisited connecting nodes of n
336 for (Enumeration
<GraphNode
> e
= n
.getNeighbours();
337 e
.hasMoreElements();) {
338 GraphNode neighbour
= e
.nextElement();
339 if (!neighbour
.isVisited() && !stack
.contains(neighbour
)) {
340 neighbour
.setParent(n
);
341 stack
.add(neighbour
);
345 expandedNodes
+= n
.getName() + ", ";
347 return "Goal not found!\n";
351 * Returnerar en text-representation av kartan satt i metoden
354 * @return En text-representation av kartan satt i metoden
357 public String
toString() {
358 return map
.toString();