Changed dijkstra_algorithm a little. Added printout of the shortest path and weight in the a_star_algorithm. Added implementation of bidirectional algorithm. Still need good heuristic function for A* and bidirectional algorithms.

This commit is contained in:
Bartosz 2021-11-02 15:17:18 +01:00
parent 602b893f81
commit 85995b3d16
4 changed files with 184 additions and 4 deletions

View File

@ -3,23 +3,43 @@ def heuristic_cost(start, goal, graph):
def a_star_algorithm(graph, point_set, start, goal, h=heuristic_cost): def a_star_algorithm(graph, point_set, start, goal, h=heuristic_cost):
def return_path_and_weight(c_f, c, s):
current_node = c_f[c]
shortest_path = [c, current_node]
while current_node != s:
current_node = c_f[current_node]
shortest_path.append(current_node)
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])]
else:
weight += graph[(shortest_path[k + 1], shortest_path[k])]
return shortest_path, weight
for edge in graph.keys(): for edge in graph.keys():
point_set[edge[0]].append(edge[1]) point_set[edge[0]].append(edge[1])
point_set[edge[1]].append(edge[0]) point_set[edge[1]].append(edge[0])
open_set = set() open_set = set()
open_set.add(start) open_set.add(start)
came_from = {} came_from = {}
g_score = {k: float('inf') for k in point_set.keys()} g_score = {k: float('inf') for k in point_set.keys()}
g_score[start] = 0 g_score[start] = 0
f_score = {k: float('inf') for k in point_set.keys()} f_score = {k: float('inf') for k in point_set.keys()}
f_score[start] = h(start, goal, graph) f_score[start] = h(start, goal, graph)
while len(open_set) > 0: while len(open_set) > 0:
current = list(open_set)[0] current = list(open_set)[0]
for k in open_set: for k in open_set:
if f_score[k] < f_score[current]: if f_score[k] < f_score[current]:
current = k current = k
if current == goal: if current == goal:
return came_from, current return return_path_and_weight(came_from, current, start)
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]

View File

@ -0,0 +1,150 @@
def heuristic_cost(start, goal, graph):
return 0
def bidirectional_algorithm(graph, point_set, start, goal, h=heuristic_cost):
def return_path_and_weight_front(c_f, c, s):
current_node = c_f[c]
shortest_path = [c, current_node]
while current_node != s:
current_node = c_f[current_node]
shortest_path.append(current_node)
weight = 0
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])]
else:
weight += graph[(shortest_path[k + 1], shortest_path[k])]
return shortest_path, weight
def return_path_and_weight_back(c_f, c, s):
current_node = c_f[c]
shortest_path = [c, current_node]
while current_node != s:
current_node = c_f[current_node]
shortest_path.append(current_node)
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])]
else:
weight += graph[(shortest_path[k + 1], shortest_path[k])]
return shortest_path, weight
def return_path_and_weight_front_meet_back(c_f_f, c_f_b, c_f, s, g):
shortest_path_front, weight_front = return_path_and_weight_back(c_f_f, c_f, s)
shortest_path_back, weight_back = return_path_and_weight_back(c_f_b, c_f, g)
shortest_path_back.reverse()
return shortest_path_front + shortest_path_back[1:], weight_front + weight_back
def return_path_and_weight_back_meet_front(c_f_f, c_f_b, c_b, s, g):
shortest_path_front, weight_front = return_path_and_weight_back(c_f_f, c_b, s)
shortest_path_back, weight_back = return_path_and_weight_back(c_f_b, c_b, g)
shortest_path_back.reverse()
return shortest_path_front + shortest_path_back[1:], weight_front + weight_back
for edge in graph.keys():
point_set[edge[0]].append(edge[1])
point_set[edge[1]].append(edge[0])
open_set_front = set()
open_set_front.add(start)
open_set_back = set()
open_set_back.add(goal)
came_from_front = {}
came_from_back = {}
g_score_front = {k: float('inf') for k in point_set.keys()}
g_score_front[start] = 0
g_score_back = {k: float('inf') for k in point_set.keys()}
g_score_back[goal] = 0
f_score_front = {k: float('inf') for k in point_set.keys()}
f_score_front[start] = h(start, goal, graph)
f_score_back = {k: float('inf') for k in point_set.keys()}
f_score_back[goal] = h(goal, start, graph)
while len(open_set_front) > 0 and len(open_set_back) > 0:
current_front = list(open_set_front)[0]
current_back = list(open_set_back)[0]
for k in open_set_front:
if f_score_front[k] < f_score_front[current_front]:
current_front = k
for k in open_set_back:
if f_score_back[k] < f_score_back[current_back]:
current_back = k
if current_front == goal:
return return_path_and_weight_front(came_from_front, current_front, start)
if current_back == start:
return return_path_and_weight_back(came_from_back, current_back, goal)
if current_front in came_from_back.keys():
return return_path_and_weight_front_meet_back(came_from_front, came_from_back, current_front, start, goal)
if current_back in came_from_front.keys():
return return_path_and_weight_back_meet_front(came_from_front, came_from_back, current_back, start, goal)
open_set_front.remove(current_front)
open_set_back.remove(current_back)
for neighbor in point_set[current_front]:
tentative_g_score = g_score_front[current_front]
if current_front > neighbor:
tentative_g_score += graph[(current_front, neighbor)]
else:
tentative_g_score += graph[(neighbor, current_front)]
if tentative_g_score < g_score_front[neighbor]:
came_from_front[neighbor] = current_front
g_score_front[neighbor] = tentative_g_score
f_score_front[neighbor] = g_score_front[neighbor] + h(neighbor, goal, graph)
if neighbor not in open_set_front:
open_set_front.add(neighbor)
for neighbor in point_set[current_back]:
tentative_g_score = g_score_back[current_back]
if current_back > neighbor:
tentative_g_score += graph[(current_back, neighbor)]
else:
tentative_g_score += graph[(neighbor, current_back)]
if tentative_g_score < g_score_back[neighbor]:
came_from_back[neighbor] = current_back
g_score_back[neighbor] = tentative_g_score
f_score_back[neighbor] = g_score_back[neighbor] + h(neighbor, goal, graph)
if neighbor not in open_set_back:
open_set_back.add(neighbor)
if __name__ == "__main__":
g = {
(2, 1): 3,
(3, 2): 2,
(5, 3): 1,
(9, 5): 5,
(10, 9): 4,
(9, 4): 3,
(4, 1): 4,
(7, 1): 6,
(3, 1): 4,
(6, 2): 3,
(8, 6): 8,
(8, 3): 2
}
v = dict()
for i in g.keys():
v[i[0]] = []
v[i[1]] = []
print(bidirectional_algorithm(g, v, 7, 8, heuristic_cost))

