Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

feat: added Astar Search Algorithm in Graphs#1739

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 ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Open
mathangpeddi wants to merge6 commits intoTheAlgorithms:master
base:master
Choose a base branch
Loading
frommathangpeddi:master
Open
Changes fromall commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
207 changes: 207 additions & 0 deletionsGraphs/Astar.js
View file
Open in desktop
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,207 @@
/**
* @author : Mathang Peddi
* 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.
*/

// Euclidean distance heuristic for 2D points
function euclideanHeuristic(pointA, pointB) {
const dx = pointA[0] - pointB[0]
const dy = pointA[1] - pointB[1]
return Math.sqrt(dx * dx + dy * dy)
}

// Priority Queue (Min-Heap) implementation
class PriorityQueue {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

Please import this (we have a priority queue implementation in this repo) rather than reimplementing it.

constructor() {
this.elements = []
}

enqueue(node, priority) {
this.elements.push({ node, priority })
this.bubbleUp()
}

bubbleUp() {
let index = this.elements.length - 1
while (index > 0) {
let parentIndex = Math.floor((index - 1) / 2)
if (this.elements[index].priority >= this.elements[parentIndex].priority)
break
;[this.elements[index], this.elements[parentIndex]] = [
this.elements[parentIndex],
this.elements[index]
]
index = parentIndex
}
}

dequeue() {
if (this.elements.length === 1) {
return this.elements.pop().node
}

const node = this.elements[0].node
this.elements[0] = this.elements.pop()
this.sinkDown(0)
return node
}

sinkDown(index) {
const length = this.elements.length
const element = this.elements[index]
while (true) {
let leftChildIndex = 2 * index + 1
let rightChildIndex = 2 * index + 2
let swapIndex = null

if (
leftChildIndex < length &&
this.elements[leftChildIndex].priority < element.priority
) {
swapIndex = leftChildIndex
}

if (
rightChildIndex < length &&
this.elements[rightChildIndex].priority <
(swapIndex === null
? element.priority
: this.elements[leftChildIndex].priority)
) {
swapIndex = rightChildIndex
}

if (swapIndex === null) break
;[this.elements[index], this.elements[swapIndex]] = [
this.elements[swapIndex],
this.elements[index]
]
index = swapIndex
}
}

isEmpty() {
return this.elements.length === 0
}
}

function aStar(graph, src, target, points) {
Copy link
Collaborator

@appgurueuappgurueuOct 23, 2024
edited
Loading

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

Where are these parameters documented? Also why is the heuristic function not a parameter (which may default to a simple euclidean heuristic)?

const openSet = new PriorityQueue() // Priority queue to explore nodes
openSet.enqueue(src, 0)

const cameFrom = Array(graph.length).fill(null) // Keep track of path
const gScore = Array(graph.length).fill(Infinity) // Actual cost from start to a node
gScore[src] = 0

const fScore = Array(graph.length).fill(Infinity) // Estimated cost from start to goal (g + h)
fScore[src] = euclideanHeuristic(points[src], points[target])

while (!openSet.isEmpty()) {
// Get the node in openSet with the lowest fScore
const current = openSet.dequeue()

// 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()
}

// Explore neighbors using destructuring for cleaner code
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

the "using destructuring for cleaner code part" is obvious

for (const [neighbor, weight] of graph[current]) {
const tentative_gScore = gScore[current] + weight

if (tentative_gScore < gScore[neighbor]) {
cameFrom[neighbor] = current
gScore[neighbor] = tentative_gScore
const priority =
gScore[neighbor] +
euclideanHeuristic(points[neighbor], points[target])
fScore[neighbor] = priority

openSet.enqueue(neighbor, priority)
}
}
}

return null // Return null if there's no path to the target
}

// Define the graph as an adjacency list
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

This should be a proper test case.

const graph = [
[
[1, 4],
[7, 8]
], // Node 0 connects to node 1 (weight 4), node 7 (weight 8)
[
[0, 4],
[2, 8],
[7, 11]
], // Node 1 connects to node 0, node 2, node 7
[
[1, 8],
[3, 7],
[5, 4],
[8, 2]
], // Node 2 connects to several nodes
[
[2, 7],
[4, 9],
[5, 14]
], // Node 3 connects to nodes 2, 4, 5
[
[3, 9],
[5, 10]
], // Node 4 connects to nodes 3 and 5
[
[2, 4],
[3, 14],
[4, 10],
[6, 2]
], // Node 5 connects to several nodes
[
[5, 2],
[7, 1],
[8, 6]
], // Node 6 connects to nodes 5, 7, 8
[
[0, 8],
[1, 11],
[6, 1],
[8, 7]
], // Node 7 connects to several nodes
[
[2, 2],
[6, 6],
[7, 7]
] // Node 8 connects to nodes 2, 6, 7
]

// Define 2D coordinates for each node (these can be changed based on actual node positions)
const points = [
[0, 0], // Point for node 0
[1, 2], // Point for node 1
[2, 1], // Point for node 2
[3, 5], // Point for node 3
[4, 3], // Point for node 4
[5, 6], // Point for node 5
[6, 8], // Point for node 6
[7, 10], // Point for node 7
[8, 12] // Point for node 8
]

// Call the aStar function with the graph, source node (0), and target node (4)
const path = aStar(graph, 0, 4, points)

console.log('Shortest path from node 0 to node 4:', path)

/**
* The function returns the optimal path from the source to the target node.
* The heuristic used is Euclidean distance between nodes' 2D coordinates.
*/

[8]ページ先頭

©2009-2025 Movatter.jp