Corrected GeneticAlgorithm2 and made a GeneticAlgorithm3 and generated fields using them. Made GeneticAccuracy to check the performance of the algorithms.

This commit is contained in:
Mateusz Czajka 2024-06-08 23:25:08 +02:00
parent 6c86eebd89
commit d61b585827
6 changed files with 900 additions and 15 deletions

139
GeneticAccuracy.py Normal file
View File

@ -0,0 +1,139 @@
import json
import random
from displayControler import NUM_Y, NUM_X
iterat = 2500
population = 120
roulette = True
plants = ['corn', 'potato', 'tomato', 'carrot']
initial_yields = {'corn': 38, 'potato': 40, 'tomato': 43, 'carrot': 45}
yield_reduction = {
'corn': {'corn': -4.5, 'potato': -3, 'tomato': -7, 'carrot': -7},
'potato': {'corn': -7, 'potato': -5, 'tomato': -10, 'carrot': -6},
'tomato': {'corn': -4, 'potato': -5, 'tomato': -7, 'carrot': -7},
'carrot': {'corn': -11, 'potato': -5, 'tomato': -4, 'carrot': -7}
}
yield_reduction2 = {
'corn': {'corn': None, 'potato': -4, 'tomato': -2, 'carrot': -4},
'potato': {'corn': None, 'potato': -5, 'tomato': -5, 'carrot': -2},
'tomato': {'corn': -5, 'potato': -3, 'tomato': -7, 'carrot': None},
'carrot': {'corn': -3, 'potato': -6, 'tomato': -4, 'carrot': -9}
}
yield_multiplier = {'corn': 1.25, 'potato': 1.17, 'tomato': 1.22, 'carrot': 1.13}
yield_multiplier2 = {'corn': 1.25, 'potato': 1.19, 'tomato': 1.22, 'carrot': 1.15}
def calculate_yields(garden):
rows = len(garden)
cols = len(garden[0])
total_yields = 0
for i in range(rows):
for j in range(cols):
plant = garden[i][j]
yield_count = initial_yields[plant]
# Sprawdzanie sąsiadów
neighbors = [
(i - 1, j), (i + 1, j), (i, j - 1), (i, j + 1)
]
for ni, nj in neighbors:
if 0 <= ni < rows and 0 <= nj < cols:
neighbor_plant = garden[ni][nj]
yield_count += yield_reduction[plant][neighbor_plant]
yield_count *= yield_multiplier[plant]
total_yields += yield_count
return total_yields
def calculate_yields2(garden):
rows = len(garden)
cols = len(garden[0])
total_yields = 0
for i in range(rows):
for j in range(cols):
plant = garden[i][j]
yield_count = initial_yields[plant]
# Sprawdzanie sąsiadów
neighbors = [
(i - 1, j), (i + 1, j), (i, j - 1), (i, j + 1)
]
neighbor_flag = False
for ni, nj in neighbors:
if 0 <= ni < rows and 0 <= nj < cols:
neighbor_plant = garden[ni][nj]
if yield_reduction2[plant][neighbor_plant] is not None: # jeśli jest wartość None to plony dla tej rośliny będą wyzerowane
yield_count += yield_reduction2[plant][neighbor_plant]
else:
neighbor_flag = True
if not neighbor_flag:
yield_count *= yield_multiplier2[plant]
total_yields += yield_count
return total_yields
def generate_garden(rows=20, cols=12):
return [[random.choice(plants) for _ in range(cols)] for _ in range(rows)]
def generate_garden_with_yields(t, rows=NUM_Y, cols=NUM_X):
garden = generate_garden(rows, cols)
if t == 1:
total_yields = calculate_yields(garden)
else:
total_yields = calculate_yields2(garden)
return [garden, total_yields]
def generate():
s1 = 0
s2 = 0
n = 150
for i in range(n):
x = generate_garden_with_yields(1)
s1 += x[1]
y = generate_garden_with_yields(2)
s2 += y[1]
return [s1/n, s2/n]
data = generate()
# print(data)
# Odczyt z pliku
with open(f'pole_pop{population}_iter{iterat}_{roulette}.json', 'r') as file:
garden_data = json.load(file)
# print("Odczytane dane ogrodu:")
# for row in garden_data:
# print(row)
print("Wygenerowane przy pomocy GA: ", calculate_yields(garden_data))
print(f"Przeciętny ogród wygenerowany randomowo ma {data[0]} plonów")
print("Uśredniony przyrost plonów (ile razy więcej plonów): ", calculate_yields(garden_data)/data[0])
# Odczyt z pliku
with open(f'pole2_pop{population}_iter{iterat}_{roulette}.json', 'r') as file:
garden_data2 = json.load(file)
# print("Odczytane dane ogrodu:")
# for row in garden_data2:
# print(row)
print("Wygenerowane: przy pomocy GA2", calculate_yields2(garden_data2))
print(f"Przeciętny ogród wygenerowany randomowo ma {data[1]} plonów")
print("Uśredniony przyrost plonów (ile razy więcej plonów): ", calculate_yields2(garden_data2)/data[1])

