Compare commits

...

4 Commits

Author SHA1 Message Date
1510a81f35 final without genetics 2022-06-09 20:25:18 +02:00
b7402c8e49 Update 'src/board.py' 2022-06-09 10:26:29 +02:00
b4eb9c22f7 Add 'src/gen_algorithms' 2022-06-09 10:13:41 +02:00
91693d2b19 Update 'src/board.py'
łączenie z algorytmem genetycznym
2022-06-09 10:12:52 +02:00
9 changed files with 222 additions and 9 deletions

8
.idea/.gitignore vendored Normal file
View File

@ -0,0 +1,8 @@
# Default ignored files
/shelf/
/workspace.xml
# Editor-based HTTP Client requests
/httpRequests/
# Datasource local storage ignored files
/dataSources/
/dataSources.local.xml

View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="PYTHON_MODULE" version="4">
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$" />
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>

View File

@ -0,0 +1,13 @@
<component name="InspectionProjectProfileManager">
<profile version="1.0">
<option name="myName" value="Project Default" />
<inspection_tool class="PyPep8Inspection" enabled="true" level="WEAK WARNING" enabled_by_default="true">
<option name="ignoredErrors">
<list>
<option value="E305" />
</list>
</option>
</inspection_tool>
<inspection_tool class="PyUnreachableCodeInspection" enabled="false" level="WARNING" enabled_by_default="false" />
</profile>
</component>

View File

@ -0,0 +1,6 @@
<component name="InspectionProjectProfileManager">
<settings>
<option name="USE_PROJECT_PROFILE" value="false" />
<version value="1.0" />
</settings>
</component>

4
.idea/misc.xml Normal file
View File

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectRootManager" version="2" project-jdk-name="Python 3.9" project-jdk-type="Python SDK" />
</project>

8
.idea/modules.xml Normal file
View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/SI-projekt-smieciarka4.iml" filepath="$PROJECT_DIR$/.idea/SI-projekt-smieciarka4.iml" />
</modules>
</component>
</project>

6
.idea/vcs.xml Normal file
View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />
</component>
</project>

View File

