# -*- coding: utf-8 -*-
import array
import random
import json
import numpy as np
# import matplotlib
# matplotlib.use('Agg')
import matplotlib.pyplot as plt
from math import sqrt
from deap import algorithms
from deap import base
from deap import benchmarks
from deap.benchmarks.tools import diversity, convergence, hypervolume
from deap import creator
from deap import tools
#目的関数2つをどちらも最小化する設定
creator.create("FitnessMin", base.Fitness, weights=(-1.0, -1.0))
creator.create("Individual", array.array, typecode='d', fitness=creator.FitnessMin)
toolbox = base.Toolbox()
#遺伝子が取り得る値の範囲を指定(遺伝子は0.0~1.0の間の連続値をとる)
BOUND_LOW, BOUND_UP = 0.0, 1.0
#1つの個体内の遺伝子の数を指定している(遺伝子数30個)
NDIM = 30
#遺伝子生成の関数(各遺伝子ごとに取り得る範囲を指定できる)
def uniform(low, up, size=None):
try:
return [random.uniform(a, b) for a, b in zip(low, up)]
except TypeError:
return [random.uniform(a, b) for a, b in zip([low] * size, [up] * size)]
toolbox.register("attr_float", uniform, BOUND_LOW, BOUND_UP, NDIM)
toolbox.register("individual", tools.initIterate, creator.Individual, toolbox.attr_float)
toolbox.register("population", tools.initRepeat, list, toolbox.individual)
#適応度を評価する目的関数の指定
toolbox.register("evaluate", benchmarks.zdt1)
toolbox.register("mate", tools.cxSimulatedBinaryBounded, low=BOUND_LOW, up=BOUND_UP, eta=20.0)
toolbox.register("mutate", tools.mutPolynomialBounded, low=BOUND_LOW, up=BOUND_UP, eta=20.0, indpb=1.0/NDIM)
#選択アルゴリズムにNSGA-Ⅱを使った選択関数tools.selNSGA2を指定
toolbox.register("select", tools.selNSGA2)
def main(seed=None):
random.seed(seed)
#世代ループの回数
NGEN = 250
#世代内の個体数
MU = 100
#交叉率
CXPB = 0.9
#世代ループ中のログに何を出力するかの設定
stats = tools.Statistics(lambda ind: ind.fitness.values)
#世代内の個体の適応度の最小値
stats.register("min", np.min, axis=0)
#世代内の個体の適応度の最大値
stats.register("max", np.max, axis=0)
logbook = tools.Logbook()
logbook.header = "gen", "evals", "min", "max"
pop = toolbox.population(n=MU)
pop_ini = pop[:]
invalid_ind = [ind for ind in pop if not ind.fitness.valid]
fitnesses = toolbox.map(toolbox.evaluate, invalid_ind)
for ind, fit in zip(invalid_ind, fitnesses):
ind.fitness.values = fit
pop = toolbox.select(pop, len(pop))
#適応度のminとmaxを算出する記述
record = stats.compile(pop)
logbook.record(gen=0, evals=len(invalid_ind), **record)
print(logbook.stream)
for gen in range(1, NGEN):
offspring = tools.selTournamentDCD(pop, len(pop))
offspring = [toolbox.clone(ind) for ind in offspring]
#交叉と突然変異
for ind1, ind2 in zip(offspring[::2], offspring[1::2]):
if random.random() <= CXPB:
toolbox.mate(ind1, ind2)
toolbox.mutate(ind1)
toolbox.mutate(ind2)
del ind1.fitness.values, ind2.fitness.values
invalid_ind = [ind for ind in offspring if not ind.fitness.valid]
fitnesses = toolbox.map(toolbox.evaluate, invalid_ind)
for ind, fit in zip(invalid_ind, fitnesses):
ind.fitness.values = fit
pop = toolbox.select(pop + offspring, MU)
record = stats.compile(pop)
logbook.record(gen=gen, evals=len(invalid_ind), **record)
print(logbook.stream)
#最終世代のハイパーボリュームを出力
#個体内の適応度は2こあるので、適応度空間は2次元になり、ハイパーボリュームは所謂面積になります。
print("Final population hypervolume is %f" % hypervolume(pop, [11.0, 11.0]))
return pop, pop_ini, logbook