View File

@ -136,7 +136,7 @@ if __name__ == '__main__':
roulette = True
attemps = 150
iterat = 2500
population = 100
population = 120
best = []
for a in range(attemps):
generation = generate(population)

View File

@ -7,12 +7,12 @@ from displayControler import NUM_X, NUM_Y
plants = ['corn', 'potato', 'tomato', 'carrot']
initial_yields = {'corn': 38, 'potato': 40, 'tomato': 43, 'carrot': 45}
yield_reduction = {
'corn': {'corn': -4.5, 'potato': -3, 'tomato': -7, 'carrot': -7},
'potato': {'corn': None, 'potato': -5, 'tomato': -10, 'carrot': -6},
'tomato': {'corn': None, 'potato': -5, 'tomato': -7, 'carrot': -7},
'carrot': {'corn': None, 'potato': -5, 'tomato': -4, 'carrot': -7}
'corn': {'corn': None, 'potato': -4, 'tomato': -2, 'carrot': -4},
'potato': {'corn': None, 'potato': -5, 'tomato': -5, 'carrot': -2},
'tomato': {'corn': -5, 'potato': -3, 'tomato': -7, 'carrot': None},
'carrot': {'corn': -3, 'potato': -6, 'tomato': -4, 'carrot': -9}
}
yield_multiplier = {'corn': 1.25, 'potato': 1.17, 'tomato': 1.22, 'carrot': 1.13}
yield_multiplier = {'corn': 1.25, 'potato': 1.19, 'tomato': 1.22, 'carrot': 1.15}
# Generowanie listy 20x12 z losowo rozmieszczonymi roślinami
@ -36,16 +36,19 @@ def calculate_yields(garden):
neighbors = [
(i - 1, j), (i + 1, j), (i, j - 1), (i, j + 1)
]
neighbor_flag = False
for ni, nj in neighbors:
if 0 <= ni < rows and 0 <= nj < cols:
neighbor_plant = garden[ni][nj]
if yield_reduction[plant][neighbor_plant] is not None: #jeśli jest wartość None to nie zostaje wcale dodane
if yield_reduction[plant][neighbor_plant] is not None: # jeśli jest wartość None to plony dla tej rośliny będą wyzerowane
yield_count += yield_reduction[plant][neighbor_plant]
else:
neighbor_flag = True
yield_count *= yield_multiplier[plant]
total_yields += yield_count
if not neighbor_flag:
yield_count *= yield_multiplier[plant]
total_yields += yield_count
return total_yields
@ -136,9 +139,9 @@ def sum_yields(x):
if __name__ == '__main__':
roulette = True
attemps = 150
attemps = 20
iterat = 2500
population = 100
population = 120
best = []
for a in range(attemps):
generation = generate(population)
@ -192,13 +195,13 @@ if __name__ == '__main__':
# print(best[i][1], calculate_yields(best[i][0]))
#
#
# with open(f'pole_pop{population}_iter{iterat}_{roulette}.json', 'w') as file: # zapis planszy/ogrodu do pliku json
# with open(f'pole2_pop{population}_iter{iterat}_{roulette}.json', 'w') as file: # zapis planszy/ogrodu do pliku json
# json.dump(best[0][0], file, indent=4)
#
# print("Dane zapisane do pliku")
#
# Odczyt z pliku
# with open(f'pole_pop{population}_iter{iterat}_{roulette}.json', 'r') as file:
# with open(f'pole2_pop{population}_iter{iterat}_{roulette}.json', 'r') as file:
# garden_data = json.load(file)
#
# print("Odczytane dane ogrodu:")

