Added handing of directed graphs to a_star and dijkstra as well as to reading graphs from file.

This commit is contained in:
Bartosz 2022-01-15 14:29:52 +01:00
parent 8c680e235e
commit 55f1ecc36c
3 changed files with 63 additions and 31 deletions

View File

@ -2,7 +2,7 @@ def heuristic_cost(start, goal, graph):
return 0 return 0
def a_star_algorithm(graph, point_set, start, goal, h=heuristic_cost): def a_star_algorithm(graph, start, goal, h=heuristic_cost, is_directed=False):
def return_path_and_weight(c_f, c, s): def return_path_and_weight(c_f, c, s):
current_node = c_f[c] current_node = c_f[c]
shortest_path = [c, current_node] shortest_path = [c, current_node]
@ -12,15 +12,24 @@ def a_star_algorithm(graph, point_set, start, goal, h=heuristic_cost):
weight = 0 weight = 0
shortest_path.reverse() shortest_path.reverse()
for k in range(len(shortest_path) - 1): for k in range(len(shortest_path) - 1):
if not is_directed:
if shortest_path[k] > shortest_path[k+1]: if shortest_path[k] > shortest_path[k+1]:
weight += graph[(shortest_path[k], shortest_path[k+1])] weight += graph[(shortest_path[k], shortest_path[k+1])]
else: else:
weight += graph[(shortest_path[k + 1], shortest_path[k])] weight += graph[(shortest_path[k + 1], shortest_path[k])]
else:
weight += graph[(shortest_path[k], shortest_path[k + 1])]
return shortest_path, weight return shortest_path, weight
for edge in graph.keys(): point_set = dict()
point_set[edge[0]].append(edge[1]) for arc in g.keys():
point_set[edge[1]].append(edge[0]) point_set[arc[0]] = []
point_set[arc[1]] = []
for arc in graph.keys():
point_set[arc[0]].append(arc[1])
if not is_directed:
point_set[arc[1]].append(arc[0])
open_set = set() open_set = set()
open_set.add(start) open_set.add(start)
@ -43,10 +52,13 @@ def a_star_algorithm(graph, point_set, start, goal, h=heuristic_cost):
open_set.remove(current) open_set.remove(current)
for neighbor in point_set[current]: for neighbor in point_set[current]:
tentative_g_score = g_score[current] tentative_g_score = g_score[current]
if not is_directed:
if current > neighbor: if current > neighbor:
tentative_g_score += graph[(current, neighbor)] tentative_g_score += graph[(current, neighbor)]
else: else:
tentative_g_score += graph[(neighbor, current)] tentative_g_score += graph[(neighbor, current)]
else:
tentative_g_score += graph[(current, neighbor)]
if tentative_g_score < g_score[neighbor]: if tentative_g_score < g_score[neighbor]:
came_from[neighbor] = current came_from[neighbor] = current
g_score[neighbor] = tentative_g_score g_score[neighbor] = tentative_g_score
@ -72,9 +84,15 @@ if __name__ == "__main__":
(9, 1): 8 (9, 1): 8
} }
v = dict() g2 = {
for i in g.keys(): (4, 1): 6,
v[i[0]] = [] (1, 3): 4,
v[i[1]] = [] (1, 2): 2,
(2, 4): 5,
(3, 4): 1,
(5, 3): 1
}
print(a_star_algorithm(g, v, 7, 10, heuristic_cost)) print(a_star_algorithm(g, 7, 10, heuristic_cost))
print(a_star_algorithm(g2, 1, 4, heuristic_cost, is_directed=True))
print(a_star_algorithm(g2, 1, 5, heuristic_cost, is_directed=True))

View File

@ -3,7 +3,7 @@ import heapq as heap
# function which takes graph, vertex set, start and goal, uses djikstra algorithm to establish shortest paths from start # function which takes graph, vertex set, start and goal, uses djikstra algorithm to establish shortest paths from start
# every other vertex in graph and returns shortest path between start and goal # every other vertex in graph and returns shortest path between start and goal
def dijkstra_algorithm(graph, point_set, start, goal): def dijkstra_algorithm(graph, start, goal, is_directed=False):
# dictionary which will store for every vertex it's distance to start # dictionary which will store for every vertex it's distance to start
dist = dict() dist = dict()
@ -16,10 +16,16 @@ def dijkstra_algorithm(graph, point_set, start, goal):
# list which is used to keep priority queue with vertexes to be explored by the algorithm # list which is used to keep priority queue with vertexes to be explored by the algorithm
queue = [] queue = []
point_set = dict()
for arc in graph.keys():
point_set[arc[0]] = []
point_set[arc[1]] = []
# creating dictionary which for every vertex keeps all it's neighbors # creating dictionary which for every vertex keeps all it's neighbors
for edge in graph.keys(): for arc in graph.keys():
point_set[edge[0]].append(edge[1]) point_set[arc[0]].append(arc[1])
point_set[edge[1]].append(edge[0]) if not is_directed:
point_set[arc[1]].append(arc[0])
for vertex in point_set: for vertex in point_set:
dist[vertex] = float('inf') dist[vertex] = float('inf')
@ -34,11 +40,13 @@ def dijkstra_algorithm(graph, point_set, start, goal):
current = heap.heappop(queue) current = heap.heappop(queue)
for neighbor in point_set[current[1]]: for neighbor in point_set[current[1]]:
new_dist = 0 new_dist = 0
if not is_directed:
if neighbor > current[1]: if neighbor > current[1]:
new_dist = dist[current[1]] + graph[(neighbor, current[1])] new_dist = dist[current[1]] + graph[(neighbor, current[1])]
else: else:
new_dist = dist[current[1]] + graph[(current[1], neighbor)] new_dist = dist[current[1]] + graph[(current[1], neighbor)]
else:
new_dist = dist[current[1]] + graph[(current[1], neighbor)]
if new_dist < dist[neighbor]: if new_dist < dist[neighbor]:
dist[neighbor] = new_dist dist[neighbor] = new_dist
for k in range(len(queue)): for k in range(len(queue)):
@ -76,9 +84,15 @@ if __name__ == "__main__":
(9, 1): 8 (9, 1): 8
} }
v = dict() g2 = {
for i in g.keys(): (4, 1): 6,
v[i[0]] = [] (1, 3): 4,
v[i[1]] = [] (1, 2): 2,
(2, 4): 5,
(3, 4): 1,
(5, 3): 1
}
print(dijkstra_algorithm(g, v, 7, 10)) print('')
print(dijkstra_algorithm(g, 7, 10))
print(dijkstra_algorithm(g2, 1, 5, is_directed=True))