遗传算法求解背包问题(纯新手)

记录第一次写出遗传算法

问题来自遗传算法求解背包问题_用遗传算法实现背包问题-CSDN博客

首先算法思路:

一、初始一个种群

二、进行繁衍(顺带突变一下)

三、种群中单个个体的适应度(可理解为繁衍下去的概率,和目标值有关)

四、child和原种群结合成一个新种群,定义一个select函数除去哪些繁衍概率小的个体, 重复二,三进程

五、经过n次迭代(繁衍)进程 得到最终的较为优秀种群,从中寻找到适应度最大的个体(解),

当作问题的最终答案。

六、写一个for循环,看看此算法的预测准确率

一、初始一个种群

pop = np.random.randint(0, 2, size=(POP_SIZE, DNA_SIZE))

这里用二进制表示方案选择情况,010101就是指背包里面放物品2,3,6

二、进行繁衍(顺带突变一下)

突变对种群pop中的单个个体随机初始一个突变点,然后采用最简的^1逻辑判断(a^b,规则:若a==b,则判断结果为0,否则为1,所以二进制序列中可以用^1来将0,1的值颠倒) 

def mutation(pop, MUTATION_RATE):
    new_pop = []
    for i in pop:
        if np.random.rand() < MUTATION_RATE:
            mutation_point = np.random.randint(0, 6)  
            i[mutation_point] = i[mutation_point] ^ 1
            new_pop.append(i)
        else:
            new_pop.append(i)
    return np.array(new_pop)

当然不是种群中所有个体都进行突变,用一个if语句来让突变概率为MUTATION_RATE

,同理个体中父类与子类繁衍也是一定概率

def crossover(pop, CROSSOVER_RATE):
    global child
    new_pop = []
    for father in pop:
        child = father
        if np.random.rand() < CROSSOVER_RATE:
            mother = pop[np.random.randint(0, POP_SIZE)]
            crossover_point = np.random.randint(0, DNA_SIZE)
            child[crossover_point:] = mother[crossover_point:]
        new_pop.append(child)
    return np.array(new_pop)

三、种群中单个个体的适应度(可理解为繁衍下去的概率,和目标值有关)

这里有个待解决的问题是:如何体现背包80公斤容量的限制

笔者采用的是将超出80kg的个体方案赋值为000000,如:随机初始化时存在个体111111(显然超出背包最大负载量)所以将其赋值为000000,这样在后面的计算适应度时,其值大小肯定是0,其nda遗传下去的概率也就是0

def update_function(pop):
    new_pop = []
    for i in pop:
        if i.dot(np.array([10, 15, 20, 25, 30, 35])) > 80:
            i = [0, 0, 0, 0, 0, 0]
        new_pop.append(i)
    return np.array(new_pop)

单个个体的适应度就是选择此方案时背包的价值数比上所有个体的价值数,也就是可以遗传dna的概率大小

def get_fitness(pop):
    function_value = pop.dot(np.array([15, 25, 35, 45, 55, 70]))
    fitness = function_value / sum(function_value)
    return fitness

全部代码如下

import numpy as np

# 先设置种群的参数,
DNA_SIZE = 6  # 这里就是指的是每个个体用二进制表示的长度
POP_SIZE = 2000
CROSSOVER_RATE = 0.8  # 表示种族交配繁衍的概率
MUTATION_RATE = 0.05  # 突变概率,单个个体基因
N_GENERATIONS = 70  # 种群进行演化的代数


def update_function(pop):
    new_pop = []
    for i in pop:
        if i.dot(np.array([10, 15, 20, 25, 30, 35])) > 80:
            i = [0, 0, 0, 0, 0, 0]
        new_pop.append(i)
    return np.array(new_pop)


def get_fitness(pop):
    function_value = pop.dot(np.array([15, 25, 35, 45, 55, 70]))
    fitness = function_value / sum(function_value)
    return fitness


