bai2

Download as txt, pdf, or txt
Download as txt, pdf, or txt
You are on page 1of 2

from collections import deque

import itertools

class Graph:
def __init__(self, adjac_lis):
self.adjac_lis = adjac_lis
self.cities = list(adjac_lis.keys()) # List of cities

def get_neighbors(self, v):


return self.adjac_lis[v]

# This is the heuristic function, estimating the remaining cost


def h(self, visited_cities, current_city):
# Heuristic: The shortest possible edge from the current city to any
unvisited city.
unvisited_cities = [city for city in self.cities if city not in
visited_cities]
if not unvisited_cities:
return 0 # No cities left to visit, cost is 0
min_edge_cost = float('inf')
for city in unvisited_cities:
for neighbor, cost in self.get_neighbors(current_city):
if neighbor == city:
min_edge_cost = min(min_edge_cost, cost)
return min_edge_cost

def a_star_algorithm(self, start):


open_lst = set([(start, tuple([start]))]) # (city, visited_cities)
closed_lst = set() # (city, visited_cities)

# Holds the current distances from the start city to all other cities
poo = {}
poo[(start, tuple([start]))] = 0

# Parent mapping for reconstructing the path


par = {}
par[(start, tuple([start]))] = None

while open_lst:
# Find the node with the lowest f() = g() + h()
n = min(open_lst, key=lambda x: poo[x] + self.h(x[1], x[0]))

current_city, visited_cities = n

if len(visited_cities) == len(self.cities): # All cities visited


# Add the cost of returning to the start city
return_to_start_cost = next(
(cost for neighbor, cost in self.get_neighbors(current_city) if
neighbor == start), float('inf')
)
total_cost = poo[n] + return_to_start_cost

# Reconstruct the path


path = []
current = n
while current:
path.append(current[0])
current = par.get(current)
path.reverse()
# Add the starting city at the end to show the return
path.append(start)

print(f"Path found: {path} with cost: {total_cost}")


return path

# Remove n from open_lst and add it to closed_lst


open_lst.remove(n)
closed_lst.add(n)

# Explore neighbors
unvisited_cities = [city for city in self.cities if city not in
visited_cities]
for city in unvisited_cities:
new_visited_cities = tuple(sorted(visited_cities + (city,)))
new_cost = poo[n] + next(
cost for neighbor, cost in self.get_neighbors(current_city) if
neighbor == city
)

if (city, new_visited_cities) not in open_lst and (city,


new_visited_cities) not in closed_lst:
open_lst.add((city, new_visited_cities))
poo[(city, new_visited_cities)] = new_cost
par[(city, new_visited_cities)] = n

print("Path does not exist!")


return None

# Define the graph with adjacency list. Each node has a list of its neighbors and
the edge weights.
adjac_lis = {
'1': [('2', 10), ('3', 15), ('4', 20)],
'2': [('1', 10), ('3', 35), ('4', 25)],
'3': [('1', 15), ('2', 35), ('4', 30)],
'4': [('1', 20), ('2', 25), ('3', 30)],
}

# Create the graph object


graph = Graph(adjac_lis)

# Example: Find the shortest path visiting all cities starting from '1'
graph.a_star_algorithm('1')

You might also like