Compare commits
7 Commits
master
...
genetical-
Author | SHA1 | Date | |
---|---|---|---|
8204825a97 | |||
4b828f878b | |||
084e96ba7d | |||
e56854690c | |||
068ee153a0 | |||
d31a708e35 | |||
6c6b1bbc5b |
BIN
__pycache__/board.cpython-311.pyc
Normal file
BIN
__pycache__/board.cpython-311.pyc
Normal file
Binary file not shown.
BIN
__pycache__/constant.cpython-311.pyc
Normal file
BIN
__pycache__/constant.cpython-311.pyc
Normal file
Binary file not shown.
BIN
__pycache__/kolejka.cpython-311.pyc
Normal file
BIN
__pycache__/kolejka.cpython-311.pyc
Normal file
Binary file not shown.
BIN
__pycache__/tractor.cpython-311.pyc
Normal file
BIN
__pycache__/tractor.cpython-311.pyc
Normal file
Binary file not shown.
66
board.py
66
board.py
@ -2,7 +2,6 @@ import pygame
|
||||
from constant import size, rows, cols
|
||||
import random
|
||||
from tractor import Tractor
|
||||
|
||||
class Board:
|
||||
def __init__(self):
|
||||
self.board = []
|
||||
@ -11,6 +10,7 @@ class Board:
|
||||
self.load_costs()
|
||||
|
||||
|
||||
|
||||
def load_images(self):
|
||||
self.grass = pygame.image.load("board/grass.png")
|
||||
self.dirt = pygame.image.load("board/dirt.png")
|
||||
@ -20,38 +20,53 @@ class Board:
|
||||
self.carrot = pygame.image.load("board/carrot.png")
|
||||
|
||||
def generate_board(self):
|
||||
self.board = [[random.choice([0,1,2,3,4,5,6,7,8,9]) for _ in range(rows)] for _ in range(cols)]
|
||||
# Najpierw wypełniamy całą planszę trawą (kod 2)
|
||||
self.board = [[2 for _ in range(rows)] for _ in range(cols)]
|
||||
|
||||
# Losowo wybieramy 5 unikalnych pozycji dla chwastów
|
||||
weed_positions = random.sample([(row, col) for row in range(rows) for col in range(cols)], 5)
|
||||
|
||||
# Umieszczamy chwasty na wylosowanych pozycjach
|
||||
for row, col in weed_positions:
|
||||
self.board[row][col] = 1 # 1 oznacza chwast
|
||||
|
||||
# Teraz losowo umieszczamy inne elementy, omijając pozycje chwastów
|
||||
for row in range(rows):
|
||||
for col in range(cols):
|
||||
if (row, col) not in weed_positions:
|
||||
# Losujemy typ terenu, ale pomijamy kod 1 (chwast)
|
||||
self.board[row][col] = random.choice([0, 2, 3, 4, 5, 6, 7, 8, 9])
|
||||
|
||||
def draw_cubes(self, win):
|
||||
|
||||
|
||||
for row in range(rows):
|
||||
for col in range(cols):
|
||||
cube_rect = pygame.Rect(row * size, col * size, size, size)
|
||||
cube=self.board[row][col]
|
||||
cube = self.board[row][col]
|
||||
|
||||
if row==4 and col==4:
|
||||
if row == 4 and col == 4:
|
||||
win.blit(self.grass, cube_rect)
|
||||
elif cube == 0:
|
||||
rock_scale = pygame.transform.scale(self.rock, (size, size))
|
||||
win.blit(self.dirt, cube_rect)
|
||||
win.blit(rock_scale, cube_rect)
|
||||
#win.blit(rock_scale, cube_rect)
|
||||
elif cube == 1:
|
||||
weed_scale = pygame.transform.scale(self.weeds, (size,size))
|
||||
weed_scale = pygame.transform.scale(self.weeds, (size, size))
|
||||
win.blit(self.grass, cube_rect)
|
||||
win.blit(weed_scale, cube_rect)
|
||||
elif cube in(2,3,4,5):
|
||||
win.blit(self.grass, cube_rect)
|
||||
elif cube in (2, 3, 4, 5):
|
||||
win.blit(self.grass, cube_rect)
|
||||
elif cube == 10:
|
||||
win.blit(self.soil, cube_rect)
|
||||
elif cube == 11:
|
||||
carrot_scale = pygame.transform.scale(self.carrot, (size,size))
|
||||
win.blit(self.carrot, cube_rect)
|
||||
carrot_scale = pygame.transform.scale(self.carrot, (size, size))
|
||||
win.blit(self.carrot, cube_rect)
|
||||
win.blit(carrot_scale, cube_rect)
|
||||
|
||||
|
||||
else:
|
||||
win.blit(self.dirt, cube_rect)
|
||||
|
||||
|
||||
win.blit(self.dirt, cube_rect)
|
||||
|
||||
def load_costs(self):
|
||||
self.costs = {
|
||||
0: 100, #kamien
|
||||
@ -63,15 +78,15 @@ class Board:
|
||||
6: 3, #ziemia
|
||||
7: 3, #ziemia
|
||||
8: 3, #ziemia
|
||||
9: 3, #ziemia
|
||||
9: 3, #ziemia
|
||||
10: 4, #zyzna
|
||||
11: 10 #marchewka
|
||||
}
|
||||
|
||||
def get_cost(self, row, col):
|
||||
tile_type = self.board[row][col]
|
||||
return self.costs.get(tile_type, 1)
|
||||
|
||||
return self.costs.get(tile_type, 1)
|
||||
|
||||
def is_rock(self, row, col):
|
||||
tractor = Tractor(row, col)
|
||||
return self.board[row][col] == 0 and not (row == tractor.row and col == tractor.col)
|
||||
@ -79,17 +94,26 @@ class Board:
|
||||
def is_weed(self,row,col):
|
||||
return self.board[row][col] == 1
|
||||
|
||||
|
||||
def set_grass(self,row,col):
|
||||
self.board[row][col]=2
|
||||
|
||||
def is_dirt(self,row,col):
|
||||
return self.board[row][col] in (6,7,8,9)
|
||||
|
||||
|
||||
def is_soil(self, row, col):
|
||||
return self.board[row][col] == 10
|
||||
|
||||
|
||||
def set_soil(self, row, col):
|
||||
self.board[row][col] = 10
|
||||
|
||||
|
||||
def set_carrot(self, row, col):
|
||||
self.board[row][col] = 11
|
||||
self.board[row][col] = 11
|
||||
|
||||
def get_weed_positions(self):
|
||||
weed_positions = []
|
||||
for row in range(rows):
|
||||
for col in range(cols):
|
||||
if self.is_weed(row, col):
|
||||
weed_positions.append([row, col])
|
||||
return weed_positions
|
188
gen_algorithm.py
Normal file
188
gen_algorithm.py
Normal file
@ -0,0 +1,188 @@
|
||||
import numpy as np
|
||||
import random
|
||||
import pygame
|
||||
from constant import width, height, size, rows, cols
|
||||
from board import Board
|
||||
from tractor import Tractor
|
||||
|
||||
routes_num = 20 # Ilość ścieżek
|
||||
board = Board()
|
||||
weed_positions = board.get_weed_positions()
|
||||
weed_count = len(weed_positions)
|
||||
|
||||
def manhattan(a, b):
|
||||
return abs(a[0] - b[0]) + abs(a[1] - b[1])
|
||||
|
||||
|
||||
def find_routes(routes_num):
|
||||
population_set = [] # zapisujemy trasy - losowe ułóżenia
|
||||
for i in range(routes_num):
|
||||
# losowo wygenerowane kolejności na trasie
|
||||
single_route = np.random.choice(list(range(weed_count)), weed_count, replace=False)
|
||||
population_set.append(single_route)
|
||||
return np.array(population_set) #zwracamy 20 roznych losowych tras
|
||||
|
||||
def sum_up_for_route(route_indices):
|
||||
|
||||
sum = 0
|
||||
for i in range(len(route_indices) - 1):
|
||||
current_weed = weed_positions[route_indices[i]]
|
||||
next_weed = weed_positions[route_indices[i + 1]]
|
||||
sum += manhattan(current_weed, next_weed)
|
||||
return sum #zwracamy odleglosc (ilosc pol) dla danej trasy manhatanem
|
||||
|
||||
def routes_sum(population_set): # zapisujemy na liście finalne sumy odległości dla każdej z tras
|
||||
list_of_sums = np.zeros(routes_num)
|
||||
for i in range(routes_num):
|
||||
list_of_sums[i] = sum_up_for_route(population_set[i]) # wywołujemy dla każdej trasy na liście
|
||||
|
||||
return list_of_sums
|
||||
|
||||
|
||||
def calculate_fitness(distances):
|
||||
# odwrotność odległości jako fitness
|
||||
# dodajemy małą wartość (np. 1) aby uniknąć dzielenia przez zero
|
||||
return 1 / (distances + 1)
|
||||
|
||||
|
||||
def selection(population_set, list_of_sums):
|
||||
#RULETKA - czesciowo faworyzuje rozwiaznaia, wiekszy fitness wieksze szanse
|
||||
# obliczamy wartości fitness (przystosowania) dla każdej trasy
|
||||
fitness_values = calculate_fitness(list_of_sums)#krotsze trasy maja miec wyzsze wartosci
|
||||
# normalizujemy wartości fitness, aby sumowały się do 1 (wymagane dla np.random.choice)
|
||||
probabilities = fitness_values / fitness_values.sum()
|
||||
# wybieramy indeksy rodziców na podstawie prawdopodobieństw
|
||||
progenitor_indices_a = np.random.choice(range(len(population_set)), len(population_set), p=probabilities, replace=True)
|
||||
progenitor_indices_b = np.random.choice(range(len(population_set)), len(population_set), p=probabilities, replace=True)
|
||||
# finalne trasy
|
||||
progenitor_a = population_set[progenitor_indices_a]
|
||||
progenitor_b = population_set[progenitor_indices_b]
|
||||
|
||||
return np.array([progenitor_a, progenitor_b]) #zwracami listy przodkow-rodzicow
|
||||
|
||||
def one_point_crossover(parent_a, parent_b): #krzyzowanie jednopunktowe
|
||||
crossover_point = np.random.randint(1, len(parent_a))
|
||||
child = np.concatenate((parent_a[:crossover_point], [x for x in parent_b if x not in parent_a[:crossover_point]]))
|
||||
return child #loosyw punkt przeciecia ktory skleja nam nowa trase, wieksza szans na lepsza tarse
|
||||
|
||||
def population_mating(progenitor_list):
|
||||
new_population_set = []
|
||||
for i in range(len(progenitor_list[0])):
|
||||
progenitor_a, progenitor_b = progenitor_list[0][i], progenitor_list[1][i]
|
||||
child = one_point_crossover(progenitor_a, progenitor_b)
|
||||
new_population_set.append(child)
|
||||
return new_population_set # lista potomkow po krzyzowaniu
|
||||
|
||||
|
||||
|
||||
def mutation_of_child(child, mutation_rate=0.2):#procent moze pomoc w niezaklucaniu trasy gdy jesy duza trasa ale idk
|
||||
num_mutations = int(len(child) * mutation_rate)
|
||||
for _ in range(num_mutations):
|
||||
x = np.random.randint(0, len(child))#losowa szansa zamiany - mutacja
|
||||
y = np.random.randint(0, len(child))
|
||||
child[x], child[y] = child[y], child[x]
|
||||
return child#zwrocenie bardziej roznorodnych potomkow
|
||||
|
||||
|
||||
def mutate_population(new_population_set):
|
||||
final_mutated_population = []
|
||||
for child in new_population_set:
|
||||
final_mutated_population.append(mutation_of_child(child)) # dodajemy zmutowane dziecko do finalnej listy
|
||||
return final_mutated_population
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
pygame.init()
|
||||
WIN = pygame.display.set_mode((width, height))
|
||||
pygame.display.set_caption('Trasa Traktora')
|
||||
clock = pygame.time.Clock()
|
||||
|
||||
board = Board()
|
||||
board.load_images()
|
||||
weed_positions = [(col, row) for col in range(cols) for row in range(rows) if board.is_weed(col, row)]
|
||||
weed_count = len(weed_positions)
|
||||
|
||||
board.set_grass(9, 9) # pozycja startowa
|
||||
tractor = Tractor(9, 9) # Start traktora
|
||||
|
||||
|
||||
# Inicjalizacja final_route
|
||||
final_route = [0, float('inf'), np.array([])]
|
||||
# [0]: indeks iteracji, [1]: najlepsza suma odległości, [2]: najlepsza trasa
|
||||
|
||||
population_set = find_routes(routes_num)
|
||||
list_of_sums = routes_sum(population_set)
|
||||
progenitor_list = selection(population_set, list_of_sums)
|
||||
new_population_set = population_mating(progenitor_list)
|
||||
final_mutated_population = mutate_population(new_population_set)
|
||||
final_route = [-1, np.inf, np.array([])] # format listy
|
||||
|
||||
for i in range(20):
|
||||
list_of_sums = routes_sum(final_mutated_population)
|
||||
# zapisujemy najlepsze rozwiązanie
|
||||
if list_of_sums.min() < final_route[1]:
|
||||
final_route[0] = i
|
||||
final_route[1] = list_of_sums.min()
|
||||
final_route[2] = np.array(final_mutated_population)[list_of_sums.min() == list_of_sums]
|
||||
|
||||
progenitor_list = selection(population_set, list_of_sums)
|
||||
new_population_set = population_mating(progenitor_list)
|
||||
final_mutated_population = mutate_population(new_population_set)
|
||||
|
||||
print(f"Najlepsza trasa znaleziona w iteracji: {final_route[0]}")
|
||||
print(f"Minimalna suma odległości: {final_route[1]}")
|
||||
|
||||
|
||||
run = True
|
||||
current_target_index = 0
|
||||
best_routes = final_route[2] #tablica z najlepszymi trasami
|
||||
visited_fields = []
|
||||
while run:
|
||||
clock.tick(2) # FPS
|
||||
|
||||
for event in pygame.event.get():
|
||||
if event.type == pygame.QUIT:
|
||||
run = False
|
||||
|
||||
for route in best_routes:
|
||||
if current_target_index < len(route):
|
||||
current_weed = weed_positions[route[current_target_index]]
|
||||
|
||||
|
||||
# ruch w kierunku bieżącego celu
|
||||
if tractor.col < current_weed[0]:
|
||||
tractor.col += 1
|
||||
tractor.direction = "right"
|
||||
elif tractor.col > current_weed[0]:
|
||||
tractor.col -= 1
|
||||
tractor.direction = "left"
|
||||
elif tractor.row < current_weed[1]:
|
||||
tractor.row += 1
|
||||
tractor.direction = "down"
|
||||
elif tractor.row > current_weed[1]:
|
||||
tractor.row -= 1
|
||||
tractor.direction = "up"
|
||||
|
||||
current_position = (tractor.col, tractor.row)
|
||||
if current_position not in visited_fields:
|
||||
visited_fields.append(current_position)
|
||||
|
||||
# Jeśli traktor dotarł do celu
|
||||
if (tractor.col, tractor.row) == current_weed:
|
||||
current_target_index += 1
|
||||
|
||||
# Aktualizacja planszy
|
||||
if board.is_weed(tractor.col, tractor.row):
|
||||
board.set_carrot(tractor.col, tractor.row)
|
||||
|
||||
|
||||
|
||||
board.draw_cubes(WIN)
|
||||
tractor.draw(WIN)
|
||||
pygame.display.update()
|
||||
|
||||
print("Odwiedzone pola:")
|
||||
for field in visited_fields:
|
||||
print(field)
|
||||
|
||||
pygame.quit()
|
Loading…
Reference in New Issue
Block a user