View File

@ -26,8 +26,8 @@ def dijkstra_algorithm(graph, point_set, start, goal):
prev[vertex] = None prev[vertex] = None
visited[vertex] = False visited[vertex] = False
dist[start] = 0
heap.heappush(queue, (0, start)) heap.heappush(queue, (0, start))
dist[start] = 0
visited[start] = True visited[start] = True
while len(queue) > 0: while len(queue) > 0:
@ -41,6 +41,10 @@ def dijkstra_algorithm(graph, point_set, start, goal):
if new_dist < dist[neighbor]: if new_dist < dist[neighbor]:
dist[neighbor] = new_dist dist[neighbor] = new_dist
for k in range(len(queue)):
if queue[k][1] == neighbor:
queue[k] = (new_dist, neighbor)
heap.heapify(queue)
prev[neighbor] = current[1] prev[neighbor] = current[1]
if not visited[neighbor]: if not visited[neighbor]:
@ -51,6 +55,7 @@ def dijkstra_algorithm(graph, point_set, start, goal):
while prev[temp] is not None: while prev[temp] is not None:
shortest_path.append(prev[temp]) shortest_path.append(prev[temp])
temp = prev[temp] temp = prev[temp]
shortest_path.reverse()
return shortest_path, dist[goal] return shortest_path, dist[goal]
@ -67,7 +72,8 @@ if __name__ == "__main__":
(3, 1): 4, (3, 1): 4,
(6, 2): 3, (6, 2): 3,
(8, 6): 8, (8, 6): 8,
(8, 3): 2 (8, 3): 2,
(9, 1): 8
} }
v = dict() v = dict()

View File

@ -1,5 +1,7 @@
import tools.file_service as op_file import tools.file_service as op_file
import algorithms.dijkstra as dijkstra import algorithms.dijkstra as dijkstra
import algorithms.a_star as a_star
import algorithms.bidirectional as bidirectional
if __name__ == '__main__': if __name__ == '__main__':
g = op_file.read_graph_from_file("dataset/deezer_clean_data/HR_edgeswith_weight.csv", has_weight=True) g = op_file.read_graph_from_file("dataset/deezer_clean_data/HR_edgeswith_weight.csv", has_weight=True)
@ -8,4 +10,6 @@ if __name__ == '__main__':
v[i[0]] = [] v[i[0]] = []
v[i[1]] = [] v[i[1]] = []
print(dijkstra.dijkstra_algorithm(g, v, 0, 4)) # print(dijkstra.dijkstra_algorithm(g, v, 0, 4))
# print(a_star.a_star_algorithm(g, v, 0, 4))
# print(bidirectional.bidirectional_algorithm(g, v, 0, 4))