From be0f33318132727b643fb7a2ae59e9fce4756b04 Mon Sep 17 00:00:00 2001 From: Aliaksei Brown Date: Mon, 19 Jun 2023 15:56:25 +0200 Subject: [PATCH] astar + graph search --- .../__pycache__/a_star.cpython-310.pyc | Bin 0 -> 3795 bytes agent/methods/a_star.py | 136 ++++++++++++++++++ agent/methods/graph_search.py | 99 +++---------- main.py | 9 +- 4 files changed, 159 insertions(+), 85 deletions(-) create mode 100644 agent/methods/__pycache__/a_star.cpython-310.pyc create mode 100644 agent/methods/a_star.py diff --git a/agent/methods/__pycache__/a_star.cpython-310.pyc b/agent/methods/__pycache__/a_star.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c780cbdd2718b6b933a9006223188f7aa620a189 GIT binary patch literal 3795 zcmai1&2J<}6|buPn4V92ZO8GV%?1*)WJ0ikKsey60@>^WLI%YfAx4Rs@l?-v#y!*H z>h`W})u0GlVmTm%6XNDQF8={1&inznRF1jeKLI2VzgOKe9(y75s9wGLc&}c)uX>Zz z>lKFY9}hl}e_3Jda~jNl4hHX_rC$bkz$BCW4DD33Xe6YAk%JMJ?hb2u9qhXD&FEJ# z9Wm@%O=*LZ2x&LZQF+bSAm#&37BeljwF>|3KqT^kaJRWV{OFD-`a7;JHDj7r_AnktGYY(H%b`SHL!zkNJBxXY#q&CLK zCJ4j+sGo%)T_L3dd``a#KdIA=H>T^`O-Iq59FWd%5m1l7Jq%4H42Ow4j0vxW;lW`$ z&R0~8h)Co)P^BRUpq9D-0c&tO^PG9;(06Ft7QoCrT#7RWTDk}@Z$Gk`BKexalsi!zhiU&LGF6L? z4u`vuf?mqlpl%RYB5-+GdrwjT?XdT>nqA1nnCZ4d=TAQ}H#IBITTqbZlHX(#fnK0@ z&^zc|?Yd05`$BDUCO!C@BmJH$OBM@yZcj`+%<+9keM5WaOqT76SOZnheabo0aBc7i zz~kYJ2i6K6m4XL6d4RLm7&yH@6T?a%tu`J)Uv`7x0oe zZOTdd;Pa>APM9yaKr+ik*gO4kN>7sIcc0P2YR&4lBGX=wi(Qa{jric_#*L$HX562? zcmJXBRKK^E8SnicKlsr@;|`NYk#X<+>=)ZGw%;C)qmi@*ZTh)|DH;twGW^(h?NKj| zOfXK;w7(li*KCgPJ?wPq*q^=*5ODel1l1b9&0X8C&-H#W@BZtgTDS($Ur96M66A>1 zExJG?hj~5C2f%K^NzlVRx!$i+rtN3eG5GJgj=2kCFRRp zjcOT3_WurzUXXjk=`V8=WsO2d#vM_b^wTUEMX7OnNjo;BZk#+ut}<>XNwaIJQeOl0 zt7vHhz!mFao%@2q#N{(>5Z!Y@O9EJJya6O54cI`@aF3g8jh*sh4qCw+AkDoZ=5yb541WPpX=od%8;JJ)yU({M5}y zp|7jwS9U+YGnWYaO41?OaFbe@Wr41q;s%iHOqO?;t`3l;W%Z27+V3eF75i;=tLyrp zLKsX32%5jy8Qd8&fHVWX4a`>6Uv&dFtq*E5Dx$`&o;{!TOo(GO{WEsfpW@xg9NnOM z>josLS?Y?-AMBiX0*5yDK6EDwlf}u6$rALlsBh?{o}=q};nbP<=>0I)Q+=i*cD{gl z@e~X0Wa{|7ufavVwN%a7)_z~|uQgHI21b7A|+b3;B%jp92+ zdBrp$sVkl^WQaiW9b^?`0YuCzShHEc21Qe-muTWPz%#Da3Ae#QPo4=VV8bMqZ()>D z>Z&1}U2(Ergi4$0kJLWK8(VSGX~*f^jVY1M+xbx>(8afjrJpB}hxa>_(5D~aB>fJW ztzNXvhLBin&k4(OVXsAVuobt5yRv=vmqbl$0`|ocP6?XaIQ!A@6;UX@DM4FNDCm1o za!@#OvNVukc2mtaoiqd7FU#}FP%ocOv5|G&`EX& zEx!xtdf*csjpIZ`(zsC^4O^&{qj75M-&V;U6&_8I<5o4Fv9EC}zy%Z4&yHL5oEcTQ z5XtaX478*)SSSlhZ>&B13W_k9-&vb_&D$uoiFj%=t&YnkS8yS z24DAF)XBH0TK;$75>-vCi6xA0;rVI+U*t8u$XEFidjDhb*~!xLrn~Y~&_g;yC^1ysXYq{8n&pJbZ~*+!hK6k5GPwB0N# zs=pLf6>5P1)#14tQ^{d{S^a>p9}>9C4YM?+=-&X{$d)Dnm2qyc8q@-}_7l5?LNN~~ Y+W6l%m|!daS9F&WmHh+IU`wU{0GR3x`~Uy| literal 0 HcmV?d00001 diff --git a/agent/methods/a_star.py b/agent/methods/a_star.py new file mode 100644 index 00000000..9c2ba32f --- /dev/null +++ b/agent/methods/a_star.py @@ -0,0 +1,136 @@ +class Node: + def __init__(self, state, parent='', action='', distance=0): + self.state = state + self.parent = parent + self.action = action + self.distance = distance + +class Search: + def __init__(self, cell_size, cell_number): + self.cell_size = cell_size + self.cell_number = cell_number + + def succ(self, state): + x = state[0] + y = state[1] + angle = state[2] + match(angle): + case 'UP': + possible = [['left', x, y, 'LEFT'], ['right', x, y, 'RIGHT']] + if y != 0: possible.append(['move', x, y - 1, 'UP']) + return possible + case 'RIGHT': + possible = [['left', x, y, 'UP'], ['right', x, y, 'DOWN']] + if x != (self.cell_number-1): possible.append(['move', x + 1, y, 'RIGHT']) + return possible + case 'DOWN': + possible = [['left', x, y, 'RIGHT'], ['right', x, y, 'LEFT']] + if y != (self.cell_number-1): possible.append(['move', x, y + 1, 'DOWN']) + return possible + case 'LEFT': + possible = [['left', x, y, 'DOWN'], ['right', x, y, 'UP']] + if x != 0: possible.append(['move', x - 1, y, 'LEFT']) + return possible + + def cost(self, node, stones, goal, flowers): + # cost = node.distance + cost = 0 + # cost += 10 if stones[node.state[0], node.state[1]] == 1 else 1 + cost += 1000 if (node.state[0], node.state[1]) in stones else 1 + cost += 10 if ((node.state[0]), (node.state[1])) in flowers else 1 + + if node.parent: + node = node.parent + cost += node.distance # should return only elem.action in prod + return cost + + def heuristic(self, node, goal): + return abs(node.state[0] - goal[0]) + abs(node.state[1] - goal[1]) + + #bandaid to know about stones + def astarsearch(self, istate, goaltest, stone_list, plant_list): + + #to be expanded + def cost_old(x, y): + if (x, y) in stones: + return 10 + else: + return 1 + + x = istate[0] + y = istate[1] + angle = istate[2] + stones = [] + flowers = [] + + for obj in stone_list: + stones.append((obj.xy[0]*50, obj.xy[1]*50)) + for obj in plant_list: + if obj.name == 'flower': + flowers.append((obj.xy[0]*50, obj.xy[1]*50)) + + # stones = [(x*50, y*50) for (x, y) in stone_list] + # flowers = [(x*50, y*50) for (x, y) in plant_list] + + print(stones) + + # fringe = [(Node([x, y, angle]), cost_old(x, y))] # queue (moves/states to check) + fringe = [(Node([x, y, angle]))] # queue (moves/states to check) + fringe[0].distance = self.cost(fringe[0], stones, goaltest, flowers) + fringe.append((Node([x, y, angle]), self.cost(fringe[0], stones, goaltest, flowers))) + fringe.pop(0) + + explored = [] + + while True: + if len(fringe) == 0: + return False + + fringe.sort(key=lambda x: x[1]) + elem = fringe.pop(0)[0] + + # if goal_test(elem.state): + # return + # print(elem.state[0], elem.state[1], elem.state[2]) + if elem.state[0] == goaltest[0] and elem.state[1] == goaltest[1]: # checks if we reached the given point + steps = [] + while elem.parent: + steps.append([elem.action, elem.state[0], elem.state[1]]) # should return only elem.action in prod + elem = elem.parent + + steps.reverse() + print(steps) # only for dev + return steps + + explored.append(elem.state) + + for (action, state_x, state_y, state_angle) in self.succ(elem.state): + x = Node([state_x, state_y, state_angle], elem, action) + x.parent = elem + + priority = self.cost(elem, stones, goaltest, flowers) + self.heuristic(elem, goaltest) + elem.distance = priority + # priority = cost_old(x, y) + self.heuristic(elem, goaltest) + fringe_states = [node.state for (node, p) in fringe] + + if x.state not in fringe_states and x.state not in explored: + fringe.append((x, priority)) + elif x.state in fringe_states: + for i in range(len(fringe)): + if fringe[i][0].state == x.state: + if fringe[i][1] > priority: + fringe[i] = (x, priority) + + + def closest_point(self, x, y, name, plant_list): + self.max_distance = self.cell_number*self.cell_number + for obj in plant_list: + if obj.name == name: + if obj.state == 0: + self.distance = (abs(obj.xy[0] - x) + abs(obj.xy[1] - y)) + if self.distance <= self.max_distance: + self.max_distance = self.distance + x_close = obj.xy[0] + y_close = obj.xy[1] + #print("distance: ",self.distance, obj.xy[0], "+", obj.xy[1], "-" ,x, "+",y) + return (x_close, y_close) \ No newline at end of file diff --git a/agent/methods/graph_search.py b/agent/methods/graph_search.py index 9c2ba32f..c3e79c03 100644 --- a/agent/methods/graph_search.py +++ b/agent/methods/graph_search.py @@ -1,9 +1,9 @@ class Node: - def __init__(self, state, parent='', action='', distance=0): + def __init__(self, state, parent='', action=''): self.state = state self.parent = parent self.action = action - self.distance = distance + class Search: def __init__(self, cell_size, cell_number): @@ -17,77 +17,36 @@ class Search: match(angle): case 'UP': possible = [['left', x, y, 'LEFT'], ['right', x, y, 'RIGHT']] - if y != 0: possible.append(['move', x, y - 1, 'UP']) + if y != 0: possible.append(['move', x, y - self.cell_size, 'UP']) return possible case 'RIGHT': possible = [['left', x, y, 'UP'], ['right', x, y, 'DOWN']] - if x != (self.cell_number-1): possible.append(['move', x + 1, y, 'RIGHT']) + if x != self.cell_size*(self.cell_number-1): possible.append(['move', x + self.cell_size, y, 'RIGHT']) return possible case 'DOWN': possible = [['left', x, y, 'RIGHT'], ['right', x, y, 'LEFT']] - if y != (self.cell_number-1): possible.append(['move', x, y + 1, 'DOWN']) + if y != self.cell_size*(self.cell_number-1): possible.append(['move', x, y + self.cell_size, 'DOWN']) return possible case 'LEFT': possible = [['left', x, y, 'DOWN'], ['right', x, y, 'UP']] - if x != 0: possible.append(['move', x - 1, y, 'LEFT']) + if x != 0: possible.append(['move', x - self.cell_size, y, 'LEFT']) return possible - def cost(self, node, stones, goal, flowers): - # cost = node.distance - cost = 0 - # cost += 10 if stones[node.state[0], node.state[1]] == 1 else 1 - cost += 1000 if (node.state[0], node.state[1]) in stones else 1 - cost += 10 if ((node.state[0]), (node.state[1])) in flowers else 1 - - if node.parent: - node = node.parent - cost += node.distance # should return only elem.action in prod - return cost - - def heuristic(self, node, goal): - return abs(node.state[0] - goal[0]) + abs(node.state[1] - goal[1]) - - #bandaid to know about stones - def astarsearch(self, istate, goaltest, stone_list, plant_list): - - #to be expanded - def cost_old(x, y): - if (x, y) in stones: - return 10 - else: - return 1 - + def graphsearch(self, istate, goaltest): x = istate[0] y = istate[1] angle = istate[2] - stones = [] - flowers = [] - - for obj in stone_list: - stones.append((obj.xy[0]*50, obj.xy[1]*50)) - for obj in plant_list: - if obj.name == 'flower': - flowers.append((obj.xy[0]*50, obj.xy[1]*50)) - - # stones = [(x*50, y*50) for (x, y) in stone_list] - # flowers = [(x*50, y*50) for (x, y) in plant_list] - - print(stones) - - # fringe = [(Node([x, y, angle]), cost_old(x, y))] # queue (moves/states to check) - fringe = [(Node([x, y, angle]))] # queue (moves/states to check) - fringe[0].distance = self.cost(fringe[0], stones, goaltest, flowers) - fringe.append((Node([x, y, angle]), self.cost(fringe[0], stones, goaltest, flowers))) - fringe.pop(0) + fringe = [Node([x, y, angle])] # queue (moves/states to check) + fringe_state = [fringe[0].state] explored = [] while True: if len(fringe) == 0: return False - fringe.sort(key=lambda x: x[1]) - elem = fringe.pop(0)[0] + elem = fringe.pop(0) + fringe_state.pop(0) # if goal_test(elem.state): # return @@ -105,32 +64,10 @@ class Search: explored.append(elem.state) for (action, state_x, state_y, state_angle) in self.succ(elem.state): - x = Node([state_x, state_y, state_angle], elem, action) - x.parent = elem - - priority = self.cost(elem, stones, goaltest, flowers) + self.heuristic(elem, goaltest) - elem.distance = priority - # priority = cost_old(x, y) + self.heuristic(elem, goaltest) - fringe_states = [node.state for (node, p) in fringe] - - if x.state not in fringe_states and x.state not in explored: - fringe.append((x, priority)) - elif x.state in fringe_states: - for i in range(len(fringe)): - if fringe[i][0].state == x.state: - if fringe[i][1] > priority: - fringe[i] = (x, priority) - - - def closest_point(self, x, y, name, plant_list): - self.max_distance = self.cell_number*self.cell_number - for obj in plant_list: - if obj.name == name: - if obj.state == 0: - self.distance = (abs(obj.xy[0] - x) + abs(obj.xy[1] - y)) - if self.distance <= self.max_distance: - self.max_distance = self.distance - x_close = obj.xy[0] - y_close = obj.xy[1] - #print("distance: ",self.distance, obj.xy[0], "+", obj.xy[1], "-" ,x, "+",y) - return (x_close, y_close) \ No newline at end of file + if [state_x, state_y, state_angle] not in fringe_state and \ + [state_x, state_y, state_angle] not in explored: + x = Node([state_x, state_y, state_angle]) + x.parent = elem + x.action = action + fringe.append(x) + fringe_state.append(x.state) \ No newline at end of file diff --git a/main.py b/main.py index 28f705d3..ba6513a0 100644 --- a/main.py +++ b/main.py @@ -6,6 +6,8 @@ from core.chicken import chicken as chick from core.field import field_settings from core.plants import plants_settings from agent.methods.genetic_algorithm import genetic_algorithm +from agent.methods import a_star + import numpy as np from agent.neural_network import inference @@ -13,7 +15,6 @@ from agent.neural_network import inference #import neural_network.inference # import core.plants.plant as plant # import core.plants.plants_settings as plants_settings -import agent.methods.graph_search as graph_search #import models.field_block as field_block @@ -59,7 +60,7 @@ class Game: #vegies_list self.Plants.locate_veggies(self.veggies_list, 'pepper', self.blocks_number-5) self.Plants.locate_veggies(self.veggies_list, 'carrot', self.blocks_number-5) - self.Plants.locate_veggies(self.veggies_list, 'pumpkin', self.blocks_number-5) + self.Plants.locate_veggies(self.veggies_list, 'papaya', self.blocks_number-5) self.Plants.locate_veggies(self.veggies_list, 'wheat', self.blocks_number) @@ -75,8 +76,8 @@ class Game: running = True clock = pygame.time.Clock() move_chicken_event = pygame.USEREVENT + 1 - pygame.time.set_timer(move_chicken_event, 1000) # chicken moves every 1000 ms - self.search_object = graph_search.Search(self.cell_size, self.cell_number) + pygame.time.set_timer(move_chicken_event, 500) # chicken moves every 1000 ms + self.search_object = a_star.Search(self.cell_size, self.cell_number) chicken_next_moves = [] veggies = dict()