实验9 模拟退火算法求解背包问题

456 阅读5分钟

传送门(所有的实验都使用python实现)

实验1 BP神经网络实验

实验2 som网实验

实验3 hopfield实现八皇后问题

实验4 模糊搜索算法预测薄冰厚度

实验5 遗传算法求解tsp问题

实验6 蚁群算法求解tsp问题

实验7 粒子群优化算法求解tsp问题

实验8 分布估计算法求解背包问题

实验9 模拟退火算法求解背包问题

实验10 禁忌搜索算法求解tsp问题

 

一、实验目的

理解并使用模拟退火算法

二、实验内容

实现基于模拟退火算法的背包问题求解

三、实验环境

使用Python3.0 在 eclipse进行编辑

四、实验步骤

1、输入介绍:

    背包物体的个数为10,背包容量C,物品价值p,物品重量c。   

    参数设定 : time 迭代次数, balance 平衡次数 best记录全局最优  T 温度  af退火率

2、产生个体:

    随机产生一个合法的初始解

3、产生新解:

    随机选取物品, 若 i 不在背包中, 则将其直接放入背包中, 或同时从背包中随机取出另一物品 j ; 若 i已在背包中, 则将其取出, 并同时随机装入另一物品j .

4、计算背包价值与合法性。

    计算物品价值总和,并判断是否超重。

5、接受新解:

(1)超重,放弃此解

(2)比当前解背包价值更优,直接接受新解

(3)比当前解背包价值更劣,概率接受新解,概率 p=exp(-dlt/T)其中dlt为背包价值差。

6、更新全局最优解。

7、若达到平衡次数,则下降温度,重置平衡次数。否则继续产生新解。

8、终止条件

    背包价值达到最优解或者温度下降到x度以下。

 

 

 

运行截图:

初始温度200 退火率0.95 平衡次数5  找到最优解所需次数36

初始温度200 退火率0.8 平衡次数5  找到最优解所需次数22

初始温度200 退火率0.95 平衡次数10  找到最优解所需次数7

初始温度200 退火率0.95 平衡次数100  找到最优解所需次数1

五、总结

退火率的设置对于算法效率影响十分明显,温度下降过快虽然较早达到稳定,但是有时找不到最优解,温度下降过慢会导致耗时增多,经过多次实验得出,退火率选择0.8为最佳。

平衡次数设置越多,所需迭代次数越少,但是单次迭代时间变长,所以平衡次数设置10次为最佳。

初始温度设置将会影响解的搜索范围,温度越高最终解的质量越优,但是耗时也相应变长,初始温度设置200为最佳。

python源码

#coding:gbk
import random
import math
global m,C;    # m个物品 ,背包容量C
global time,balance;    #  time 迭代次数, balance  平衡次数
global best,T,af;   #best 记录全局最优  T 温度  af退火率
m=10; T=200.0; af =0.95;
time =10;  balance = 100; 
best_way=[0]*m;   now_way=[0]*m  #  best_way 记录全局最优解方案   now_way 记录当前解方案  
weight=[95, 4, 60, 32, 23, 72, 80, 62,65, 46]; value=[55, 10, 47, 5, 4, 50, 8, 61,85, 87]

def cop(a,b,le):     #复制函数 把b数组的值赋值a数组
    for i in range(le):
        a[i]=b[i]
def calc(x):  #计算背包价值
    global C,wsum;
    vsum=0;wsum=0;
    for i in range(m):
        vsum +=x[i]*value[i];  wsum += x[i]*weight[i];    
    return  vsum;
def produce():  #初始产生随机解
    while (1>0):
        for k in range(m):
            if(random.random() < 0.5):  now_way[k]=1;
            else: now_way[k]=0;
        calc(now_way)
        if(wsum <C): break;
    global best;
    best=calc(now_way);
    cop(best_way,now_way,m);

def init():   #初始化函数
    global C,best,T;
    C = 269;
    best=-1;
    produce()    #产生初始解
def get(x):      #随机将背包中已经存在的物品取出
    while(1>0):
        ob = random.randint(0,m-1);
        if(x[ob]==1): x[ob]=0;break;
def put(x):      #随机放入背包中不存在的物品
    while(1>0):
        ob = random.randint(0,m-1);
        if(x[ob]==0): x[ob]=1;break;       
def slove():  #迭代函数
    global best,T,balance;
    test=[0]*m;
    now = 0;   #当前背包价值
    for i in range(balance):
        now = calc(now_way);
        cop(test,now_way,m);
        ob = random.randint(0,m-1); #随机选取某个物品
        if(test[ob]==1): put(test);test[ob]=0;  #在背包中则将其拿出,并加入其它物品
        else:   #不在背包中则直接加入或替换掉已在背包中的物品
            if(random.random()<0.5):test[ob]=1; 
            else : get(test); test[ob]=1;
        temp= calc(test);
        if(wsum>C):continue;    # 非法解则跳过
        if(temp > best): best=temp; cop(best_way,test,m);     #更新全局最优
        
        if(temp > now): cop(now_way,test,m);       #直接接受新解 
        else:
            g = 1.0*(temp-now)/T;
            if(random.random() < math.exp(g)):   #概率接受劣解
                cop(now_way,test,m);    
                
#*****************************主函数**********************        
init();
isGood = 0;
for i in range(time):      
    slove();
    T = T*af;    #温度下降
    if(best==295):  
        print('找到最优解:295,迭代次数',i+1); isGood = 1;  break;    #达到最优解提前退出
        
if(isGood == 0):   print('只找到次优解:',best,'迭代次数',time);
print('方案为:',best_way);               #打印方案

本文已参与「新人创作礼」活动,一起开启掘金创作之路