dodanie algorytmu genetycznego
This commit is contained in:
parent
71e9bea0ba
commit
4b9a06b7ee
@ -6,7 +6,7 @@ class Constants:
|
|||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.BLACK = (0, 0, 0)
|
self.BLACK = (0, 0, 0)
|
||||||
self.RED = (255, 0, 0)
|
self.RED = (255, 0, 0)
|
||||||
self.GRID_SIZE = 75
|
self.GRID_SIZE = 65
|
||||||
self.GRID_WIDTH = 30
|
self.GRID_WIDTH = 30
|
||||||
self.GRID_HEIGHT = 15
|
self.GRID_HEIGHT = 15
|
||||||
self.WINDOW_SIZE = (self.GRID_WIDTH * self.GRID_SIZE, self.GRID_HEIGHT * self.GRID_SIZE)
|
self.WINDOW_SIZE = (self.GRID_WIDTH * self.GRID_SIZE, self.GRID_HEIGHT * self.GRID_SIZE)
|
||||||
|
148
genetics.py
Normal file
148
genetics.py
Normal file
@ -0,0 +1,148 @@
|
|||||||
|
from state_space_search import graphsearch, generate_cost_map
|
||||||
|
import random
|
||||||
|
|
||||||
|
# Parametry algorytmu genetycznego
|
||||||
|
POPULATION_SIZE = 700
|
||||||
|
MUTATION_RATE = 0.01
|
||||||
|
NUM_GENERATIONS = 600
|
||||||
|
|
||||||
|
# Generowanie początkowej populacji
|
||||||
|
def generate_individual(animals):
|
||||||
|
return random.sample(animals, len(animals))
|
||||||
|
|
||||||
|
def generate_population(animals, size):
|
||||||
|
return [generate_individual(animals) for _ in range(size)]
|
||||||
|
|
||||||
|
# Obliczanie odległości między zwierzetami
|
||||||
|
def calculate_distance(animal1, animal2):
|
||||||
|
x1, y1 = animal1
|
||||||
|
x2, y2 = animal2
|
||||||
|
return abs(x1 - x2) + abs(y1 - y2) # Odległość Manhattana
|
||||||
|
|
||||||
|
def calculate_total_distance(animals):
|
||||||
|
total_distance = 0
|
||||||
|
for i in range(len(animals) - 1):
|
||||||
|
total_distance += calculate_distance(animals[i], animals[i+1])
|
||||||
|
total_distance += calculate_distance(animals[-1], animals[0]) # Zamknięcie cyklu
|
||||||
|
return total_distance
|
||||||
|
|
||||||
|
# Selekcja rodziców za pomocą metody ruletki
|
||||||
|
def select_parents(population, num_parents):
|
||||||
|
fitness_scores = [1 / calculate_total_distance(individual) for individual in population]
|
||||||
|
total_fitness = sum(fitness_scores)
|
||||||
|
selection_probs = [fitness / total_fitness for fitness in fitness_scores]
|
||||||
|
|
||||||
|
parents = random.choices(population, weights=selection_probs, k=num_parents)
|
||||||
|
return parents
|
||||||
|
|
||||||
|
# Krzyżowanie rodziców (OX,Davis)
|
||||||
|
def crossover(parent1, parent2):
|
||||||
|
child1 = [None] * len(parent1)
|
||||||
|
child2 = [None] * len(parent1)
|
||||||
|
start_index = random.randint(0, len(parent1) - 1)
|
||||||
|
end_index = random.randint(start_index, len(parent1) - 1)
|
||||||
|
child1[start_index:end_index+1] = parent1[start_index:end_index+1]
|
||||||
|
child2[start_index:end_index+1] = parent2[start_index:end_index+1]
|
||||||
|
|
||||||
|
# Uzupełnienie brakujących zwierząt z drugiego rodzica
|
||||||
|
for i in range(len(parent1)):
|
||||||
|
if parent2[i] not in child1:
|
||||||
|
for j in range(len(parent2)):
|
||||||
|
if child1[j] is None:
|
||||||
|
child1[j] = parent2[i]
|
||||||
|
break
|
||||||
|
|
||||||
|
for i in range(len(parent1)):
|
||||||
|
if parent1[i] not in child2:
|
||||||
|
for j in range(len(parent1)):
|
||||||
|
if child2[j] is None:
|
||||||
|
child2[j] = parent1[i]
|
||||||
|
break
|
||||||
|
|
||||||
|
return child1, child2
|
||||||
|
|
||||||
|
# Mutacja: zamiana dwóch losowych zwierząt z prawdopodobieństwem MUTATION_RATE
|
||||||
|
def mutate(individual):
|
||||||
|
if random.random() < MUTATION_RATE:
|
||||||
|
index1, index2 = random.sample(range(len(individual)), 2)
|
||||||
|
individual[index1], individual[index2] = individual[index2], individual[index1]
|
||||||
|
|
||||||
|
# Algorytm genetyczny
|
||||||
|
def genetic_algorithm(animals):
|
||||||
|
population = generate_population(animals, POPULATION_SIZE)
|
||||||
|
|
||||||
|
for generation in range(NUM_GENERATIONS):
|
||||||
|
# Selekcja rodziców
|
||||||
|
parents = select_parents(population, POPULATION_SIZE // 2)
|
||||||
|
|
||||||
|
# Krzyżowanie i tworzenie nowej populacji
|
||||||
|
next_generation = []
|
||||||
|
for i in range(0, len(parents), 2):
|
||||||
|
parent1 = parents[i]
|
||||||
|
if i + 1 < len(parents):
|
||||||
|
parent2 = parents[i + 1]
|
||||||
|
else:
|
||||||
|
parent2 = parents[0]
|
||||||
|
child1, child2 = crossover(parent1, parent2)
|
||||||
|
next_generation.extend([child1, child2])
|
||||||
|
|
||||||
|
# Mutacja nowej populacji
|
||||||
|
for individual in next_generation:
|
||||||
|
mutate(individual)
|
||||||
|
|
||||||
|
# Zastąpienie starej populacji nową
|
||||||
|
population = next_generation
|
||||||
|
|
||||||
|
# Znalezienie najlepszego osobnika
|
||||||
|
best_individual = min(population, key=calculate_total_distance)
|
||||||
|
|
||||||
|
return best_individual
|
||||||
|
|
||||||
|
# def calculate_distance(start, goal, max_x, max_y, obstacles, cost_map):
|
||||||
|
# istate = (start[0], start[1], 'N') # Zakładamy, że zaczynamy od kierunku północnego
|
||||||
|
# actions, cost = graphsearch(istate, goal, max_x, max_y, obstacles, cost_map)
|
||||||
|
# return cost
|
||||||
|
|
||||||
|
# def calculate_total_distance(animals, max_x, max_y, obstacles, cost_map):
|
||||||
|
# total_distance = 0
|
||||||
|
# for i in range(len(animals) - 1):
|
||||||
|
# total_distance += calculate_distance(animals[i], animals[i+1], max_x, max_y, obstacles, cost_map)
|
||||||
|
# total_distance += calculate_distance(animals[-1], animals[0], max_x, max_y, obstacles, cost_map) # Zamknięcie cyklu
|
||||||
|
# return total_distance
|
||||||
|
|
||||||
|
# # Selekcja rodziców za pomocą metody ruletki
|
||||||
|
# def select_parents(population, num_parents, max_x, max_y, obstacles, cost_map):
|
||||||
|
# fitness_scores = [1 / calculate_total_distance(individual, max_x, max_y, obstacles, cost_map) for individual in population]
|
||||||
|
# total_fitness = sum(fitness_scores)
|
||||||
|
# selection_probs = [fitness / total_fitness for fitness in fitness_scores]
|
||||||
|
|
||||||
|
# parents = random.choices(population, weights=selection_probs, k=num_parents)
|
||||||
|
# return parents
|
||||||
|
|
||||||
|
|
||||||
|
# def genetic_algorithm(animals, max_x, max_y, obstacles, cost_map):
|
||||||
|
# population = generate_population(animals, POPULATION_SIZE)
|
||||||
|
|
||||||
|
# for generation in range(NUM_GENERATIONS):
|
||||||
|
# # Selekcja rodziców
|
||||||
|
# parents = select_parents(population, POPULATION_SIZE // 2, max_x, max_y, obstacles, cost_map)
|
||||||
|
|
||||||
|
# # Krzyżowanie i tworzenie nowej populacji
|
||||||
|
# next_generation = []
|
||||||
|
# for i in range(0, len(parents), 2):
|
||||||
|
# parent1 = parents[i]
|
||||||
|
# parent2 = parents[i + 1]
|
||||||
|
# child1, child2 = crossover(parent1, parent2)
|
||||||
|
# next_generation.extend([child1, child2])
|
||||||
|
|
||||||
|
# # Mutacja nowej populacji
|
||||||
|
# for individual in next_generation:
|
||||||
|
# mutate(individual)
|
||||||
|
|
||||||
|
# # Zastąpienie starej populacji nową
|
||||||
|
# population = next_generation
|
||||||
|
|
||||||
|
# # Znalezienie najlepszego osobnika
|
||||||
|
# best_individual = min(population, key=lambda individual: calculate_total_distance(individual, max_x, max_y, obstacles, cost_map))
|
||||||
|
|
||||||
|
# return best_individual
|
52
main.py
52
main.py
@ -13,6 +13,7 @@ from constants import Constants, init_pygame
|
|||||||
from draw import draw_goal, draw_grid, draw_house
|
from draw import draw_goal, draw_grid, draw_house
|
||||||
from season import draw_background
|
from season import draw_background
|
||||||
from night import change_time
|
from night import change_time
|
||||||
|
from genetics import genetic_algorithm
|
||||||
|
|
||||||
const = Constants()
|
const = Constants()
|
||||||
init_pygame(const)
|
init_pygame(const)
|
||||||
@ -77,12 +78,13 @@ def main():
|
|||||||
actions = []
|
actions = []
|
||||||
clock = pygame.time.Clock()
|
clock = pygame.time.Clock()
|
||||||
spawned = False
|
spawned = False
|
||||||
|
route = False
|
||||||
|
|
||||||
# Lista zawierająca klatki do odwiedzenia
|
# # Lista zawierająca klatki do odwiedzenia
|
||||||
enclosures_to_visit = Enclosures.copy()
|
# enclosures_to_visit = Enclosures.copy()
|
||||||
current_enclosure_index = -1 # Indeks bieżącej klatki
|
# current_enclosure_index = -1 # Indeks bieżącej klatki
|
||||||
actions_to_compare_list = [] # Lista zawierająca ścieżki do porównania
|
# actions_to_compare_list = [] # Lista zawierająca ścieżki do porównania
|
||||||
goals_to_compare_list = list() # Lista zawierająca cele do porównania
|
# goals_to_compare_list = list() # Lista zawierająca cele do porównania
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
for event in pygame.event.get():
|
for event in pygame.event.get():
|
||||||
@ -106,6 +108,11 @@ def main():
|
|||||||
animal._feed = random.randint(0, 10)
|
animal._feed = random.randint(0, 10)
|
||||||
spawned = True
|
spawned = True
|
||||||
|
|
||||||
|
if not route:
|
||||||
|
animals = [(animal.x, animal.y) for animal in Animals]
|
||||||
|
best_route = genetic_algorithm(animals)
|
||||||
|
route = True
|
||||||
|
|
||||||
draw_Animals(Animals, const)
|
draw_Animals(Animals, const)
|
||||||
draw_Terrain_Obstacles(Terrain_Obstacles, const)
|
draw_Terrain_Obstacles(Terrain_Obstacles, const)
|
||||||
agent.draw(const)
|
agent.draw(const)
|
||||||
@ -118,31 +125,34 @@ def main():
|
|||||||
pygame.time.wait(200)
|
pygame.time.wait(200)
|
||||||
else:
|
else:
|
||||||
if agent._dryfood > 1 and agent._wetfood > 1 :
|
if agent._dryfood > 1 and agent._wetfood > 1 :
|
||||||
if not goals_to_compare_list:
|
# if not goals_to_compare_list:
|
||||||
current_enclosure_index = (current_enclosure_index + 1) % len(enclosures_to_visit)
|
# current_enclosure_index = (current_enclosure_index + 1) % len(enclosures_to_visit)
|
||||||
current_enclosure = enclosures_to_visit[current_enclosure_index]
|
# current_enclosure = enclosures_to_visit[current_enclosure_index]
|
||||||
|
|
||||||
for animal in current_enclosure.animals:
|
# for animal in current_enclosure.animals:
|
||||||
goal = (animal.x, animal.y)
|
# goal = (animal.x, animal.y)
|
||||||
goals_to_compare_list.append(goal)
|
# goals_to_compare_list.append(goal)
|
||||||
|
|
||||||
actions_to_compare = graphsearch(agent.istate, goal, const.GRID_WIDTH, const.GRID_HEIGHT, obstacles, cost_map)
|
# actions_to_compare = graphsearch(agent.istate, goal, const.GRID_WIDTH, const.GRID_HEIGHT, obstacles, cost_map)
|
||||||
actions_to_compare_list.append((actions_to_compare, goal))
|
# actions_to_compare_list.append((actions_to_compare, goal))
|
||||||
|
|
||||||
chosen_path_and_goal = min(actions_to_compare_list, key=lambda x: len(x[0]))
|
# chosen_path_and_goal = min(actions_to_compare_list, key=lambda x: len(x[0]))
|
||||||
goal = chosen_path_and_goal[1]
|
# goal = chosen_path_and_goal[1]
|
||||||
|
# draw_goal(const, goal)
|
||||||
|
|
||||||
|
# # Usuń wybrany element z listy
|
||||||
|
# actions_to_compare_list.remove(chosen_path_and_goal)
|
||||||
|
# goals_to_compare_list.remove(goal)
|
||||||
|
goal = best_route.pop(0)
|
||||||
|
best_route.append(goal)
|
||||||
draw_goal(const, goal)
|
draw_goal(const, goal)
|
||||||
|
|
||||||
# Usuń wybrany element z listy
|
actions, cost = graphsearch(agent.istate, goal, const.GRID_WIDTH, const.GRID_HEIGHT, obstacles, cost_map)
|
||||||
actions_to_compare_list.remove(chosen_path_and_goal)
|
|
||||||
goals_to_compare_list.remove(goal)
|
|
||||||
|
|
||||||
actions = graphsearch(agent.istate, goal, const.GRID_WIDTH, const.GRID_HEIGHT, obstacles, cost_map)
|
|
||||||
|
|
||||||
else:
|
else:
|
||||||
goal = (3,1)
|
goal = (3,1)
|
||||||
draw_goal(const, goal)
|
draw_goal(const, goal)
|
||||||
actions = graphsearch(agent.istate, goal, const.GRID_WIDTH, const.GRID_HEIGHT, obstacles, cost_map)
|
actions, cost = graphsearch(agent.istate, goal, const.GRID_WIDTH, const.GRID_HEIGHT, obstacles, cost_map)
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
main()
|
main()
|
@ -40,7 +40,7 @@ def graphsearch(istate, goal, max_x, max_y, obstacles, cost_map):
|
|||||||
state, _, _ = node
|
state, _, _ = node
|
||||||
|
|
||||||
if goaltest(state, goal):
|
if goaltest(state, goal):
|
||||||
return build_action_sequence(node)
|
return build_action_sequence(node), current_cost(node, cost_map)
|
||||||
|
|
||||||
explored.add(state)
|
explored.add(state)
|
||||||
|
|
||||||
@ -61,7 +61,7 @@ def graphsearch(istate, goal, max_x, max_y, obstacles, cost_map):
|
|||||||
else:
|
else:
|
||||||
break
|
break
|
||||||
|
|
||||||
return False
|
return False, float('inf')
|
||||||
|
|
||||||
def is_state_in_queue(state, queue):
|
def is_state_in_queue(state, queue):
|
||||||
for _, (s, _, _) in queue.queue:
|
for _, (s, _, _) in queue.queue:
|
||||||
@ -125,3 +125,4 @@ def generate_cost_map(Animals, Terrain_Obstacles, cost_map={}):
|
|||||||
cost_map[(terrain_obstacle.x , terrain_obstacle.y )] = bush_cost
|
cost_map[(terrain_obstacle.x , terrain_obstacle.y )] = bush_cost
|
||||||
|
|
||||||
return cost_map
|
return cost_map
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user