Projekt_KELNER/restaurant.py
2022-06-10 04:05:23 +02:00

164 lines
4.8 KiB
Python

import numpy as np
import pygame
import tiles
#Parameters for genetic algorithm
n_trashes = tiles.howManyMesses
n_population = 100
mutation_rate = 0.5
listDraft = []
#Some settings for the whole project window
pygame.display.set_caption('Inteligentny Kelner - projekt SI 2022')
Icon = pygame.image.load('waiter.png')
pygame.display.set_icon(Icon)
#Take data from tiles.py
for i in range(len(tiles.messesArray)):
# Generating a list of coordinates representing each trash
coordinates_list = [[x*32,y*32] for x,y in tiles.messesArray]
listDraft.append(tiles.coordsToNum(coordinates_list[i]))
#Add some data
names_list = np.array(listDraft)
trashes_dict = {x:y for x, y in zip(names_list, coordinates_list)}
#Testing:
#print(trashes_dict)
#Function computing the distance between two points by its coordinates
def compute_trash_distance_coordinates(a, b):
return ((a[0]-b[0])**2+(a[1]-b[1])**2)**0.5
def compute_trash_distance_numbers(trash_a, trash_b, trash_dict):
return compute_trash_distance_coordinates(trash_dict[trash_a], trash_dict[trash_b])
#First step is to create the first population set
def genesis(trash_list, n_population):
population_set = []
for i in range(n_population):
#Randomly generated new solution
sol_i = trash_list[np.random.choice(list(range(n_trashes)), n_trashes, replace=False)]
population_set.append(sol_i)
return np.array(population_set)
population_set = genesis(names_list, n_population)
#Testing
#print(population_set)
def fitness_eval(trash_list, trash_dict):
total = 0
for i in range(n_trashes - 1):
a = trash_list[i]
b = trash_list[i + 1]
total += compute_trash_distance_numbers(a, b, trash_dict)
return total
def get_all_fitnes(population_set, trash_dict):
fitnes_list = np.zeros(n_population)
#Looping over all solutions computing the fitness for each solution
for i in range(n_population):
fitnes_list[i] = fitness_eval(population_set[i], trash_dict)
return fitnes_list
fitnes_list = get_all_fitnes(population_set, trashes_dict)
#Testing
#print(fitnes_list)
def ancestors_choose(population_set, fitnes_list):
total_fit = fitnes_list.sum()
prob_list = fitnes_list / total_fit
pop_len = len(population_set)
ancestor_list_a = np.random.choice(list(range(pop_len)), pop_len, p=prob_list, replace=True)
ancestor_list_b = np.random.choice(list(range(pop_len)), pop_len, p=prob_list, replace=True)
ancestor_list_a = population_set[ancestor_list_a]
ancestor_list_b = population_set[ancestor_list_b]
return np.array([ancestor_list_a, ancestor_list_b])
ancestor_list = ancestors_choose(population_set, fitnes_list)
#print(ancestor_list[0][2])
def mate_ancestors(prog_a, prog_b):
offspring = prog_a[0:5]
for trash in prog_b:
if not trash in offspring:
offspring = np.concatenate((offspring, [trash]))
return offspring
def mate_population(progenitor_list):
new_population_set = []
for i in range(progenitor_list.shape[1]):
prog_a, prog_b = progenitor_list[0][i], progenitor_list[1][i]
offspring = mate_ancestors(prog_a, prog_b)
new_population_set.append(offspring)
return new_population_set
new_population_set = mate_population(ancestor_list)
#print(new_population_set[0])
def mutate_offspring(offspring):
for q in range(int(n_trashes * mutation_rate)):
a = np.random.randint(0, n_trashes)
b = np.random.randint(0, n_trashes)
offspring[a], offspring[b] = offspring[b], offspring[a]
return offspring
def mutate_population(new_population_set):
mutated_pop = []
for offspring in new_population_set:
mutated_pop.append(mutate_offspring(offspring))
return mutated_pop
mutated_pop = mutate_population(new_population_set)
#print(mutated_pop[0])
best_solution = [-1, np.inf, np.array([])]
for i in range(1001):
#What I put here: iteration number, minimal fitness value, average fitness value
if i % 100 == 0: print(i, fitnes_list.min(), fitnes_list.mean())
fitnes_list = get_all_fitnes(mutated_pop, trashes_dict)
#Saving the best solution
if fitnes_list.min() < best_solution[1]:
best_solution[0] = i
best_solution[1] = fitnes_list.min()
best_solution[2] = np.array(mutated_pop)[fitnes_list.min() == fitnes_list]
ancestor_list = ancestors_choose(population_set, fitnes_list)
new_population_set = mate_population(ancestor_list)
mutated_pop = mutate_population(new_population_set)
trashesList = []
for i in range(len(best_solution[2][0])):
trashesList.append(0)
for i in range(len(best_solution[2][0])):
trashesList[i] = best_solution[2][0][i]
#Prints some specs to recreate if needed
print(trashesList)
print(tiles.messesArray)
#Pass solution to draw
tiles.main(trashesList)