genetic algorithms

This commit is contained in:
doasdsk 2023-06-16 10:47:38 +02:00
parent 7eaf166f2a
commit 704f19c23a
8 changed files with 337 additions and 57 deletions

3
.idea/.gitignore vendored Normal file
View File

@ -0,0 +1,3 @@
# Default ignored files
/shelf/
/workspace.xml

View File

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="PYTHON_MODULE" version="4">
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$">
<excludeFolder url="file://$MODULE_DIR$/.venv" />
</content>
<orderEntry type="jdk" jdkName="Python 3.9" jdkType="Python SDK" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>

View File

@ -0,0 +1,6 @@
<component name="InspectionProjectProfileManager">
<settings>
<option name="USE_PROJECT_PROFILE" value="false" />
<version value="1.0" />
</settings>
</component>

4
.idea/misc.xml Normal file
View File

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectRootManager" version="2" project-jdk-name="Python 3.9" project-jdk-type="Python SDK" />
</project>

8
.idea/modules.xml Normal file
View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/Intelegentny_Pszczelarz.iml" filepath="$PROJECT_DIR$/.idea/Intelegentny_Pszczelarz.iml" />
</modules>
</component>
</project>

6
.idea/vcs.xml Normal file
View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />
</component>
</project>

213
src/GeneticAlgorithm.py Normal file
View File

@ -0,0 +1,213 @@
import copy
import random
from Field import Field, Neighbors
import heapq as h
FLOWER = 0
SHORT = 1
TALL = 80
TREE = 100
population_size = 50
num_of_trees = 30
crossover_rate = 0.8
mutation_rate = 0.1
tilemapSizeX = 12
tilemapSizeY = 12
SHORT_VALUE = 1
TALL_VALUE = 100
TREE_VALUE = 200
tilemap_values = []
class Individual:
def __init__(self, genes):
self.genes = genes
self.fitness = 0
def __getitem__(self, index):
return self.genes[index]
def __setitem__(self, index, value):
self.genes[index] = value
class GA:
def __init__(self, population_size, generations, flower_positions, tilemap):
self.population_size = population_size
self.generations = generations
self.population = []
self.mutation_rate = mutation_rate
self.crossover_rate = crossover_rate
self.flower_positions = flower_positions
self.tilemap = tilemap
def initialize_population(self):
# Generate random individuals representing tree arrangements
for _ in range(self.population_size):
individual = self.generate_individual()
self.population.append(individual)
def generate_individual(self):
# Generate a random tree arrangement
individual = []
available_positions = [(x, y) for x in range(1, tilemapSizeX - 1) for y in range(1, tilemapSizeY - 1)]
random.shuffle(available_positions)
for i in range(num_of_trees):
individual.append(available_positions[i])
return Individual(individual)
def evaluate_fitness(self):
for individual in self.population:
individual.fitness = self.calculate_average_distance(individual.genes)
print(f"Fitness for individual {individual}: {individual.fitness}")
def calculate_average_distance(self, individual):
tilemap_values = []
local_tile_map = copy.deepcopy(self.tilemap)
total_distance = 0
# Set trees on the local tile map
for tree_x, tree_y in individual:
local_tile_map[tree_x][tree_y] = TREE
for X in range(0, len(local_tile_map)):
tilemap_values.append([])
for Y in range(0, len(local_tile_map[X])):
if local_tile_map[X][Y] == SHORT:
value = SHORT_VALUE
elif local_tile_map[X][Y] == TALL:
value = TALL_VALUE
elif local_tile_map[X][Y] == TREE:
value = TREE_VALUE
elif local_tile_map[X][Y] == FLOWER:
value = 1
tilemap_values[X].append(value)
field = Field(local_tile_map, tilemap_values)
for flower_x, flower_y in self.flower_positions:
totalFlowerDistance = 0
for flower2_x, flower2_y in self.flower_positions:
if flower_x == flower2_x and flower_y == flower2_y:
continue
pathAstar = A_star(field, (flower_x, flower_y, 3), (flower2_x, flower2_y))
if pathAstar is None:
continue
# Check for trees in the path
has_tree = False
for x, y, _ in pathAstar:
if local_tile_map[x][y] == TREE:
has_tree = True
break
if has_tree:
continue
# Calculate the unique positions in the path
check_path_A = []
for x, y, _ in pathAstar:
if (x, y) not in check_path_A:
check_path_A.append((x, y))
totalFlowerDistance += len(check_path_A)
total_distance += totalFlowerDistance
average_distance = total_distance / (len(self.flower_positions))
return average_distance
def selection(self):
# Select individuals based on their fitness
weights = [individual.fitness for individual in self.population]
selected = random.choices(self.population, weights=weights, k=self.population_size)
# Copy the selected individuals as the new population
self.population = selected
def crossover(self):
# Perform crossover between selected individuals to create offspring
offspring = []
while len(offspring) < self.population_size:
parent1, parent2 = random.sample(self.population, 2)
child = self.perform_crossover(parent1, parent2)
offspring.append(child)
self.population = offspring
def perform_crossover(self, parent1, parent2):
child_genes = []
for i in range(len(parent1.genes)):
# Perform crossover by randomly selecting genes from parents
if random.random() < self.crossover_rate:
child_genes.append(parent1.genes[i])
else:
child_genes.append(parent2.genes[i])
child = Individual(child_genes)
return child
def mutation(self):
# Perform mutation on the offspring
for individual in self.population:
if random.random() < mutation_rate:
self.perform_mutation(individual)
def perform_mutation(self, individual):
# Perform mutation operation on the individual
index1 = random.randint(0, num_of_trees - 1)
index2 = random.randint(0, num_of_trees - 1)
individual.genes[index1], individual.genes[index2] = individual.genes[index2], individual.genes[index1]
def run(self):
self.initialize_population()
for _ in range(self.generations):
self.evaluate_fitness()
self.selection()
self.crossover()
self.mutation()
self.evaluate_fitness()
best_individual = max(self.population, key=lambda x: x.fitness)
max_dist=best_individual.fitness
print(max_dist)
return best_individual
def Manhattan_dis(start, end):
start_x, start_y = start
end_x, end_y = end
return abs(start_x - end_x) + abs(start_y - end_y)
def Make_path(start, end, previos):
path = [end]
while start not in path:
path.append(previos[path[-1]])
path.reverse()
return path
def A_star(field, start, end):
open = []
previous = {}
closed = set()
checked = set()
now = (0, start)
h.heappush(open, (0, start))
while len(open) > 0:
now = h.heappop(open)
if now[1] in closed:
continue
if now[1][0:2] == end:
path = Make_path(start, now[1], previous)
return path
closed.add(now[1])
checked.add(now[1][0:2])
for x in Neighbors(field, now[1]):
if x not in closed and x not in checked:
previous[x] = now[1]
if now[1][0:2] != x[0:2]:
added_cost = field[x[0], x[1]] + Manhattan_dis(x[0:2], end)
else:
added_cost = 0
h.heappush(open, (now[0] + added_cost, x))
checked.add(x[0:2])

