AI_PRO/Graphsearch.py

175 lines
5.1 KiB
Python

from operator import itemgetter
import constants
class Istate:
def __init__(self, direction, horizontal_index, vertical_index):
self.__direction = direction
self.__horizontal_index = horizontal_index
self.__vertical_index = vertical_index
@property
def direction(self):
return self.__direction
@property
def horizontal_index(self):
return self.__horizontal_index
@property
def vertical_index(self):
return self.__vertical_index
class Node:
def __init__(self, action, direction, parent, horizontal_index, vertical_index):
self.__action = action
self.__direction = direction
self.__parent = parent
self.__horizontal_index = horizontal_index
self.__vertical_index = vertical_index
@property
def action(self):
return self.__action
@property
def direction(self):
return self.__direction
@property
def parent(self):
return self.__parent
@property
def horizontal_index(self):
return self.__horizontal_index
@property
def vertical_index(self):
return self.__vertical_index
def goal_test(elem, goaltest):
if elem.horizontal_index == goaltest[0] and elem.vertical_index == goaltest[1]:
return True
else:
# print("Traktor wartosc horizontal_index: ", elem.horizontal_index)
# print("Traktor wartosc vertical_index: ", elem.vertical_index)
return False
def print_moves(elem):
moves_list = []
while elem.parent is not None:
moves_list.append(elem.action)
elem = elem.parent
moves_list.reverse()
return moves_list
def cost(board, node):
cost_value = 0
while node.parent is not None:
field = board[node.horizontal_index][node.vertical_index]
cost_value = cost_value + field.cost + 1
node = node.parent
return cost_value
def heuristic(node, goaltest):
return abs(node.horizontal_index - goaltest[0]) + abs(node.vertical_index - goaltest[1])
def f(board, node, goaltest):
cost_value = cost(board, node)
return cost_value + heuristic(node, goaltest)
def succ(elem):
actions_list = []
direction = elem.direction
if direction == "UP":
direction = "RIGHT"
elif direction == "RIGHT":
direction = "DOWN"
elif direction == "DOWN":
direction = "LEFT"
elif direction == "LEFT":
direction = "UP"
actions_list.append(("Right_Rotation", (direction, elem.horizontal_index, elem.vertical_index)))
direction = elem.direction
if direction == "UP":
direction = "LEFT"
elif direction == "LEFT":
direction = "DOWN"
elif direction == "DOWN":
direction = "RIGHT"
elif direction == "RIGHT":
direction = "UP"
actions_list.append(("Left_Rotation", (direction, elem.horizontal_index, elem.vertical_index)))
horizontal_change = 0
vertical_change = 0
if elem.direction == "RIGHT" and elem.horizontal_index < constants.HORIZONTAL_TILES_NUMBER - 1:
horizontal_change = 1
elif elem.direction == "LEFT" and elem.horizontal_index > 0:
horizontal_change = -1
elif elem.direction == "UP" and elem.vertical_index > 0:
vertical_change = -1
elif elem.direction == "DOWN" and elem.vertical_index < constants.VERTICAL_TILES_NUMBER - 1:
vertical_change = 1
actions_list.append(("Move", (elem.direction, elem.horizontal_index + horizontal_change,
elem.vertical_index + vertical_change)))
return actions_list
def graphsearch(fringe, explored, istate, goaltest, board):
node = Node(None, istate.direction, None, istate.horizontal_index, istate.vertical_index)
fringe.append((node, 0))
while True:
if not fringe:
return False
elem = fringe.pop(0)
temp = elem[0]
if goal_test(elem[0], goaltest) is True:
return print_moves(elem[0])
explored.append(elem)
for (action, state) in succ(temp):
fringe_list = []
fringe_list_priority = []
explored_list = []
for (x, y) in fringe:
fringe_list.append((x.direction, x.horizontal_index, x.vertical_index))
fringe_list_priority.append(((x.direction, x.horizontal_index, x.vertical_index), y))
for (x, y) in explored:
explored_list.append((x.direction, x.horizontal_index, x.vertical_index))
x = Node(action, state[0], elem[0], state[1], state[2])
p = f(board, x, goaltest)
if state not in fringe_list and state not in explored_list:
fringe.append((x, p))
fringe = sorted(fringe, key=itemgetter(1))
elif state in fringe_list:
index = 0
for (state_priority, r) in fringe_list_priority:
if state_priority == state:
if r > p:
fringe.insert(index, (x, p))
fringe.pop(index + 1)
fringe = sorted(fringe, key=itemgetter(1))
break
index = index + 1