SprytnyTraktor/geneticalgorithm.py

177 lines
11 KiB
Python
Raw Permalink 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
2021-06-18 12:16:19 +02:00
2021-06-13 16:28:40 +02:00
def create_genetic_algorithm():
2021-06-18 12:16:19 +02:00
if os.path.exists(
"resources/genetic_algorithm/optimalastar.pkl"): # jeżeli algorytm genetyczny utworzył plik wcześcniej to odczytaj
2021-06-18 12:07:34 +02:00
astar_costs = pickle.load(open(os.path.join('resources/genetic_algorithm', "optimalastar.pkl"), "rb"))
2021-06-18 12:16:19 +02:00
# 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:16:19 +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
2021-06-18 12:07:34 +02:00
astar_costs = evolve(astar_costs)
pickle.dump(astar_costs, open(os.path.join('resources/genetic_algorithm', "optimalastar.pkl"), "wb"))
2021-06-18 12:16:19 +02:00
2021-06-18 12:07:34 +02:00
def evolve(astar_costs):
2021-06-18 12:16:19 +02:00
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
2021-06-18 12:07:34 +02:00
for _ in range(definitions.GENETIC_ALGORITHM_COSTS_AMOUNT):
first_generation.append(random.uniform(0, 10))
2021-06-18 12:16:19 +02:00
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
2021-06-18 12:07:34 +02:00
print(f"=== Generation {gen + 1} ===")
2021-06-18 12:16:19 +02:00
ranked_solutions = [] # rozwiązania z wynikiem
2021-06-18 12:07:34 +02:00
index = 0
2021-06-18 12:16:19 +02:00
for s in solutions: # przypisanie rozwiązaniom wyniku funkcji fitness
2021-06-18 12:07:34 +02:00
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])
2021-06-18 12:16:19 +02:00
# TODO warunek stopu
best_solutions = ranked_solutions[
:definitions.GENETIC_ALGORITHM_NUMBER_OF_BEST_INDIVIDUALS] # najlepsze osobniki w danej generacji
2021-06-18 12:07:34 +02:00
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])
2021-06-18 12:16:19 +02:00
next_generation = [] # nowa ganeracja
2021-06-18 12:07:34 +02:00
e = []
2021-06-18 12:16:19 +02:00
for individual in range(
definitions.GENETIC_ALGORITHM_NUMBER_OF_INDIVIDUALS): # liczba osobników w kolejnej generacji
2021-06-18 12:07:34 +02:00
for el in range(definitions.GENETIC_ALGORITHM_COSTS_AMOUNT):
2021-06-18 12:16:19 +02:00
# mutacje
2021-06-18 12:07:34 +02:00
e.append(random.choice(elements[el]) * random.uniform(0.99, 1.01))
next_generation.append(e)
2021-06-18 12:16:19 +02:00
solutions = next_generation # zastąpnienie osobników nową generacją
2021-06-18 12:07:34 +02:00
overall_solutions.sort()
2021-06-18 12:16:19 +02:00
for _ in range(definitions.GENETIC_ALGORITHM_COSTS_AMOUNT): # przyspianie finalnych kosztów astara
2021-06-18 12:07:34 +02:00
astar_costs[_] = overall_solutions[0][1][_]
return astar_costs
2021-06-18 12:16:19 +02:00
2021-06-18 12:07:34 +02:00
def fitness(astar_costs, index):
ans = harvest(astar_costs, index)
2021-06-18 12:16:19 +02:00
if ans == 0: # TODO
2021-06-13 16:28:40 +02:00
return 0
else:
return 1 / ans
2021-06-18 12:16:19 +02:00
2021-06-18 12:07:34 +02:00
def harvest(astar_costs, index):
2021-06-18 12:16:19 +02:00
# 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:16:19 +02:00
# tworzenie podstawowych obiektów
2021-06-13 16:28:40 +02:00
map1 = map.Map([])
map1.create_base_map()
2021-06-18 12:16:19 +02:00
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}
2021-06-13 16:28:40 +02:00
collected_plants_dict_cart = {"beetroot": 0, "carrot": 0, "potato": 0, "wheat": 0}
collected_plants_dict_station = {"beetroot": 0, "carrot": 0, "potato": 0, "wheat": 0}
2021-06-18 12:16:19 +02:00
fertilizer_dict = {"beetroot": definitions.CART_FERTILIZER, "carrot": definitions.CART_FERTILIZER,
"potato": definitions.CART_FERTILIZER, "wheat": definitions.CART_FERTILIZER}
2021-06-13 16:28:40 +02:00
station1 = station.Station(collected_plants_dict_station)
2021-06-18 12:16:19 +02:00
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)
2021-06-13 16:28:40 +02:00
cart1_rect = pygame.Rect(cart1.get_x(), cart1.get_y(), definitions.BLOCK_SIZE, definitions.BLOCK_SIZE)
2021-06-18 12:16:19 +02:00
tree = treelearn.treelearn() # tworzenie drzewa decyzyjnego
decision = [0] # początkowa decyzja o braku powrotu do stacji (0)
2021-06-13 16:28:40 +02:00
grow_flower_dandelion = False
random_movement = False
2021-06-18 12:16:19 +02:00
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
2021-06-13 16:28:40 +02:00
grow_flower_dandelion = True
2021-06-18 12:16:19 +02:00
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
2021-06-13 16:28:40 +02:00
random_movement = False
2021-06-18 12:16:19 +02:00
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
2021-06-13 16:28:40 +02:00
else:
random_movement = True
2021-06-18 12:16:19 +02:00
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
2021-06-13 16:28:40 +02:00
if random_movement is True:
2021-06-18 12:16:19 +02:00
cart1.handle_movement_random(cart1_rect) # wykonuj losowe ruchy
2021-06-13 16:28:40 +02:00
if grow_flower_dandelion is True:
2021-06-18 12:16:19 +02:00
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())
2021-06-18 12:16:19 +02:00
return station1.get_all_collected_plants()