Skip to content
This repository has been archived by the owner on Sep 21, 2021. It is now read-only.

Ids #2

Open
wants to merge 22 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added Alpha-Beta Pruning.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
16 changes: 10 additions & 6 deletions Projects/P1/a_star.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ def heuristic(self, coor_1, coor_2):
return abs(x1 - x2) + abs(y1 - y2)


def positioning(self, matrix, neighbor, robot, butters):
def positioning(self, matrix, neighbor, robot, butters, all_goals):
''' Repositions the Robot to push the Butter in desired direction '''

parent = neighbor.parent
Expand Down Expand Up @@ -53,14 +53,15 @@ def positioning(self, matrix, neighbor, robot, butters):
start = parent.positioning[-1],
goal = dest,
butters = butters,
all_goals = all_goals,
abundants = [parent.get_coor()]
) + [(parent.get_coor(), [])] # Add the parent node which robot will push

# Return final results
return [] if (len(path) == 0) else [node[0] for node in path]


def search(self, matrix, start, goal, butters, robot = None, abundants = []):
def search(self, matrix, start, goal, butters, all_goals, robot = None, abundants = []):
''' Core A* algorithm '''

graph = Graph(matrix)
Expand All @@ -70,6 +71,8 @@ def search(self, matrix, start, goal, butters, robot = None, abundants = []):
graph.abundant(abundants = butters, exceptions = [goal])
elif len(abundants) != 0:
graph.abundant(abundants = butters + abundants, exceptions = [])
else:
graph.abundant(abundants = butters, exceptions = [start])

# Convert coordinates to Node objects
start = Node(start, 0)
Expand Down Expand Up @@ -100,11 +103,11 @@ def search(self, matrix, start, goal, butters, robot = None, abundants = []):
if current.get_coor() == goal.get_coor():

# Backtrack the path
path = []
path = []
while current.parent is not None:
path.append((current.get_coor(), current.positioning))
current = current.parent

return [(start.get_coor(), start.positioning)] + path[::-1]

# Move current node from open set to closed set
Expand All @@ -131,15 +134,16 @@ def search(self, matrix, start, goal, butters, robot = None, abundants = []):
open_set.append(neighbor.get_coor()) # Add the neighbor to the frontier

# Set parent
neighbor.parent = current
neighbor.parent = current

# Trace robot if not None
if robot is not None:
neighbor.positioning = self.positioning(
matrix = matrix,
neighbor = neighbor,
robot = robot,
butters = butters
butters = butters,
all_goals = all_goals,
)

if len(neighbor.positioning) == 1:
Expand Down
254 changes: 254 additions & 0 deletions Projects/P1/bi_bfs.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,254 @@
# imports
from node import Node
from graph import Graph
import math
from a_star import Astar

class AdjacentNode:
''' AdjacentNode object '''

def __init__(self, vertex):
''' Constructor '''

self.vertex = vertex
self.next = None


class BI_BFS:
''' BI_BFS Object '''

def __init__(self):
''' Constructor '''

# Initialize vertices and graph with vertices
self.vertices = 100

# Dictionaries for paths of robot
self.src_robot_paths, self.dest_robot_paths = {}, {}


def positioning(self, matrix, neighbor, robot, butters, all_goals, parents, robot_paths):
''' Repositions the Robot to push the Butter in desired direction '''

parent = parents[neighbor.get_coor()]

# In case its the starting node
# if parent == -1: return []

parent = Node(parent, matrix[parent[0]][parent[1]])
butters = butters.copy()

# Calculate deltas
delta_x = neighbor.x - parent.x
delta_y = neighbor.y - parent.y

if delta_x == 0: # Horizontal
dest = (parent.x, parent.y + 1) if (delta_y < 0) else (parent.x, parent.y - 1)
else: # Vertical
dest = (parent.x + 1, parent.y) if (delta_x < 0) else (parent.x - 1, parent.y)

# If no previous positioning is available, then robot has not moved
if parent.get_coor() not in robot_paths:
robot_paths[parent.get_coor()] = [robot]

# Remove initial target butter location (IDK but it works)
for node in robot_paths[parent.get_coor()]:
try: butters.remove(node)
except: pass

# Get a path
astar = Astar()
# path = self.search(
path = astar.search(
matrix = matrix,
start = robot_paths[parent.get_coor()][-1],
goal = dest,
butters = butters,
all_goals = all_goals,
abundants = [parent.get_coor()]
) + [(parent.get_coor(), [])] # Add the parent node which robot will push

# Return final results
return [] if (len(path) == 0) else [node[0] for node in path]


# Function for adding undirected edge
def add_edge(self, src, dest):

node1 = AdjacentNode(dest)
self.graph[dest] = node1

node2 = AdjacentNode(src)
self.graph[src] = node2

node2.next = self.graph[dest]
node1.next = self.graph[src]


# Function for Breadth First Search
def bfs(self, graph, list_edges, queue, visited, parents, robot, all_goals, butters, robot_paths):
''' Core BFS algorithm '''

current = queue.pop(0) # Get current node

start = Node(current, 0)
for node in graph.get_neighbors(start, shuffle = False):
if (current, node.get_coor()) or (node.get_coor() , current) not in list_edges:
self.add_edge(current, node.get_coor())
list_edges.append((current, node.get_coor()))