View File

@ -3,10 +3,56 @@ import random
#import Flower #import Flower
import Beehive import Beehive
import Frames import Frames
from GeneticAlgorithm import GA
from Field import Field, Neighbors from Field import Field, Neighbors
from queue import Queue from queue import Queue
import heapq as h import heapq as h
def Manhattan_dis(start, end):
start_x, start_y = start
end_x, end_y = end
return abs(start_x - end_x) + abs(start_y - end_y)
def Make_path(start, end, previos):
path = [end]
while start not in path:
path.append(previos[path[-1]])
path.reverse()
return path
def A_star(field, start, end):
open = []
previous = {}
closed = set()
checked = set()
now = (0, start)
h.heappush(open, (0, start))
while len(open) > 0:
now = h.heappop(open)
if now[1] in closed:
continue
if now[1][0:2] == end:
path = Make_path(start, now[1], previous)
return path
closed.add(now[1])
checked.add(now[1][0:2])
for x in Neighbors(field, now[1]):
if x not in closed and x not in checked:
previous[x] = now[1]
if now[1][0:2] != x[0:2]:
added_cost = field[x[0], x[1]] + Manhattan_dis(x[0:2], end)
else:
added_cost = 0
h.heappush(open, (now[0] + added_cost, x))
checked.add(x)
white = (255, 255, 255) white = (255, 255, 255)
#setting caption and icon #setting caption and icon
@ -42,13 +88,13 @@ tiles_types = {
SHORT: pygame.image.load('spritesNtiles/shortGrass64.png'), SHORT: pygame.image.load('spritesNtiles/shortGrass64.png'),
TALL: pygame.image.load('spritesNtiles/tallGrass64.png'), TALL: pygame.image.load('spritesNtiles/tallGrass64.png'),
TREE: pygame.image.load('spritesNtiles/dirtTree64.png'), TREE: pygame.image.load('spritesNtiles/dirtTree64.png'),
FLOWER: pygame.image.load('spritesNtiles/input.png') FLOWER: pygame.image.load('spritesNtiles/flower64.png')
} }
tilemapSizeX = 25 tilemapSizeX = 12
tilemapSizeY = 15 tilemapSizeY = 12
tileSize = 64 tileSize = 64
tilemap_types = [] tilemap_types = []
@ -63,17 +109,12 @@ for x in range(tilemapSizeX):
#example tilemap values #example tilemap values
tilemap_values = [] tilemap_values = []
SHORT_VALUE = 5 SHORT_VALUE = 1
TALL_VALUE = 100 TALL_VALUE = 100
TREE_VALUE = 50 TREE_VALUE = 200
FLOWER_VALUE = 1
for X in range(0, len(tilemap_types)):
tilemap_values.append([])
for Y in range(0, len(tilemap_types[X])):
if tilemap_types[X][Y] == SHORT: value = SHORT_VALUE
elif tilemap_types[X][Y] == TALL: value = TALL_VALUE
elif tilemap_types[X][Y] == TREE: value = TREE_VALUE
tilemap_values[X].append(value)
### ###
@ -90,52 +131,43 @@ dis = pygame.display.set_mode((disX, disY))
clock = pygame.time.Clock() clock = pygame.time.Clock()
#position of the bee and pos changings #position of the bee and pos changings
bee_x = 2
bee_y = 1
bee_dir = 'west'
# Define parameters
flower_positions = [(flower_x, flower_y) for flower_x in range(tilemapSizeX) for flower_y in range(tilemapSizeY) if tilemap_types[flower_x][flower_y] == FLOWER]
generations = 10
# Create an instance of the GeneticAlgorithm class
ga = GA(10, generations,flower_positions, tilemap_types)
# Run the genetic algorithm
best_individual = ga.run()
print(best_individual)
# Retrieve the best tree arrangement from the best individual
tree_arrangement = best_individual
# Render the tilemap with the optimized tree positions
for x, y in tree_arrangement:
tilemap_types[x][y] = TREE
print(x,y)
for X in range(0, len(tilemap_types)):
tilemap_values.append([])
for Y in range(0, len(tilemap_types[X])):
if tilemap_types[X][Y] == SHORT: value = SHORT_VALUE
elif tilemap_types[X][Y] == TALL: value = TALL_VALUE
elif tilemap_types[X][Y] == TREE: value = TREE_VALUE
elif tilemap_types[X][Y] == FLOWER: value = FLOWER_VALUE
tilemap_values[X].append(value)
field = Field(tilemap_types, tilemap_values) field = Field(tilemap_types, tilemap_values)
def Manhattan_dis(start, end): bee_dir = 'west'
start_x, start_y = start while True:
end_x, end_y = end bee_x = random.randint(0, tilemapSizeX-2)
return abs(start_x - end_x) + abs(start_y - end_y) bee_y = random.randint(0, tilemapSizeY-2)
if(field.get_type([bee_x, bee_y]) != TREE):
def Make_path(start, end, previos): break
path = [end]
while start not in path:
path.append(previos[path[-1]])
path.reverse()
return path
def A_star(field, start, end):
open = []
previous = {}
closed = set()
checked = set()
now = (0, start)
h.heappush(open, (0, start))
while len(open) > 0:
now = h.heappop(open)
if now[1] in closed:
continue
if now[1][0:2] == end:
path = Make_path(start, now[1], previous)
return path
closed.add(now[1])
checked.add(now[1][0:2])
for x in Neighbors(field, now[1]):
if x not in closed and x not in checked:
previous[x] = now[1]
if now[1][0:2] != x[0:2]:
added_cost = field[x[0], x[1]] + Manhattan_dis(x[0:2], end)
else : added_cost = 0
h.heappush(open, (now[0] + added_cost, x))
checked.add(x)
while True: while True:
@ -154,6 +186,7 @@ for x in path_A_star:
if x[0:2] not in check_path_A: if x[0:2] not in check_path_A:
check_path_A.append(x[0:2]) check_path_A.append(x[0:2])
print(check_path_A) print(check_path_A)
print(len(check_path_A))
path = path_A_star path = path_A_star
@ -198,6 +231,3 @@ while True:
if(step == -1 and current_node == 0): if(step == -1 and current_node == 0):
step *= -1 step *= -1
current_node += step current_node += step
## setitem, bfs