mirror of
https://github.com/TheAlgorithms/Python.git
synced 2025-02-25 10:28:39 +00:00
Added uniform cost search algorithm for 2D grid based environment. There are start point, end point and a 20x20 grid for testing the UCS code.
This commit is contained in:
parent
23184249da
commit
dcecedc2fe
228
graphs/uniform_search_cost.py
Normal file
228
graphs/uniform_search_cost.py
Normal file
@ -0,0 +1,228 @@
|
||||
from typing import List
|
||||
import heapq
|
||||
from copy import deepcopy
|
||||
|
||||
|
||||
class UniformCostSearch:
|
||||
def __init__(self, current, final, grid):
|
||||
self.m = len(grid[0])
|
||||
self.n = len(grid)
|
||||
|
||||
# diagonal clockwise
|
||||
dxy1 = [
|
||||
(1, 1),
|
||||
(1, 0),
|
||||
(1, -1),
|
||||
(0, -1),
|
||||
(-1, -1),
|
||||
(-1, 0),
|
||||
(-1, 1),
|
||||
(0, 1),
|
||||
]
|
||||
# diagonal anti-clockwise
|
||||
dxy2 = [
|
||||
(-1, -1),
|
||||
(-1, 0),
|
||||
(0, -1),
|
||||
(0, 1),
|
||||
(1, 1),
|
||||
(1, 0),
|
||||
(1, -1),
|
||||
(-1, 1),
|
||||
]
|
||||
|
||||
# start point and end point on same row and column right side
|
||||
dxy3 = [
|
||||
(0, -1),
|
||||
(-1, -1),
|
||||
(-1, 0),
|
||||
(0, 1),
|
||||
(1, 1),
|
||||
(1, 0),
|
||||
(1, -1),
|
||||
(-1, 1),
|
||||
]
|
||||
# start point and end point on same row and column left side
|
||||
dxy4 = [
|
||||
(0, 1),
|
||||
(1, 1),
|
||||
(1, 0),
|
||||
(1, -1),
|
||||
(0, -1),
|
||||
(-1, -1),
|
||||
(-1, 0),
|
||||
(-1, 1),
|
||||
]
|
||||
# start point and end point on same column and row down side
|
||||
dxy5 = [
|
||||
(1, 0),
|
||||
(0, 1),
|
||||
(1, 1),
|
||||
(1, -1),
|
||||
(0, -1),
|
||||
(-1, -1),
|
||||
(-1, 0),
|
||||
(-1, 1),
|
||||
]
|
||||
# start point and end point on same column and row up side
|
||||
dxy6 = [
|
||||
(0, -1),
|
||||
(0, 1),
|
||||
(1, 1),
|
||||
(1, 0),
|
||||
(1, -1),
|
||||
(-1, -1),
|
||||
(-1, 0),
|
||||
(-1, 1),
|
||||
]
|
||||
|
||||
def get_shortest_path(self, start, end, dist, dxy):
|
||||
shortest_path = []
|
||||
curr_node = end
|
||||
while curr_node != start:
|
||||
shortest_path.append(curr_node)
|
||||
row, col = curr_node
|
||||
min_cell = float("inf")
|
||||
next_cell = None
|
||||
for dr, dc in dxy:
|
||||
if (
|
||||
0 <= row + dr < self.m
|
||||
and 0 <= col + dc < self.n
|
||||
and [row + dr, col + dc] not in shortest_path
|
||||
):
|
||||
if dist[row + dr][col + dc] <= min_cell:
|
||||
min_cell = dist[row + dr][col + dc]
|
||||
next_cell = [row + dr, col + dc]
|
||||
curr_node = next_cell
|
||||
shortest_path.append(start)
|
||||
return shortest_path
|
||||
|
||||
def ucs(self, current, final, grid, prev, dxy, goal_answer):
|
||||
dist = [[float("inf") for _ in range(self.m)] for _ in range(self.n)]
|
||||
visited = [[0 for _ in range(self.m)] for _ in range(self.n)]
|
||||
|
||||
x = current[0]
|
||||
y = current[1]
|
||||
dist[x][y] = 0
|
||||
final_cnt = 0
|
||||
heap = [(0, x, y)]
|
||||
while heap:
|
||||
d, x, y = heapq.heappop(heap)
|
||||
if visited[x][y]:
|
||||
continue
|
||||
visited[x][y] = 1
|
||||
if [x, y] in final:
|
||||
idxs = [ix for ix, iy in enumerate(final) if iy == [x, y]]
|
||||
if len(idxs) > 1:
|
||||
return None
|
||||
if goal_answer[idxs[0]] == 10**8:
|
||||
final_cnt += 1
|
||||
if goal_answer[idxs[0]] > d:
|
||||
goal_answer[idxs[0]] = d
|
||||
if final_cnt == len(final):
|
||||
path = self.get_shortest_path(current, final[0], dist, dxy)
|
||||
return path
|
||||
for dx, dy in dxy:
|
||||
if (
|
||||
0 <= x + dx < self.m
|
||||
and 0 <= y + dy < self.n
|
||||
and grid[x + dx][y + dy] != 1
|
||||
):
|
||||
weight = 1
|
||||
diagonal_weight = 1.414
|
||||
if (
|
||||
(dx == -1 and dy == -1)
|
||||
or (dx == 1 and dy == 1)
|
||||
or (dx == 1 and dy == -1)
|
||||
or (dx == -1 and dy == 1)
|
||||
):
|
||||
new_dist = d + diagonal_weight
|
||||
else:
|
||||
new_dist = d + weight
|
||||
if new_dist < dist[x + dx][y + dy]:
|
||||
dist[x + dx][y + dy] = new_dist
|
||||
prev[x + dx][y + dy] = (x, y)
|
||||
heapq.heappush(heap, (new_dist, x + dx, y + dy))
|
||||
|
||||
def your_algorithm(
|
||||
self, start_point: List[int], end_point: List[int], grid: List[List[int]]
|
||||
) -> List[int]:
|
||||
prev = [[None for _ in range(self.m)] for _ in range(self.n)]
|
||||
dxy = []
|
||||
if start_point[1] - end_point[1] == 0 and start_point[0] - end_point[0] < 0:
|
||||
dxy = self.dxy5
|
||||
elif start_point[1] - end_point[1] == 0 and start_point[0] - end_point[0] > 0:
|
||||
dxy = self.dxy6
|
||||
elif start_point[0] - end_point[0] == 0 and start_point[1] - end_point[1] < 0:
|
||||
dxy = self.dxy4
|
||||
elif start_point[0] - end_point[0] == 0 and start_point[1] - end_point[1] > 0:
|
||||
dxy = self.dxy3
|
||||
elif start_point[0] - end_point[0] > 0:
|
||||
dxy = self.dxy2
|
||||
elif start_point[0] - end_point[0] < 0:
|
||||
dxy = self.dxy1
|
||||
goal_answer = []
|
||||
for cell in end_point:
|
||||
goal_answer.append(10**8)
|
||||
path = self.ucs(start_point, [end_point], grid, prev, dxy, goal_answer)
|
||||
return path
|
||||
|
||||
|
||||
def run():
|
||||
executed_object = UniformCostSearch(
|
||||
[0, 7],
|
||||
[19, 17],
|
||||
[
|
||||
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
[0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0],
|
||||
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0],
|
||||
[0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0],
|
||||
[0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0],
|
||||
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0],
|
||||
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0],
|
||||
[0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0],
|
||||
[0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
[0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
[0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
[0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0],
|
||||
[0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
[0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
[0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
[0, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
[0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
],
|
||||
)
|
||||
path_result = executed_object.your_algorithm(
|
||||
[0, 7],
|
||||
[19, 17],
|
||||
[
|
||||
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
[0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0],
|
||||
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0],
|
||||
[0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0],
|
||||
[0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0],
|
||||
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0],
|
||||
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0],
|
||||
[0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0],
|
||||
[0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
[0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
[0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
[0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0],
|
||||
[0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
[0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
[0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
[0, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
[0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
],
|
||||
)
|
||||
print(path_result)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
run()
|
Loading…
x
Reference in New Issue
Block a user