Compare commits
5 Commits
068ee153a0
...
8204825a97
Author | SHA1 | Date | |
---|---|---|---|
8204825a97 | |||
4b828f878b | |||
084e96ba7d | |||
e56854690c | |||
0c5532ac0d |
207
astar.py
207
astar.py
@ -3,124 +3,108 @@ from board import Board
|
|||||||
from constant import width, height, rows, cols
|
from constant import width, height, rows, cols
|
||||||
from tractor import Tractor
|
from tractor import Tractor
|
||||||
import heapq
|
import heapq
|
||||||
import math
|
|
||||||
|
|
||||||
fps = 2
|
fps = 2
|
||||||
WIN = pygame.display.set_mode((width, height))
|
WIN = pygame.display.set_mode((width, height))
|
||||||
pygame.display.set_caption('Inteligenty Traktor')
|
pygame.display.set_caption('Inteligenty Traktor')
|
||||||
|
|
||||||
|
|
||||||
class Node:
|
class Node:
|
||||||
def __init__(self, x, y):
|
def __init__(self, state, parent=None, action=None, cost=0):
|
||||||
self.x = x
|
self.state = state # Stan reprezentowany przez węzeł
|
||||||
self.y = y
|
self.parent = parent # Węzeł rodzica
|
||||||
self.f = 0
|
self.action = action # Akcja prowadząca do tego stanu
|
||||||
self.g = 0
|
self.cost = cost # Koszt przejścia do tego stanu
|
||||||
self.h = 0
|
self.f = 0 # Wartość funkcji priorytetowej
|
||||||
self.cost = 1
|
self.tie_breaker = 0 # Wartość używana do rozwiązywania konfliktów priorytetów
|
||||||
self.visited = False
|
|
||||||
self.closed = False
|
|
||||||
self.parent = None
|
|
||||||
|
|
||||||
def __lt__(self, other):
|
def __lt__(self, other):
|
||||||
|
# Porównanie węzłów w celu ustalenia kolejności w kolejce priorytetowej
|
||||||
|
if self.f == other.f:
|
||||||
|
return self.tie_breaker > other.tie_breaker # Większy tie_breaker ma wyższy priorytet
|
||||||
return self.f < other.f
|
return self.f < other.f
|
||||||
|
# Jesli pare wezlow ma taie same f, to tilebreaker ustawia
|
||||||
def neighbors(self, grid):
|
# prorytety akcje right i down maja wyzszy priorytet
|
||||||
ret = []
|
|
||||||
x, y = self.x, self.y
|
|
||||||
if x > 0 and grid[x - 1][y]:
|
|
||||||
ret.append(grid[x - 1][y])
|
|
||||||
if x < len(grid) - 1 and grid[x + 1][y]:
|
|
||||||
ret.append(grid[x + 1][y])
|
|
||||||
if y > 0 and grid[x][y - 1]:
|
|
||||||
ret.append(grid[x][y - 1])
|
|
||||||
if y < len(grid[0]) - 1 and grid[x][y + 1]:
|
|
||||||
ret.append(grid[x][y + 1])
|
|
||||||
return ret
|
|
||||||
|
|
||||||
def init(grid):
|
|
||||||
for x in range(len(grid)):
|
|
||||||
for y in range(len(grid[x])):
|
|
||||||
node = grid[x][y]
|
|
||||||
node.f = 0
|
|
||||||
node.g = 0
|
|
||||||
node.h = 0
|
|
||||||
node.cost = 1
|
|
||||||
node.visited = False
|
|
||||||
node.closed = False
|
|
||||||
node.parent = None
|
|
||||||
|
|
||||||
def heap():
|
|
||||||
return []
|
|
||||||
|
|
||||||
def search(grid, start, end, board, heuristic=None):
|
|
||||||
init(grid)
|
|
||||||
if heuristic is None:
|
|
||||||
heuristic = manhattan
|
|
||||||
open_heap = heap()
|
|
||||||
heapq.heappush(open_heap, start)
|
|
||||||
|
|
||||||
while open_heap:
|
|
||||||
current_node = heapq.heappop(open_heap)
|
|
||||||
if (current_node.x, current_node.y) == (end.x, end.y):
|
|
||||||
|
|
||||||
ret = []
|
|
||||||
while current_node.parent:
|
|
||||||
ret.append(current_node)
|
|
||||||
current_node = current_node.parent
|
|
||||||
ret.append(start)
|
|
||||||
ret_path = ret[::-1]
|
|
||||||
for node in ret_path:
|
|
||||||
print(f"({node.x}, {node.y}): {node.g}")
|
|
||||||
print("Znaleziono ścieżkę [(x,y)jako(kolumna,wiersz)] o koszcie:", ret_path[-1].g)
|
|
||||||
return ret_path, start
|
|
||||||
current_node.closed = True
|
|
||||||
for neighbor in current_node.neighbors(grid):
|
|
||||||
if neighbor.closed:
|
|
||||||
continue
|
|
||||||
g_score = current_node.g + board.get_cost(neighbor.x, neighbor.y)
|
|
||||||
been_visited = neighbor.visited
|
|
||||||
if not been_visited or g_score < neighbor.g:
|
|
||||||
neighbor.visited = True
|
|
||||||
neighbor.parent = current_node
|
|
||||||
neighbor.h = neighbor.h or heuristic((neighbor.x, neighbor.y), (end.x, end.y))
|
|
||||||
neighbor.g = g_score
|
|
||||||
neighbor.f = neighbor.g + neighbor.h
|
|
||||||
if not been_visited:
|
|
||||||
heapq.heappush(open_heap, neighbor)
|
|
||||||
|
|
||||||
print("Nie znaleziono ścieżki.")
|
|
||||||
return None
|
|
||||||
|
|
||||||
|
|
||||||
def manhattan(pos0, pos1):
|
def manhattan(pos0, pos1):
|
||||||
|
# Heurystyka odległości Manhattan
|
||||||
d1 = abs(pos1[0] - pos0[0])
|
d1 = abs(pos1[0] - pos0[0])
|
||||||
d2 = abs(pos1[1] - pos0[1])
|
d2 = abs(pos1[1] - pos0[1])
|
||||||
return d1 + d2
|
return d1 + d2
|
||||||
|
|
||||||
|
|
||||||
|
def nastepnik(state, board):
|
||||||
|
# Funkcja generująca możliwe następne stany (akcje)
|
||||||
|
x, y = state
|
||||||
|
successors = []
|
||||||
|
actions = [('right', (x+1, y), 1), ('down', (x, y+1), 1), ('up', (x, y-1), 0), ('left', (x-1, y), 0)]
|
||||||
|
for action, next_state, tie_breaker in actions:
|
||||||
|
if 0 <= next_state[0] < cols and 0 <= next_state[1] < rows:
|
||||||
|
cost = board.get_cost(next_state[0], next_state[1])
|
||||||
|
successors.append((action, next_state, cost, tie_breaker))
|
||||||
|
return successors
|
||||||
|
|
||||||
|
|
||||||
|
def goal_test(state, goal):
|
||||||
|
# Czy dany stan jest stanem docelowym
|
||||||
|
return state == goal
|
||||||
|
|
||||||
|
|
||||||
|
def graphsearch(istate, goal, board, heuristic=manhattan):
|
||||||
|
# Algorytm przeszukiwania grafu
|
||||||
|
fringe = [] # Kolejka priorytetowa przechowująca węzły do odwiedzenia
|
||||||
|
explored = set() # Zbiór odwiedzonych stanów
|
||||||
|
start_node = Node(istate)
|
||||||
|
start_node.f = heuristic(istate, goal) # Obliczenie wartości heurystycznej dla stanu początkowego
|
||||||
|
start_node.tie_breaker = 0 # Ustawienie tie_breaker dla węzła startowego,
|
||||||
|
heapq.heappush(fringe, start_node)
|
||||||
|
|
||||||
|
while fringe:
|
||||||
|
elem = heapq.heappop(fringe)
|
||||||
|
if goal_test(elem.state, goal):
|
||||||
|
path = []
|
||||||
|
total_cost = elem.cost # Zapisanie całkowitego kosztu
|
||||||
|
while elem:
|
||||||
|
path.append((elem.state, elem.action))
|
||||||
|
elem = elem.parent
|
||||||
|
return path[::-1], total_cost # Zwrócenie ścieżki i kosztu
|
||||||
|
|
||||||
|
explored.add(elem.state)
|
||||||
|
for action_index, (action, state, cost, tie_breaker) in enumerate(nastepnik(elem.state, board)):
|
||||||
|
x = Node(state, parent=elem, action=action, cost=elem.cost + cost)
|
||||||
|
x.f = x.cost + heuristic(state, goal) # Obliczenie wartości funkcji priorytetowej
|
||||||
|
x.tie_breaker = elem.tie_breaker * 4 + action_index # Obliczanie tie_breaker na podstawie akcji
|
||||||
|
|
||||||
|
if state not in explored and not any(node.state == state for node in fringe):
|
||||||
|
heapq.heappush(fringe, x)
|
||||||
|
else:
|
||||||
|
for i, node in enumerate(fringe):
|
||||||
|
if node.state == state and (node.f > x.f or (node.f == x.f and node.tie_breaker < x.tie_breaker)):
|
||||||
|
fringe[i] = x
|
||||||
|
heapq.heapify(fringe)
|
||||||
|
break
|
||||||
|
|
||||||
|
print("Nie znaleziono ścieżki.")
|
||||||
|
return None, 0 # Zwrócenie ścieżki jako None i kosztu jako 0 w przypadku braku ścieżki
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
run = True
|
run = True
|
||||||
clock = pygame.time.Clock()
|
clock = pygame.time.Clock()
|
||||||
board = Board()
|
board = Board()
|
||||||
board.load_images()
|
board.load_images()
|
||||||
|
|
||||||
start_row, start_col = 0,0
|
start_state = (9, 9) # Stan początkowy
|
||||||
end_row, end_col = 9,9
|
goal_state = (0, 0) # Stan docelowy
|
||||||
tractor = Tractor(start_row, start_col)
|
tractor = Tractor(start_state[1], start_state[0])
|
||||||
board.set_grass(start_row, start_col)
|
board.set_grass(start_state[0], start_state[1]) # Ustawienie startowego pola jako trawę
|
||||||
board.set_grass(end_row, end_col)
|
board.set_grass(goal_state[0], goal_state[1]) # Ustawienie docelowego pola jako trawę
|
||||||
|
|
||||||
grid = [[Node(x, y) for y in range(rows)] for x in range(cols)]
|
path, total_cost = graphsearch(start_state, goal_state, board)
|
||||||
|
|
||||||
start = grid[start_row][start_col]
|
|
||||||
end = grid[end_row][end_col]
|
|
||||||
|
|
||||||
path, start_node = search(grid, start, end, board)
|
|
||||||
|
|
||||||
|
|
||||||
while run:
|
while run:
|
||||||
clock.tick(fps)
|
clock.tick(fps)
|
||||||
|
|
||||||
for event in pygame.event.get():
|
for event in pygame.event.get():
|
||||||
if event.type == pygame.QUIT:
|
if event.type == pygame.QUIT:
|
||||||
run = False
|
run = False
|
||||||
@ -129,39 +113,38 @@ def main():
|
|||||||
run = False
|
run = False
|
||||||
continue
|
continue
|
||||||
|
|
||||||
next_node = path.pop(0) if path else start_node
|
next_state, action = path.pop(0) if path else (start_state, None)
|
||||||
dx = next_node.x - tractor.col
|
print(next_state) # Wypisanie następnego stanu
|
||||||
dy = next_node.y - tractor.row
|
tractor.row, tractor.col = next_state[1], next_state[0]
|
||||||
tractor.row, tractor.col = next_node.y, next_node.x
|
|
||||||
|
|
||||||
|
if action == "right":
|
||||||
if dx > 0:
|
|
||||||
tractor.direction = "right"
|
tractor.direction = "right"
|
||||||
elif dx < 0:
|
elif action == "left":
|
||||||
tractor.direction = "left"
|
tractor.direction = "left"
|
||||||
elif dy > 0:
|
elif action == "down":
|
||||||
tractor.direction = "down"
|
tractor.direction = "down"
|
||||||
elif dy < 0:
|
elif action == "up":
|
||||||
tractor.direction = "up"
|
tractor.direction = "up"
|
||||||
|
|
||||||
if board.is_weed(tractor.col, tractor.row ):
|
# Aktualizacja planszy na podstawie położenia traktora
|
||||||
board.set_grass(tractor.col, tractor.row )
|
if board.is_weed(tractor.col, tractor.row):
|
||||||
|
board.set_grass(tractor.col, tractor.row)
|
||||||
elif board.is_dirt(tractor.col, tractor.row ):
|
elif board.is_dirt(tractor.col, tractor.row):
|
||||||
board.set_soil(tractor.col, tractor.row )
|
board.set_soil(tractor.col, tractor.row)
|
||||||
|
elif board.is_soil(tractor.col, tractor.row):
|
||||||
elif board.is_soil(tractor.col, tractor.row ):
|
board.set_carrot(tractor.col, tractor.row)
|
||||||
board.set_carrot(tractor.col, tractor.row )
|
|
||||||
|
|
||||||
|
|
||||||
board.draw_cubes(WIN)
|
board.draw_cubes(WIN)
|
||||||
tractor.draw(WIN)
|
tractor.draw(WIN)
|
||||||
pygame.display.update()
|
pygame.display.update()
|
||||||
|
|
||||||
|
print(f"Całkowity koszt trasy: {total_cost}")
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
for event in pygame.event.get():
|
for event in pygame.event.get():
|
||||||
if event.type == pygame.QUIT:
|
if event.type == pygame.QUIT:
|
||||||
pygame.quit()
|
pygame.quit()
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|
||||||
main()
|
main()
|
47
board.py
47
board.py
@ -10,6 +10,7 @@ class Board:
|
|||||||
self.load_costs()
|
self.load_costs()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def load_images(self):
|
def load_images(self):
|
||||||
self.grass = pygame.image.load("board/grass.png")
|
self.grass = pygame.image.load("board/grass.png")
|
||||||
self.dirt = pygame.image.load("board/dirt.png")
|
self.dirt = pygame.image.load("board/dirt.png")
|
||||||
@ -19,37 +20,52 @@ class Board:
|
|||||||
self.carrot = pygame.image.load("board/carrot.png")
|
self.carrot = pygame.image.load("board/carrot.png")
|
||||||
|
|
||||||
def generate_board(self):
|
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):
|
def draw_cubes(self, win):
|
||||||
|
|
||||||
|
|
||||||
for row in range(rows):
|
for row in range(rows):
|
||||||
for col in range(cols):
|
for col in range(cols):
|
||||||
cube_rect = pygame.Rect(row * size, col * size, size, size)
|
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)
|
win.blit(self.grass, cube_rect)
|
||||||
elif cube == 0:
|
elif cube == 0:
|
||||||
rock_scale = pygame.transform.scale(self.rock, (size, size))
|
rock_scale = pygame.transform.scale(self.rock, (size, size))
|
||||||
win.blit(self.dirt, cube_rect)
|
win.blit(self.dirt, cube_rect)
|
||||||
win.blit(rock_scale, cube_rect)
|
#win.blit(rock_scale, cube_rect)
|
||||||
elif cube == 1:
|
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(self.grass, cube_rect)
|
||||||
win.blit(weed_scale, cube_rect)
|
win.blit(weed_scale, cube_rect)
|
||||||
elif cube in(2,3,4,5):
|
elif cube in (2, 3, 4, 5):
|
||||||
win.blit(self.grass, cube_rect)
|
win.blit(self.grass, cube_rect)
|
||||||
elif cube == 10:
|
elif cube == 10:
|
||||||
win.blit(self.soil, cube_rect)
|
win.blit(self.soil, cube_rect)
|
||||||
elif cube == 11:
|
elif cube == 11:
|
||||||
carrot_scale = pygame.transform.scale(self.carrot, (size,size))
|
carrot_scale = pygame.transform.scale(self.carrot, (size, size))
|
||||||
win.blit(self.carrot, cube_rect)
|
win.blit(self.carrot, cube_rect)
|
||||||
win.blit(carrot_scale, cube_rect)
|
win.blit(carrot_scale, cube_rect)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
win.blit(self.dirt, cube_rect)
|
win.blit(self.dirt, cube_rect)
|
||||||
|
|
||||||
|
|
||||||
def load_costs(self):
|
def load_costs(self):
|
||||||
self.costs = {
|
self.costs = {
|
||||||
@ -78,6 +94,7 @@ class Board:
|
|||||||
def is_weed(self,row,col):
|
def is_weed(self,row,col):
|
||||||
return self.board[row][col] == 1
|
return self.board[row][col] == 1
|
||||||
|
|
||||||
|
|
||||||
def set_grass(self,row,col):
|
def set_grass(self,row,col):
|
||||||
self.board[row][col]=2
|
self.board[row][col]=2
|
||||||
|
|
||||||
@ -93,10 +110,10 @@ class Board:
|
|||||||
def set_carrot(self, row, col):
|
def set_carrot(self, row, col):
|
||||||
self.board[row][col] = 11
|
self.board[row][col] = 11
|
||||||
|
|
||||||
def get_dirt_positions(self):
|
def get_weed_positions(self):
|
||||||
dirt_positions = []
|
weed_positions = []
|
||||||
for row in range(rows):
|
for row in range(rows):
|
||||||
for col in range(cols):
|
for col in range(cols):
|
||||||
if self.is_dirt(row, col):
|
if self.is_weed(row, col):
|
||||||
dirt_positions.append([row, col])
|
weed_positions.append([row, col])
|
||||||
return dirt_positions
|
return weed_positions
|
132
gen_algorithm.py
132
gen_algorithm.py
@ -5,36 +5,34 @@ from constant import width, height, size, rows, cols
|
|||||||
from board import Board
|
from board import Board
|
||||||
from tractor import Tractor
|
from tractor import Tractor
|
||||||
|
|
||||||
|
|
||||||
routes_num = 20 # Ilość ścieżek
|
routes_num = 20 # Ilość ścieżek
|
||||||
board = Board()
|
board = Board()
|
||||||
dirt_positions = board.get_dirt_positions()
|
weed_positions = board.get_weed_positions()
|
||||||
dirt_count = len(dirt_positions)
|
weed_count = len(weed_positions)
|
||||||
|
|
||||||
def manhattan(a, b):
|
def manhattan(a, b):
|
||||||
return abs(a[0] - b[0]) + abs(a[1] - b[1])
|
return abs(a[0] - b[0]) + abs(a[1] - b[1])
|
||||||
|
|
||||||
|
|
||||||
def find_routes(routes_num):
|
def find_routes(routes_num):
|
||||||
population_set = [] # zapisujemy trasy - losowe ułóżenia
|
population_set = [] # zapisujemy trasy - losowe ułóżenia
|
||||||
for i in range(routes_num):
|
for i in range(routes_num):
|
||||||
# losowo wygenerowane kolejności na trasie
|
# losowo wygenerowane kolejności na trasie
|
||||||
single_route = np.random.choice(list(range(dirt_count)), dirt_count, replace=False)
|
single_route = np.random.choice(list(range(weed_count)), weed_count, replace=False)
|
||||||
population_set.append(single_route)
|
population_set.append(single_route)
|
||||||
return np.array(population_set)
|
return np.array(population_set) #zwracamy 20 roznych losowych tras
|
||||||
|
|
||||||
|
|
||||||
def sum_up_for_route(route_indices):
|
def sum_up_for_route(route_indices):
|
||||||
|
|
||||||
sum = 0
|
sum = 0
|
||||||
for i in range(len(route_indices) - 1):
|
for i in range(len(route_indices) - 1):
|
||||||
current_dirt = dirt_positions[route_indices[i]]
|
current_weed = weed_positions[route_indices[i]]
|
||||||
next_dirt = dirt_positions[route_indices[i + 1]]
|
next_weed = weed_positions[route_indices[i + 1]]
|
||||||
sum += manhattan(current_dirt, next_dirt)
|
sum += manhattan(current_weed, next_weed)
|
||||||
return sum
|
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
|
||||||
def routes_sum(population_set): # zapisujemy na liście finalne sumy odległości dla każdej z opcji tras
|
|
||||||
list_of_sums = np.zeros(routes_num)
|
list_of_sums = np.zeros(routes_num)
|
||||||
|
|
||||||
for i in range(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
|
list_of_sums[i] = sum_up_for_route(population_set[i]) # wywołujemy dla każdej trasy na liście
|
||||||
|
|
||||||
@ -42,29 +40,30 @@ def routes_sum(population_set): # zapisujemy na liście finalne sumy odległoś
|
|||||||
|
|
||||||
|
|
||||||
def calculate_fitness(distances):
|
def calculate_fitness(distances):
|
||||||
# Odwrotność odległości jako fitness
|
# odwrotność odległości jako fitness
|
||||||
# Dodajemy małą wartość (np. 1) aby uniknąć dzielenia przez zero
|
# dodajemy małą wartość (np. 1) aby uniknąć dzielenia przez zero
|
||||||
return 1 / (distances + 1)
|
return 1 / (distances + 1)
|
||||||
|
|
||||||
|
|
||||||
def selection(population_set, list_of_sums):
|
def selection(population_set, list_of_sums):
|
||||||
# Oblicz wartości fitness dla każdej trasy
|
#RULETKA - czesciowo faworyzuje rozwiaznaia, wiekszy fitness wieksze szanse
|
||||||
fitness_values = calculate_fitness(list_of_sums)
|
# obliczamy wartości fitness (przystosowania) dla każdej trasy
|
||||||
# Normalizuj wartości fitness, aby sumowały się do 1 (wymagane dla np.random.choice)
|
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()
|
probabilities = fitness_values / fitness_values.sum()
|
||||||
# Wybierz rodziców na podstawie prawdopodobieństw (wartości fitness)
|
# 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_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)
|
progenitor_indices_b = np.random.choice(range(len(population_set)), len(population_set), p=probabilities, replace=True)
|
||||||
# Wybierz rzeczywiste trasy
|
# finalne trasy
|
||||||
progenitor_a = population_set[progenitor_indices_a]
|
progenitor_a = population_set[progenitor_indices_a]
|
||||||
progenitor_b = population_set[progenitor_indices_b]
|
progenitor_b = population_set[progenitor_indices_b]
|
||||||
|
|
||||||
return np.array([progenitor_a, progenitor_b])
|
return np.array([progenitor_a, progenitor_b]) #zwracami listy przodkow-rodzicow
|
||||||
|
|
||||||
def one_point_crossover(parent_a, parent_b): #krzyzowanie jednopunktowe
|
def one_point_crossover(parent_a, parent_b): #krzyzowanie jednopunktowe
|
||||||
crossover_point = np.random.randint(1, len(parent_a))
|
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]]))
|
child = np.concatenate((parent_a[:crossover_point], [x for x in parent_b if x not in parent_a[:crossover_point]]))
|
||||||
return child
|
return child #loosyw punkt przeciecia ktory skleja nam nowa trase, wieksza szans na lepsza tarse
|
||||||
|
|
||||||
def population_mating(progenitor_list):
|
def population_mating(progenitor_list):
|
||||||
new_population_set = []
|
new_population_set = []
|
||||||
@ -72,24 +71,17 @@ def population_mating(progenitor_list):
|
|||||||
progenitor_a, progenitor_b = progenitor_list[0][i], progenitor_list[1][i]
|
progenitor_a, progenitor_b = progenitor_list[0][i], progenitor_list[1][i]
|
||||||
child = one_point_crossover(progenitor_a, progenitor_b)
|
child = one_point_crossover(progenitor_a, progenitor_b)
|
||||||
new_population_set.append(child)
|
new_population_set.append(child)
|
||||||
return new_population_set
|
return new_population_set # lista potomkow po krzyzowaniu
|
||||||
|
|
||||||
def mutation_of_child(child):
|
|
||||||
for i in range(dirt_count): # dla każdego elementu dajemy losową szansę zamiany int *rate
|
|
||||||
x = np.random.randint(0, dirt_count)
|
|
||||||
y = np.random.randint(0, dirt_count)
|
|
||||||
|
|
||||||
child[x], child[y] = child[y], child[x] # zamiana miejscami
|
|
||||||
|
|
||||||
return child
|
def mutation_of_child(child, mutation_rate=0.2):#procent moze pomoc w niezaklucaniu trasy gdy jesy duza trasa ale idk
|
||||||
|
|
||||||
'''def mutation_of_child(child, mutation_rate=0.1):#procent moze pomoc w niezaklucaniu trasy gdy jesy duza trasa ale idk
|
|
||||||
num_mutations = int(len(child) * mutation_rate)
|
num_mutations = int(len(child) * mutation_rate)
|
||||||
for _ in range(num_mutations):
|
for _ in range(num_mutations):
|
||||||
x = np.random.randint(0, len(child))
|
x = np.random.randint(0, len(child))#losowa szansa zamiany - mutacja
|
||||||
y = np.random.randint(0, len(child))
|
y = np.random.randint(0, len(child))
|
||||||
child[x], child[y] = child[y], child[x]
|
child[x], child[y] = child[y], child[x]
|
||||||
return child'''
|
return child#zwrocenie bardziej roznorodnych potomkow
|
||||||
|
|
||||||
|
|
||||||
def mutate_population(new_population_set):
|
def mutate_population(new_population_set):
|
||||||
@ -100,6 +92,23 @@ def mutate_population(new_population_set):
|
|||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
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)
|
population_set = find_routes(routes_num)
|
||||||
list_of_sums = routes_sum(population_set)
|
list_of_sums = routes_sum(population_set)
|
||||||
@ -107,6 +116,7 @@ if __name__ == '__main__':
|
|||||||
new_population_set = population_mating(progenitor_list)
|
new_population_set = population_mating(progenitor_list)
|
||||||
final_mutated_population = mutate_population(new_population_set)
|
final_mutated_population = mutate_population(new_population_set)
|
||||||
final_route = [-1, np.inf, np.array([])] # format listy
|
final_route = [-1, np.inf, np.array([])] # format listy
|
||||||
|
|
||||||
for i in range(20):
|
for i in range(20):
|
||||||
list_of_sums = routes_sum(final_mutated_population)
|
list_of_sums = routes_sum(final_mutated_population)
|
||||||
# zapisujemy najlepsze rozwiązanie
|
# zapisujemy najlepsze rozwiązanie
|
||||||
@ -115,12 +125,64 @@ if __name__ == '__main__':
|
|||||||
final_route[1] = list_of_sums.min()
|
final_route[1] = list_of_sums.min()
|
||||||
final_route[2] = np.array(final_mutated_population)[list_of_sums.min() == list_of_sums]
|
final_route[2] = np.array(final_mutated_population)[list_of_sums.min() == list_of_sums]
|
||||||
|
|
||||||
|
|
||||||
progenitor_list = selection(population_set, list_of_sums)
|
progenitor_list = selection(population_set, list_of_sums)
|
||||||
new_population_set = population_mating(progenitor_list)
|
new_population_set = population_mating(progenitor_list)
|
||||||
final_mutated_population = mutate_population(new_population_set)
|
final_mutated_population = mutate_population(new_population_set)
|
||||||
|
|
||||||
print(f"Najlepsza trasa znaleziona w iteracji: {final_route[0]}")
|
print(f"Najlepsza trasa znaleziona w iteracji: {final_route[0]}")
|
||||||
print(f"Minimalna suma odległości: {final_route[1]}")
|
print(f"Minimalna suma odległości: {final_route[1]}")
|
||||||
print(f"Kolejne pola: {final_route[2]}")
|
|
||||||
|
|
||||||
|
|
||||||
|
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