分佈估計算法求解0-1揹包問題一

0-1揹包問題是:有一個固定容量的揹包,和固定種類的物品,每種物品只有一件。每件物品有各自的價值和重量,求解哪些物品放入揹包可以使價值總和最大,且不超過揹包容量。

本例中用分佈估計算法求解0-1揹包問題結果如下:

可以看到,分佈估計算法可能在很靠前的迭代中就能得到很好的解,但是由於該算法不會保留上一代最優解,因此該解很可能丟失。從平均收益圖來看,種羣的整體收益平均值還是增加的。

主程序

主程序主要有以下四步:

forgen = 1:maxgen

pop = makepop(popsize,stuffsize, p); % 製作種羣

pop = capacitylimit(pop,capacity, weights, p); % 限制重量

spop = selection(pop, sn,profits); % 選擇優勢個體

p = makep(spop, p,alpha); % 更新概率向量

end

根據概率向量隨機採樣得到種羣,並限制種羣中個體的重量(不能超過揹包容量),之後選擇優勢個體,並根據優勢個體更新概率向量。進行下次迭代。

主程序如下:

functionmain()

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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章