@ -1,5 +1,7 @@
from pathlib import Path
import time
import numpy as np
import astar
@ -7,6 +9,7 @@ import pygame
import snn
import joblib
import os
import gen_algorithms
screen = []
objectArray = []
@ -29,19 +32,19 @@ truck_working = 0
weightsMap = ([1, 2, 1, 4, 5, 2, 7, 8, 5, 4, 15, 3, 4, 5, 8],
[1, 2, 1, 4, 5, 2, 7, 8, 1, 4, 1, 3, 4, 5, 1],
[1, 2, 1, 4, 5, 2, 7, 8, 1, 4, 1, 3, 4, 5, 3],
[1, 20, 1, 4, 5, 2, 7, 8, 1, 4, 1, 3, 4, 5, 3],
[1, 2, 1, 4, 5, 2, 7, 8, 1, 4, 3, 3, 8, 5, 4],
[1, 2, 1, 4, 5, 2, 7, 8, 1, 4, 1, 3, 9, 5, 2],
[1, 2, 1, 4, 5, 2, 7, 8, 1, 4, 1, 12, 4, 5, 6],
[1, 2, 1, 4, 5, 2, 7, 20, 1, 4, 20, 3, 9, 5, 2],
[1, 2, 1, 4, 20, 2, 7, 8, 1, 4, 1, 12, 4, 5, 6],
[1, 2, 1, 4, 5, 2, 7, 8, 1, 4, 7, 3, 4, 5, 7],
[5, 2, 1, 4, 5, 2, 7, 8, 1, 4, 17, 14, 4, 5, 1],
[1, 2, 1, 4, 5, 2, 7, 8, 1, 4, 1, 3, 4, 14, 3],
[1, 2, 1, 4, 5, 2, 7, 8, 1, 4, 1, 3, 4, 14, 2],
[5, 2, 1, 4, 5, 2, 7, 8, 1, 4, 1, 3, 4, 14, 6],
[1, 2, 1, 4, 5, 2, 20, 8, 1, 4, 1, 3, 4, 14, 2],
[5, 2, 1, 20, 5, 2, 7, 8, 20, 4, 30, 3, 4, 14, 6],
[1, 2, 1, 4, 5, 2, 7, 8, 1, 4, 1, 13, 14, 15, 7],
[1, 2, 1, 4, 5, 2, 7, 8, 1, 4, 1, 14, 4, 14, 1],
[1, 2, 1, 4, 5, 2, 7, 8, 1, 4, 1, 3, 4, 15, 2],
[1, 2, 1, 4, 5, 2, 7, 8, 1, 4, 1, 3, 4, 15, 2])
[1, 2, 1, 4, 5, 2, 7, 8, 1, 4, 1, 3, 4, 20, 2])
class Position:
def __init__(self, x, y):
@ -174,7 +177,8 @@ def draw(square_num, objectArr):
def kb_listen(objectArray, gridLength, path):
agent = objectArray[0]
#agent.move(gridLength, path)
agent.move(path)
if __name__ == '__main__':
pygame.init() # inicjalizacja modułów, na razie niepotrzebna
@ -182,7 +186,7 @@ if __name__ == '__main__':
# Tworzymy nowego playera, czy tam agenta
agent = Agent("smieciarka", Position(0, 0))
junkyard = Junkyard("wysypisko", Position(10, 10))
junkyard = Junkyard("wysypisko", Position(14, 14))
houses = [House(f'dom-{i}', pos) for i, pos in enumerate([Position(x, y) for x, y in [
(7, 4), (3, 10), (8, 10), (4, 5), (1, 2), (10, 4), (13, 14), (6, 9)
]])]
@ -222,6 +226,40 @@ if __name__ == '__main__':
pathPos = 0
nextCheckpoint = 1
#od tąd podstawiony algorytm genetyczny
# parametry
num_of_houses = 8 # ilość domków
routes_num = 40 # ilość ścieżek, które będziemy generować
# rate = 0.3 # do mutacji, by liczby były ładniejsze
houses_coordinates = [[7, 4], [3, 10], [8, 10], [4, 5], [1, 2], [10, 4], [13, 14], [6, 9]] # generowanie losowych współrzędnych między 1, a 9
names = np.array(['Dom A', 'Dom B', 'Dom C', 'Dom D', 'Dom E', 'Dom F', 'Dom G', 'Dom H']) # nazwy domów
houses_info = {x: y for x, y in
zip(names, houses_coordinates)} # zawiera nazwę domu i jego współrzędne X, Y - słownik
population_set = gen_algorithms.generate_routes(names, routes_num)
list_of_sums = gen_algorithms.sums_for_all_routes(population_set, houses_info)
progenitor_list = gen_algorithms.selection(population_set, list_of_sums)
new_population_set = gen_algorithms.population_mating(progenitor_list)
final_mutated_population = gen_algorithms.mutate_population(new_population_set)
final_route = [-1, np.inf, np.array([])] # format listy
for i in range(400):
list_of_sums = gen_algorithms.sums_for_all_routes(final_mutated_population, houses_info)
# zapisujemy najlepsze rozwiązanie
if list_of_sums.min() < final_route[1]:
final_route[0] = i
final_route[1] = list_of_sums.min()
final_route[2] = np.array(final_mutated_population)[list_of_sums.min() == list_of_sums]
progenitor_list = gen_algorithms.selection(population_set, list_of_sums)
new_population_set = gen_algorithms.population_mating(progenitor_list)
final_mutated_population = gen_algorithms.mutate_population(new_population_set)
print("tutaj")
print(final_route) # ostateczny wynik
print(final_route[2][0][0]) # żeby wyciągnąć z wyniku nazwę domu, który jest na i-tym miejscy trzeba wziąć final_route[2][0][i]
print(houses_info[final_route[2][0][0]]) # podstawiając jako argument nazwę domu z final_route dostajemy jego współrzędne x, y
while True:
agent_x, agent_y = astarPath[pathPos]
checkpoint_x, checkpoint_y = checkpoints[nextCheckpoint]
@ -250,6 +288,6 @@ if __name__ == '__main__':
draw(gridSize, objectArray)
kb_listen(objectArray, gridSize, astarPath)
pygame.display.update() # by krata pojawiła się w okienku - update powierzc
pygame.time.wait(100)
pygame.time.wait(150)

122
src/gen_algorithms.py Normal file
View File

