Merge branch 'master' into genetic_algorithm

This commit is contained in:
Kacper Kalinowski 2022-06-10 11:20:51 +02:00
commit 03f983f35b
9 changed files with 270 additions and 88 deletions

View File

View File

@ -1,3 +1,96 @@
<<<<<<< HEAD
|--- feature_2 <= 3.50
| |--- feature_4 <= 3.50
| | |--- feature_0 <= 1.50
| | | |--- class: 0
| | |--- feature_0 > 1.50
| | | |--- feature_3 <= 3.50
| | | | |--- feature_4 <= 2.50
| | | | | |--- class: 1
| | | | |--- feature_4 > 2.50
| | | | | |--- feature_2 <= 2.50
| | | | | | |--- class: 1
| | | | | |--- feature_2 > 2.50
| | | | | | |--- class: 0
| | | |--- feature_3 > 3.50
| | | | |--- feature_3 <= 4.50
| | | | | |--- feature_1 <= 2.50
| | | | | | |--- feature_0 <= 2.50
| | | | | | | |--- feature_1 <= 1.50
| | | | | | | | |--- feature_4 <= 2.50
| | | | | | | | | |--- class: 1
| | | | | | | | |--- feature_4 > 2.50
| | | | | | | | | |--- feature_2 <= 2.00
| | | | | | | | | | |--- class: 1
| | | | | | | | | |--- feature_2 > 2.00
| | | | | | | | | | |--- class: 0
| | | | | | | |--- feature_1 > 1.50
| | | | | | | | |--- class: 0
| | | | | | |--- feature_0 > 2.50
| | | | | | | |--- feature_2 <= 2.50
| | | | | | | | |--- class: 1
| | | | | | | |--- feature_2 > 2.50
| | | | | | | | |--- feature_4 <= 2.50
| | | | | | | | | |--- class: 1
| | | | | | | | |--- feature_4 > 2.50
| | | | | | | | | |--- class: 0
| | | | | |--- feature_1 > 2.50
| | | | | | |--- feature_1 <= 3.50
| | | | | | | |--- feature_0 <= 3.50
| | | | | | | | |--- class: 0
| | | | | | | |--- feature_0 > 3.50
| | | | | | | | |--- feature_4 <= 2.50
| | | | | | | | | |--- class: 1
| | | | | | | | |--- feature_4 > 2.50
| | | | | | | | | |--- feature_2 <= 2.00
| | | | | | | | | | |--- class: 1
| | | | | | | | | |--- feature_2 > 2.00
| | | | | | | | | | |--- class: 0
| | | | | | |--- feature_1 > 3.50
| | | | | | | |--- class: 0
| | | | |--- feature_3 > 4.50
| | | | | |--- class: 0
| |--- feature_4 > 3.50
| | |--- feature_2 <= 1.50
| | | |--- feature_4 <= 4.50
| | | | |--- feature_3 <= 3.50
| | | | | |--- feature_0 <= 1.50
| | | | | | |--- class: 0
| | | | | |--- feature_0 > 1.50
| | | | | | |--- class: 1
| | | | |--- feature_3 > 3.50
| | | | | |--- feature_1 <= 2.50
| | | | | | |--- feature_0 <= 2.50
| | | | | | | |--- class: 0
| | | | | | |--- feature_0 > 2.50
| | | | | | | |--- feature_3 <= 4.50
| | | | | | | | |--- class: 1
| | | | | | | |--- feature_3 > 4.50
| | | | | | | | |--- class: 0
| | | | | |--- feature_1 > 2.50
| | | | | | |--- class: 0
| | | |--- feature_4 > 4.50
| | | | |--- class: 0
| | |--- feature_2 > 1.50
| | | |--- class: 0
|--- feature_2 > 3.50
| |--- feature_1 <= 1.50
| | |--- feature_4 <= 1.50
| | | |--- feature_2 <= 4.50
| | | | |--- feature_0 <= 1.50
| | | | | |--- class: 0
| | | | |--- feature_0 > 1.50
| | | | | |--- feature_3 <= 4.50
| | | | | | |--- class: 1
| | | | | |--- feature_3 > 4.50
| | | | | | |--- class: 0
| | | |--- feature_2 > 4.50
| | | | |--- class: 0
| | |--- feature_4 > 1.50
| | | |--- class: 0
| |--- feature_1 > 1.50
| | |--- class: 0
=======
|--- feature_2 <= 3.50 |--- feature_2 <= 3.50
| |--- feature_4 <= 3.50 | |--- feature_4 <= 3.50
| | |--- feature_0 <= 1.50 | | |--- feature_0 <= 1.50
@ -89,3 +182,4 @@
| | | |--- class: 0 | | | |--- class: 0
| |--- feature_1 > 1.50 | |--- feature_1 > 1.50
| | |--- class: 0 | | |--- class: 0
>>>>>>> genetic_algorithm

