From 55f1ecc36ce709680107e19e6ef33e397a6339e3 Mon Sep 17 00:00:00 2001 From: Bartosz Date: Sat, 15 Jan 2022 14:29:52 +0100 Subject: [PATCH] Added handing of directed graphs to a_star and dijkstra as well as to reading graphs from file. --- algorithms/a_star.py | 48 +++++++++++++++++++++++++++++------------- algorithms/dijkstra.py | 38 ++++++++++++++++++++++----------- tools/file_service.py | 8 +++---- 3 files changed, 63 insertions(+), 31 deletions(-) diff --git a/algorithms/a_star.py b/algorithms/a_star.py index 073bfdc..0920a22 100644 --- a/algorithms/a_star.py +++ b/algorithms/a_star.py @@ -2,7 +2,7 @@ def heuristic_cost(start, goal, graph): 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): current_node = c_f[c] shortest_path = [c, current_node] @@ -12,15 +12,24 @@ def a_star_algorithm(graph, point_set, start, goal, h=heuristic_cost): weight = 0 shortest_path.reverse() for k in range(len(shortest_path) - 1): - if shortest_path[k] > shortest_path[k+1]: - weight += graph[(shortest_path[k], shortest_path[k+1])] + if not is_directed: + if shortest_path[k] > shortest_path[k+1]: + weight += graph[(shortest_path[k], shortest_path[k+1])] + else: + weight += graph[(shortest_path[k + 1], shortest_path[k])] else: - weight += graph[(shortest_path[k + 1], shortest_path[k])] + weight += graph[(shortest_path[k], shortest_path[k + 1])] return shortest_path, weight - for edge in graph.keys(): - point_set[edge[0]].append(edge[1]) - point_set[edge[1]].append(edge[0]) + point_set = dict() + for arc in g.keys(): + 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.add(start) @@ -43,10 +52,13 @@ def a_star_algorithm(graph, point_set, start, goal, h=heuristic_cost): open_set.remove(current) for neighbor in point_set[current]: tentative_g_score = g_score[current] - if current > neighbor: - tentative_g_score += graph[(current, neighbor)] + if not is_directed: + if current > neighbor: + tentative_g_score += graph[(current, neighbor)] + else: + tentative_g_score += graph[(neighbor, current)] else: - tentative_g_score += graph[(neighbor, current)] + tentative_g_score += graph[(current, neighbor)] if tentative_g_score < g_score[neighbor]: came_from[neighbor] = current g_score[neighbor] = tentative_g_score @@ -72,9 +84,15 @@ if __name__ == "__main__": (9, 1): 8 } - v = dict() - for i in g.keys(): - v[i[0]] = [] - v[i[1]] = [] + g2 = { + (4, 1): 6, + (1, 3): 4, + (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)) diff --git a/algorithms/dijkstra.py b/algorithms/dijkstra.py index ca7681c..ec117cf 100644 --- a/algorithms/dijkstra.py +++ b/algorithms/dijkstra.py @@ -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 # 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 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 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 - for edge in graph.keys(): - point_set[edge[0]].append(edge[1]) - point_set[edge[1]].append(edge[0]) + for arc in graph.keys(): + point_set[arc[0]].append(arc[1]) + if not is_directed: + point_set[arc[1]].append(arc[0]) for vertex in point_set: dist[vertex] = float('inf') @@ -34,11 +40,13 @@ def dijkstra_algorithm(graph, point_set, start, goal): current = heap.heappop(queue) for neighbor in point_set[current[1]]: new_dist = 0 - if neighbor > current[1]: - new_dist = dist[current[1]] + graph[(neighbor, current[1])] + if not is_directed: + if neighbor > current[1]: + new_dist = dist[current[1]] + graph[(neighbor, current[1])] + else: + new_dist = dist[current[1]] + graph[(current[1], neighbor)] else: new_dist = dist[current[1]] + graph[(current[1], neighbor)] - if new_dist < dist[neighbor]: dist[neighbor] = new_dist for k in range(len(queue)): @@ -76,9 +84,15 @@ if __name__ == "__main__": (9, 1): 8 } - v = dict() - for i in g.keys(): - v[i[0]] = [] - v[i[1]] = [] + g2 = { + (4, 1): 6, + (1, 3): 4, + (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)) diff --git a/tools/file_service.py b/tools/file_service.py index b8cec19..d45b896 100644 --- a/tools/file_service.py +++ b/tools/file_service.py @@ -15,10 +15,10 @@ def read_graph_from_file(path, separator=",", read_first_line=False, is_directed if not is_directed: if node1 < node2: node1, node2 = node2, node1 - if not has_weight: - edges[(node1, node2)] = 1 - else: - edges[(node1, node2)] = int(split[2]) + if not has_weight: + edges[(node1, node2)] = 1 + else: + edges[(node1, node2)] = int(split[2]) else: read_line = True line = file.readline()