0-1背包问题及其可视化

该博客介绍了一种使用遗传算法求解0-1背包问题的方法。通过MATLAB实现,展示了代码细节,包括物品价值、体积、背包容量等参数设定,以及遗传算法的初始化、交叉、变异等操作。最终,博主给出了多次迭代的最佳解和结果对比,并绘制了性能曲线。
摘要由CSDN通过智能技术生成

经过长时间的查找,终于找到能把论文下载下来的软件了。昨天发的图片是算例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 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值