Skip to content
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

added a star #497

Merged
merged 1 commit into from
Feb 28, 2025
Merged
Show file tree
Hide file tree
Changes from all 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
41 changes: 41 additions & 0 deletions pysnippets/Path_Algoithms/a_star.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
from typing import Tuple, List, Dict
from heapq import heappop, heappush
import math
from data_classes import Graph
from logger_config import logger

def heuristic(node: Tuple[int, int], goal: Tuple[int, int]) -> float:
"""Euclidean distance heuristic."""
return math.sqrt((node[0] - goal[0])**2 + (node[1] - goal[1])**2)

def a_star(graph: Graph, start: Tuple[int, int], end: Tuple[int, int]) -> Tuple[List[Tuple[int, int]], float]:
try:
open_set = []
heappush(open_set, (0, start))
g_score: Dict[Tuple[int, int], float] = {vertex: float('inf') for vertex in graph.vertices}
g_score[start] = 0
came_from: Dict[Tuple[int, int], Tuple[int, int]] = {}

while open_set:
_, current = heappop(open_set)

if current == end:
path = []
while current in came_from:
path.insert(0, current)
current = came_from[current]
path.insert(0, start)
return path, g_score[end]

for neighbor, weight in graph.edges.get(current, {}).items():
tentative_g_score = g_score[current] + weight
if tentative_g_score < g_score[neighbor]:
g_score[neighbor] = tentative_g_score
f_score = tentative_g_score + heuristic(neighbor, end)
heappush(open_set, (f_score, neighbor))
came_from[neighbor] = current

raise ValueError("Path not found")
except Exception as e:
logger.error(f"Error in A* algorithm: {e}")
raise
49 changes: 49 additions & 0 deletions pysnippets/Path_Algoithms/test_a_star.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import unittest
from data_classes import Graph
from a_star import a_star
import sys
import os
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))
class TestAStar(unittest.TestCase):
def setUp(self):
vertices = {(0, 0), (1, 0), (1, 1), (2, 1), (2, 2)}
edges = {
(0, 0): {(1, 0): 1},
(1, 0): {(1, 1): 1, (0, 0): 1},
(1, 1): {(2, 1): 1, (1, 0): 1},
(2, 1): {(2, 2): 1, (1, 1): 1},
(2, 2): {(2, 1): 1}
}
self.graph = Graph(vertices, edges)
self.graph.vertices = {
(0, 0), (1, 0), (1, 1), (2, 1), (2, 2)
}
self.graph.edges = {
(0, 0): {(1, 0): 1},
(1, 0): {(1, 1): 1, (0, 0): 1},
(1, 1): {(2, 1): 1, (1, 0): 1},
(2, 1): {(2, 2): 1, (1, 1): 1},
(2, 2): {(2, 1): 1}
}

def test_valid_path(self):
path, cost = a_star(self.graph, (0, 0), (2, 2))
self.assertEqual(path, [(0, 0), (1, 0), (1, 1), (2, 1), (2, 2)])
self.assertEqual(cost, 4)

def test_no_path(self):
self.graph.edges = {
(0, 0): {(1, 0): 1},
(1, 0): {(0, 0): 1},
(2, 2): {} # Disconnected node
}
with self.assertRaises(ValueError):
a_star(self.graph, (0, 0), (2, 2))

def test_same_start_end(self):
path, cost = a_star(self.graph, (1, 1), (1, 1))
self.assertEqual(path, [(1, 1)])
self.assertEqual(cost, 0)

if __name__ == "__main__":
unittest.main()
Loading