智能控制作业遗传算法求解背包问题Word文档格式.docx
《智能控制作业遗传算法求解背包问题Word文档格式.docx》由会员分享,可在线阅读,更多相关《智能控制作业遗传算法求解背包问题Word文档格式.docx(17页珍藏版)》请在冰豆网上搜索。
proceduresearch(k,v:
integer);
{搜索第k个物品,剩余空间为v}
vari,j:
integer;
begin
ifv<
bestthenbest:
=v;
ifv-(s[n]-s[k-1])>
=bestthenexit;
{s[n]为前n个物品的重量和}
ifk<
=nthenbegin
ifv>
w[k]thensearch(k+1,v-w[k]);
search(k+1,v);
end;
2.DP:
F[I,j]为前i个物品中选择若干个放入使其体积正好为j的标志,为布尔型。
实现:
将最优化问题转化为判定性问题
f[I,j]=f[i-1,j-w[i]](w[I]<
=j<
=v)边界:
f[0,0]:
=true.
ForI:
=1tondo
Forj:
=w[I]tovdoF[I,j]:
=f[I-1,j-w[I]];
优化:
当前状态只与前一阶段状态有关,可降至一维。
F[0]:
=true;
=1tondobegin
F1:
=f;
=w[I]tovdo
Iff[j-w[I]]thenf1[j]:
F:
=f1;
End;
B.求可以放入的最大价值。
F[I,j]为容量为I时取前j个背包所能获得的最大价值。
F[i,j]=max{f[i–w[j],j-1]+p[j],f[i,j-1]}
C.求恰好装满的情况数。
DP:
Procedureupdate;
varj,k:
c:
=a;
forj:
=0tondo
ifa[j]>
0then
ifj+now<
=ntheninc(c[j+now],a[j]);
a:
=c;
方法2:
可重复背包
A求最多可放入的重量。
状态转移方程为
f[I,j]=f[I-1,j–w[I]*k](k=1..jdivw[I])
进行一次竞赛,总时间T固定,有若干种可选择的题目,每种题目可选入的数量不限,每种题目有一个ti(解答此题所需的时间)和一个si(解答此题所得的分数),现要选择若干题目,使解这些题的总时间在T以内的前提下,所得的总分最大,求最大的得分。
*易想到:
f[i,j]=max{f[i-k*w[j],j-1]+k*p[j]}(0<
=k<
=idivw[j])
其中f[i,j]表示容量为i时取前j种背包所能达到的最大值。
*实现:
Begin
FillChar(f,SizeOf(f),0);
Fori:
=1ToMDo
=1ToNDo
Ifi-problem[j].time>
=0Then
t:
=problem[j].point+f[i-problem[j].time];
Ift>
f[i]Thenf[i]:
=t;
Writeln(f[M]);
End.
求自然数n本质不同的质数和的表达式的数目。
思路一:
生成每个质数的系数的排列,在一一测试,这是通法。
proceduretry(dep:
cal;
{此过程计算当前系数的计算结果,now为结果}
ifnow>
nthenexit;
{剪枝}
ifdep=l+1thenbegin{生成所有系数}
ifnow=ntheninc(tot);
exit;
fori:
=0tondivpr[dep]dobegin
xs[dep]:
=i;
try(dep+1);
=0;
思路二:
递归搜索效率较高
proceduretry(dep,rest:
vari,j,x:
if(rest<
=0)or(dep=l+1)thenbegin
ifrest=0theninc(tot);
=0torestdivpr[dep]do
try(dep+1,rest-pr[dep]*i);
{main:
try(1,n);
}
思路三:
可使用动态规划求解
设V个物品,背包容量为n,求放法总数。
转移方程:
fork:
=1tondivnowdo
ifj+now*k<
=ntheninc(c[j+now*k],a[j]);
{main}
read(now);
{读入第一个物品的重量}
i:
{a[i]为背包容量为i时的放法总数}
whilei<
=ndobegin
a[i]:
=1;
inc(i,now);
end;
{定义第一个物品重的整数倍的重量a值为1,作为初值}
=2tovdo
update;
{动态更新}
writeln(a[n]);
三.算法综述
遗传算法是从代表问题可能潜在的解集的一个种群开始的,而一个种群则由经过基因编码的一定数目的个体组成。
每个个体实际上是染色体带有特征的实体。
染色体作为遗传物质的主要载体,即多个基因的集合,其内部表现(即基因型)是某种基因组合,它决定了个体的形状的外部表现,如黑头发的特征是由染色体中控制这一特征的某种基因组合决定的。
因此,在一开始需要实现从表现型到基因型的映射即编码工作。
由于仿照基因编码的工作很复杂,我们往往进行简化,如二进制编码,初代种群产生之后,按照适者生存和优胜劣汰的原理,逐代演化产生出越来越好的近似解,在每一代,根据问题域中个体的适应度大小选择个体,并借助于自然遗传学的遗传算子进行组合交叉和变异,产生出代表新的解集的种群。
这个过程将导致种群像自然进化一样的后生代种群比前代更加适应于环境,末代种群中的最优个体经过解码,可以作为问题近似最优解。
贪婪算法是从眼前最大的利益出发,寻找最优解的方法,虽然很多情况下不能找到最优解,但是找到较好的解的可能性还是比较大的。
这似乎一种符合人的直觉的算法,时间复杂度比较低。
四.遗传算法求解背包问题
1.贪婪算法求解背包问题
贪婪算法属于一步式启发算法,即每采用一个贪婪准则便做出一个不可撤回的决策。
用贪婪算法求解背包问题的特点是每一步迭代选一物品入包,直到无法再装。
该算法没有在两个可行解之间比较选择,算法结束时得到一个可行解。
常用的贪婪准则是价值密度(价值重量比C/W)贪婪算法,这种选择准则为:
从剩余物品中选择可装入包的C/W值最大的物品,这也是通常所使用的贪婪策略,因为它是一个直觉上的近似的解。
2.基于贪婪算法的混合遗传算法求解背包问题
将贪婪算法与遗传算法相结合构成的混合遗传算法,通过遗传算法的择优,不断重复执行选择、杂交和变异以及贪婪算法的修正这样一个过程,所求解将不断进化越来越接近最优解。
(1)基因编码
基因编码将n个Xi的值顺序排列,就可构成背包问题的遗传编码。
即我们使用的是等长度的二进制编码方法,编码串中1表示将对应的物品放入背包中,0表示不将其放入。
例如“11100111000000000000……00000011”就代表一个解,它表示将第1,2,3,6,7,8,…n-1,n号物品放入背包中,其他的物品则不放入。
(2)编码修复
上述基因编码的方案虽然比较直观,但对于任意一个编码串,或者由交叉,变异所产生的任意一个个体,由于它们不一定满足约束条件,就不一定表示可行解,也就是说这种编码方案会产生很多无效染色体。
对于这些不满足约束条件的基因编码串,我们可以利用贪婪算法的思想进行修复。
修复的基本思想为:
在Xj=1的所有物品中,将价值重量比(C/W)最小的物品取出,直到满足背包的容量约束为止。
由此可产生一些新的基因编码串,并且这些新编码串总是相对来说质量比较好的,特别是它们肯定满足问题的约束条件。
(3)适应度函数
由于对每个个体使用贪婪算法修正已保证了不会产生无效染色体,所以在进行个体适应度评价时无须引入罚函数项,而是直接用目标函数值作为适应度函数
值,即:
(4)选择:
采用轮盘赌的方式进行选择。
在本算法中,将各基因的适应值事先作处理:
fi(i)=fit(i)-min(fit)+1;
以防止适廊度函数值出现小于零的情况,并且可以在一定程度上防止适应值差别过大时丢失低适应值基因的有用信息。
(5)交叉:
采用单点交叉方式,随机选取一点作为基因的交叉点,交叉概率pc=0.5。
(6)变异:
采用一个较小的值如pm=0.01。
算法步骤:
3.不使用贪婪算法的遗传算法求解背包问题。
为了通过对比显示出使用贪婪算法的遗传算法的优势,使用纯粹的遗传算法解决背包问题。
适应度函数与使用贪婪算法不同,需要加入惩罚项。
fit=v*value'
-cf*v*value'
./(v*c'
).*((v*c'
-m1)>
0).*(v*c'
-m1);
cf表示惩罚力度
其他过程与加入贪婪算法的基本一致。
五.背包问题的遗传算法应用程序(matlab)
1.将贪婪算法、遗传算法结合解决背包问题:
源代码:
%遗传算法解决背包问题GA.m
clc;
clear;
closeall;
%初始化物品价值value和质量c
c=[989295707270838065255055404850322260303240383532252830225030453060502065202530105650302015108531];
value=[3003182981921801802652421601381551301251221201181151101051011001009896959088828077757372706966656360582025151020107522];
g=value./c;
%价值重量比,用于贪婪算法
m1=1000;
%总重量约束值
v=2*rand(50,50)-1;
v=hardlim(v);
%v为50*50随机产生的矩阵值为0或1
%贪婪算法修复解
%v=greedy(v,c,g,m1);
[N,L]=size(v);
ger=500;
pc=0.5;
pm=0.01;
disp(sprintf('
代数:
%d'
ger));
种群大小:
N));
交叉概率:
%.3f'
pc));
变异概率:
pm));
%初始化与参数设定
sol1=1;
it=1;
updatef=-10;
%soll为当前算出的总价值,it为代数
;
t0=clock;
%记录初始时间
figure
(1);
holdon;
whileit<
=ger
%选择(轮盘赌方法)
fori=1:
N
fi(i)=fit(i)-min(fit)+1;
end
sp(i)=fi(i)/sum(fi);
endfori=2:
sp(i)=sp(i-1)+sp(i);
p=rand
(1);
sindex=1;
whilep>
sp(sindex)
sindex=sindex+1;
%寻找要选择个体的位置
newv(i,:
)=v(sindex,:
);
v(i,:
)=newv(i,:
%用选择出的个体构成的种群替代旧的种群
%交叉
cindex(i)=i;
N%产生要配对的父代的序号;
经过N次顺序调换,将原有顺序打乱,使相邻两个个体作为交叉的父代
point=unidrnd(N-i+1);
temp=cindex(i);
cindex(i)=cindex(i+point-1);
cindex(i+point-1)=temp;
2:
if(p<
pc)
point=unidrnd(L-1)+1;
%1<
point<
L产生交叉点
forj=point:
(L-1)%交叉
ch=v(cindex(i),j);
v(cindex(i),j)=v(cindex(i+1),j);
%cindex中相邻的两个为两个父代的序号
v(cindex(i+1),j)=ch;
%变异
M=rand(N,L)<
=pm;
%产生(N,L)维的01矩阵,为1的位置进行变异
v=v-2.*(v.*M)+M;
%计算适应度与进化
v=greedy(v,c,g,m1);
fit=v*value'
[sol1,indb1]=max(fit);
%indb1为适应度最大的染色体
ifupdatef>
=sol1
sol1=updatef;
v(indb1,:
)=updatec;
updatef=sol1;
updatec=v(indb1,:
[sol2,indb2]=min(fit);
%indb2为适应度最小的染色体
v(indb2,:
)=v(indb1,:
media=mean(fit);
it=it+1;
plot(it,sol1,'
r'
T=etime(clock,t0);
fx=sol1;
P=v;
程序运行时间%2.4f'
T));
最优解:
[%.2f]'
fx));
%******************************************
修正函数:
functionv=greedy(v,c,g,m1)
[mn]=size(v);
fori=1:
m
label=g;
label=label.*v(i,:
ifsum(v(i,:
).*c)>
m1
%修复
whilesum(v(i,:
min=10000;
forj=1:
n
iflabel(j)~=0&
&
label(j)<
min
min=label(j);
modify=j;
v(i,modify)=0;
label(modify)=0;
end
weight=v*c'
2.纯粹的遗传算法解决背包问题:
cf=2;
%惩罚系数
ger=1000;
fori=2:
sp(i)=sp(i-1)+sp(i);
p=rand
(1);
whilep>
newv(i,:
%v=greedy(v,c,g,m1);
fit=v*value'
fit2=v*value'
-v*value'
.*((v*c'
0);
[so