Skip to content

Commit 1553639

Browse files
marcosvillacanas-A-Star
1 parent 88d65ff commit 1553639

File tree

1 file changed

+158
-0
lines changed

1 file changed

+158
-0
lines changed

DataStructures/Graphs/A_Star.java

+158
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
1+
package A_Star;
2+
3+
import java.util.*;
4+
5+
public class A_Star {
6+
7+
private static class Graph {
8+
//Graph's structure can be changed only applying changes to this class.
9+
private ArrayList<Edge> [] graph;
10+
11+
//Initialise ArrayLists in Constructor
12+
public Graph(int size) {
13+
this.graph = new ArrayList[size];
14+
for (int i = 0; i < size; i++) {
15+
this.graph[i] = new ArrayList<>();
16+
}
17+
}
18+
19+
private ArrayList<Edge> getNeighbours(int from) { return this.graph[from]; }
20+
21+
//Graph is bidirectional, for just one direction remove second instruction of this method.
22+
private void addEdge (Edge edge) {
23+
this.graph[edge.getFrom()].add(new Edge(edge.getFrom(), edge.getTo(), edge.getWeight()));
24+
this.graph[edge.getTo()].add(new Edge(edge.getTo(), edge.getFrom(), edge.getWeight()));
25+
}
26+
27+
private void initializeGraph() {
28+
this.addEdge(new Edge(0, 19, 75)); this.addEdge(new Edge(0, 15, 140));
29+
this.addEdge(new Edge(0, 16, 118)); this.addEdge(new Edge(19, 12, 71));
30+
this.addEdge(new Edge(12, 15, 151));this.addEdge(new Edge(16, 9, 111));
31+
this.addEdge(new Edge(9, 10, 70)); this.addEdge(new Edge(10, 3, 75));
32+
this.addEdge(new Edge(3, 2, 120)); this.addEdge(new Edge(2, 14, 146));
33+
this.addEdge(new Edge(2, 13, 138)); this.addEdge(new Edge(2, 6, 115));
34+
this.addEdge(new Edge(15, 14, 80)); this.addEdge(new Edge(15, 5, 99));
35+
this.addEdge(new Edge(14, 13, 97)); this.addEdge(new Edge(5, 1, 211));
36+
this.addEdge(new Edge(13, 1, 101)); this.addEdge(new Edge(6, 1, 160));
37+
this.addEdge(new Edge(1, 17, 85)); this.addEdge(new Edge(17, 7, 98));
38+
this.addEdge(new Edge(7, 4, 86)); this.addEdge(new Edge(17, 18, 142));
39+
this.addEdge(new Edge(18, 8, 92)); this.addEdge(new Edge(8, 11, 87));
40+
41+
/*
42+
.x. node
43+
(y) cost
44+
- or | or / bidirectional connection
45+
46+
( 98)- .7. -(86)- .4.
47+
|
48+
( 85)- .17. -(142)- .18. -(92)- .8. -(87)- .11.
49+
|
50+
. 1. -------------------- (160)
51+
| \ |
52+
(211) \ .6.
53+
| \ |
54+
. 5. (101)-.13. -(138) (115)
55+
| | | /
56+
( 99) ( 97) | /
57+
| | | /
58+
.12. -(151)- .15. -(80)- .14. | /
59+
| | | | /
60+
( 71) (140) (146)- .2. -(120)
61+
| | |
62+
.19. -( 75)- . 0. .10. -(75)- .3.
63+
| |
64+
(118) ( 70)
65+
| |
66+
.16. -(111)- .9.
67+
*/
68+
}
69+
}
70+
71+
private static class Edge {
72+
private int from;
73+
private int to;
74+
private int weight;
75+
76+
public Edge(int from, int to, int weight) {
77+
this.from = from;
78+
this.to = to;
79+
this.weight = weight;
80+
}
81+
82+
public int getFrom() { return from; }
83+
84+
public int getTo() { return to; }
85+
86+
public int getWeight() { return weight; }
87+
}
88+
89+
//class to iterate during the algorithm execution, and also used to return the solution.
90+
private static class PathAndDistance {
91+
private int distance; //distance advanced so far.
92+
private ArrayList<Integer> path; //list of visited nodes in this path.
93+
private int estimated; //heuristic value associated to the last node od the path (current node).
94+
95+
public PathAndDistance(int distance, ArrayList<Integer> path, int estimated) {
96+
this.distance = distance;
97+
this.path = path;
98+
this.estimated = estimated;
99+
}
100+
101+
public int getDistance() { return distance; }
102+
103+
public ArrayList<Integer> getPath() { return path; }
104+
105+
public int getEstimated() { return estimated; }
106+
107+
private void printSolution () {
108+
if (this.path != null)
109+
System.out.println("Optimal path: " + this.path.toString() +
110+
", distance: " + this.distance);
111+
else
112+
System.out.println("There is no path available to connect the points");
113+
}
114+
}
115+
116+
public static void main(String[] args) {
117+
//heuristic function optimistic values
118+
int[] heuristic = {366, 0, 160, 242, 161, 178, 77, 151, 226,
119+
244, 241, 234, 380, 98, 193, 253, 329, 80, 199, 374};
120+
121+
Graph graph = new Graph(20);
122+
graph.initializeGraph();
123+
124+
PathAndDistance solution = aStar(3, 1, graph, heuristic);
125+
solution.printSolution();
126+
127+
}
128+
129+
public static PathAndDistance aStar(int from, int to, Graph graph, int[] heuristic) {
130+
//nodes are prioritised by the less value of the current distance of their paths, and the estimated value
131+
//given by the heuristic function to reach the destination point from the current point.
132+
PriorityQueue<PathAndDistance> queue = new PriorityQueue<>
133+
(Comparator.comparingInt(a -> (a.getDistance() + a.getEstimated())));
134+
135+
//dummy data to start the algorithm from the beginning point
136+
queue.add(new PathAndDistance(0, new ArrayList<>(Arrays.asList(from)), 0));
137+
138+
boolean solutionFound = false;
139+
PathAndDistance currentData = new PathAndDistance(-1, null, -1);
140+
while (!queue.isEmpty() && !solutionFound) {
141+
currentData = queue.poll(); //first in the queue, best node so keep exploring.
142+
int currentPosition = currentData.getPath().get(currentData.getPath().size() - 1); //current node.
143+
if (currentPosition == to)
144+
solutionFound = true;
145+
else
146+
for (Edge edge : graph.getNeighbours(currentPosition))
147+
if (!currentData.getPath().contains(edge.getTo())) { //Avoid Cycles
148+
ArrayList<Integer> updatedPath = new ArrayList<>(currentData.getPath());
149+
updatedPath.add(edge.getTo()); //Add the new node to the path, update the distance,
150+
// and the heuristic function value associated to that path.
151+
queue.add(new PathAndDistance(currentData.getDistance() + edge.getWeight(),
152+
updatedPath, heuristic[edge.getTo()]));
153+
}
154+
}
155+
return (solutionFound) ? currentData : new PathAndDistance(-1, null, -1);
156+
//Out of while loop, if there is a solution, the current Data stores the optimal path, and its distance
157+
}
158+
}

0 commit comments

Comments
 (0)