def mutation(pop, MUTATION_RATE):
    new_pop = []
    for i in pop:
        if np.random.rand() < MUTATION_RATE:
            mutation_point = np.random.randint(0, 6)  # 注意randint是不包含最大值的
            i[mutation_point] = i[mutation_point] ^ 1
            new_pop.append(i)
        else:
            new_pop.append(i)
    return np.array(new_pop)


def crossover(pop, CROSSOVER_RATE):
    global child
    new_pop = []
    for father in pop:
        child = father
        if np.random.rand() < CROSSOVER_RATE:
            mother = pop[np.random.randint(0, POP_SIZE)]
            crossover_point = np.random.randint(0, DNA_SIZE)
            child[crossover_point:] = mother[crossover_point:]
        new_pop.append(child)
    return np.array(new_pop)


def select(pop, fitness):
    idx = np.random.choice(np.arange(POP_SIZE), size=POP_SIZE, replace=True, p=fitness)
    return pop[idx]


def print_info(pop):
    fitness = get_fitness(pop)
    max_fitness_idx = np.argmax(fitness)
    # print("最优方案是", pop[max_fitness_idx])
    # print("最优值是", pop[max_fitness_idx].dot(np.array([15, 25, 35, 45, 55, 70])))
    return pop[max_fitness_idx].dot(np.array([15, 25, 35, 45, 55, 70]))


def single_process():
    pop = np.random.randint(0, 2, size=(POP_SIZE, DNA_SIZE))
    for _ in range(N_GENERATIONS):
        pop = mutation(pop, MUTATION_RATE)
        pop = crossover(pop, CROSSOVER_RATE)
        fitness = get_fitness(pop)
        pop = select(pop, fitness)
        pop = update_function(pop)
    y = print_info(pop)
    return y


if __name__ == '__main__':
    # pop = np.random.randint(0, 2, size=(POP_SIZE, DNA_SIZE))
    # for _ in range(N_GENERATIONS):
    #     pop = mutation(pop, MUTATION_RATE)
    #     pop = crossover(pop, CROSSOVER_RATE)
    #     fitness = get_fitness(pop)
    #     pop = select(pop, fitness)
    #     pop = update_function(pop)
    # print_info(pop)
    # 写一个准确率函数
    volume = []
    for epoch in range(70):
        y = single_process()
        if y == 150:
            print("预测正确")
            volume.append(epoch)
        else:
            print("预测错误")
    print(len(volume)/70)







服了,写完才发现存在一个问题,那就是没有完全模拟自然界种群的繁衍规则,虽然准确率很好。

这里求fitness大小只用来做种群的死亡选择上了,没有用到繁衍的过程(默认单个为同等概率繁衍),应当在crossover函数里面加上一个choice函数用来选择pop中的父类和母类而不是随机选择,这样种群进化的估计会更快,模型计算时间估计会减少

  • 4
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
遗传算法是一种模拟生物进化的计算方法,可以用于解决复杂的优化问题,如背包问题背包问题是在给定的一组物品中,选取部分物品使其总价值最大,但是总重量不能超过背包的限制。 在使用遗传算法求解背包问题的过程中,首先需要定义适应度函数,该函数用于衡量染色体的优劣程度。对于背包问题,适应度函数可以考虑总价值与总重量之比,希望比值最大化。然后,生成初始种群,每个个体表示一种解决方案,即在背包中物品的选择与否。 接下来,通过交叉和变异操作,对种群进行迭代更新。交叉操作是将两个个体的基因片段进行互换,生成新的个体。变异操作是随机改变染色体中的一个或多个基因值。这样能够产生更多的解决方案,并逐渐优化种群。 最后,选择适应度高的个体形成下一代种群,并重复进行交叉和变异操作,直到满足停止条件。最终得到的个体即为背包问题解决方案。 在MATLAB中,可以使用遗传算法工具箱来实现背包问题求解。通过定义目标函数和约束条件,设置遗传算法的参数和操作,调用遗传算法函数即可得到结果。 需要注意的是,遗传算法是一种启发式算法,结果可能接近最优解,但不一定能够保证获得最优解。因此,在实际应用中,需要根据具体情况进行参数调整和优化策略设计,以获得更好的性能和效果。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值