分布估计算法求解0-1背包问题一

0-1背包问题是:有一个固定容量的背包,和固定种类的物品,每种物品只有一件。每件物品有各自的价值和重量,求解哪些物品放入背包可以使价值总和最大,且不超过背包容量。

本例中用分布估计算法求解0-1背包问题结果如下:

每代最优选择收益图
每代平均收益图

本例中的算例在下面下载:

0-1背包问题算例下载 people.sc.fsu.edu

0-1背包问题算例下载 本站

可以看到,分布估计算法可能在很靠前的迭代中就能得到很好的解,但是由于该算法不会保留上一代最优解,因此该解很可能丢失。从平均收益图来看,种群的整体收益平均值还是增加的。

主程序

主程序主要有以下四步:

for gen = 1:maxgen
    pop = makepop(popsize, stuffsize, p);               % 制作种群
    pop = capacitylimit(pop, capacity, weights, p);     % 限制重量
    spop = selection(pop, sn, profits);     % 选择优势个体
    p = makep(spop, p, alpha);              % 更新概率向量
end

根据概率向量随机采样得到种群,并限制种群中个体的重量(不能超过背包容量),之后选择优势个体,并根据优势个体更新概率向量。进行下次迭代。

主程序如下:

function main()
capacity = load("bag\P08\p08_c.txt");       % 背包容量
bks = load("bag\P08\p08_s.txt");            % 最优解
bks = bks';
weights = load("bag\P08\p08_w.txt");        % 重量
weights = weights';
profits = load("bag\P08\p08_p.txt");        % 收益
profits = profits';

popsize = 100;                  % 群体规模
maxgen = 50;                    % 迭代次数
stuffsize = length(weights);    % 物品数量
p = ones(1, stuffsize) .* 0.5;  % 概率向量
alpha = 1;                      % 学习速率
sn = 0.7;                       % 优势个体数量
sn = ceil(popsize * sn);

bestselection = zeros(maxgen, stuffsize);   % 记录每代最优选择
avgweights = zeros(1, maxgen);              % 记录每代平均收益

for gen = 1:maxgen
    pop = makepop(popsize, stuffsize, p);               % 制作种群
    pop = capacitylimit(pop, capacity, weights, p);     % 限制重量
    
    wgtsum = weightsum(pop, weights);
    [~, index] = max(wgtsum);
    bestselection(gen, :) = pop(index, :);
    avgweights(1, gen) = sum(wgtsum) / popsize;
    
    spop = selection(pop, sn, profits);     % 选择优势个体
    p = makep(spop, p, alpha);              % 更新概率向量
end
wgtsum = weightsum(bestselection, weights);
[~, index] = max(wgtsum);
figure(1);
plot(1:1:maxgen, wgtsum');
title("每代最优选择收益图");
figure(2);
plot(1:1:maxgen, avgweights);
title("每代平均收益图");
end

制作种群函数

制作种群函数根据概率向量p进行随机采样,直至达到种群规模。概率向量p中的一项代表在该位置上取1的概率:

function pop = makepop(popsize, stuffsize, p)
% 初始化种群,但没有限制重量
% popsize       input  种群规模
% stuffsize     input  物品数目
% p             input  概率向量
% pop           output 构造的种群
pop = zeros(popsize, stuffsize);
for i =1:popsize
    pop(i, :) = makepopv(stuffsize, p);
end
end

function pop = makepopv(stuffsize, p)
% 初始化个体,没有限制重量
% stuffsize     input  物品数目
% p             input  概率向量
% pop           output 构造的个体
tpop = rand(1, stuffsize);
pop = zeros(1, stuffsize);
for j = 1:stuffsize
    if tpop(1, j) <= p(1, j)
        pop(1, j) = 1;
    end
end
end

限制重量函数

如果种群中某一个个体重量超过背包容量,则重新生成该个体:

function npop = capacitylimit(pop, capacity, weights, p)
% 限制重量
% pop           input  种群
% capacity      input  背包容量
% weights       input  重量
% p             input  概率向量
% npop          output 新种群
npop = pop;
[popsize, stuffsize] = size(pop);
for i = 1:popsize
    wgtsum = weightsumv(npop(i, :), weights);
    while wgtsum > capacity
        npop(i, :) = makepopv(stuffsize, p);
        wgtsum = weightsumv(npop(i, :), weights);
    end
end
end

选择优势个体函数

从种群中选择指定数量的优势个体:

function spop = selection(pop, sn, profits)
% 选择
% pop           input  种群
% sn            input  选择数量
% profits       input  收益向量
% spop          output 选择的种群
pftsum = profitssum(pop, profits);
pftsum = pftsum';
[~, index] = sort(pftsum, 'descend');
index = index(1: sn);
spop = pop(index, :);
end

更新概率向量函数

该函数更新概率向量:

function np = makep(pop, p, alpha)
% 更新概率向量
% pop           input  种群
% p             input  概率向量
% alpha         input  学习速率
% np            output 更新后的概率向量
popsize = size(pop, 1);
np = (1 - alpha) .* p + alpha .* sum(pop) ./ popsize;
end
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 157,298评论 4 360
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 66,701评论 1 290
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 107,078评论 0 237
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,687评论 0 202
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,018评论 3 286
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,410评论 1 211
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,729评论 2 310
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,412评论 0 194
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,124评论 1 239
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,379评论 2 242
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,903评论 1 257
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,268评论 2 251
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,894评论 3 233
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,014评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,770评论 0 192
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,435评论 2 269
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,312评论 2 260

推荐阅读更多精彩内容