Binary file not shown.

Binary file not shown.

10
main_test.py Normal file
View File

@ -0,0 +1,10 @@
from map import map_utils
from path_search_algorthms import a_star, a_star_utils
import numpy
file = open('last_map.nparr', 'rb')
array = numpy.load(file)
file.close
actions = a_star.search_path(12, 0, a_star_utils.Rotation.UP, 1, 5, array)
print(actions)

71
neurone/main.py Normal file
View File

@ -0,0 +1,71 @@
import pybrain3
import pickle
import matplotlib.pylab as plt
from numpy import ravel
from pybrain3.tools.shortcuts import buildNetwork
from pybrain3.datasets import SupervisedDataSet
from pybrain3.supervised.trainers import BackpropTrainer
from pybrain3.tools.xml.networkwriter import NetworkWriter
from pybrain3.tools.xml.networkreader import NetworkReader
# https://www.machinelearningmastery.ru/how-to-configure-the-number-of-layers-and-nodes-in-a-neural-network/
class SupervisedDataSetModel():
def __init__(self, metrics:int = 4,
predictions:int = 1,
input_layer:int = 4,
hidden_layer:int = 3,
output_layer:int = 1):
# 4 метрики, 1 предикшн
self.metrics = metrics
self.predictions = predictions
self.input_layer = input_layer
self.hidden_layer = hidden_layer
self.output_layer = output_layer
self.ds = SupervisedDataSet(metrics, predictions)
def activateModel(self):
self.net = buildNetwork(self.input_layer, self.hidden_layer, self.output_layer, bias=True)
self.trainer = BackpropTrainer(self.net, dataset=self.ds, momentum=0.1, learningrate=0.01, verbose=True, weightdecay=0.01)
self.trnerr, self.valerr = self.trainer.trainUntilConvergence()
plt.plot(self.trnerr, 'b', self.valerr, 'r')
plt.show()
def addDataToModel(self, input:list, target:list):
self.ds.addSample(inp=input, target=target)
def predict(self, data:list):
y = self.net.activate(data)
print(y)
return y
def saveModel(self):
fileObject = open('model.txt', 'wb')
pickle.dump(self.net, fileObject)
fileObject.close()
def getModel():
fileObject = open('model.txt', 'rb')
net2 = pickle.load(fileObject)
fileObject.close()
return net2
model = SupervisedDataSetModel()
# model.addDataToModel([2, 3, 80, 1], [5])
# model.addDataToModel([5, 5, 50, 2], [4])
# model.addDataToModel([10, 7, 40, 3], [3])
# model.addDataToModel([15, 9, 20, 4], [2])
# model.addDataToModel([20, 11, 10, 5], [1])
# model.activateModel()
# model.saveModel()
# USE MODEL - >
model = getModel()
print(model.activate([2, 3, 80, 1]))

BIN
neurone/model.txt Normal file

Binary file not shown.

View File

