遗传算法的01背包问题c语言Word文件下载.docx
- 文档编号:21944710
- 上传时间:2023-02-01
- 格式:DOCX
- 页数:35
- 大小:229.11KB
遗传算法的01背包问题c语言Word文件下载.docx
《遗传算法的01背包问题c语言Word文件下载.docx》由会员分享,可在线阅读,更多相关《遗传算法的01背包问题c语言Word文件下载.docx(35页珍藏版)》请在冰豆网上搜索。
经过近30年的研究、应用,遗传算法已被广泛地应用于函数优化、机器人系统、神经网络学习过程、模式识别、图象处理、工业优化控制等领域。
遗传算法是将问题的每一个可能性解看作是群体中的一个个体(染色体),并将每一个染色体编码成串的形式,再根据预定的目标函数对每个个体进行评价,给出一个适应值。
算法将根据适应度值进行它的寻优过程,遗传算法的寻优过程是通过选择、杂交和变异三个遗传算子来具体实现的。
它的搜索能力由选择算子和杂交算子决定,变异算子则保证了算法能够搜索到问题空间的尽可能多的点,从而使其具有搜索全局最优的能力。
遗传算法的高效性和强壮性可由Holland提出的模式定理(SchemaTherem)和隐式并行性得以解释。
在遗传算法中,定义长度较短、低阶且适应值超过平均适应值的模式在群体中数目的期望值按指数递增,这个结论称为遗传算法的基本定理。
遗传算法是通过定义长度短、确定位数少、适应度值高的模式的反复抽样、组合来寻找最佳点,称这些使遗传算法有效工作的模式为积木块,是遗传算法构造答案的基本材料。
但归根到底,要使遗传算法有效工作必须按照遗传算法的模式定理(或积木块假设)根据具体问题设计合理的编码方案。
在运行遗传算法程序时,需要对一些参数作事先选择,它们包括种群的大小、染色体长、交叉率、变异率、最大进化代数等,这些参数对GA的性能都有很重要的影响。
在试验中参数一般选取如下:
种群大小N=20~100,交叉概率
=0.4~0.9,变异概率
=0.001~0.1,最大进化代数maxgen=100~500。
遗传算法是具有“生成+检测”的迭代过程的搜索算法。
它的基本处理流程如图1所示。
初始化种群
评估种群中个体适应度
选择
编码
交叉
变异
演化
图1、遗传算法的基本流程
遗传算法的基本流程描述如下:
(1)编码:
将解空间的解数据进行二进制编码,表达为遗传空间的基因型串(即染色体)结构数据,如将数据9编码为“1001”;
(2)初始化种群:
定义整数pop_size作为染色体的个数,并且随机产生pop_size个染色体作为初始种群;
(3)评估种群中个体适应度:
评价函数对种群中的每个染色体(chromosome)求得其个体适应度
;
(4)选择:
选择把当前群体中适应度较高的个体按某种规则或者模型遗传到下一代种群中,这里所用的规则是:
染色体在种群中被选择的可能性与其个体的适应度的大小成正比;
(5)交叉:
定义参数
作为交叉操作的概率,由(4)选择得到的两个个体以概率
交换各自的部分染色体,得到新的两个个体;
(6)变异:
作为变异操作的概率,由(5)得到每个个体中的每个基因值都以概率
进行变异;
(7)演化:
经过选择、交叉和变异操作,得到一个新的种群,对上述步骤经过给定的循环次数(maxgen)的种群演化,遗传算法终止。
五、背包问题的遗传算法求解描述
基于背包问题的模型(*),我们设计了针对于背包问题的染色体编码方法:
将待求解的各量
表示成长为
的二进制字符串
,j=1,2,…,n。
表示物体j不放入背包,
表示物体j放入背包。
例如:
111001100…000111代表一个解,它表示将第1、2、3、6、7…n-2,n-1,n号物体放入背包中,其它的物体则不放入。
根据遗传算法的基本流程,我们确定了求解背包问题的遗传算法:
步骤1、初始化过程
1.1确定种群规模popsize、杂交概率
、变异概率
、染色体长度lchrom及最大进化代数maxgen;
1.2读入背包问题的相关信息,如每个物体的重量weight[j]、每个物体的收益profit[j]和背包的容量contain,其中
1.3取
,其中
表示0-1整数的均匀分布函数,即随机地生成数0或1,生成的
串即可看为一个染色体个体。
若不满足模型(*)的约束条件,则拒绝接受,由1.2重新生成一个新的染色体个体chrom;
如果产生的染色体可行,则接受它作为种群的一名成员,经过有限次的1.2抽样后,得到popsize个可行的染色体chrom,形成新的种群。
1.4置种群的代数gen=0;
步骤2、计算种群中个体适应度以及统计种群适应度情况
2.1按照下列公式计算种群中个体适应度:
公式
(2)的下半部分即为适应度的惩罚函数,其中参数
。
2.2按公式(3)计算种群的总体适应度,
并且按照排序的方法统计出种群中的最大、最小适应度的染色体个体,分别标记为maxpop、minpop;
步骤3、选择操作
3.1生成一个随机数rand_Number,要求
3.2按照赌轮法选择个体,赌轮法的算法描述如下:
intselection()
{
i=0;
//个体的编号
sum=0;
//部分个体适应度的累加和
//根据随机数和群体的总适应度确定赌轮的位置
wheel-pos=rand_Number*sufitness;
whilesum<
wheel-pos&
&
i<
=popsize
{i=i+1;
sum=sum+fitness[i];
//fitness为第i个个体的适应度
}
returni-1;
//选择了个体i-1
3.3重复两次操作3.1、3.2,生成两个个体作为交叉操作的父代;
步骤四、交叉操作
4.1根据事先定义好的交叉概率
,为了确定是否进行交叉操作,则生成[0,1]的随机数pp,若
,则进行4.2交叉操作,否则将两个父代保留为下一代的两个个体;
4.2随机生成
的整数作为交叉点,对两个父代个体交叉生成新的两个个体;
4.3重复pop_size/2次4.1、4.2便可生成pop_size个个体组成新的种群;
步骤五、变异操作
5.1根据事先定义好的变异概率
,为了确定新种群上的每个个体上的每个基因是否进行变异操作,则生成[0,1]的随机数pp,若
,则进行5.2变异操作,否则基因不变异;
5.2基因变异操作为原基因若为1,则新基因则变异为0,若原基因为0,则新基因变异为0;
步骤6、演化
6.1按步骤2的方法计算新种群的个体适应度和总体适应度情况,尤其是找出新种群中最大适应度的个体和最小适应度的个体;
6.2若旧种群的最大个体适应度〉新种群的最大个体适应度,把旧种群的最大适应度的个体代替新种群中的最小适应度的个体,否则进行6.3;
6.3种群的代数gen=genm+1,若gen〉Maxgen,则结束种群的演化,否则转到步骤2。
六、遗传算法求解的实现
1、遗传算法的主要参数
#definepopsize80//种群的规模
#definepc0.7//杂交概率
#definepm0.1//变异概率
#definelchrom50//染色体长度
#definemaxgen5000//最大进化代数
doublealpha;
//计算适应度时使用的惩罚函数系数
2、数据结构
(1)背包信息:
//背包问题中物体重量、收益、背包容量
intweight[lchrom],profit[lchrom],contain;
(2)种群个体结构体
structpopulation
unsignedintchrom[lchrom];
//染色体
doublefitness;
//适应度
unsignedintparent1,parent2,cross;
//双亲、交叉点
};
(3)父代种群和新生代种群
//父代种群、新生代种群
structpopulationoldpop[popsize],newpop[popsize];
//pop_size为种群大小
(4)适应度信息
//种群的总适应度、最小、最大适应度
doublesumfitness,minfitness,maxfitness;
//一个种群中最大和最小适应度的个体编号
intminpop,maxpop;
3、主要函数说明
(1)、intread_infor()
功能:
从文件knapsack.txt中读出背包信息(物体重量、收益、背包容量);
参数:
无;
返回值:
返回读取文件信息是否正确;
流程图:
见图2。
图2、read_infor()流程图
(2)doublecal_fit(unsignedint*chr)
种群中个体适应度计算;
unsignedint*chr是染色体个体的指针,根据指针所指向的染色体计算个体的适应度;
染色体个体适应度的大小;
见图3。
图3、函数cal_fit的流程图
(3)、voidstatistics(structpopulation*pop)
群体适应度的最大最小值以及其他信息;
structpopulation*pop是种群指针,根据指针所指向的种群信息统计群体适应度的信息;
见图4。
(4)、voidreport(structpopulation*pop,intgen)
报告种群的适应度信息,尤其是最大个体适应度、最大适应度个体的染色体信息;
structpopulation*pop是种群指针,根据指针所指向的种群报告群体适应度的信息,gen是表示此种群所在的演化代数
见图5。
图4、函数statistics的流程图
图5、函数report的流程图
(5)、voidinitpop()
生成初始种群;
见图6。
图6、函数initpop流程图
(6)、intexecise(doubleprobability)
概率选择试验,以概率probability做随机试验,判断是否进行交叉或变异操作;
doubleprobability为交叉概率或变异概率
试验是否成功,0代表不试验成功,将不做交叉或者变异操作,1代表试验成功,即进行交叉或者变异操作;
见图7。
图7、函数execise的流程图
(7)、intselection(intpop)
在父代种群中选择个体,规则为适应度越大的个体被选择的概率越大;
intpop为父代种群;
父体中被选择的个体i;
见图8。
图8、函数selection的流程图
(8)、intcrossover(unsignedint*parent1,unsignedint*parent2,inti)
两个父代个体在染色体的第i个位置进行交叉,生成两个新个体;
unsignedint*parent1,unsignedint*parent2分别为两个父代染色体指针,指针指向父代个体的染色体,i为新种群的个体编号;
交叉是否成功;
见图9。
图9、函数crossover的流程图
(9)、intmutation(unsignedintalleles)
根据变异概率进行变异操作;
unsignedintalleles是染色体上的基因型,在这里就是0或1的取值;
变异后的基因型;
见图10。
否
是
进行变异
返回变异或者原值
概率选择试验成功
图10、函数mutation的流程图
(10)、voidgeneration()
综合选择、交叉、变异等操作,生成新的种群;
见图11。
置个体编号i=0
i<
pop_size?
调用selection生成两个父体
调用crossover,交叉生成两个新个体
对每个个体的基因调用mutation进行变异
置个体编号i=i+2
生成新的种群完毕
图11、函数generation的流程图
(11)、voidmain()
遗传算法的主函数;
图12、主函数main的流程图
七、成果说明
1、程序开发环境
开发环境:
VisualC++6.0(把Fortran程序改为VC)
操作系统:
Windows2003Professional
2、程序性能对比
运行时间与加速比(如表1所示)
进程数p(个)
1
2
4
运行时间t(秒)
129s
78s
38s
加速比s
1.65
3.38
表1、运行时间与加速比
3、程序运行结果:
实例数据:
假设物体的重量Weight、物体的收益Profit和背包的容量Contain分别为:
Weight={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}
Profit={220,208,198,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}
Contain=1000,
如何选择哪些物品装入该背包可使得在背包的容量约束限制之所装物品的总价值最大?
传统的算法(动态规划、递归回溯法和贪心算法所得结果:
总价值为3077,总重量为999。
2001年铃,钹教授在计算机学报上发表的《佳点集遗传算法》所得结果
总价值为3103,总重量为1000。
我们算法所得结果:
总价值为3103,总重量为1000。
我们所求得最优解的个体分配情况为:
110101011110110110110111111101000010100110000
01000
算法
最大迭代次数
总价值为
总重量为
传统的算法
400
3077
999
佳点集算法
70
3103
1000
遗传算法
75
八、收获、体会和课题展望
在本课题中,我们研究了如何用遗传算法求解组合优化问题中的背包问题。
我们可以看出在求解背包问题上显示了超出想象、良好的搜索能力,它具有收敛快、搜索速度快的特点,在试验中取得了比动态规划、递归回溯法和贪心法等更好的求解效果。
然而在一般情况下,使用基本遗传算法解决背包问题时,得到问题的近似解也不能满足逼近最优解的要求。
如何改进基本遗传算法使它所求得的解逼近最优解,成为我们当前亟待解决的问题,也是我们将来的课题中所要研究的重要问题。
//knapsack.cpp:
Definestheentrypointfortheconsoleapplication.
//
#include"
stdafx.h"
#include<
AfxWin.h>
stdlib.h>
math.h>
time.h>
conio.h>
stdio.h>
//重要常量参数
#definepopsize200//种群的规模
#definepc0.618//杂交概率
#definepm0.03//变异概率
#definemaxgen1000//最大进化代数
structpopulation
doubleweight;
//背包重量
//新生代种群、父代种群
//背包问题中物体重量、收益、背包容量
//种群的总适应度、最小、最大、平均适应度
doublesumfitness,minfitness,maxfitness,avgfitness;
//计算适应度时使用的惩罚函数系数
//一个种群中最大和最小适应度的个体
/*读入背包信息,并且计算惩罚函数系数*/
voidread_infor()
FILE*fp;
intj;
//获取背包问题信息文件
if((fp=fopen("
knapsack.txt"
"
r"
))==NULL)
{
//读取文件失败
AfxMessageBox("
Thefileisnotfound"
MB_OK,NULL);
return;
//读入物体收益信息
for(j=0;
j<
lchrom;
j++)
{
fscanf(fp,"
%d"
&
profit[j]);
//读入物体重量信息
weight[j]);
}
//读入背包容量
fscanf(fp,"
contain);
fclose(fp);
}
//根据计算的个体重量,判断此个体是否该留在群体中
doublecal_weight(unsignedint*chr)
doublepop_weight;
//背包重量
pop_weight=0;
pop_weight=pop_weight+(*chr)*weight[j];
chr++;
returnpop_weight;
/*种群中个体适应度计算*/
doublecal_fit(unsignedint*chr)
doublepop_profit;
//适应度
pop_profit=0;
//pop_weight=0;
pop_profit=pop_profit+(*chr)*profit[j];
//pop_weight=pop_weight+(*chr)*weight[j];
returnpop_profit;
/*群体适应度的最大最小值以及其他信息*/
voidstatistics(structpopulation*pop)
inti;
doubletmp_fit;
sumfitness=pop[0].fitness;
minfitness=pop[0].fitness;
minpop=0;
maxfitness=pop[0].fitness;
maxpop=0;
for(i=1;
popsize;
i++)
//计算种群的总适应度
sumfitness=sumfitness+pop[i].fitness;
tmp_fit=pop[i].fitness;
//选择种群中最大适应度的个体
if((tmp_fit>
maxfitness)&
((int)(tmp_fit*10)%10==0))
{
maxfitness=pop[i].fitness;
maxpop=i;
}
//选择种群中最小适应度的个体
if(tmp_fit<
minfitness)
minfitness=pop[i].fitness;
minpop=i;
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 遗传 算法 01 背包 问题 语言