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 Beehive
import Frames
from GeneticAlgorithm import GA
from Field import Field, Neighbors
from queue import Queue
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)
#setting caption and icon
@ -42,13 +88,13 @@ tiles_types = {
SHORT: pygame.image.load('spritesNtiles/shortGrass64.png'),
TALL: pygame.image.load('spritesNtiles/tallGrass64.png'),
TREE: pygame.image.load('spritesNtiles/dirtTree64.png'),
FLOWER: pygame.image.load('spritesNtiles/input.png')
FLOWER: pygame.image.load('spritesNtiles/flower64.png')
}
tilemapSizeX = 25
tilemapSizeY = 15
tilemapSizeX = 12
tilemapSizeY = 12
tileSize = 64
tilemap_types = []
@ -63,17 +109,12 @@ for x in range(tilemapSizeX):
#example tilemap values
tilemap_values = []
SHORT_VALUE = 5
SHORT_VALUE = 1
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()
#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)
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)
bee_dir = 'west'
while True:
bee_x = random.randint(0, tilemapSizeX-2)
bee_y = random.randint(0, tilemapSizeY-2)
if(field.get_type([bee_x, bee_y]) != TREE):
break
while True:
@ -154,6 +186,7 @@ for x in path_A_star:
if x[0:2] not in check_path_A:
check_path_A.append(x[0:2])
print(check_path_A)
print(len(check_path_A))
path = path_A_star
@ -198,6 +231,3 @@ while True:
if(step == -1 and current_node == 0):
step *= -1
current_node += step
## setitem, bfs