@ -1,76 +1,76 @@
from data_structures.heap import Heap from data_structures.heap import Heap
from path_search_algorthms import a_star_utils as utils from path_search_algorthms import a_star_utils as utils
def get_cost(start_x: int, start_y: int, target_x: int, target_y: int, array): def get_cost(start_x: int, start_y: int, target_x: int, target_y: int, array):
actions = search_path(start_x, start_y, utils.Rotation.NONE, target_x, target_y, array) actions = search_path(start_x, start_y, utils.Rotation.NONE, target_x, target_y, array)
if actions is None: if actions is None:
return 1 return 1
return len(actions) return len(actions)
def search_path(start_x: int, start_y: int, agent_rotation: utils.Rotation, target_x: int, target_y: int, array): def search_path(start_x: int, start_y: int, agent_rotation: utils.Rotation, target_x: int, target_y: int, array):
start_node = utils.Node(start_x, start_y, agent_rotation) start_node = utils.Node(start_x, start_y, agent_rotation)
target_node = utils.Node(target_x, target_y, utils.Rotation.NONE) target_node = utils.Node(target_x, target_y, utils.Rotation.NONE)
# heap version # heap version
# nodes for check # nodes for check
search_list = Heap() search_list = Heap()
search_list.append(start_node, 0) search_list.append(start_node, 0)
# checked nodes # checked nodes
searched_list: list[(int, int)] = [] searched_list: list[(int, int)] = []
while (search_list.length() > 0): while (search_list.length() > 0):
node: utils.Node = search_list.take_first() node: utils.Node = search_list.take_first()
searched_list.append((node.x, node.y)) searched_list.append((node.x, node.y))
# check for target node # check for target node
if ((node.x, node.y) == (target_x, target_y)): if ((node.x, node.y) == (target_x, target_y)):
return trace_path(node) return trace_path(node)
# neightbours processing # neightbours processing
neighbours = utils.get_neighbours(node, searched_list, array) neighbours = utils.get_neighbours(node, searched_list, array)
for neighbour in neighbours: for neighbour in neighbours:
# calculate new g cost for neightbour (start -> node -> neightbour) # calculate new g cost for neightbour (start -> node -> neightbour)
new_neighbour_cost = node.g_cost + utils.get_neighbour_cost(node, neighbour) new_neighbour_cost = node.g_cost + utils.get_neighbour_cost(node, neighbour)
if (new_neighbour_cost < neighbour.g_cost or not search_list.contains(neighbour)): if (new_neighbour_cost < neighbour.g_cost or not search_list.contains(neighbour)):
# replace cost and set parent node # replace cost and set parent node
neighbour.g_cost = new_neighbour_cost neighbour.g_cost = new_neighbour_cost
neighbour.h_cost = utils.get_h_cost(neighbour, target_node) neighbour.h_cost = utils.get_h_cost(neighbour, target_node)
neighbour.parent = node neighbour.parent = node
# add to search # add to search
if (not search_list.contains(neighbour)): if (not search_list.contains(neighbour)):
search_list.append(neighbour, neighbour.f_cost()) search_list.append(neighbour, neighbour.f_cost())
def trace_path(end_node: utils.Node): def trace_path(end_node: utils.Node):
path = [] path = []
node = end_node node = end_node
# set final rotation of end_node because we don't do it before # set final rotation of end_node because we don't do it before
node.rotation = utils.get_needed_rotation(node.parent, node) node.rotation = utils.get_needed_rotation(node.parent, node)
while (node.parent != False): while (node.parent != False):
if (node.parent == utils.Rotation.NONE): if (node.parent == utils.Rotation.NONE):
path += "forward" path += "forward"
else: else:
path += utils.get_move(node.parent, node) path += utils.get_move(node.parent, node)
node = node.parent node = node.parent
# delete move on initial tile # delete move on initial tile
path.pop() path.pop()
# we found path from end, so we need to reverse it (get_move reverse move words) # we found path from end, so we need to reverse it (get_move reverse move words)
path.reverse() path.reverse()
# last forward to destination # last forward to destination
path.append("forward") path.append("forward")
return path return path

View File

