implemented graphsearch

Co-authored-by: Sebastian Piotrowski <sebpio@st.amu.edu.pl>
Co-authored-by: Ladislaus3III <Ladislaus3III@users.noreply.github.com>
This commit is contained in:
eugenep 2021-04-14 03:55:35 +02:00
parent e4c3814d41
commit 5c48777709
5 changed files with 104 additions and 39 deletions

3
.vscode/settings.json vendored Normal file
View File

@ -0,0 +1,3 @@
{
"python.pythonPath": "C:\\Users\\ryodenshi\\AppData\\Local\\Programs\\Python\\Python39\\python.exe"
}

View File

@ -5,4 +5,3 @@
...###. ...###.
...#^#. ...#^#.
....... .......

View File

@ -2,6 +2,7 @@ import sys
from collections import deque from collections import deque
from os import path from os import path
import queue import queue
import numpy
from utils import * from utils import *
from settings import * from settings import *
@ -13,7 +14,7 @@ class Problem:
__init__, goal_test, and path_cost. Then you will create instances __init__, goal_test, and path_cost. Then you will create instances
of your subclass and solve them with the various search functions.""" of your subclass and solve them with the various search functions."""
def __init__(self, initial=[], goal=[]): def __init__(self, initial, goal):
"""The constructor specifies the initial state, and possibly a goal """The constructor specifies the initial state, and possibly a goal
state, if there is a unique goal. Your subclass's constructor can add state, if there is a unique goal. Your subclass's constructor can add
other arguments.""" other arguments."""
@ -27,14 +28,14 @@ class Problem:
iterator, rather than building them all at once.""" iterator, rather than building them all at once."""
moves = [] moves = []
if self.turn_left(self, state): if self.turn_left(state):
moves.append('Left') moves.append('Left')
if self.turn_right(self, state): if self.turn_right(state):
moves.append('Right') moves.append('Right')
if self.move_forward(self, state): if self.move_forward(state):
moves.append('Forward') moves.append('Forward')
print(moves) #print(moves)
return moves return moves
@ -90,55 +91,65 @@ class Problem:
return False return False
def turn_me_or_move(self, state, do_it): def turn_me_or_move(self, state, do_it):
a_row = 0
a_column = 0 temp_map = [list(item) for item in state]
#print(temp_map)
#a_row = 0
#a_column = 0
for row in range(MAP_SIZE): for row in range(MAP_SIZE):
for column, pos in enumerate(state[row]): for column, pos in enumerate(temp_map[row]):
if pos == ">": if pos == ">":
a_row = row a_row = row
a_column = column a_column = column
#print("a_row:" + str(a_row))
#print("a_column" + str(a_column))
if(do_it == 'Left'): if(do_it == 'Left'):
state[a_row][a_column] = '^' temp_map[a_row][a_column] = "^"
if(do_it == 'Right'): if(do_it == 'Right'):
state[a_row][a_column] = 'v' temp_map[a_row][a_column] = 'v'
if(do_it == 'Forward'): if(do_it == 'Forward'):
state[a_row][a_column] = '.' temp_map[a_row][a_column] = '.'
state[a_row][a_column+1] = '>' temp_map[a_row][a_column+1] = '>'
return temp_map
if pos == "<": if pos == "<":
a_row = row a_row = row
a_column = column a_column = column
if(do_it == 'Left'): if(do_it == 'Left'):
state[a_row][a_column] = 'v' temp_map[a_row][a_column] = 'v'
if(do_it == 'Right'): if(do_it == 'Right'):
state[a_row][a_column] = '^' temp_map[a_row][a_column] = '^'
if(do_it == 'Forward'): if(do_it == 'Forward'):
state[a_row][a_column] = '.' temp_map[a_row][a_column] = '.'
state[a_row][a_column-1] = '<' temp_map[a_row][a_column-1] = '<'
return temp_map
if pos == "v": if pos == "v":
a_row = row a_row = row
a_column = column a_column = column
if(do_it == 'Left'): if(do_it == 'Left'):
state[a_row][a_column] = '>' temp_map[a_row][a_column] = '>'
if(do_it == 'Right'): if(do_it == 'Right'):
state[a_row][a_column] = '<' temp_map[a_row][a_column] = '<'
if(do_it == 'Forward'): if(do_it == 'Forward'):
state[a_row][a_column] = '.' temp_map[a_row][a_column] = '.'
state[a_row+1][a_column] = 'v' temp_map[a_row+1][a_column] = 'v'
return temp_map
if pos == "^": if pos == "^":
a_row = row a_row = row
a_column = column a_column = column
if(do_it == 'Left'): if(do_it == 'Left'):
state[a_row][a_column] = '<' temp_map[a_row][a_column] = '<'
if(do_it == 'Right'): if(do_it == 'Right'):
state[a_row][a_column] = '>' temp_map[a_row][a_column] = '>'
if(do_it == 'Forward'): if(do_it == 'Forward'):
state[a_row][a_column] = '.' temp_map[a_row][a_column] = '.'
state[a_row-1][a_column] = '^' temp_map[a_row-1][a_column] = '^'
return state return temp_map
return temp_map
def result(self, state, action): def result(self, state, action):
"""Return the state that results from executing the given """Return the state that results from executing the given
@ -153,17 +164,30 @@ class Problem:
elif action == 'Forward': elif action == 'Forward':
new_state = self.turn_me_or_move(state, 'Forward') new_state = self.turn_me_or_move(state, 'Forward')
return new_state super_new_state = tuple(map(tuple,new_state))
return super_new_state
def goal_test(self, state): def goal_test(self, state):
"""Return True if the state is a goal. The default method compares the """Return True if the state is a goal. The default method compares the
state to self.goal or checks for state in self.goal if it is a state to self.goal or checks for state in self.goal if it is a
list, as specified in the constructor. Override this method if list, as specified in the constructor. Override this method if
checking against a single self.goal is not enough.""" checking against a single self.goal is not enough."""
if isinstance(self.goal, list):
"""if isinstance(self.goal, list):
return is_in(state, self.goal) return is_in(state, self.goal)
else: else:
return state == self.goal return state == self.goal"""
if self.goal == state:
return True
return False
@ -186,6 +210,9 @@ class Node:
self.parent = parent self.parent = parent
self.action = action self.action = action
def __repr__(self):
return "<Node {}>".format(self.state)
def expand(self, problem): def expand(self, problem):
"""List the nodes reachable in one step from this node.""" """List the nodes reachable in one step from this node."""
return [self.child_node(problem, action) return [self.child_node(problem, action)
@ -196,6 +223,16 @@ class Node:
next_node = Node(next_state, self, action) next_node = Node(next_state, self, action)
return next_node return next_node
def __eq__(self, other):
return isinstance(other, Node) and self.state == other.state
def __hash__(self):
# We use the hash value of the state
# stored in the node instead of the node
# object itself to quickly search a node
# with the same state in a Hash Table
return hash(self.state)
class BFS: class BFS:
@ -211,6 +248,8 @@ class BFS:
if problem.goal_test(node.state): if problem.goal_test(node.state):
return node return node
frontier = deque([node]) frontier = deque([node])
final_child = node
history = []
explored = set() explored = set()
while frontier: while frontier:
node = frontier.popleft() node = frontier.popleft()
@ -218,8 +257,16 @@ class BFS:
for child in node.expand(problem): for child in node.expand(problem):
if child.state not in explored and child not in frontier: if child.state not in explored and child not in frontier:
if problem.goal_test(child.state): if problem.goal_test(child.state):
return child while(child.parent != None):
history.append(child.action)
child = child.parent
#return child
history.reverse()
#print(history)
return history
frontier.append(child) frontier.append(child)
#BFS.print_node_state(child.state)
return None return None
@staticmethod @staticmethod
@ -228,16 +275,26 @@ class BFS:
map_folder = path.dirname(__file__) map_folder = path.dirname(__file__)
with open(path.join(map_folder, map_name), 'rt') as f: with open(path.join(map_folder, map_name), 'rt') as f:
for line in f: for line in f:
maze.append(line) maze.append(line.rstrip('\n'))
#print(maze)
return maze return maze
@staticmethod @staticmethod
def run(): def run():
initial_map = BFS.loadMap('map.txt') initial_map = tuple(map(tuple,BFS.loadMap('map.txt')))
goal_map = BFS.loadMap('goal_map.txt') goal_map = tuple(map(tuple,BFS.loadMap('goal_map.txt')))
problem = Problem(initial_map, goal_map) problem = Problem(initial_map, goal_map)
#BFS.print_node_state(initial_map)
#BFS.print_node_state(goal_map)
result = BFS.breadth_first_graph_search(problem) result = BFS.breadth_first_graph_search(problem)
print(result) print(result)
#return result
#print(BFS.print_node_state(result))
@staticmethod
def print_node_state(node_state):
print(numpy.matrix(node_state))

View File

@ -42,7 +42,13 @@ class Game:
Grenade(self, col, row) Grenade(self, col, row)
if tile == "#": if tile == "#":
Wall(self, col, row) Wall(self, col, row)
if tile == 'A': if tile == '>':
self.player = Player(self, col, row)
if tile == '^':
self.player = Player(self, col, row)
if tile == '<':
self.player = Player(self, col, row)
if tile == 'v':
self.player = Player(self, col, row) self.player = Player(self, col, row)

View File

@ -1,5 +1,5 @@
.>..... .>.....
#.#.... ###....
....... .......
....... .......
...###. ...###.