# Traverse neighbors
connected_node = self.graph[current]
for node in graph.get_neighbors(start, shuffle = False):
vertex = node.get_coor()

if vertex not in visited:
queue.append(vertex)
visited[vertex] = True
parents[vertex] = current
else:
if not visited[vertex]:
queue.append(vertex)
visited[vertex] = True
parents[vertex] = current

if robot is not None:
robot_path = self.positioning(
matrix = graph.matrix,
neighbor = node,
robot = robot,
butters = butters,
all_goals = all_goals,
parents = parents,
robot_paths = robot_paths,
)


if len(robot_path) == 1:
continue

# print(start.get_coor(), node.get_coor(), robot_path)
robot_paths[node.get_coor()] = robot_path

connected_node = connected_node.next


# Check for intersecting vertex
def is_intersecting(self):

# Returns intersecting node if present else -1
for coor_1 in self.src_visited.keys():
for coor_2 in self.dest_visited.keys():
if (coor_1 == coor_2): return coor_1

return None


def search(self, matrix, start, goal, butters, all_goals, robot = None, abundants = []):
''' Core Bi-BFS algorithm '''

src, dest = start, goal

graph = Graph(matrix)
start = Node(src, 0)
goal = Node(dest, 0)
list_edges = []

self.graph = {}

# ONLY IF GOAL IS A BUTTER!
if goal in butters:
graph.abundant(abundants = butters, exceptions = [goal])
elif len(abundants) != 0:
graph.abundant(abundants = butters + abundants, exceptions = [])
else:
graph.abundant(abundants = butters, exceptions = [start])

# Initializing queue for forward and backward search
self.src_queue, self.dest_queue = list(), list()

# Initializing source and destination visited nodes as False
self.src_visited, self.dest_visited = {}, {}

# Initializing source and destination parent nodes
self.src_parents, self.dest_parents = {}, {}


def initialize(self, queue, visited, parent, node, coor):

# Append neighbors for source
for i in graph.get_neighbors(node):
if (coor, i.get_coor()) or (i.get_coor() , coor) not in list_edges:
self.add_edge(coor, i.get_coor())
list_edges.append((coor, i.get_coor()))

queue.append(coor)
visited[coor], parent[coor] = True, -1


# Initialzie start
initialize(self, self.src_queue, self.src_visited, self.src_parents, start, src)

# Initialzie goal
initialize(self, self.dest_queue, self.dest_visited, self.dest_parents, goal, dest)


while self.src_queue and self.dest_queue:

# BFS in forward direction from Source Vertex
self.bfs(
graph = graph,
list_edges = list_edges,
queue = self.src_queue,
visited = self.src_visited,
parents = self.src_parents,
robot = robot,
all_goals = all_goals,
butters = butters,
robot_paths = self.src_robot_paths,
)

# BFS in reverse direction from Destination Vertex
self.bfs(
graph = graph,
list_edges = list_edges,
queue = self.dest_queue,
visited = self.dest_visited,
parents = self.dest_parents,
robot = None,
all_goals = all_goals,
butters = butters,
robot_paths = self.dest_robot_paths,
)

# Check for intersecting vertex
intersecting_node = self.is_intersecting()

# If intersecting vertex exists then path from source to destination exists
if intersecting_node is not None:

path = []
node = intersecting_node

while node != start.get_coor():
robot_path = []
if robot is not None:
if node in self.src_robot_paths:
robot_path = self.src_robot_paths[node]
else:
return []

path.insert(0, (node, robot_path))
node = self.src_parents[node]

# Insert initial position
path.insert(0, (start.get_coor(), []))

node = intersecting_node
while node != goal.get_coor():
path.append((self.dest_parents[node], [self.dest_parents[node], node]))
node = self.dest_parents[node]

return path

return []
21 changes: 19 additions & 2 deletions Projects/P1/graph.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
# Imports
import random
from node import Node

class Graph:
''' Graph object '''

def __init__(self, matrix):
''' Constructor '''

self.graph = []
self.matrix = matrix.copy()

# Create graph with node objects
for i, row in enumerate(matrix):
Expand All @@ -21,9 +24,23 @@ def abundant(self, abundants, exceptions):
self.graph[node[0]][node[1]].g = -1


def get_neighbors(self, node):
def get_neighbors(self, node, shuffle = True):
''' Returns the neightbors of the given node '''
x, y = node.get_coor()
width, height = len(self.graph), len(self.graph[0])

return [self.graph[x + step[0]][y + step[1]] for step in [(-1,0), (1,0), (0,-1), (0,1)] if ((0 <= x + step[0] < width) and (0 <= y + step[1] < height) and self.graph[x + step[0]][y + step[1]].g != -1)]
neightbors = [self.graph[x + step[0]][y + step[1]] for step in [(-1,0), (1,0), (0,-1), (0,1)] if ((0 <= x + step[0] < width) and (0 <= y + step[1] < height) and self.graph[x + step[0]][y + step[1]].g != -1)]

# Shuffle
if shuffle: random.shuffle(neightbors)

return neightbors


def reset(self):
''' Resets all the parents for a new start '''

for i, row in enumerate(self.graph):
for j, col in enumerate(row):
self.graph[i][j].parent = None
self.graph[i][j].positioning = []
Loading