SprytnyTraktor/geneticalgorithm.py
2021-06-18 12:16:19 +02:00

177 lines
11 KiB
Python

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():
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
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]
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
return 0
else:
return 1 / ans
def harvest(astar_costs, index):
# kolejność alfabetyczna
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
for run in range(definitions.GENETIC_ALGORITHM_NUMBER_OF_CART_MOVES): # liczba ruchów wózka
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
print("individual no.", index + 1, "score:", station1.get_all_collected_plants())
return station1.get_all_collected_plants()