-
-
Notifications
You must be signed in to change notification settings - Fork 5.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: added Astar Search Algorithm in Graphs #1739
base: master
Are you sure you want to change the base?
Changes from 3 commits
ff23c98
3c30bce
a9e17ed
90eac72
45b8231
6142d3d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
@@ -0,0 +1,107 @@ | ||||||
/** | ||||||
* Author: Mathang Peddi | ||||||
* A* Search Algorithm implementation in JavaScript | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Removed this line. |
||||||
* A* Algorithm calculates the minimum cost path between two nodes. | ||||||
* It is used to find the shortest path using heuristics. | ||||||
* It uses graph data structure. | ||||||
*/ | ||||||
|
||||||
function createGraph(V, E) { | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This function is unnecessary. Just take the graph in adjacency list representation. There is also no need to restrict this to undirected graphs. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Removed this function, created an adjacency list and directly passed it to the function. |
||||||
// V - Number of vertices in graph | ||||||
// E - Number of edges in graph (u,v,w) | ||||||
const adjList = [] // Adjacency list | ||||||
for (let i = 0; i < V; i++) { | ||||||
adjList.push([]) | ||||||
} | ||||||
for (let i = 0; i < E.length; i++) { | ||||||
adjList[E[i][0]].push([E[i][1], E[i][2]]) | ||||||
adjList[E[i][1]].push([E[i][0], E[i][2]]) | ||||||
} | ||||||
return adjList | ||||||
} | ||||||
|
||||||
// Heuristic function to estimate the cost to reach the goal | ||||||
// You can modify this based on your specific problem, for now, we're using Manhattan distance | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is not a useful manhattan distance. This is just the absolute distance between vertex IDs. Instead you want some kind of associated "points" (say, in 2d or 3d space) for which you compute distances. In any case, the heuristic function should probably be a (mandatory) parameter. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I have made the changes, I am using Euclidian Distance here, do I need to make any other change here? |
||||||
function heuristic(a, b) { | ||||||
return Math.abs(a - b) | ||||||
} | ||||||
|
||||||
function aStar(graph, V, src, target) { | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Again, just take the graph in adjacency list representation. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Changed it. |
||||||
const openSet = new Set([src]) // Nodes to explore | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This should be a priority queue by There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Have changed the logic, have used the priority queue implementation - have coded it using the normal approach(without using inbuilt PQ package), is this fine or do I need to make any other changes here? |
||||||
const cameFrom = Array(V).fill(-1) // Keep track of path | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Use There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Changed. |
||||||
const gScore = Array(V).fill(Infinity) // Actual cost from start to a node | ||||||
gScore[src] = 0 | ||||||
|
||||||
const fScore = Array(V).fill(Infinity) // Estimated cost from start to goal (g + h) | ||||||
fScore[src] = heuristic(src, target) | ||||||
|
||||||
while (openSet.size > 0) { | ||||||
// Get the node in openSet with the lowest fScore | ||||||
let current = -1 | ||||||
openSet.forEach((node) => { | ||||||
if (current === -1 || fScore[node] < fScore[current]) { | ||||||
current = node | ||||||
} | ||||||
}) | ||||||
|
||||||
// If the current node is the target, reconstruct the path and return | ||||||
if (current === target) { | ||||||
const path = [] | ||||||
while (cameFrom[current] !== -1) { | ||||||
path.push(current) | ||||||
current = cameFrom[current] | ||||||
} | ||||||
path.push(src) | ||||||
return path.reverse() | ||||||
} | ||||||
|
||||||
openSet.delete(current) | ||||||
|
||||||
// Explore neighbors | ||||||
for (let i = 0; i < graph[current].length; i++) { | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Just do There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Changed. |
||||||
const neighbor = graph[current][i][0] | ||||||
const tentative_gScore = gScore[current] + graph[current][i][1] | ||||||
|
||||||
if (tentative_gScore < gScore[neighbor]) { | ||||||
cameFrom[neighbor] = current | ||||||
gScore[neighbor] = tentative_gScore | ||||||
fScore[neighbor] = gScore[neighbor] + heuristic(neighbor, target) | ||||||
|
||||||
if (!openSet.has(neighbor)) { | ||||||
openSet.add(neighbor) | ||||||
} | ||||||
} | ||||||
} | ||||||
} | ||||||
|
||||||
return [] // Return empty path if there's no path to the target | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should be There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Changed. |
||||||
} | ||||||
|
||||||
module.exports = { createGraph, aStar } | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Changed. |
||||||
|
||||||
// const V = 9 | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should be a test instead. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Removed this part, do you want me to add a Astar.test.js file as a part of Unit Testing? |
||||||
// const E = [ | ||||||
// [0, 1, 4], | ||||||
// [0, 7, 8], | ||||||
// [1, 7, 11], | ||||||
// [1, 2, 8], | ||||||
// [7, 8, 7], | ||||||
// [6, 7, 1], | ||||||
// [2, 8, 2], | ||||||
// [6, 8, 6], | ||||||
// [5, 6, 2], | ||||||
// [2, 5, 4], | ||||||
// [2, 3, 7], | ||||||
// [3, 5, 14], | ||||||
// [3, 4, 9], | ||||||
// [4, 5, 10] | ||||||
// ] | ||||||
|
||||||
// const graph = createGraph(V, E) | ||||||
// const path = aStar(graph, V, 0, 4) // Find path from node 0 to node 4 | ||||||
// console.log(path) | ||||||
|
||||||
/** | ||||||
* The function returns the optimal path from the source to the target node. | ||||||
* The heuristic used is Manhattan distance but it can be modified. | ||||||
*/ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please use JSDoc annotations like
@author
.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Have changed it to @author: Mathang Peddi
Do I need to make any other change here?