
背包问题的目标是在给定物品和约束条件下,选择一定的物品,使得它们的总价值最大,同时满足总重量不超过给定的限制。模拟退火是一种基于概率的优化算法,主要用于解决全局最优化问题,尤其适用于解决非线性、不规则的优化问题。
模拟退火算法的基本思想
模拟退火算法借用了物理学中固体退火过程的概念。在物理退火过程中,物体从高温状态逐渐冷却,粒子逐步移动到能量最低的状态,最终达到热平衡。模拟退火的核心思想是,通过模拟物理退火过程来避免局部最优解,从而寻找全局最优解。
模拟退火算法的步骤
1. 初始化:
(1)初始解(解空间中的一个点)是随机的,在这个解下计算目标函数值。
(2)设置初始温度 t0 和结束温度 tf ,以及冷却系数 a (通常 0 < a < 1 )。温度表示搜索的“热度”,随着时间推移温度逐渐降低。
2. 扰动解:
在当前解的基础上,通过一定的随机扰动(例如随机选择某些物品的状态进行改变),生成一个新解。扰动的目的是为了探索解空间,避免陷入局部最优。
3. 接受新解的准则:
(1)如果新解的目标函数值比当前解好(即目标值较小),则直接接受新解。
(2)如果新解的目标函数值较差(即目标值较大),则按照一定的概率接受新解,这个概率由下式决定:
概率公式: exp(-(E_new - E_current) / t)
其中,E_new 是新解的目标函数值,E_current 是当前解的目标函数值,t 是当前温度。这个公式意味着,如果新解较差,温度较高时接受较差解的概率大,温度较低时则接受较差解的概率小。
4. 温度更新:
(1)在每次扰动和接受/拒绝新解后,温度会逐步降低,通常使用冷却因子 a 来控制温度的降低速度:t = t * a 。
(2)随着温度逐渐降低,算法会变得越来越“保守”,即更多地倾向于接受较好的解,从而逐渐逼近全局最优解。
5. 终止条件:
当温度降到一定程度(即 t <= tf )时,算法终止,输出当前最优解。
在背包问题中的应用
对于背包问题,模拟退火的应用如下:
1.解的表示:
解可以用一个二进制向量来表示,每个位置对应一个物品,值为1表示该物品被选中,值为0表示该物品没有被选中。
2.目标函数:
目标函数是背包中选中物品的总价值。问题的目标是最大化这个价值。
3.约束条件:
背包的总重量不能超过给定的最大重量。即,对于每个解(物品的选择组合),需要检查该组合的总重量是否满足限制。
4.扰动过程:
在模拟退火中,通过随机翻转物品选择的状态(从选中变为不选中,或反之)来生成新的解。每次翻转会改变物品的总价值和总重量。
5.接受准则:
(1)如果新的解比当前解更好(即价值更大且重量满足约束),则接受新解。
(2)如果新的解比当前解更差,则根据某个概率接受新解,这样做可以避免陷入局部最优解。
6.温度的作用:
初期温度较高时,算法会接受更多较差的解,进行广泛的探索。随着温度的降低,算法会更加保守,只接受更好的解,从而逐步收敛到最优解。
结果
最优解:模拟退火最终会输出一组物品的选择,表示哪些物品应该放入背包以使得总价值最大,同时不超过最大重量限制。
物品总价值:最优解下物品的总价值。
物品总重量:最优解下所选物品的总重量。
通过这个过程,模拟退火算法能够在大范围的解空间中搜索,并且通过逐渐减少接受劣解的概率,帮助找到全局最优解。
clear
clc
%% 数据初始化
k = [5;10;13;4;3;11;13;10;8;16;7;4];
k = -k; % 模拟退火算法是求解最小值,故取负数
d = [2;5;18;3;2;5;10;4;11;7;14;6];
restriction = 46;
num = 12;
%% 模拟退火
% E_current是当前解对应的目标函数值(即背包中物品总价值);
% E_new是新解的目标函数值;
% E_best是最优解的
E_current = inf;E_best = inf;
sol_new = ones(1,num); % 生成初始解
sol_current = sol_new; sol_best = sol_new;
t0=97; tf=3; t=t0;a = 0.95;
p=1;
while t>=tf
for r=1:100
%产生随机扰动
tmp=ceil(rand.*num);
sol_new(1,tmp)=~sol_new(1,tmp);
%检查是否满足约束
while 1
q=(sol_new*d <= restriction);
if ~q
p=~p; %实现交错着逆转头尾的第一个1
tmp=find(sol_new==1);
if p
sol_new(1,tmp(1))=0; % 变成0还是1视情况而定
else
sol_new(1,tmp(end))=0;
end
else
break
end
end
% 计算背包中的物品价值
E_new=sol_new*k;
if E_new<E_current
E_current=E_new;
sol_current=sol_new;
if E_new<E_best
% 把冷却过程中最好的解保存下来
E_best=E_new;
sol_best=sol_new;
end
else
if rand<exp(-(E_new-E_current)./t)
E_current=E_new;
sol_current=sol_new;
else
sol_new=sol_current;
end
end
end
t=t.*a;
end
disp('最优解为:')
disp(sol_best)
disp('物品总价值等于:')
val=-E_best;
disp(val)
disp('背包中物品重量是:')
disp(sol_best * d)


本文转载自微信公众号:数学建模CUMCM |