@ -0,0 +1,122 @@
import numpy as np
import random
# parametry
num_of_houses = 8 # ilość domków
routes_num = 40 # ilość ścieżek, które będziemy generować
# rate = 0.3 # do mutacji, by liczby były ładniejsze
houses_coordinates = [[x, y] for x, y in zip(np.random.randint(1, 9, num_of_houses), np.random.randint(1, 9,
num_of_houses))] # generowanie losowych współrzędnych między 1, a 9
names = np.array(['Dom A', 'Dom B', 'Dom C', 'Dom D', 'Dom E', 'Dom F', 'Dom G', 'Dom H']) # nazwy domów
houses_info = {x: y for x, y in zip(names, houses_coordinates)} # zawiera nazwę domu i jego współrzędne X, Y - słownik
print(houses_coordinates)
# dystans - to się wywali i użyje astara
def house_distance(a, b):
return ((a[0] - b[0]) ** 2 + (a[1] - b[1]) ** 2) ** 0.5
def generate_routes(names,
routes_num): # tu się robią te zestawy domów - routes_num różnych opcji ułożenia trasy przez wszystkie domy
population_set = [] # tu zapisujemy trasy - losowe ułóżenia wszystkich domów na trasie śmieciarki - nasza populacja
for i in range(routes_num):
# losowo wygenerowane kolejności domów na trasie
single_route = names[np.random.choice(list(range(num_of_houses)), num_of_houses, replace=False)]
population_set.append(single_route)
return np.array(population_set)
def sum_up_for_route(names, houses_info): # liczymy odległości między kolejnymi miastami z listy i sumujemy
sum = 0
for i in range(num_of_houses - 1):
sum += house_distance(houses_info[names[i]],
houses_info[names[i + 1]]) # wywołana funkcja, która oblicza dystans - ma być astar
return sum
def sums_for_all_routes(population_set,
houses_info): # zapisujemy na liście finalne sumy odległości(astara) dla każdej z opcji tras
list_of_sums = np.zeros(routes_num)
for i in range(routes_num):
list_of_sums[i] = sum_up_for_route(population_set[i], houses_info) # wywołujemy dla każdej trasy na liście
return list_of_sums
def selection(population_set,
list_of_sums): # korzystamy z Roulette Wheel Selection tzn. im większy fitness tym większa szansa na zostanie wybranym
determinant = list_of_sums.sum()
probability = list_of_sums / determinant # nasza funkcja przynależności - dzielimy każdy dystans konkretnej ścieżki przez sumę wszystkich
progenitor_a = np.random.choice(list(range(len(population_set))), len(population_set), p=probability,
replace=True) # randomowa lista złożona z liczb między 0, a routes_num - 1
progenitor_b = np.random.choice(list(range(len(population_set))), len(population_set), p=probability,
replace=True) # gdzie p to prawdopodobieństwo każdego wejścia
progenitor_a = population_set[progenitor_a] # zmieniamy kolejność ułożenia tras
progenitor_b = population_set[progenitor_b] # teraz nie zawierają liczb, tylko podlisty z trasami
return np.array([progenitor_a, progenitor_b])
def mating_of_progenitors(progenitor_a, progenitor_b):
child = progenitor_a[0:5] # bierzemy 5 domów z rodzica
for house in progenitor_b:
if not house in child: # jeżeli jakiegoś domu z rodzica b nie ma w dziecku z a to łączymy
child = np.concatenate((child, [house]))
return child
def population_mating(progenitor_list):
new_population_set = []
for i in range(progenitor_list.shape[1]):
progenitor_a, progenitor_b = progenitor_list[0][i], progenitor_list[1][i]
child = mating_of_progenitors(progenitor_a, progenitor_b)
new_population_set.append(child)
return new_population_set
def mutation_of_child(child):
for i in range(num_of_houses): # dla każdego elementu dajemy losową szansę zamiany int *rate
x = np.random.randint(0, num_of_houses)
y = np.random.randint(0, num_of_houses)
child[x], child[y] = child[y], child[x] # zamiana miejscami
return child
def mutate_population(new_population_set):
final_mutated_population = []
for child in new_population_set:
final_mutated_population.append(mutation_of_child(child)) # dodajemy zmutowane dziecko do finalnej listy
return final_mutated_population
if __name__ == '__main__':
population_set = generate_routes(names, routes_num)
list_of_sums = sums_for_all_routes(population_set, houses_info)
progenitor_list = selection(population_set, list_of_sums)
new_population_set = population_mating(progenitor_list)
final_mutated_population = mutate_population(new_population_set)
final_route = [-1, np.inf, np.array([])] # format listy
for i in range(20):
list_of_sums = sums_for_all_routes(final_mutated_population, houses_info)
# zapisujemy najlepsze rozwiązanie
if list_of_sums.min() < final_route[1]:
final_route[0] = i
final_route[1] = list_of_sums.min()
final_route[2] = np.array(final_mutated_population)[list_of_sums.min() == list_of_sums]
progenitor_list = selection(population_set, list_of_sums)
new_population_set = population_mating(progenitor_list)
final_mutated_population = mutate_population(new_population_set)
print(final_route)