经过长时间的查找,终于找到能把论文下载下来的软件了。昨天发的图片是算例2,今天是算例1的问题及源码。求解结果有图片,我把未经过FB处理和经过FB处理的图片做过比较,前面三张是未经过FB处理。变化最大的是“20次循环结果”,未处理是看不见他的三个点在哪的。
本例的特点是已知物品价值及其重量,背包的容量也是已知的。所以此代码可适应已知所有条件的0-1背包问题。
clc
clear
close all
LoopNumber=1;
traceAll=cell(LoopNumber);
for ii=1:LoopNumber
%% 基于遗传算法的0-1背包算法
% 物品价值
val =[220 208 18 192 180 180 165 162 160 158 155 130 125 122 120 ...
118 115 110 105 101 100 100 98 96 95 90 88 82 80 77 75....
73 72 70 69 66 65 63 60 58 56 50 30 20 15 10 8 ...
5 3 1];
% 物品体积
vol =[80 82 85 70 72 70 66 50 55 25 50 55 40 48 50 32 22 60 30 32 ...
40 38 35 32 25 28 30 22 50 30 45 30 60 50 20 65 20 25 30 10 20 ...
25 15 10 10 10 4 4 2 1];
% 背包的最大容量
MAX_CAP = 1000;
% 参数
LEN=size(val, 2); %样本长度
POP_NUM=50; %群体数
P_CROSS=0.8; %交叉概率
P_MUTA=0.07; %变异概率
% 最大迭代代数
MAX_GEN = 500;
% 初始化样本
samp_arr= 2*rand(POP_NUM, LEN) - 1;
samp_arr=hardlim(samp_arr);
% 记录参数
max_samp=samp_arr(1,:);
max_val_old=-9999999;
max_index_old=0;
max_val_new=0;
max_index_new=0;
min_val=0;
min_index=0;
% 记录参数
% 存放优胜劣汰得到的样本的索引
winner_index =ones(1, POP_NUM);
% 轮盘
rtable=ones(1, POP_NUM);
% 最大适应度值记录
fit_best=zeros(1, MAX_GEN);
fit_worst=zeros(1,MAX_GEN);
fit_mean=zeros(1,MAX_GEN);
% 适应度
fit_arr=zeros(1, POP_NUM);
% 初始化随机种子
rand('state',sum(100*clock));
% 迭代计数器
count=0;
while 1
count=count + 1;
P_MUTA=0.05+count*0.0001;
% 计算适应度值
temp_sum=vol*samp_arr'; %利用矩阵相乘的方便性来计算每个个体的总体积注意第二个矩阵必须取其转置
rate=val./vol; %计算每个物体单位体积的价值量即价值密度
for i=1:POP_NUM
j = 0;
if temp_sum(i) > MAX_CAP
[temp, index]=sort(rate, 'ascend');
while temp_sum(i) > MAX_CAP
j=j+1;
if samp_arr(i,index(j) )==1
samp_arr(i,index(j)) = 0;
temp_sum(i)=temp_sum(i)-vol(index(j));
end
end
end
end
% 更新最优值
fit_arr = val*samp_arr'; %同上方法一样采用计算每个个体的总价值
[max_val_new, max_index_new]= max(fit_arr);
fit_worst(count)=min(fit_arr);
fit_mean(count)=mean(fit_arr);
%如果比上一次的小用上一次的替换
if max_val_new < max_val_old
max_val_new = max_val_old;
samp_arr(max_index_new, :)= max_samp;
fit_arr(max_index_new)= max_val_old;
end
%保存这一次的结果
max_val_old=max_val_new;
max_index_old=max_index_new;
max_samp=samp_arr(max_index_new, :);
%找到适应度最小的个体淘汰之用适应度最大的个体替换
[min_val, min_index]=min(fit_arr);%找到适应度最小个体的编号
samp_arr(min_index, :)=max_samp;
fit_arr(min_index)=max_val_new;
%将这一代得到的最大适应度值保存起来方便最后的曲线绘制
fit_best(count)=max_val_new;
%依据迭代次数的终止判断
if count >=MAX_GEN
break;
end
% 选择操作轮盘赌
fit_sum=sum(fit_arr);
rtable=fit_arr./fit_sum; %轮盘rotary table
%生成轮盘类似于概率分布
for i=2:POP_NUM
rtable(i)=rtable(i-1) + rtable(i);
end
for i=1:POP_NUM
p=rand(1);
index=1;
while p > rtable(index)
index= index + 1;
end
winner_index(i)=index;
end
% 更新样本集
samp_arr=samp_arr(winner_index, :);
% 交叉操作
cross_index=1:POP_NUM; %参与交叉的样本的索引
for i=1:POP_NUM
temp=unidrnd(POP_NUM - i + 1);%在1到POP_NUM - i + 1之间取随机数
temp_pos=i+temp - 1;
temp_val=cross_index(temp_pos);
cross_index(temp_pos)= cross_index(i);
cross_index(i)=temp_val;
end
% 交叉操作
for i = 1:2:POP_NUM %相邻两个进行交叉
%随机得到一个数小于交叉概率的话进行交叉
if rand(1) < P_CROSS
cross_pos=unidrnd(POP_NUM - 1 ); %交叉点位置,[1, POP_NUM-1]
temp_cross=samp_arr(cross_index(i), cross_pos:end);
samp_arr(cross_index(i), cross_pos:end) = ...
samp_arr(cross_index(i+1), cross_pos:end);
samp_arr(cross_index(i+1), cross_pos:end) = temp_cross;
end
end
%变异操作直接针对整个样本集操作
muta_arr=( rand(POP_NUM, LEN) < P_MUTA );
index= find(muta_arr);
samp_arr(index)=1-samp_arr(index);
end
%找到最后一代中的最佳样本
[max_val, max_index]=max(fit_arr);
temp=samp_arr(max_index, :);
index=find(temp); %index记录所取得物体编号
trace(count,:)=[max(fit_arr,[],2),min(fit_arr,[],2),mean(fit_arr)];
traceAll{ii}=trace;
tracedo(ii,:)=max(trace);
end
%绘制结果曲线
figure(1);
plot(1:MAX_GEN, fit_best, 'b-');
title('历代最优解');
grid on;
figure(3)
plot(1:LoopNumber, tracedo);
title('20次循环结果');
grid on;
disp( sprintf('求解结果如下所示 ') );
disp('==================================================================');
disp( sprintf('\n\n%-10s\t%-10s\t%-10s\n', '物品编号', '价值','容量') );
for i = 1:size(index, 2)
disp( sprintf('%-10d\t%-10d\t%-10d\n', index(i), val(i), vol(i) ));
end
disp('==================================================================');
disp( sprintf('物品总数%d\n', size(index, 2) ) );
disp( sprintf('总价值%d\n', val*temp'));
disp( sprintf('总体积%d\n', vol*temp' ));
figure
plot(fit_best)
hold on
plot(fit_mean,'r')
plot(fit_worst,'k')
legend('best','mean','worst')
grid on