Задача: создать программу для моделирования генетического алгоритма на языке Python. Чтобы использовать обмен битами в качестве мутации, оператор выбора должен масштабировать приспособленность, создать трехмерный график, использовать на графике гладкую поверхность. X: [-15, -2], Y: [-15, -2], формула пригодности = 0,5*(X-3)(Y-5)(Y-1)*sin(Y)cos (2X).
Проблема: в строке 127 обновления возвращается ошибка
x_points.append(x[entity[0]])
~~~~~~~~~^^^
IndexError: invalid index to scalar variable.
Не могу понять, где допущена ошибка. Без функции масштабирования фитнеса симуляция работает без проблем.
import random
import matplotlib.pyplot as plt
import numpy as np
Q = 20 # Количество поколений
MAX_ENT = 100 # размер популяции
MAX_CH = 20 # количество детей в одном цикле воспроизводства
N = 15 # длина хромосомы
minFitAim = 500 # минимальный желаемый результат
maxFitAim = 1500 # максимальный желаемый результат
razmer = 100
def f(x, y):
return 0.5 * (x - 3) * (y - 5) * (y - 1) * np.sin(y) * np.cos(2 * x)
def fitness(inp): # inp - входной список из нолей и единиц
z = 0.0
x1 = x[inp[0]]
y1 = y[inp[1]]
z = f(x1, y1)
return z
def update(event):
# Начальное поколение
entity = [[random.randint(0, razmer - 1) for j in range(N)] for i in range(MAX_ENT)]
print(entity)
# Инициализация точек для графика
x_points = []
y_points = []
z_points = []
for i in range(MAX_ENT):
x_points.append(x[entity[0]])
y_points.append(y[entity[1]])
z_points.append(f(x_points, y_points))
scatter = ax.scatter(x_points, y_points, z_points, c='r', marker='o')
for q in range(Q):
ax.set_title("Поколение: " + str(q))
fit = [0 for _ in range(MAX_ENT)] # fitness для каждого организма
tmp_fit = [0 for _ in range(MAX_ENT + 2 * MAX_CH)] # фитнес всех организмов вместе с потомками
for i in range(MAX_ENT):
fit = fitness(entity)
print('fit = ', max(fit))
# Воспроизводство
fl_parent = np.full(MAX_ENT, True) # до цикла воспроизводства всe могут быть родителями
child1 = [0 for _ in range(N)]
child2 = [0 for _ in range(N)]
k = 0
while k < MAX_CH: # цикл воспроизводства по 2 потомка
m1 = random.randint(0, MAX_ENT - 1) # первый кандидат родитель
m2 = random.randint(0, MAX_ENT - 1) # второй кандидат родитель
if m1 == m2:
continue # должны быть разные
if not (fl_parent[m1] & fl_parent[m2]):
continue # кто-то уже имел потомка
# построение 2-х потомков от m1 и m2
l1 = random.randint(0, N - 1) # точка обмена хромосом
child1[:l1] = entity[m1][:l1] + entity[m2][l1:] # первый потомок
child2[:l1] = entity[m2][:l1] + entity[m1][l1:] # второй потомок
ch1 = child1[:]
ch2 = child2[:]
# добавка к массиву организмов двух потомков
entity.append(ch1)
entity.append(ch2)
fl_parent[m1] = False
fl_parent[m2] = False
k += 1
#Мутация
p_vm = 0.1 # Вероятность победы менее приспособленного
p_m = 0.2 # Вероятность мутации гена
mut_entity = [0 for _ in range(N)] # мутант
for j in range(MAX_ENT + 2 * MAX_CH): # цикл по всем организмом вместе с потомками
mut_entity = entity[j]
for k in range(N): # цикл по всем битам каждого организма
if random.random() < p_m: # Мутация обменом для мутанта
mut_entity[k] = entity[j][(N - 1) - k]
mut_entity[(N - 1) - k] = entity[j][k]
f1 = fitness(entity[j]) # приспособленность организма
f2 = fitness(mut_entity) # приспособленность мутанта
if f1 > f2:
if random.random() < p_vm:
entity[j] = mut_entity[:] # останется менее приспособленный
else:
entity[j] = mut_entity[:] # остается более приспособленный
# ЕСТЕСТВЕННЫЙ ОТБОР
tmp_entity = []
for j in range(MAX_ENT + 2 * MAX_CH):
tmp_fit[j] = fitness(entity[j]) # новое значение фитнеса
print('tmp_fit = ', tmp_fit)
min_fitness = min(tmp_fit) # минимальный фитнес в поколении
max_fitness = max(tmp_fit) # максимальный фитнес в поколении
a = (minFitAim - maxFitAim) / (min_fitness - max_fitness) # коэффициент для малого индивидуума
b = minFitAim - a * min_fitness # коэффициент для большего
for j in range(MAX_ENT + 2 * MAX_CH):
tmp_entity.append(a * tmp_fit[j] + b)
entity = tmp_entity[:MAX_ENT]
# Удаление старых точек
scatter.remove()
# Создание новых точек для графика
x_points = []
y_points = []
z_points = []
for i in range(MAX_ENT):
x_points.append(x[entity[0]])
y_points.append(y[entity[1]])
z_points.append(f(x_points, y_points[i]))
# Отображение группы точек для графика
scatter = ax.scatter(x_points, y_points, z_points, c='r', marker='o')
# Обновление графика
fig.canvas.draw()
plt.pause(0.001)
q += 1
# Настройка параметров
x = np.linspace(-15, 2, razmer)
y = np.linspace(-15, 2, razmer)
X, Y = np.meshgrid(x, y)
# Создание плавной поверхности
Z = f(X, Y)
# Инициализация графика
fig = plt.figure(figsize=(6, 6))
ax = fig.add_subplot(111, projection='3d')
# Отображение поверхности
ax.plot_surface(X, Y, Z, rstride=1, cstride=1)
# Настройка меток и заголовков
ax.set_xlabel('X-хромосомы')
ax.set_ylabel('Y-хромосомы')
ax.set_zlabel('Приспособленность')
# Создание кнопки
ax_button = plt.axes([0.8, 0.05, 0.1, 0.075])
button = plt.Button(ax_button, 'START')
button.on_clicked(update)
# Показ графика
plt.show()
Подробнее здесь: https://stackoverflow.com/questions/790 ... -on-python