SprytnyTraktor/geneticalgorithm.py

132 lines
9.7 KiB
Python
Raw Normal View History

2021-06-13 16:28:40 +02:00
import astar
import cart
import definitions
import graph
import map
import os
import pickle
import plant
import pygame
import random
import station
import treelearn
def create_genetic_algorithm():
2021-06-18 12:07:34 +02:00
if os.path.exists("resources/genetic_algorithm/optimalastar.pkl"): #jeżeli algorytm genetyczny utworzył plik wcześcniej to odczytaj
astar_costs = pickle.load(open(os.path.join('resources/genetic_algorithm', "optimalastar.pkl"), "rb"))
#kolejność alfabetyczna
2021-06-13 16:28:40 +02:00
definitions.BEETROOTS_ADULT_COST = astar_costs[0]
definitions.BEETROOTS_GROW_COST = astar_costs[1]
definitions.CARROTS_ADULT_COST = astar_costs[2]
definitions.CARROTS_GROW_COST = astar_costs[3]
definitions.DIRT_COST = astar_costs[4]
definitions.FARMLAND_DRY_COST = astar_costs[5]
definitions.FARMLAND_WET_COST = astar_costs[6]
definitions.FLOWER_DANDELION_COST = astar_costs[7]
definitions.POTATOES_ADULT_COST = astar_costs[8]
definitions.POTATOES_GROW_COST = astar_costs[9]
definitions.STATION_COST = astar_costs[10]
definitions.WHEAT_ADULT_COST = astar_costs[11]
definitions.WHEAT_GROW_COST = astar_costs[12]
2021-06-18 12:07:34 +02:00
else: #w przeciwnym razie ucz algorytmem genetycznym
astar_costs = [definitions.BEETROOTS_ADULT_COST, definitions.BEETROOTS_GROW_COST, definitions.CARROTS_ADULT_COST, definitions.CARROTS_GROW_COST, definitions.DIRT_COST, definitions.FARMLAND_DRY_COST, definitions.FARMLAND_WET_COST, definitions.FLOWER_DANDELION_COST, definitions.POTATOES_ADULT_COST, definitions.POTATOES_GROW_COST, definitions.STATION_COST, definitions.WHEAT_ADULT_COST, definitions.WHEAT_GROW_COST] #kolejność alfabetyczna
astar_costs = evolve(astar_costs)
pickle.dump(astar_costs, open(os.path.join('resources/genetic_algorithm', "optimalastar.pkl"), "wb"))
def evolve(astar_costs):
first_generation = [] #pierwsza generacja
overall_solutions = [] #rozwiązania końcowe
solutions = [] #rozwiązania danej generacji
for individual in range(definitions.GENETIC_ALGORITHM_NUMBER_OF_INDIVIDUALS_ZERO): #liczba osobników pierwszej generacji
for _ in range(definitions.GENETIC_ALGORITHM_COSTS_AMOUNT):
first_generation.append(random.uniform(0, 10))
solutions.append(first_generation) #generowanie losowych kosztów pól dla pierwszej generacji
for gen in range(definitions.GENETIC_ALGORITHM_NUMBER_OF_GENERATIONS): #liczba generacji
print(f"=== Generation {gen + 1} ===")
ranked_solutions = [] #rozwiązania z wynikiem
index = 0
for s in solutions: #przypisanie rozwiązaniom wyniku funkcji fitness
ranked_solutions.append((fitness(s, index), s))
index = index + 1
ranked_solutions.sort()
print(f"=== Gen {gen + 1} best solution ===")
print(ranked_solutions[0])
overall_solutions.append(ranked_solutions[0])
#TODO warunek stopu
best_solutions = ranked_solutions[:definitions.GENETIC_ALGORITHM_NUMBER_OF_BEST_INDIVIDUALS] #najlepsze osobniki w danej generacji
elements = []
for element in range(definitions.GENETIC_ALGORITHM_COSTS_AMOUNT):
elems = []
elements.append(elems)
for solution in best_solutions:
for element in range(definitions.GENETIC_ALGORITHM_COSTS_AMOUNT):
elements[element].append(solution[1][element])
next_generation = [] #nowa ganeracja
e = []
for individual in range(definitions.GENETIC_ALGORITHM_NUMBER_OF_INDIVIDUALS): #liczba osobników w kolejnej generacji
for el in range(definitions.GENETIC_ALGORITHM_COSTS_AMOUNT):
#mutacje
e.append(random.choice(elements[el]) * random.uniform(0.99, 1.01))
next_generation.append(e)
solutions = next_generation #zastąpnienie osobników nową generacją
overall_solutions.sort()
for _ in range(definitions.GENETIC_ALGORITHM_COSTS_AMOUNT): #przyspianie finalnych kosztów astara
astar_costs[_] = overall_solutions[0][1][_]
return astar_costs
def fitness(astar_costs, index):
ans = harvest(astar_costs, index)
if ans == 0: #TODO
2021-06-13 16:28:40 +02:00
return 0
else:
return 1 / ans
2021-06-18 12:07:34 +02:00
def harvest(astar_costs, index):
#kolejność alfabetyczna
2021-06-13 16:28:40 +02:00
definitions.BEETROOTS_ADULT_COST = astar_costs[0]
definitions.BEETROOTS_GROW_COST = astar_costs[1]
definitions.CARROTS_ADULT_COST = astar_costs[2]
definitions.CARROTS_GROW_COST = astar_costs[3]
definitions.DIRT_COST = astar_costs[4]
definitions.FARMLAND_DRY_COST = astar_costs[5]
definitions.FARMLAND_WET_COST = astar_costs[6]
definitions.FLOWER_DANDELION_COST = astar_costs[7]
definitions.POTATOES_ADULT_COST = astar_costs[8]
definitions.POTATOES_GROW_COST = astar_costs[9]
definitions.STATION_COST = astar_costs[10]
definitions.WHEAT_ADULT_COST = astar_costs[11]
definitions.WHEAT_GROW_COST = astar_costs[12]
#tworzenie podstawowych obiektów
map1 = map.Map([])
map1.create_base_map()
move_list = ["rotate_left", "move", "move", "move", "move", "move", "move", "rotate_left", "rotate_left", "move", "rotate_left", "rotate_left", "rotate_left", "rotate_left", "move", "rotate_left", "rotate_left", "rotate_left", "rotate_left", "move", "rotate_left", "rotate_left", "rotate_left", "move", "rotate_left", "rotate_left", "rotate_left", "rotate_left", "move", "rotate_left", "rotate_left", "rotate_left", "move", "rotate_left", "rotate_left", "rotate_left", "rotate_left", "move", "rotate_left", "rotate_left", "rotate_left", "move", "rotate_left", "rotate_left", "move", "rotate_left", "rotate_left", "rotate_left", "move", "rotate_left", "rotate_left", "rotate_left", "rotate_left", "rotate_left", "move", "move", "rotate_left", "rotate_left", "rotate_left", "rotate_left", "rotate_left", "move", "rotate_left", "rotate_left", "rotate_left", "move", "rotate_left", "move", "rotate_left", "rotate_left", "rotate_left", "rotate_left", "move", "rotate_left", "rotate_left", "move", "move", "move", "rotate_left", "rotate_left", "rotate_left", "rotate_left", "rotate_left", "move", "move", "rotate_left", "rotate_left", "rotate_left", "rotate_left", "rotate_left", "move", "rotate_left", "rotate_left", "rotate_left", "move", "rotate_left", "rotate_left", "rotate_left", "move", "rotate_left", "rotate_left", "rotate_left", "rotate_left", "rotate_left", "move", "rotate_left", "rotate_left", "rotate_left", "move"] #początkowe ruchy
amount_of_seeds_dict = {"beetroot": definitions.CART_AMOUNT_OF_SEEDS_EACH_TYPE, "carrot": definitions.CART_AMOUNT_OF_SEEDS_EACH_TYPE, "potato": definitions.CART_AMOUNT_OF_SEEDS_EACH_TYPE, "wheat": definitions.CART_AMOUNT_OF_SEEDS_EACH_TYPE}
collected_plants_dict_cart = {"beetroot": 0, "carrot": 0, "potato": 0, "wheat": 0}
collected_plants_dict_station = {"beetroot": 0, "carrot": 0, "potato": 0, "wheat": 0}
fertilizer_dict = {"beetroot": definitions.CART_FERTILIZER, "carrot": definitions.CART_FERTILIZER, "potato": definitions.CART_FERTILIZER, "wheat": definitions.CART_FERTILIZER}
station1 = station.Station(collected_plants_dict_station)
cart1 = cart.Cart(amount_of_seeds_dict, collected_plants_dict_cart, definitions.CART_DIRECTION_WEST, fertilizer_dict, definitions.CART_FUEL, definitions.CART_WATER_LEVEL, 0 * definitions.BLOCK_SIZE, 0 * definitions.BLOCK_SIZE)
cart1_rect = pygame.Rect(cart1.get_x(), cart1.get_y(), definitions.BLOCK_SIZE, definitions.BLOCK_SIZE)
tree = treelearn.treelearn() #tworzenie drzewa decyzyjnego
decision = [0] #początkowa decyzja o braku powrotu do stacji (0)
grow_flower_dandelion = False
random_movement = False
2021-06-18 12:07:34 +02:00
for run in range(definitions.GENETIC_ALGORITHM_NUMBER_OF_CART_MOVES): #liczba ruchów wózka
2021-06-13 16:28:40 +02:00
if not move_list: #jeżeli są jakieś ruchy do wykonania w move_list
grow_flower_dandelion = True
istate = graph.Istate(cart1.get_direction(), cart1.get_x() / definitions.BLOCK_SIZE, cart1.get_y() / definitions.BLOCK_SIZE) #stan początkowy wózka (jego orientacja oraz jego aktualne miejsce)
if plant.Plant.if_any_mature_plant(map1) is True: #jeżeli istnieje jakaś dojrzała roślina
random_movement = False
if decision == [0]: #jeżeli decyzja jest 0 (brak powrotu do stacji) to uprawiaj pole
move_list = (astar.graphsearch([], astar.f, [], plant.Plant.get_closest_mature_plant(istate, map1), istate, map1, graph.succ)) #lista z ruchami, które należy po kolei wykonać, astar
else: #jeżeli decyzja jest 1 (powrót do stacji) to wróć do stacji uzupełnić zapasy
move_list = (graph.graphsearch([], [], (0, 0), istate, graph.succ)) #lista z ruchami, które należy po kolei wykonać, graphsearch
else:
random_movement = True
elif move_list: #jeżeli move_list nie jest pusta
cart1.handle_movement(cart1_rect, move_list.pop(0)) #wykonaj kolejny ruch oraz zdejmij ten ruch z początku listy
if random_movement is True:
cart1.handle_movement_random(cart1_rect) #wykonuj losowe ruchy
if grow_flower_dandelion is True:
plant.Plant.grow_flower_dandelion(map1) #losuj urośnięcie kwiatka dandeliona
cart1.do_work(cart1_rect, map1, station1) #wykonaj pracę na danym polu
decision = treelearn.make_decision(cart1.get_all_amount_of_seeds(), cart1.get_all_collected_plants(), cart1.get_all_fertilizer(), cart1.get_fuel(), tree, cart1.get_water_level()) #podejmij decyzję czy wracać do stacji (0 : NIE, 1 : TAK)
plant.Plant.grow_plants(map1) #zwiększ poziom dojrzałości roślin
2021-06-18 12:07:34 +02:00
print("individual no.", index + 1, "score:", station1.get_all_collected_plants())
return station1.get_all_collected_plants()