@ -3,6 +3,7 @@ from enum import Enum
from map import map_utils from map import map_utils
from settings import * from settings import *
class Rotation(Enum): class Rotation(Enum):
UP = 0 UP = 0
RIGHT = 1 RIGHT = 1
@ -13,34 +14,37 @@ class Rotation(Enum):
def __int__(self): def __int__(self):
return self.value return self.value
class Node: class Node:
def __init__(self, x: int, y: int, rotation: Rotation): def __init__(self, x: int, y: int, rotation: Rotation):
self.x = x self.x = x
self.y = y self.y = y
self.g_cost = 0 self.g_cost = 0
self.h_cost = 0 self.h_cost = 0
self.parent = 0 self.parent: Node | bool = False
self.rotation = rotation self.rotation: Rotation = rotation
def f_cost(self): def f_cost(self):
return self.g_cost + self.h_cost return self.g_cost + self.h_cost
def get_neighbours(node, searched_list, array): def get_neighbours(node, searched_list, array):
neighbours = [] neighbours = []
for offset_x in range (-1, 2): for offset_x in range(-1, 2):
for offset_y in range (-1, 2): for offset_y in range(-1, 2):
# don't look for cross neighbours # don't look for cross neighbours
if(abs(offset_x) + abs(offset_y) == 1): if (abs(offset_x) + abs(offset_y) == 1):
x = node.x + offset_x x = node.x + offset_x
y = node.y + offset_y y = node.y + offset_y
# prevent out of map coords # prevent out of map coords
if (x >= 0 and x < MAP_WIDTH and y >= 0 and y < MAP_HEIGHT): if (x >= 0 and x < MAP_WIDTH and y >= 0 and y < MAP_HEIGHT):
if(map_utils.isRoadTile(array[y][x]) and (x, y) not in searched_list): if (map_utils.isRoadTile(array[y][x]) and (x, y) not in searched_list):
neighbour = Node(x, y, Rotation.NONE) neighbour = Node(x, y, Rotation.NONE)
neighbour.rotation = get_needed_rotation(node, neighbour) neighbour.rotation = get_needed_rotation(node, neighbour)
neighbours.append(neighbour) neighbours.append(neighbour)
return neighbours return neighbours
# move cost schema: # move cost schema:
# - move from tile to tile: 10 # - move from tile to tile: 10
# - add extra 10 (1 rotation) if it exists # - add extra 10 (1 rotation) if it exists
@ -49,11 +53,12 @@ def get_h_cost(start_node: Node, target_node: Node):
distance_y = abs(start_node.y - target_node.y) distance_y = abs(start_node.y - target_node.y)
cost = (distance_x + distance_y) * 10 cost = (distance_x + distance_y) * 10
if(distance_x > 0 and distance_y > 0): if (distance_x > 0 and distance_y > 0):
cost += 10 cost += 10
return cost return cost
# move cost schema: # move cost schema:
# - move from tile to tile: 10 # - move from tile to tile: 10
# - every rotation 90*: 10 # - every rotation 90*: 10
@ -67,6 +72,7 @@ def get_neighbour_cost(start_node: Node, target_node: Node) -> int:
else: else:
return 30 return 30
# translate rotation change to move # translate rotation change to move
def get_move(start_node: Node, target_node: Node): def get_move(start_node: Node, target_node: Node):
rotate_change = get_rotate_change(start_node.rotation, target_node.rotation) rotate_change = get_rotate_change(start_node.rotation, target_node.rotation)
@ -79,10 +85,12 @@ def get_move(start_node: Node, target_node: Node):
else: else:
return ["left", "forward"] return ["left", "forward"]
# simple calc func # simple calc func
def get_rotate_change(rotationA: Rotation, rotationB: Rotation) -> int: def get_rotate_change(rotationA: Rotation, rotationB: Rotation) -> int:
return int(rotationA) - int(rotationB) return int(rotationA) - int(rotationB)
# get new rotation for target_node as neighbour of start_node # get new rotation for target_node as neighbour of start_node
def get_needed_rotation(start_node: Node or bool, target_node: Node) -> Rotation: def get_needed_rotation(start_node: Node or bool, target_node: Node) -> Rotation:
if(start_node == False): if(start_node == False):
@ -94,10 +102,9 @@ def get_needed_rotation(start_node: Node or bool, target_node: Node) -> Rotation
if (start_node.y - target_node.y > 0): if (start_node.y - target_node.y > 0):
return Rotation.UP return Rotation.UP
if (start_node.y - target_node.y < 0): if (start_node.y - target_node.y < 0):
return Rotation.DOWN return Rotation.DOWN