diff --git a/genetic_algorithm_matrix.pkl b/genetic_algorithm_matrix.pkl new file mode 100644 index 0000000..532187a Binary files /dev/null and b/genetic_algorithm_matrix.pkl differ diff --git a/main.py b/main.py index eb7655d..0c39300 100644 --- a/main.py +++ b/main.py @@ -1,7 +1,7 @@ import pygame import sys import random -from settings import SIZE, directions, draw_lines_on_window +from settings import SIZE, directions, draw_lines_on_window, matrix_plants_type from src.map import drawRoads, seedForFirstTime, return_fields_list, WORLD_MATRIX, get_type_by_position from src.Tractor import Tractor from src.bfs import Astar @@ -45,6 +45,7 @@ def recognize_plants(fields, destination): print(pred) return pred + # pygame initialization pygame.init() clock = pygame.time.Clock() diff --git a/settings.py b/settings.py index 9263560..f26018c 100644 --- a/settings.py +++ b/settings.py @@ -1,6 +1,11 @@ from cmath import sqrt import pygame +import pickle +def load_matrix(filename): + with open(filename, 'rb') as file: + matrix = pickle.load(file) + return matrix screen_width = 1368 screen_height = 936 @@ -18,6 +23,7 @@ field_width = 4 field_height = 4 field_size = field_width*field_height fields_amount = 25 +matrix_plants_type = load_matrix("genetic_algorithm_matrix.pkl") directions = {0: 'UP', 90: 'RIGHT', 180: 'DOWN', 270: 'LEFT'} @@ -29,4 +35,6 @@ def draw_lines_on_window(background): pygame.draw.line(background, (0, 0, 0), (968, 285), (1336 , 285)) pygame.draw.line(background, (0, 0, 0), (968, 649), (1336 , 649)) pygame.draw.line(background, (0, 0, 0), (968, 285), (968, 649)) - pygame.draw.line(background, (0, 0, 0), (1336, 285), (1336, 649)) \ No newline at end of file + pygame.draw.line(background, (0, 0, 0), (1336, 285), (1336, 649)) + + diff --git a/src/genetic_algorithm.py b/src/genetic_algorithm.py new file mode 100644 index 0000000..4ef097b --- /dev/null +++ b/src/genetic_algorithm.py @@ -0,0 +1,161 @@ +import random +import copy +import pickle +import numpy + +# Constants +GRID_SIZE = 5 +PLANT_TYPES = [1, 2, 3] +POPULATION_SIZE = 1000 +MAX_GENERATIONS = 100 +MUTATION_RATE = 0.1 + +def generate_random_chromosome(): + # Generate a random chromosome (random matrix) + chromosome = [[0] * GRID_SIZE for _ in range(GRID_SIZE)] + + for row in range(GRID_SIZE): + for col in range(GRID_SIZE): + available_types = PLANT_TYPES.copy() + chromosome[row][col] = random.choice(available_types) + + return chromosome + +def calculate_fitness(chromosome): + # Calculate the fitness by counting the number of adjacent fields with the same plant type + fitness = 0 + appearances = [0,0,0] + + for row in range(GRID_SIZE): + for col in range(GRID_SIZE): + plant_type = chromosome[row][col] + + # Check left neighbor + if col > 0 and chromosome[row][col - 1] == plant_type: + fitness += 1 + # Check top neighbor + if row > 0 and chromosome[row - 1][col] == plant_type: + fitness += 1 + + + for row in chromosome: + appearances[0] = appearances[0] + row.count(1) + appearances[1] = appearances[1] + row.count(2) + appearances[2] = appearances[2] + row.count(3) + + for i in range(len(appearances)): + if appearances[i] < 7 and appearances[i] > 9: + fitness = fitness + abs(appearances[i]-8) + return fitness + +def selection(population): + # Perform tournament selection to choose parents for reproduction + tournament_size = 5 + parents = [] + + for _ in range(len(population)): + tournament = random.sample(population, tournament_size) + tournament.sort(key=lambda chromosome: calculate_fitness(chromosome)) + parents.append(tournament[0]) + + return parents + +def crossover(parent1, parent2): + # Perform single-point crossover to create two offspring + crossover_point = random.randint(0, (GRID_SIZE*GRID_SIZE)-1) + + row = crossover_point // GRID_SIZE + column = crossover_point % GRID_SIZE + offspring1 = [] + offspring2 = [] + counter = 0 + while counter