211
GeneticAlgorithm3.py Normal file
View File

@ -0,0 +1,211 @@
import copy
import json
import random
from displayControler import NUM_X, NUM_Y
# Definiowanie stałych dla roślin i plonów
plants = ['corn', 'potato', 'tomato', 'carrot']
initial_yields = {'corn': 38, 'potato': 40, 'tomato': 43, 'carrot': 45}
yield_reduction = {
'corn': {'corn': None, 'potato': 0, 'tomato': 0, 'carrot': 0},
'potato': {'corn': None, 'potato': 0, 'tomato': 0, 'carrot': 0},
'tomato': {'corn': 0, 'potato': 0, 'tomato': 0, 'carrot': None},
'carrot': {'corn': 0, 'potato': 0, 'tomato': 0, 'carrot': 0}
}
yield_multiplier = {'corn': 1.25, 'potato': 1.19, 'tomato': 1.22, 'carrot': 1.13}
# Generowanie listy 20x12 z losowo rozmieszczonymi roślinami
def generate_garden(rows=20, cols=12):
return [[random.choice(plants) for _ in range(cols)] for _ in range(rows)]
# Funkcja do obliczania liczby plonów
def calculate_yields(garden):
rows = len(garden)
cols = len(garden[0])
total_yields = 0
for i in range(rows):
for j in range(cols):
plant = garden[i][j]
# Sprawdzanie sąsiadów
neighbors = [
(i - 1, j), (i + 1, j), (i, j - 1), (i, j + 1)
]
neighbor_flag = False
for ni, nj in neighbors:
if 0 <= ni < rows and 0 <= nj < cols:
neighbor_plant = garden[ni][nj]
if yield_reduction[plant][neighbor_plant] is None: # jeśli jest wartość None to plony dla tej rośliny będą wyzerowane
neighbor_flag = True
if not neighbor_flag:
total_yields += 1
return total_yields
# Funkcja do generowania planszy/ogrodu i zapisywania go jako lista z liczbą plonów
def generate_garden_with_yields(rows=NUM_Y, cols=NUM_X):
garden = generate_garden(rows, cols)
total_yields = calculate_yields(garden)
return [garden, total_yields]
# Funkcja do generowania linii cięcia i zapisywania jej jako liczba roślin w kolumnie z pierwszej planszy/ogrodu
def line():
path = []
flag = False
x = random.randint(4, 8)
position = (0, x)
path.append(position)
while not flag: # wybór punktu dopóki nie wybierze się skrajnego
# prawdopodobieństwo "ruchu" -> 0.6: w prawo, 0.2: w góre, 0.2: w dół
p = [(position[0] + 1, position[1]), (position[0], position[1] + 1), (position[0], position[1] - 1)]
w = [0.6, 0.2, 0.2]
position2 = random.choices(p, w)[0]
if position2 not in path: # sprawdzenie czy dany punkt nie był już wybrany aby nie zapętlać się
path.append(position2)
position = position2
if position[0] == NUM_X or position[1] == 0 or position[1] == NUM_Y: # sprawdzenie czy osiągnięto skrajny punkt
flag = True
info = [] # przeformatowanie sposobu zapisu na liczbę roślin w kolumnie, które będzię się dzidziczyło z pierwszej planszy/ogrodu
for i in range(len(path) - 1):
if path[i + 1][0] - path[i][0] == 1:
info.append(NUM_Y - path[i][1])
if len(info) < NUM_X: # uzupełnienie informacji o dziedziczeniu z planszy/ogrodu
if path[-1:][0][1] == 0:
x = NUM_Y
else:
x = 0
while len(info) < NUM_X:
info.append(x)
# return path, info
return info
# Funkcja do generowania potomstwa
def divide_gardens(garden1, garden2):
info = line()
new_garden1 = [[] for _ in range(NUM_Y)]
new_garden2 = [[] for _ in range(NUM_Y)]
for i in range(NUM_X):
for j in range(NUM_Y):
# do utworzonych kolumn w nowych planszach/ogrodach dodajemy dziedziczone rośliny
if j < info[i]:
new_garden1[j].append(garden1[j][i])
new_garden2[j].append(garden2[j][i])
else:
new_garden1[j].append(garden2[j][i])
new_garden2[j].append(garden1[j][i])
return [new_garden1, calculate_yields(new_garden1)], [new_garden2, calculate_yields(new_garden2)]
# Funkcja do mutacji danej planszy/ogrodu
def mutation(garden, not_used):
new_garden = copy.deepcopy(garden)
for i in range(NUM_X):
x = random.randint(0, 11) # wybieramy, w którym wierszu w i-tej kolumnie zmieniamy roślinę na inną
other_plants = [plant for plant in plants if plant != new_garden[x][i]]
new_garden[x][i] = random.choice(other_plants)
return [new_garden, calculate_yields(new_garden)]
# Funkcja do generowania pierwszego pokolenia
def generate(n):
generation = []
for i in range(n * 3):
generation.append(generate_garden_with_yields())
generation.sort(reverse=True, key=lambda x: x[1])
return generation[:n]
# Funkcja do implementacji ruletki (sposobu wyboru) - sumuje wszystkie plony generacji
def sum_yields(x):
s = 0
for i in range(len(x)):
s += x[i][1]
return s
if __name__ == '__main__':
roulette = True
attemps = 1
population = 120
best = []
iter = 0
for a in range(attemps):
generation = generate(population)
print(generation[0][1])
while generation[0][1] != NUM_X*NUM_Y: # ile iteracji - nowych pokoleń
iter += 1
print(iter)
print(generation[0][1])
new_generation = generation[:(population // 7)] # dziedziczenie x najlepszych osobników
j = 0
while j < (
population - (
population // 7)): # dobór reszty osobników do pełnej liczby populacji danego pokolenia
if roulette: # zasada ruletki -> "2 rzuty kulką"
s = sum_yields(generation) # suma wszystkich plnów całego pokolenia
z = []
if s == 0: # wtedy każdy osobnik ma takie same szanse
z.append(random.randint(0, population - 1))
z.append(random.randint(0, population - 1))
else:
weights = [] # wagi prawdopodobieństwa dla każdego osobnika generacji
pos = [] # numery od 0 do 49 odpowiadające numerom osobnikom w generacji
for i in range(population):
weights.append(generation[i][1] / s)
pos.append(i)
z.append(random.choices(pos, weights)[0]) # wybranie osobnika według wag prawdopodobieństwa
z.append(random.choices(pos, weights)[0]) # wybranie osobnika według wag prawdopodobieństwa
else: # metoda rankingu
z = random.sample(range(0, int(population // 1.7)), 2)
# krzyzowanie 90% szans, mutacja 10% szans
function = [divide_gardens, mutation]
weight = [0.9, 0.1]
fun = random.choices(function, weight)[0]
h = fun(generation[z[0]][0], generation[z[1]][0])
if len(h[0]) == 2:
new_generation.append(h[0])
new_generation.append(h[1])
j += 2
else:
new_generation.append(h)
j += 1
new_generation.sort(reverse=True, key=lambda x: x[1]) # sortowanie malejąco listy według wartości plonów
generation = new_generation[:population]
best.append(generation[0])
best.sort(reverse=True, key=lambda x: x[1])
# Zapis do pliku
# for i in range(len(best)):
# print(best[i][1], calculate_yields(best[i][0]))
#
#
# with open(f'pole3_pop{population}_{iter}_{roulette}.json', 'w') as file: # zapis planszy/ogrodu do pliku json
# json.dump(best[0][0], file, indent=4)
#
# print("Dane zapisane do pliku")
#
# Odczyt z pliku
# with open(f'pole3_pop{population}_{iter}_{roulette}.json', 'r') as file:
# garden_data = json.load(file)
#
# print("Odczytane dane ogrodu:")
# for row in garden_data:
# print(row)
#
# print(calculate_yields(garden_data))
# if best[0][0] == garden_data:
# print("POPRAWNE: ", calculate_yields(garden_data), calculate_yields(best[0][0]))

View File

@ -0,0 +1,266 @@
[
[
"tomato",
"corn",
"tomato",
"tomato",
"corn",
"tomato",
"tomato",
"corn",
"carrot",
"potato",
"potato",
"tomato",
"corn",
"tomato",
"corn",
"tomato",
"corn",
"tomato",
"corn",
"tomato"
],
[
"corn",
"carrot",
"potato",
"potato",
"carrot",
"potato",
"potato",
"carrot",
"potato",
"potato",
"carrot",
"corn",
"tomato",
"corn",
"carrot",
"corn",
"tomato",
"corn",
"tomato",
"corn"
],
[
"carrot",
"potato",
"potato",
"carrot",
"corn",
"carrot",
"potato",
"carrot",
"potato",
"carrot",
"corn",
"tomato",
"corn",
"tomato",
"corn",
"tomato",
"corn",
"tomato",
"corn",
"tomato"
],
[
"potato",
"potato",
"carrot",
"corn",
"tomato",
"corn",
"carrot",
"corn",
"carrot",
"corn",
"tomato",
"corn",
"tomato",
"corn",
"tomato",
"corn",
"tomato",
"corn",
"tomato",
"corn"
],
[
"potato",
"carrot",
"corn",
"tomato",
"corn",
"tomato",
"corn",
"tomato",
"corn",
"tomato",
"corn",
"tomato",
"corn",
"tomato",
"corn",
"tomato",
"corn",
"tomato",
"corn",
"tomato"
],
[
"tomato",
"corn",
"tomato",
"corn",
"tomato",
"corn",
"tomato",
"corn",
"tomato",
"corn",
"tomato",
"corn",
"tomato",
"corn",
"tomato",
"corn",
"tomato",
"corn",
"tomato",
"corn"
],
[
"corn",
"tomato",
"corn",
"tomato",
"corn",
"tomato",
"corn",
"tomato",
"corn",
"tomato",
"corn",
"tomato",
"corn",
"tomato",
"corn",
"tomato",
"corn",
"tomato",
"corn",
"tomato"
],
[
"tomato",
"corn",
"tomato",
"corn",
"tomato",
"corn",
"tomato",
"corn",
"tomato",
"corn",
"tomato",
"corn",
"tomato",
"corn",
"tomato",
"corn",
"tomato",
"corn",
"tomato",
"corn"
],
[
"corn",
"tomato",
"corn",
"tomato",
"corn",
"tomato",
"corn",
"tomato",
"corn",
"tomato",
"corn",
"tomato",
"corn",
"tomato",
"corn",
"tomato",
"corn",
"carrot",
"corn",
"tomato"
],
[
"tomato",
"corn",
"tomato",
"corn",
"tomato",
"corn",
"tomato",
"corn",
"tomato",
"corn",
"tomato",
"corn",
"tomato",
"corn",
"tomato",
"corn",
"carrot",
"potato",
"tomato",
"potato"
],
[
"corn",
"tomato",
"corn",
"tomato",
"corn",
"tomato",
"corn",
"tomato",
"corn",
"tomato",
"corn",
"carrot",
"corn",
"carrot",
"corn",
"carrot",
"potato",
"potato",
"tomato",
"potato"
],
[
"tomato",
"corn",
"tomato",
"corn",
"tomato",
"corn",
"tomato",
"corn",
"tomato",
"corn",
"tomato",
"corn",
"tomato",
"corn",
"tomato",
"potato",
"potato",
"carrot",
"corn",
"tomato"
]
]

266
pole3_pop120_365_True.json Normal file
View File

@ -0,0 +1,266 @@
[
[
"potato",
"carrot",
"carrot",
"potato",
"potato",
"carrot",
"carrot",
"potato",
"tomato",
"potato",
"carrot",
"potato",
"carrot",
"potato",
"carrot",
"carrot",
"potato",
"potato",
"potato",
"carrot"
],
[
"tomato",
"potato",
"carrot",
"potato",
"tomato",
"potato",
"carrot",
"carrot",
"potato",
"carrot",
"carrot",
"carrot",
"carrot",
"carrot",
"carrot",
"carrot",
"potato",
"potato",
"carrot",
"potato"
],
[
"corn",
"carrot",
"corn",
"carrot",
"potato",
"carrot",
"carrot",
"corn",
"tomato",
"corn",
"carrot",
"potato",
"potato",
"carrot",
"carrot",
"corn",
"carrot",
"potato",
"potato",
"tomato"
],
[
"tomato",
"potato",
"carrot",
"corn",
"tomato",
"corn",
"carrot",
"carrot",
"corn",
"carrot",
"potato",
"carrot",
"carrot",
"corn",
"carrot",
"carrot",
"potato",
"potato",
"tomato",
"tomato"
],
[
"tomato",
"potato",
"carrot",
"carrot",
"corn",
"carrot",
"carrot",
"potato",
"tomato",
"potato",
"carrot",
"carrot",
"potato",
"carrot",
"carrot",
"potato",
"tomato",
"tomato",
"potato",
"potato"
],
[
"potato",
"tomato",
"potato",
"potato",
"tomato",
"corn",
"carrot",
"potato",
"potato",
"tomato",
"potato",
"carrot",
"carrot",
"potato",
"carrot",
"potato",
"tomato",
"potato",
"carrot",
"carrot"
],
[
"potato",
"potato",
"tomato",
"tomato",
"corn",
"carrot",
"carrot",
"potato",
"tomato",
"potato",
"carrot",
"carrot",
"potato",
"carrot",
"carrot",
"carrot",
"potato",
"carrot",
"carrot",
"potato"
],
[
"carrot",
"potato",
"tomato",
"potato",
"carrot",
"carrot",
"potato",
"potato",
"tomato",
"tomato",
"potato",
"carrot",
"potato",
"potato",
"carrot",
"carrot",
"potato",
"carrot",
"corn",
"carrot"
],
[
"carrot",
"potato",
"tomato",
"potato",
"carrot",
"carrot",
"carrot",
"potato",
"tomato",
"potato",
"potato",
"carrot",
"carrot",
"potato",
"carrot",
"carrot",
"carrot",
"potato",
"tomato",
"corn"
],
[
"potato",
"tomato",
"tomato",
"potato",
"carrot",
"potato",
"potato",
"carrot",
"potato",
"potato",
"carrot",
"potato",
"carrot",
"carrot",
"potato",
"carrot",
"corn",
"tomato",
"potato",
"tomato"
],
[
"potato",
"tomato",
"corn",
"tomato",
"potato",
"potato",
"potato",
"potato",
"carrot",
"carrot",
"carrot",
"potato",
"carrot",
"carrot",
"potato",
"carrot",
"carrot",
"corn",
"tomato",
"potato"
],
[
"potato",
"potato",
"carrot",
"corn",
"carrot",
"potato",
"potato",
"potato",
"carrot",
"carrot",
"carrot",
"potato",
"carrot",
"carrot",
"potato",
"carrot",
"corn",
"carrot",
"corn",
"tomato"
]
]