Made some changes to bidirectional. Among them added handling of directed graphs. Added some descriptive comments to dijkstra.
This commit is contained in:
parent
55f1ecc36c
commit
abb169a2f3
@ -2,7 +2,7 @@ def heuristic_cost(start, goal, graph):
|
|||||||
return 0
|
return 0
|
||||||
|
|
||||||
|
|
||||||
def bidirectional_algorithm(graph, point_set, start, goal, h=heuristic_cost):
|
def bidirectional_algorithm(graph, start, goal, h=heuristic_cost, is_directed=False):
|
||||||
def return_path_and_weight_front(c_f, c, s):
|
def return_path_and_weight_front(c_f, c, s):
|
||||||
current_node = c_f[c]
|
current_node = c_f[c]
|
||||||
shortest_path = [c, current_node]
|
shortest_path = [c, current_node]
|
||||||
@ -11,10 +11,13 @@ def bidirectional_algorithm(graph, point_set, start, goal, h=heuristic_cost):
|
|||||||
shortest_path.append(current_node)
|
shortest_path.append(current_node)
|
||||||
weight = 0
|
weight = 0
|
||||||
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 + 1], shortest_path[k])]
|
||||||
return shortest_path, weight
|
return shortest_path, weight
|
||||||
|
|
||||||
def return_path_and_weight_back(c_f, c, s):
|
def return_path_and_weight_back(c_f, c, s):
|
||||||
@ -26,27 +29,46 @@ def bidirectional_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 + 1], shortest_path[k])]
|
||||||
return shortest_path, weight
|
return shortest_path, weight
|
||||||
|
|
||||||
def return_path_and_weight_front_meet_back(c_f_f, c_f_b, c_f, s, g):
|
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_front, weight_front = return_path_and_weight_front(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, weight_back = return_path_and_weight_back(c_f_b, c_f, g)
|
||||||
shortest_path_back.reverse()
|
shortest_path_back.reverse()
|
||||||
|
shortest_path_front.reverse()
|
||||||
return shortest_path_front + shortest_path_back[1:], weight_front + weight_back
|
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):
|
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_front, weight_front = return_path_and_weight_front(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, weight_back = return_path_and_weight_back(c_f_b, c_b, g)
|
||||||
shortest_path_back.reverse()
|
shortest_path_back.reverse()
|
||||||
|
shortest_path_front.reverse()
|
||||||
return shortest_path_front + shortest_path_back[1:], weight_front + weight_back
|
return shortest_path_front + shortest_path_back[1:], weight_front + weight_back
|
||||||
|
|
||||||
for edge in graph.keys():
|
point_set_front = dict()
|
||||||
point_set[edge[0]].append(edge[1])
|
point_set_back = dict()
|
||||||
point_set[edge[1]].append(edge[0])
|
for arc in g.keys():
|
||||||
|
point_set_front[arc[0]] = []
|
||||||
|
point_set_front[arc[1]] = []
|
||||||
|
point_set_back[arc[0]] = []
|
||||||
|
point_set_back[arc[1]] = []
|
||||||
|
|
||||||
|
for arc in graph.keys():
|
||||||
|
point_set_front[arc[0]].append(arc[1])
|
||||||
|
if not is_directed:
|
||||||
|
point_set_back[arc[1]].append(arc[0])
|
||||||
|
point_set_front[arc[1]].append(arc[0])
|
||||||
|
point_set_back[arc[0]].append(arc[1])
|
||||||
|
else:
|
||||||
|
point_set_back[arc[1]].append(arc[0])
|
||||||
|
|
||||||
open_set_front = set()
|
open_set_front = set()
|
||||||
open_set_front.add(start)
|
open_set_front.add(start)
|
||||||
|
|
||||||
@ -56,16 +78,16 @@ def bidirectional_algorithm(graph, point_set, start, goal, h=heuristic_cost):
|
|||||||
came_from_front = {}
|
came_from_front = {}
|
||||||
came_from_back = {}
|
came_from_back = {}
|
||||||
|
|
||||||
g_score_front = {k: float('inf') for k in point_set.keys()}
|
g_score_front = {k: float('inf') for k in point_set_front.keys()}
|
||||||
g_score_front[start] = 0
|
g_score_front[start] = 0
|
||||||
|
|
||||||
g_score_back = {k: float('inf') for k in point_set.keys()}
|
g_score_back = {k: float('inf') for k in point_set_back.keys()}
|
||||||
g_score_back[goal] = 0
|
g_score_back[goal] = 0
|
||||||
|
|
||||||
f_score_front = {k: float('inf') for k in point_set.keys()}
|
f_score_front = {k: float('inf') for k in point_set_front.keys()}
|
||||||
f_score_front[start] = h(start, goal, graph)
|
f_score_front[start] = h(start, goal, graph)
|
||||||
|
|
||||||
f_score_back = {k: float('inf') for k in point_set.keys()}
|
f_score_back = {k: float('inf') for k in point_set_back.keys()}
|
||||||
f_score_back[goal] = h(goal, start, graph)
|
f_score_back[goal] = h(goal, start, graph)
|
||||||
|
|
||||||
while len(open_set_front) > 0 and len(open_set_back) > 0:
|
while len(open_set_front) > 0 and len(open_set_back) > 0:
|
||||||
@ -86,6 +108,15 @@ def bidirectional_algorithm(graph, point_set, start, goal, h=heuristic_cost):
|
|||||||
if current_back == start:
|
if current_back == start:
|
||||||
return return_path_and_weight_back(came_from_back, current_back, goal)
|
return return_path_and_weight_back(came_from_back, current_back, goal)
|
||||||
|
|
||||||
|
if current_front in came_from_back.keys() and current_back in came_from_front.keys():
|
||||||
|
path1, weight1 = return_path_and_weight_front_meet_back(came_from_front, came_from_back, current_front,
|
||||||
|
start, goal)
|
||||||
|
path2, weight2 = return_path_and_weight_back_meet_front(came_from_front, came_from_back, current_back,
|
||||||
|
start, goal)
|
||||||
|
if weight1 < weight2:
|
||||||
|
return path1, weight1
|
||||||
|
return path2, weight2
|
||||||
|
|
||||||
if current_front in came_from_back.keys():
|
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)
|
return return_path_and_weight_front_meet_back(came_from_front, came_from_back, current_front, start, goal)
|
||||||
|
|
||||||
@ -95,14 +126,16 @@ def bidirectional_algorithm(graph, point_set, start, goal, h=heuristic_cost):
|
|||||||
open_set_front.remove(current_front)
|
open_set_front.remove(current_front)
|
||||||
open_set_back.remove(current_back)
|
open_set_back.remove(current_back)
|
||||||
|
|
||||||
for neighbor in point_set[current_front]:
|
for neighbor in point_set_front[current_front]:
|
||||||
tentative_g_score = g_score_front[current_front]
|
tentative_g_score = g_score_front[current_front]
|
||||||
|
|
||||||
|
if not is_directed:
|
||||||
if current_front > neighbor:
|
if current_front > neighbor:
|
||||||
tentative_g_score += graph[(current_front, neighbor)]
|
tentative_g_score += graph[(current_front, neighbor)]
|
||||||
else:
|
else:
|
||||||
tentative_g_score += graph[(neighbor, current_front)]
|
tentative_g_score += graph[(neighbor, current_front)]
|
||||||
|
else:
|
||||||
|
tentative_g_score += graph[(current_front, neighbor)]
|
||||||
if tentative_g_score < g_score_front[neighbor]:
|
if tentative_g_score < g_score_front[neighbor]:
|
||||||
came_from_front[neighbor] = current_front
|
came_from_front[neighbor] = current_front
|
||||||
g_score_front[neighbor] = tentative_g_score
|
g_score_front[neighbor] = tentative_g_score
|
||||||
@ -110,14 +143,15 @@ def bidirectional_algorithm(graph, point_set, start, goal, h=heuristic_cost):
|
|||||||
if neighbor not in open_set_front:
|
if neighbor not in open_set_front:
|
||||||
open_set_front.add(neighbor)
|
open_set_front.add(neighbor)
|
||||||
|
|
||||||
for neighbor in point_set[current_back]:
|
for neighbor in point_set_back[current_back]:
|
||||||
tentative_g_score = g_score_back[current_back]
|
tentative_g_score = g_score_back[current_back]
|
||||||
|
if not is_directed:
|
||||||
if current_back > neighbor:
|
if current_back > neighbor:
|
||||||
tentative_g_score += graph[(current_back, neighbor)]
|
tentative_g_score += graph[(current_back, neighbor)]
|
||||||
else:
|
else:
|
||||||
tentative_g_score += graph[(neighbor, current_back)]
|
tentative_g_score += graph[(neighbor, current_back)]
|
||||||
|
else:
|
||||||
|
tentative_g_score += graph[(neighbor, current_back)]
|
||||||
if tentative_g_score < g_score_back[neighbor]:
|
if tentative_g_score < g_score_back[neighbor]:
|
||||||
came_from_back[neighbor] = current_back
|
came_from_back[neighbor] = current_back
|
||||||
g_score_back[neighbor] = tentative_g_score
|
g_score_back[neighbor] = tentative_g_score
|
||||||
@ -143,9 +177,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(bidirectional_algorithm(g, v, 7, 10, heuristic_cost))
|
print(bidirectional_algorithm(g, 7, 10, heuristic_cost))
|
||||||
|
print(bidirectional_algorithm(g2, 1, 4, heuristic_cost, is_directed=True))
|
||||||
|
print(bidirectional_algorithm(g2, 1, 5, heuristic_cost, is_directed=True))
|
||||||
|
@ -16,6 +16,7 @@ def dijkstra_algorithm(graph, start, goal, is_directed=False):
|
|||||||
# 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 = []
|
||||||
|
|
||||||
|
# dictionary for keeping neighbors of vertexes.
|
||||||
point_set = dict()
|
point_set = dict()
|
||||||
for arc in graph.keys():
|
for arc in graph.keys():
|
||||||
point_set[arc[0]] = []
|
point_set[arc[0]] = []
|
||||||
@ -27,19 +28,31 @@ def dijkstra_algorithm(graph, start, goal, is_directed=False):
|
|||||||
if not is_directed:
|
if not is_directed:
|
||||||
point_set[arc[1]].append(arc[0])
|
point_set[arc[1]].append(arc[0])
|
||||||
|
|
||||||
|
# initialization of needed lists
|
||||||
for vertex in point_set:
|
for vertex in point_set:
|
||||||
|
# setting distance of every vertex from the starting vertex to infinity
|
||||||
dist[vertex] = float('inf')
|
dist[vertex] = float('inf')
|
||||||
|
# setting previous vertex in currently found shortest path for every vertex to None
|
||||||
prev[vertex] = None
|
prev[vertex] = None
|
||||||
|
# setting flag for every vertex keeping track if it was already visited my the algorithm
|
||||||
visited[vertex] = False
|
visited[vertex] = False
|
||||||
|
|
||||||
|
# pushing start vertex to priority queue
|
||||||
heap.heappush(queue, (0, start))
|
heap.heappush(queue, (0, start))
|
||||||
|
# setting distance to start for start vertex to 0
|
||||||
dist[start] = 0
|
dist[start] = 0
|
||||||
|
# setting start vertex not to be added to priority queue again
|
||||||
visited[start] = True
|
visited[start] = True
|
||||||
|
|
||||||
|
# main loop
|
||||||
while len(queue) > 0:
|
while len(queue) > 0:
|
||||||
|
# getting first vertex from the priority queue and saving it in current variable
|
||||||
current = heap.heappop(queue)
|
current = heap.heappop(queue)
|
||||||
|
# iterating trough all neighbors of the current vertex
|
||||||
for neighbor in point_set[current[1]]:
|
for neighbor in point_set[current[1]]:
|
||||||
|
# initializing potential distance to be replaced with the current neighbors
|
||||||
new_dist = 0
|
new_dist = 0
|
||||||
|
#
|
||||||
if not is_directed:
|
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])]
|
||||||
@ -93,6 +106,5 @@ if __name__ == "__main__":
|
|||||||
(5, 3): 1
|
(5, 3): 1
|
||||||
}
|
}
|
||||||
|
|
||||||
print('')
|
|
||||||
print(dijkstra_algorithm(g, 7, 10))
|
print(dijkstra_algorithm(g, 7, 10))
|
||||||
print(dijkstra_algorithm(g2, 1, 5, is_directed=True))
|
print(dijkstra_algorithm(g2, 1, 5, is_directed=True))
|
||||||
|
Loading…
Reference in New Issue
Block a user