基于遗传算法的最小值问题

通过遗传算法,使一段长度固定的二进制字符串所有位置上数字之和最小。

算法主要分为:参数定义、适应度函数,以及循环变异

1.参数定义

在deap框架中,通过toolbox.register来定义函数,creator.create来创建类

2.适应度函数

遗传算法通过适应度来评价族群是否合适,循环是否停止,在最小值问题中,通过sum函数求和即可

3.循环变异

在规定的迭代次数内,不断交叉、变异,来求得和最小的字符串组合

from deap import base
from deap import creator
from deap import tools
import random
import matplotlib.pyplot as plt

#超参数声明
ONE_MIN_LENGTH = 100    #length of bit string to be optimized
POPULATION_SIZE = 100   #number of individuals in population
P_CROSSOVER = 0.9       #probability for crossover
P_MUTATION = 0.1        #probability for mutating an individual
MAX_GENERATION = 100     #max number of generations for stopping condition

toolbox = base.Toolbox()#定义toolbox变量
toolbox.register("zeroOrOne",random.randint,0,1)#注册zeroOrOne运算
#定了适应度评估时的权重,权重值1.0,表示这是一个最大化问题。权重值-1.0,则表示这是一个最小化问题。
creator.create("FitnessMix",base.Fitness,weights=(-1.0,))
#定义个体类型为list,并赋予成员变量fitness作为适应度标签
creator.create("Individual", list, fitness=creator.FitnessMix)
#定义个体生成函数
toolbox.register("individualCreator",tools.initRepeat,creator.Individual,toolbox.zeroOrOne,ONE_MIN_LENGTH)
#定义族群生成函数
toolbox.register("populationCreator",tools.initRepeat,list,toolbox.individualCreator)

#sum函数将数组中的所有元素相加,作为算法的评价函数
def oneMinFitness(individual):
    return sum(individual),#deap中的适用度表示为元组,因此,当返回单个值时,需要用逗号将其声明为元组。

toolbox.register("evaluate",oneMinFitness)

toolbox.register("select",tools.selTournament,tournsize=3)
toolbox.register("mate",tools.cxOnePoint)
# mutFlipBit函数遍历个体的所有特征,并且对于每个特征值,
# 都将使用indpb参数值作为翻转(应用not运算符)该特征值的概率。
# 该值与突变概率无关,后者由P_MUTATION常数设置。
# 突变概率用于确定是否为种群中的给定个体调用mutFlipBit函数
toolbox.register("mutate",tools.mutFlipBit,indpb=1.0/ONE_MIN_LENGTH)

def main():
    population = toolbox.populationCreator(n=POPULATION_SIZE)#初始化种群
    generationCounter = 0
    fitnessValues = list(map(toolbox.evaluate,population))#通过fitness函数来评估适应度,map函数包含一个函数和一个迭代对象,
    #map将迭代对象中的每一个元素送入函数中,返回迭代器
    for individual,fitnessValue in zip(population,fitnessValues):#遍历种群中的每个个体及其对应的适应度值,并将适应度值分配给每个个体的fitness.values属性
        individual.fitness.values = fitnessValue

    fitnessValues = [individual.fitness.values[0] for individual in population]

        #初始化最大适应度值和平均适应度值列表
    minFitnessValues = []
    meanFitnessValues = []

    #开始遗传变异,直到适应度符合需求或达到最大迭代次数
    while  generationCounter < MAX_GENERATION:
        generationCounter = generationCounter + 1#每次循环开始时,代数计数器加1
        
        offspring = toolbox.select(population,len(population))#使用select函数从当前种群population中选择个体以生成下一代
        offspring = list(map(toolbox.clone,offspring))#对选中的个体进行克隆,以避免在后续操作中修改原始种群。

        #对克隆后的个体进行成对交叉操作,交叉的概率由P_CROSSOVER决定。交叉后,删除子代个体的适应度值,因为它们需要被重新评估。
        for child1,child2 in zip(offspring[::2],offspring[1::2]):
            if random.random() < P_CROSSOVER:
                toolbox.mate(child1,child2)
                del child1.fitness.values
                del child2.fitness.values
        #对每个子代个体进行变异操作,变异的概率由P_MUTATION决定。变异后同样删除适应度值。
        for mutant in offspring:
            if random.random() < P_MUTATION:
                toolbox.mutate(mutant)
                del mutant.fitness.values
        #评估新个体的适应度:
        freshIndividuals = [ind for ind in offspring if not ind.fitness.valid]
        freshFitnessValues = list(map(toolbox.evaluate,freshIndividuals))
        for individual,fitnessValue in zip(freshIndividuals,freshFitnessValues):
            individual.fitness.values = fitnessValue
        #更新种群:
        population[:] = offspring
        #更新适应度值列表:
        fitnessValues = [ind.fitness.values[0] for ind in population]
        #记录统计信息:
        minFitnessValue = min(fitnessValues)
        meanFitnessValue = sum(fitnessValues) / len(population)
        minFitnessValues.append(minFitnessValue)
        meanFitnessValues.append(meanFitnessValue)
        print("- Generation {}: Min Fitness = {}, Avg Fitness = {}".format(generationCounter,minFitnessValue,meanFitnessValue))
        #打印最佳个体:
        best_index = fitnessValues.index(min(fitnessValues))
        print("Best Indivadual = ", *population[best_index],"\n")
    
    plt.plot(minFitnessValues,color="red")
    plt.plot(meanFitnessValues,color="green")
    plt.xlabel("Generation")
    plt.ylabel("Min / Average Fitness")
    plt.title("Min and Average fitness over Generation")
    plt.show()


if __name__ == "__main__":
    main()

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值