用遗传算法解决0-1背包问题要点

用遗传算法解决0-1背包问题要点
用遗传算法解决0-1背包问题要点

实现遗传算法的0-1背包问题

求解及其改进

姓名:

学号:

班级:

提交日期:2012年6月27日

实现遗传算法的0-1背包问题求解

摘要:研究了遗传算法解决0-1背包问题中的几个问题:

1)对于过程中不满足重量限制条件的个体的处理,通过代换上代最优解保持种群的进化性

2)对于交换率和变异率的理解和处理方法,采用逐个体和逐位判断的处理方法

3)对于早熟性问题,引入相似度衡量值并通过重新生成个体替换最差个体方式保持种群多样性。4)一种最优解只向更好进化方法的尝试。

通过实际计算比较表明,本文改进遗传算法在背包问题求解中具有很好的收敛性、稳定性和计算效率。通过实例计算,表明本文改进遗传算法优于简单遗传算法和普通改进的遗传算法。

关键词:遗传算法;背包问题;优化

1.基本实现原理:

一、问题描述

0-1背包问题属于组合优化问题的一个例子,求解0-1背包问题的过程可以被视作在很多可行解当中求解一个最优解。01背包问题的一般描述如下:

给定n个物品和一个背包,物品i的重量为Wi,其价值为Vi,背包的容量为C。选择合适的物品装入背包,使得背包中装入的物品的总价值最大。注意的一点是,背包内的物品的重量之和不能大于背包的容量C。在选择装入背包的物品时,对每种物品i只有两种选择:装入背包或者不装入背包,即只能将物品i装入背包一次。称此类问题为0/1背包问题。

其数学模型为:

0-1背包问题传统的解决方法有动态规划法、分支界限法、回溯法等等。传统的方法不能有效地解决0-1背包问题。遗传算法(Genetic Algorithms)则是一种适合于在大量的可行解中搜索最优(或次优)解的有效算法。

二、遗传算法特点介绍:

遗传算法(Genetic Algorithm, GA)是1962年Holland教授首次提出了GA算法的思想是近年来随着信息数据量激增,发展起来的一种崭新的全局优化算法,它借用了生物遗传学的观点,通过自然选择、遗传、变异等作用机制,实现各个个体的适应性的提高。

基本遗传算法求解步骤:

Step 1 参数设置:在论域空间U上定义一个适应度函数f(x),给定种群规模N,交叉率P c 和变异率P m,代数T;

Step 2 初始种群:随机产生U中的N个染色体s1, s2, …, s N,组成初始种群S={s1, s2, …, s N},置代数计数器t=1;

Step 3计算适应度:S中每个染色体的适应度f() ;

Step 4 判断:若终止条件满足,则取S中适应度最大的染色体作为所求结果,算法结束。Step 5 选择-复制:按选择概率P(x i)所决定的选中机会,每次从S中随机选定1个染色体并将其复制,共做N次,然后将复制所得的N个染色体组成群体S1;

Step 6 交叉:按交叉率P c所决定的参加交叉的染色体数c,从S1中随机确定c个染色体,配对进行交叉操作,并用产生的新染色体代替原染色体,得群体S2;

Step 7 变异:按变异率P m所决定的变异次数m,从S2中随机确定m个染色体,分别进行变异操作,并用产生的新染色体代替原染色体,得群体S3;

Step 8 更新:将群体S3作为新一代种群,即用S3代替S,t=t+1,转步3;

遗传算法是一种仿生算法, 即模拟生命演化的算法,它从一个代表问题初始解的初始种群出发, 不断重复执行选择, 杂交和变异的过程, 使种群进化越来越接近某一目标既最优解,如果视种群为超空间的一组点, 选择、杂交和变异的过程即是在超空间中进行点集之间的某种变换, 通过信息交换使种群不断变化,遗传算法通过模拟达尔文“优胜劣汰, 适者生存”的原理激励好的结构, 同时寻找更好的结构, 作为一种随机的优化与搜索方法, 遗传算法有着其鲜明的特点。

—遗传算法一般是直接在解空间搜索, 而不像图搜索那样一般是在问题空间搜索, 最后才找到解(如果搜索成功的话)。

—遗传算法的搜索随机地始于搜索空间的一个点集, 而不像图搜索那样固定地始于搜索空间的初始节点或终止节点, 所以遗传算法是一种随机搜索算法。

—遗传算法总是在寻找优解(最优解或次优解), 而不像图搜索那样并非总是要求优解,

而一般是设法尽快找到解(当然包括优解), 所以遗传算法又是一种优化搜索算法。

—遗传算法的搜索过程是从空间的一个点集(种群)到另一个点集(种群)的搜索,而不像图搜索那样一般是从空间的一个点到另一个点地搜索。因而它实际是一种并行搜索, 适合大规模并行计算, 而且这种种群到种群的搜索有能力跳出局部最优解。

—遗传算法的适应性强, 除需知适应度函数外, 几乎不需要其他的先验知识。

—遗传算法长于全局搜索, 它不受搜索空间的限制性假设的约束,不要求连续性, 能以很大的概率从离散的、多极值的、含有噪声的高维问题中找到全局最优解。

3.程序步骤:

一、使用基本遗传算法解决0- 1背包问题:

1: 打开数据文件

2: 设置程序运行主界面

3: 调用初始化种群模块

3- 1: 按照一定的种群规模和染色体长度以基因为单位用随机产生的0- 1对个体赋值3- 2: 调用计算适应度函数

4: 以最大进化代数为循环终止条件开始进行循环

4- 1: 调用产生新一代个体的函数

4- 1- 1: 调用选择函数

4- 1- 2: 调用交叉函数

4- 1- 3: 调用变异函数

4- 1- 4: 调用计算适应度函数

5: 调用计算新一代种群统计数据函数

6: 调用输出新一代统计数据函数

7: 返回到第四步, 直至循环结束

二、基本遗传算法解决0- 1背包问题存在的不足:

1.对于过程中不满足重量限制条件的个体的处理

在用基本遗传算法解决0- 1背包问题的时候,在初始化或者交叉变异后可能会产生不满足重量约束条件的伪解,而对于这些伪解,基本遗传算法没有给出一个很好的处理方法,而只是又随机生成了一个满足约束条件的解作为新的个体从而替换掉原来的个体。根据遗传算法的根本思想“优胜劣汰,适者生存”的原则,可以将不满足条件的个体用已有的最优个体来进行替换,这样,既使得种群中所有的个体均满足重量的约束条件,又保留了较优解,符合遗传算法的思想。

具体做法为:

在程序中加入一个变量保存每代的最优解,当前代在进行选择、复制、交叉、变异后如果有不满足约束条件的个体,则在种群更新时采用这个最优值作为替代。

具体做法为:在每代遗传后通过函数FindBestandWorstIndividual()找到当前最优值并保存bestindividual中,在计算适应度函数CalculateFitnessValue()中加入:

if(w>KW) X[i]=bestindividual; //如果不是解,找最好的一个解代之

其中w为当前个体的总重量,KW为背包最大承重量,X[i]表示种群中第i个个体,bestindividual 为保存的个体最优解。

2.对于交换率和变异率的理解和处理方法

根据遗传算法的基本步骤的交叉和变异操作

Step 6 交叉:按交叉率P c所决定的参加交叉的染色体数c,从S1中随机确定c个染色体,配对进行交叉操作,并用产生的新染色体代替原染色体,得群体S2;

Step 7 变异:按变异率P m所决定的变异次数m,从S2中随机确定m个染色体,分别进行变异操作,并用产生的新染色体代替原染色体,得群体S3;

可以有两种处理方法:

其一,采用先确定数目在随机选取的方法,步骤如下:

对于交叉操作:

1,根据交叉率确定应该交叉的个体数目n

2,在种群中进行n次循环

2-1随机选中种群中的一个个体a

2-2随机选中种群中异于a的一个个

体b

2-3随机确定交叉位数

2-4进行交叉对于变异操作:

1,根据变异率确定应该变异的染色体数目n

2,在种群中进行n次循环

2-1随机选中种群中的一个个体的染

色体a

2-2随机选中染色体a 的某位基因

2-3对进行0-1互换变异

其二,采用对每个操作单元分别进行特定概率下处理的方法,步骤如下:

对于交叉操作:

1,在种群中进行S次循环,其中S代表种群中个体的数量

2,对于每一个个体X[i](X为种群数组)做如下操作

2-1生成随机数p[0,1],判断p 与的大小关系

2-2如果p说明X[i]需要交换

2-2-1 随机在种群中找到异于X[i]的另一个体进行交换

2-3如果p说明X[i]不需要交换对于变异操作:

1,在种群中进行S次循环,其中S代表种群中个体的数量

2,对每一个个体X[i]做N次循环,其中N为染色体位数

2-1对染色体的每一位

3-1生成随机数q[0,1],判断q 与

的大小关系

3-2如果q 说明需要进行0-1互换变异2-3如果q 说明不需要变

分析这两种处理方法可知:方法一没有很好地体现随机机会均等的思想,因为在步骤1中确定的需要操作的数目n后,总体上是保证了交叉或者变异的数目,但不是对于每一个个体而言的,因而会出现有的个体被选择交叉或者变异多次而有的没有机会交叉或者变异的情况,而如果采用方法二,就体现了机会的均等性,即要求对每一个单元操作目标进行概率的验证,以确定是否变异或者交叉。在程序中具体的实现方法体现在交叉和变异函数中:

void CrossoverOperator(void)//交叉操作for(i=0; i

do{p=rand()%S;//两个[0,S]的随机数q=rand()%S; }while(p==q);

int w=1+rand()%N;//[1,N]交换的位数double p=(rand()%1001)/1000.0; if(p<=Pc) for(j=0;j

void MutationOperator(void)//变异操作

for (i=0; i

for (j=0; j

q=(rand()%1001)/1000.0;//产生q[0,1] if (q

if(X[i].chromsome[j]==1)X[i].chromsome[j]=0;

else X[i].chromsome[j]=1;

2.对于算法早熟性的分析及解决方法

遗传算法中种群中的个体由初始化时的具有多样性,可能会由于在进化过程中一些超常个体限制其它个体的进化——这个个体的适应度大大优于种群内的其它值,由于适者生存原则这个个体被不断复制从而充满了整个种群,使得种群的多样应大大降低,进化停滞,从而出现算法收敛于局部最优解的现象,称为早熟现象。

早熟现象的可能解法:

1)通过提高变异率来增加种群的多样性,以期更优解的出现,这也是最简单基本遗传算法中不添加相关操作的情况下唯一的一种方法,然而这种方法有明显的弊端:在提高变异率获得多样性种群的同时,个体变异的机会增加,使得较优解发生变异,从而遗传算法丧失了其优于其它算法的优越性,所以这种方法不是很好地解决方法。

2)引入多样性衡量和处理

基本思路:在出现进化停滞现象时要引入新的个体来增强种群的多样性。

做法:1,判断是否达到早熟现象

对于种群中S个个体,判断等位基因的相等程度,即引入一个参数值same,如果same达到一定的理论值大小就可以认为达到了早熟现象。

2,早熟现象的处理,即引入新的个体。

处理过程中应该不违反适者生存的原则,所以应该保留较好的个体,所以首先选中适应度最小的个体执行删除操作,然后随机生成一个新的符合重量限制且打破早熟现象的新个体。

具体实现见函数:void checkalike(void)

//相似度校验

for( i=0;i

for(j=0;j

bool temp=X[i].chromsome[j];

for(int k=1;k

if(temp!=X[k].chromsome[j])

break;

if(j==N)same++;

if(same>N*0.5)//大于50%作为判定为早熟//确定最小

int minindex=0;

for(intn=0;n

if(X[n].fitness

for (j=0; j

bool m=(rand()%10<5)?0:1;

X[minindex].chromsome[j]=m;

X[minindex].weight+=m*weight[j];

//个体的总重量

X[minindex].fitness+=m*value[j];

//个体的总价值

3.一种最优解只向更好进化方法的尝试

基本思路为:每一组的最优解是一个独特的个体,我们求解的问题最终的最优解或者近似解都产生于这个特殊的个体,最优解只向更好进化方法中规定:每代中选出一个最优解并做好相应的记录或者标记,最优解参与交叉和变异,只是在交叉或者变异时对最优解进行前后适应度的比较,如果发现交叉或者变异后适应度大于操作前适应度,则保存操作后的结果,如果发现交叉或者变异后适应度小于操作前适应度,则禁止最优解的操作,而不禁止与最优解进行交叉的个体的变化。这样,每一代中的最优解的特性可以通过交叉传递给同代中的其它个体,而保证种群一定会向更好的方向进化。

做法在交叉后和变异后调用以下函数判断:

int comp(individual bestindividual,individual temp)//比较函数

{

int fit=0,w=0;//第一种不变:操作后不满足重量函数,第二种:操作后适应度小于操作前

for(int i=0;i

if(w>KW)return -1;

return (bestindividual.fitness>fit?-1:1);//如果小于原来值或者不满足重量函数,则返回-1

}

三、改进的遗传算法解决0- 1背包问题:

1、参数设置:

#define S 500 //种群的规模

#define Pc 0.8 //交叉概率

#define Pm 0.01 //突变概率

#define KW 878 //背包最大载重

#define N 20 //物体总数

#define T 1000 //最大换代数

2个体的表示和染色体编码

用变量i代表物件, i = 1, 2, ,n 定义变量xi,其含义为:xi= 1表示:第i个物件被选入背包, xi = 0表示第i个物件没有被选入背包。考虑n 个物件的选择与否, 就可以得到一个长度为n的0, 1序列。由此可见遗传算法应用于上述背包问题时,采用简单二进制编码较为适宜1 每一组编码即为某一个个体的基因表示, 称其为染色体, 染色体长度取决于待分配的物件的个数n.在编码形式的表示方法中,形如二进制编码10010101 表示为一个待分配的物件的个数为8(编码长度)的一个背包问题的一个解, 则该个体对应于选择了物件1, 4, 6, 8,即第1, 4, 6, 8个物品被放入了背包。用数据格式表示为:

struct individual //个体结构体

{

bool chromsome[N]; //染色体编码

double fitness; //适应度//即本问题中的个体所得价值

double weight; //总重量

};

2产生初始种群

n个待分配的物件随机产生S个长度为n的二进制串, 即种群中个体的染色体编码的每一位按等概率在0与1中选择S 指的是种群规模, 即种群中的个体数目.

void GenerateInitialPopulation(void); //初始种群

3适应度函数

背包内物件的总重量为a1x1 + a2x2 + ,anxn, 物件的总价值为c1x1 + c2x2 + , + cn xn

0-1背包问题中采用每个个体的总价值作为适应度,在满足背包容量的条件下,价值越大,适应度越高。所以适应度求解方法为:

f i = c1x1 + c2x2 + , + cnxn ( 当t a1x1 + a2x 2 + , + anxn < = c ,xj = 0, 1)

考虑到会有不不满足容量条件的个体则:

f i = 0 (当a1x1 + a2x2 + , + anxn > c,xj = 0, 1)

上述适应度函数基于一个考虑违背约束条件的惩罚处理,根据上述具体问题适应度函数值不可能为零, 所以当随机产生的某个个体违背约束条件时, 通过把其适应度函数值罚为0而达到淘汰该个体的目的。

4选择-复制操作

参照适应度函数值和约束条件用赌轮选择法进行模拟,具体为

( 1)根据适应度函数值和约束条件, 罚掉部分个体(前述不满足容量条件的个体)

(2)对于满足约束条件的个体, 根据适应度函数值计算个体被选中的概率,称为选择概率:

公式为:

P

=

p()称为染色体x i (i =1, 2, …, n )的选择概率

(3)根据轮盘赌累计公式为:

称为染色体x i (i =1, 2, …, n )的积累概率

( 4) 对已得到的累计概率作如下处理,完成选择操作: 1)在[0, 1]区间内产生一个均匀分布的伪随机数r 。 2)若r≤q1,则染色体

x1 3)若qk-1

对于每一个个体,根据交叉率P c 做如下操作: ( 1)随机产生一个交叉点的位置 ( 2)随机选取当前代中的两个个体作为父个体 ( 3)根据交叉点的位置, 做单点交叉 6变异操作: 根据变异率P m

( 1)随机产生变异点的位置 ( 2)在变异点位置作0- 1翻转 8、算法终止

程序中定义了一个最优值,stop=

一般情况下这个最优值达不到,一旦程序在执行过

程中达到此最优值,也就没有必要在执行下去,因为这必定是最好的解,所以保存最优值和最优解,结束。

如果程序的最优值达不到理想情况下的stop ,那么根据最大换代次数来结束程序,在结束后的种群中找到一个最好的解作为本问题的最优解,程序结束。

4算例(可以使用参考文献[2]中的典型算例):

1. 小规模问题的算例:

算例1-1:设定物品价值value={50,30,60,80,20}重量weight{35,40,40,20,15}背包的最大承重量为100

遗传算法中参数:群体大小S=5,交叉率Pc=0.8,变异率Pm=0.05,最大换代次数T=20, 通过多次试验比较本文改进后遗传算法和其他得到结果如下表所示:

(右图中输出第一行数为最优价值;第二行数

为重量;第三行为最优解)

∑==i

j j i x P q 1)

(

本文改进的遗传算法:

实验总次数:30

达到全局最优解次数:27

未达到全局最优解:3 效果截图

由实验结果可知在小规模算例中,本文改进的遗传算法优于前两者。

2.较大规模问题求解算例:

遗传算法中参数:

群体大小S=5,交叉率Pc=0.8,变异率Pm=0.05,最大换代次数T=800,相似度取5%

实例1:

价值value:{ 92,4,43,83,84,68,92,82,6,44,32,18,56,83,25,96,70,48,14,58}

重量weight:{ {44,46,90,72,91,40,75,35,8,54,78,40,77,15,61,17,75,29,75,63}}

背包的最大承重量:878

实例2:

价值value:

{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};

重量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,25,30,45,30,60,50 ,20,65, 20,25,30,10,20,25,15,10,10,10,4,4,2,1};

背包最大承重量:1000

实例3:

(说明:参考论文中的实例3价值数组中缺少一个值,这里以0补上,使价值和重量一一对应)

价值value:

{597,596,593,586,581,568,567,560,549,548,547,529,529,527,520,491,482,478,475,475,466,462,459,458,4 54,451,449,443,442,421,410,409,395,394,390,377,375,366,361,347,334,322,315,313,311,309,296,295,294,28 9,285,279,277,276,272,248,246,245,238,237,232,231,230,225,192,184,183,176,171,169,165,165,154,153,150, 149,147,143,140,138,134,132,127,124,123,114,111,104,89,74,63,62,58,55,48,27,22,12,6,0};

重量weight:

{54,183,106,82,30,58,71,166,117,190,90,191,205,128,110,89,63,6,140,86,30,91,156,31,70,199,142,98,17 8,16,140,31,24,197,101,73,16,73,2,159,71,102,144,151,27,131,209,164,177,177,129,146,17,53,64,146,43,170, 180,171,130,183,5,113,207,57,13,163,20,63,12,24,9,42,6,109,170,108,46,69,43,175,81,5,34,146,148,114,160,1 74,156,82,47,126,102,83,58,34,21,14};

各运行30次后比较30次中的最好值,比较结果如下本文改进的遗传算法和先前算法结果如下:

本文改进遗传算法实验结果:

实例1:(输出第一行数为最优价值;第二行数为重量;第三行为最优解)

实例2:

实例3:

根据得到最优解的情况本文改进的遗传算法所得最好值均好于先前两种算法,特别是实例3中,在缺少一个价值值补0的情况下得到的结果仍然优于前两种算法。

由此得出结论:本文改进的遗传算法优于前两种。

4.心得体会:

遗传算法是一种模拟生物进化在解中求解最优值的方法,实现起来方便,适于处理大宗数据,然而基于简单基本遗传算法在求解不同问题时应该具体问题具体分析,找的结合所解问题的优化方法,例如本文分析的遗传算法解决0-1背包问题,虽然简单基本遗传算法可以求出一个比较好的解出来,但是分析可知,结果并不令人满意,在对问题进行细致的分析、查阅相关资料和深入思考后,我提出了自己认为比较好的4点改进方法并通过实践结合具体的算例把改进后的遗传算法和与原来的简单遗传算法和参考文献中的一种改进方法进行了比较,结果显示本文改进的遗传算法无论在小规模数据处理还是较大规模数据处理方面均优于前两者,这一点很令人高兴。

另外,通过本次实践,我也深刻体会到对于算法分析和改进的重要性,往往一个算法经过认真地分析和合理的改进后会获得性能上的提高——时间复杂度或者空间复杂度的降低,

而且能够获得更好的解,本文就是一个很好的例证。

6.参考文献:

[1]M.H.Alsuwaiyel著,方世昌等译《算法设计技巧与分析》电子工业出版社,北京,2009

[2]闫丽《用基本遗传算法解决0- 1背包问题》通化师范学院学报第26卷第4期,2005,7

[3]赵新超,韩宇,艾文宝《求解背包问题的一种改进遗传算法》计算机工程与应用2011,47(24) 7. [附]实现程序:

已通过vc6.0编译后运行

#include

#include

#include

#include

/*小规模***********************************************************************

#define S 5 //种群的规模

#define N 5 //物体总数

#define Pc 0.8 //交叉概率

#define Pm 0.05 //突变概率

#define KW 100 //背包最大载重

#define T 20 //最大换代数

#define ALIKE 0.05 //判定相似度

int stop=0; //初始化函数中初始化为所有价值之和

int t=0; //目前的代数

int weight[]={35,40,40,20,15}; //物体重量

int value[]={50,30,60,80,20}; //物体价值

/*实例1***********************************************************************

#define S 5 //种群的规模

#define N 20 //物体总数

#define Pc 0.8 //交叉概率

#define Pm 0.05 //突变概率

#define KW 878 //背包最大载重

#define T 800 //最大换代数

#define ALIKE 0.05 //判定相似度

int stop=0; //初始化函数中初始化为所有价值之和

int t=0; //目前的代数

int weight[]={44,46,90,72,91,40,75,35,8,54,78,40,77,15,61,17,75,29,75,63}; //物体重量

int value[]={92,4,43,83,84,68,92,82,6,44,32,18,56,83,25,96,70,48,14,58}; //物体价值

/*实例2***********************************************************************

#define S 5 //种群的规模

#define Pc 0.8 //交叉概率

#define Pm 0.05 //突变概率

#define KW 1000 //背包最大载重1000

#define N 50 //物体总数

#define T 800 //最大换代数

#define ALIKE 0.05 //判定相似度

int stop=0; //初始化函数中初始化为所有价值之和

int t=0; //目前的代数

int vaue[]={

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};

int 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,25,30,45,30,60,50,20,65 ,20,25,30,10,20,25,15,10,10,10,4,4,2,1};

/*实例3***********************************************************************/

#define S 5 //种群的规模

#define Pc 0.8 //交叉概率

#define Pm 0.05 //突变概率

#define KW 6718 //背包最大载重1000

#define N 100 //物体总数

#define T 800 //最大换代数

#define ALIKE 0.05 //判定相似度

int stop=0; //初始化函数中初始化为所有价值之和

int t=0; //目前的代数

int vaue[]={

597,596,593,586,581,568,567,560,549,548,547,529,529,527,520,491,482,478,475,475,466,462,459,458,454,45 1,449,443,442,421,410,409,395,394,390,377,375,366,361,347,334,322,315,313,311,309,296,295,294,289,285, 279,277,276,272,248,246,245,238,237,232,231,230,225,192,184,183,176,171,169,165,165,154,153,150,149,14 7,143,140,138,134,132,127,124,123,114,111,104,89,74,63,62,58,55,48,27,22,12,6,250};

Int weight[]={

54,183,106,82,30,58,71,166,117,190,90,191,205,128,110,89,63,6,140,86,30,91,156,31,70,199,142,98,178,16,1 40,31,24,197,101,73,16,73,2,159,71,102,144,151,27,131,209,164,177,177,129,146,17,53,64,146,43,170,180,17 1,130,183,5,113,207,57,13,163,20,63,12,24,9,42,6,109,170,108,46,69,43,175,81,5,34,146,148,114,160,174,156 ,82,47,126,102,83,58,34,21,14};

/************************************************************************/

struct individual //个体结构体

{

bool chromsome[N]; //染色体编码

double fitness; //适应度//即本问题中的个体所得价值

double weight; //总重量

};

int best=0;

int same=0;

individual X[S],Y[S],bestindividual;//

/************************************************************************/

int comp(individual bestindividual,individual temp); //比较函数

void checkalike(void); //检查相似度函数

void GenerateInitialPopulation(void); //初始种群

void CalculateFitnessValue(void); //适应度

void SelectionOperator(void); //选择

void CrossoverOperator(void); //交叉

void MutationOperator(void); //变异

void FindBestandWorstIndividual(void); //寻找最优解

void srand(unsigned int seed); //随机生成

/************************************************************************/

int comp(individual bestindividual,individual temp)//比较函数

{

int fit=0,w=0;//第一种不变:操作后不满足重量函数,第二种:操作后适应度小于操作前for(int i=0;iKW)return -1;

return (bestindividual.fitness>fit?-1:1);//如果小于原来值或者不满足重量函数,则返回-1 }

/************************************************************************/

void Checkalike(void)

{

int i=0,j=0;

for( i=0;i

{

for(j=0;j

{

bool temp=X[i].chromsome[j];

for(int k=1;k

{

if(temp!=X[k].chromsome[j])

break;

}

}

if(j==N)same++;

}

if(same>N*ALIKE)//大于ALIKE作为判定为早熟

{

int minindex=0;

for(int n=0;n

if(X[n].fitness

for (j=0; j

{

bool m=(rand()%10<5)?0:1;

X[minindex].chromsome[j]=m;

X[minindex].weight+=m*weight[j];//个体的总重量

X[minindex].fitness+=m*value[j]; //个体的总价值

}

}

}

/************************************************************************/

void GenerateInitialPopulation(void)//初始种群,保证每个值都在符合条件的解

{

int i=0,j=0; bool k;

for(i=0;i

for (i=0; i

{

int w=0,v=0;

for (j=0; j

{

k=(rand()%10<5)?0:1;

X[i].chromsome[j]=k;

w+=k*weight[j];//个体的总重量

v+=k*value[j]; //个体的总价值

}

if(w>KW) i--; //如果不是解,重新生成

else

{

X[i].fitness=v;

X[i].weight=w;

if(v==stop){bestindividual=X[i];return;}//这种情况一般不会发生

}

}

}

/************************************************************************/

void CalculateFitnessValue()

{

int i=0,j=0;

for (i=0; i

{

int w=0,v=0;

for (j=0; j

{

w+=X[i].chromsome[j]*weight[j];//个体的总重量

v+=X[i].chromsome[j]*value[j]; //个体的总价值

}

X[i].fitness=v;

X[i].weight=w;

if(v==stop){bestindividual=X[i];return;}//符合条件情况下最优解这种情况一般不会发生if(w>KW) X[i]=bestindividual; //如果不是解,找最好的一个解代之}

}

/************************************************************************/

void SelectionOperator(void)

{

int i, index;

double p, sum=0.0;

double cfitness[S];//选择、累积概率

individual newX[S];

for (i=0;i

for (i=0;i

for (i=1;i

for (i=0;i

{

p=(rand()%1001)/1000.0;//产生一个[0,1]之间的随机数

index=0;

while(p>cfitness[index])//轮盘赌进行选择

{

index++;

}

newX[i]=X[index];

}

for (i=0; i

}

/************************************************************************/ void CrossoverOperator(void)//交叉操作

{

int i=0, j=0,k=0;individual temp;

for(i=0; i

{

int p=0,q=0;

do

{

p=rand()%S;//产生两个[0,S]的随机数

q=rand()%S;

}while(p==q);

int w=1+rand()%N;//[1,N]表示交换的位数

double r=(rand()%1001)/1000.0;//[0,1]

if(r<=Pc)

{

for(j=0;j

{

temp.chromsome[j]=X[p].chromsome[j];//将要交换的位先放入临时空间

X[p].chromsome[j]=X[q].chromsome[j];

X[q].chromsome[j]=temp.chromsome[j];

}

}

if(p==best)

if(-1==comp(bestindividual,X[p]))//如果变异后适应度变小

X[p]=bestindividual;

if(q==best)

if(-1==comp(bestindividual,X[q]))//如果变异后适应度变小

X[q]=bestindividual;

}

}

/************************************************************************/ void MutationOperator(void)

{

int i=0, j=0,k=0,q=0;

double p=0;

for (i=0; i

{

for (j=0; j

{

p=(rand()%1001)/1000.0;

if (p

{

if(X[i].chromsome[j]==1)X[i].chromsome[j]=0;

else X[i].chromsome[j]=1;

}

}

if(i==best)

if(-1==comp(bestindividual,X[i]))//如果变异后适应度变小

X[i]=bestindividual;

}

}

/************************************************************************/ void FindBestandWorstIndividual(void)

{

int i;

bestindividual=X[0];

for (i=1;i

{

if (X[i].fitness>bestindividual.fitness)

{

bestindividual=X[i];

best=i;

}

}

}

/*主函数*****************************************************************/ void main(void)

{

srand((unsigned)time(0));

t=0;

GenerateInitialPopulation(); //初始群体包括产生个体和计算个体的初始值

while (t<=T)

{

FindBestandWorstIndividual(); //保存当前最优解

SelectionOperator(); //选择

CrossoverOperator(); //交叉

MutationOperator(); //变异

Checkalike(); //检查相似度

CalculateFitnessValue(); //计算新种群适应度

t++;

}

FindBestandWorstIndividual(); //找到最优解

cout<

<

for(int k=0;k

cout<

}

/*结束***********************************************************************/

贪心算法0-1背包问题(算法实验代码)

实验三、0-1背包问题(贪心算法) 实验代码: #include int max(int a,int b) { if(a>b) return a; else return b; } void Knapsack(int *v,int *w,int *x,int c,int n, int m[8][100]) { int i,j; for(j=0;j=1;i--) { for(j=w[i];j<=c;j++) m[i][j]=max(m[i+1][j],m[i+1][j-w[i]]+v[i]); } for(i=1;i

printf("物品总数为:7\n"); printf("物品重量和价值分别为:\n"); printf("\n重量价值\n"); for (i=1;i<=n;i++) printf("%d %d \n",w[i],v[i]); int m=15; int array[8][100]={0}; Knapsack(v,w,x,m,7,array); printf("背包能装的最大价值为: %d\n",array[1][m]); printf("贪心算法的解为: "); for(i=1;i<=n;i++) { if(i==1) printf("%d",x[i]); else printf(" %d",x[i]); } printf("\n"); return 0; } 测试截图为:

基于遗传算法的一种新的约束处理方法

基于遗传算法的一种新的约束处理方法 苏勇彦1,王攀1,范衠2 (1武汉理工大学 自动化学院, 湖北 武汉 430070) (2丹麦理工大学 机械系 哥本哈根) 摘 要:本文针对目前的约束处理方法中存在的问题,提出一种新的约束处理方法。该方法通过可行解和不可行解混合交叉的方法对问题的解空间进行搜索,对可行种群和不可行种群分别进行选择操作。避免了惩罚策略中选取惩罚因子的困难,使得约束处理问题简单化。实例测试结果表明,该约束处理方法的有效性。 关键词:遗传算法、约束处理、可行解、不可行解、两种群混合交叉 1引言 科学研究和工程应用中许多问题都可以转化为求解一个带约束条件的函数优化问题[1]。遗传算法(Genetic Algorithm )与许多基于梯度的算法比较,具有不需要目标函数和约束条件可微,且能收敛到全局最优解的优点 [2],因此,它成为一种约束优化问题求解的有力工具。目前,基于GA 的约束处理方法有拒绝策略,修复策略,改进遗传算子策略以及惩罚函数策略等。但是这些方法都存在一些问题[3]:修复策略对问题本身的依赖性,对于每个问题必须设计专门的修复程序。改进遗传算子策略则需要设计针对问题的表达方式以及专门的遗传算子来维持解的可行性。惩罚策略解的质量严重依赖于惩罚因子的选取,当惩罚因子不适当时,算法可能收敛于不可行解。 本文针对目前的约束处理方法中存在的问题,提出一种新的约束处理方法。该方法通过可行解和不可行解混合交叉的方法对问题的解空间进行搜索,对可行种群和不可行种群分别进行选择操作。避免了惩罚策略中选取惩罚因子的困难,使得约束处理问题简单化。实例测试结果表明,该约束处理方法的有效性。 2约束处理方法描述 2.1单目标有约束优化问题一般形式 )(max x f ..t s ;0)(≤x g i 1,,2,1m i L L =;0)(=x h i )(,,1211m m m m i +=+=L X x ∈ 这里都是定义在m m m m h h h g g g f ,,,;,,;2121111L L ++n E 上的实值函数。X 是n E 上的 子集,x 是维实向量,其分量为。上述问题要求在变量满足约 束的同时极大化函数。函数通常为目标函数。约束n n x x x ,,,21L n x x x ,,,21L f f ;0)(≤x g i 称为不等式约束;约束称为等式约束。集合;0)(=x h i X 通常为变量的上下界限定的区域。向量且满足所有约束,则称之为问题的可行解。所有可行解构成可行域。否则,为问题的不可行解,所有不可行解构成不可行域。问题的目标是找到一个可行解X x ∈x 使得)()(x f x f ≤对于所有可行解x 成立。那么,x 为最优解[4]。 2.2算法描述 目前,最常采用的约束处理方法为惩罚函数法。但优化搜索的效率对惩罚因子的选择有

用遗传算法解决0-1背包问题概述

实现遗传算法的0-1背包问题 求解及其改进 姓名: 学号: 班级: 提交日期:2012年6月27日

实现遗传算法的0-1背包问题求解 摘要:研究了遗传算法解决0-1背包问题中的几个问题: 1)对于过程中不满足重量限制条件的个体的处理,通过代换上代最优解保持种群的进化性 2)对于交换率和变异率的理解和处理方法,采用逐个体和逐位判断的处理方法 3)对于早熟性问题,引入相似度衡量值并通过重新生成个体替换最差个体方式保持种群多样性。4)一种最优解只向更好进化方法的尝试。 通过实际计算比较表明,本文改进遗传算法在背包问题求解中具有很好的收敛性、稳定性和计算效率。通过实例计算,表明本文改进遗传算法优于简单遗传算法和普通改进的遗传算法。 关键词:遗传算法;背包问题;优化 1.基本实现原理: 一、问题描述 0-1背包问题属于组合优化问题的一个例子,求解0-1背包问题的过程可以被视作在很多可行解当中求解一个最优解。01背包问题的一般描述如下: 给定n个物品和一个背包,物品i的重量为Wi,其价值为Vi,背包的容量为C。选择合适的物品装入背包,使得背包中装入的物品的总价值最大。注意的一点是,背包内的物品的重量之和不能大于背包的容量C。在选择装入背包的物品时,对每种物品i只有两种选择:装入背包或者不装入背包,即只能将物品i装入背包一次。称此类问题为0/1背包问题。 其数学模型为: 0-1背包问题传统的解决方法有动态规划法、分支界限法、回溯法等等。传统的方法不能有效地解决0-1背包问题。遗传算法(Genetic Algorithms)则是一种适合于在大量的可行解中搜索最优(或次优)解的有效算法。 二、遗传算法特点介绍: 遗传算法(Genetic Algorithm, GA)是1962年Holland教授首次提出了GA算法的思想是近年来随着信息数据量激增,发展起来的一种崭新的全局优化算法,它借用了生物遗传学的观点,通过自然选择、遗传、变异等作用机制,实现各个个体的适应性的提高。 基本遗传算法求解步骤: Step 1 参数设置:在论域空间U上定义一个适应度函数f(x),给定种群规模N,交叉率P c 和变异率P m,代数T; Step 2 初始种群:随机产生U中的N个染色体s1, s2, …, s N,组成初始种群S={s1, s2, …, s N},置代数计数器t=1; Step 3计算适应度:S中每个染色体的适应度f() ; Step 4 判断:若终止条件满足,则取S中适应度最大的染色体作为所求结果,算法结束。Step 5 选择-复制:按选择概率P(x i)所决定的选中机会,每次从S中随机选定1个染色体并将其复制,共做N次,然后将复制所得的N个染色体组成群体S1; Step 6 交叉:按交叉率P c所决定的参加交叉的染色体数c,从S1中随机确定c个染色体,配对进行交叉操作,并用产生的新染色体代替原染色体,得群体S2; Step 7 变异:按变异率P m所决定的变异次数m,从S2中随机确定m个染色体,分别进行变异操作,并用产生的新染色体代替原染色体,得群体S3; Step 8 更新:将群体S3作为新一代种群,即用S3代替S,t=t+1,转步3;

算法设计实验_贪心算法背包问题

《算法分析与设计》 课程实验 专业年级:信息与计算科学 学生学号: 学生姓名: 实验题目:用贪婪法求解背包问题 指导老师: 实验时间:20xx年xx月x日 一、实验内容 用贪婪法求解背包问题 要求:用非递归实现 二、实验步骤 2.1、理解算法思想和问题要求; 2.2、写出每个操作的算法 非递归算法: greedbag() { int N; int c;

int[] w; int[] v; Scanner scan=new Scanner(System.in); System.out.print("输入背包的容量:"); c=scan.nextInt(); System.out.print("输入物品的数量:"); N=scan.nextInt(); System.out.print("分别输入物品的价值:"); v=new int[N]; for(int i=0;i

遗传算法求解背包问题

遗传算法求解背包问题 信管专业李鹏 201101002044 一、遗传算法(Genetic Algorithm)是模拟达尔文生物进化论的自然选择和遗传学机理的生物进化过程的计算模型,是一种通过模拟自然进化过程搜索最优解的方法,是从代表问题可能潜在的解集的一个种群(population)开始的,而一个种群则由经过基因(gene)编码的一定数目的个体(individual)组成。在每一代,根据问题域中个体的适应度(fitness)大小选择(selection)个体,并借助于自然遗传学的遗传算子(genetic operators)进行组合交叉(crossover)和变异(mutation),产生出代表新的解集的种群。 二、背包问题描述 背包问题是一个典型的组合优化问题,在计算理论中属于NP完全问题,主要应用于管理中的资源分配,资金预算,投资决策、装载问题的建模。传统“0/1”背包问题可以描述为:把具有一定体积和价值的n件不同种类物品放到一个有限容量的背包里,使得背包中物品的价值总量最大。 三、数学模型 背包问题可以描述如下:假设有n个物体,其重量用表示,价值用表示,背包的最大容量为b。这里和b都大于0。问题是要求背包所装的物体的总价值最大。背包问题的数学模型描述如下: (1) (2) (3) 约束条件(3)中表示物体i被选入背包,反之,表示物体i没有被选入背包。约束条件(2)表示背包的容量约束。

四、使用遗传算法解决“0-1背包问题”的思路:0-1背包的解可以编码为一串0-1字符串(0:不取,1:取);首先,随机产生M个0-1字符串,然后评价这些0-1字符串作为0-1背包问题的解的优劣;然后,随机选择一些字符串通过交叉、突变等操作产生下一代的M个字符串,而且较优的解被选中的概率要比较高。这样经过G代的进化后就可能会产生出0-1背包问题的一个“近似最优解”。 五、程序整体流程 (1)读取存取包的限种、商品的重要和价值的TXT文件; (2)初始化种群; (3)计算群体上每个个体的适应度值(Fitness) ; (4)评估适应度,对当前群体P(t)中每个个体Pi计算其适应度F(Pi),适应度表示了该个体的性能好坏; (5)依照Pc选择个体进行交叉操作; (6)仿照Pm对繁殖个体进行变异操作 (7)没有满足某种停止条件,则转第3步,否则进入8 ; (8)输出种群中适应度值最优的个体。 六、代码 function Main() %定义全局变量 global VariableNum POPSIZE MaxGens PXOVER PMutation VariableNum=3 %变量个数 POPSIZE=50 %种群大小 MaxGens=1000 %种群代数 PXOVER=0.8 %交叉概率 PMutation=0.2 %变异概率 %读取数据文件

【精选】贪心算法的应用

贪心算法的应用 课程名称:算法设计与分析 院系:计算机科学与信息工程学院 学生姓名:**** 学号:********** 专业班级:********************************** 指导教师:****** 201312-27

贪心算法的应用 摘要:顾名思义,贪心算法总是作出在当前看来最好的选择。也就是说贪心算法并不从整体最优考虑,它所作出的选择只是在某种意义上的局部最优选择。当然,希望贪心算法得到的最终结果也是整体最优的。虽然贪心算法不能对所有问题都得到整体最优解,但对许多问题它能产生整体最优解。如单源最短路经问题,最小生成树问题等。在一些情况下,即使贪心算法不能得到整体最优解,其最终结果却是最优解的很好近似。贪心算法求问题一般具有两个重要性质:贪心选择性质和最优子结构性质。所谓贪心选择性是指所求问题的整体最优解可以通过一系列局部最优解的选择,即贪心选择达到。这是贪心算法可行的第一个基本要素,也是贪心算法与动态规划算法主要区别。当一个问题的最优解包含其子问题的最优解时,称此问题具有最优子结构性质。问题的最优子结构性质是该问题可用动态规划算法或贪心算法求解的关键特征。 背包问题是一个经典的问题,我们可以采用多种算法去求解0/1背包问题,比如动态规划法、分支限界法、贪心算法、回溯法。在这里我们采用贪心法解决这个问题。 关键词:贪心法背包问题最优化

目录 第1章绪论 (3) 1.1 贪心算法的背景知识 (3) 1.2 贪心算法的前景意义 (3) 第2章贪心算法的理论知识 (4) 2.1 问题的模式 (4) 2.2 贪心算法的一般性描述 (4) 第3章背包问题 (5) 3.1 问题描述 (5) 3.2 问题分析 (5) 3.3算法设计 (5) 3.4 测试结果与分析 (10) 第4章结论 (12) 参考文献 (13) 附件 (13)

C语言版贪心算法背包问题

#include<> #define N 100 typedef struct bao{ int num; float w; float v; }; typedef struct avg{ int num; ( float val; float w; float v; }; struct bao b[N]; struct avg d[N]; int n; float c; ^ void Sort() { int i,j,k; struct avg temp[N]; for(i=0;i

float x[N],sum = 0; for(i=0;ic) break; x[d[i].num] = 1; sum += d[i].v; c -= d[i].w; } if(i

matlab、lingo程序代码3-背包问题(遗传算法)复习过程

背包问题---遗传算法解决 function Population1=GA_copy(Population,p,w0,w) %复制算子 %Population为种群 n=length(Population(:,1)); fvalue=zeros(1,n); for i=1:n fvalue(i)=GA_beibao_fitnessvalue(Population(i,:),p,w0,w); end fval=fvalue/sum(fvalue); F(1)=0; for j=1:n F(j+1)=0; for k=1:j F(j+1)=F(j+1)+fval(k); end end for i=1:n test=rand; for j=1:n if((test>=F(j))&&(test

POP(j,z)=Population(i,z); end POP(j,l+1)=i; p(j)=randint(1,1,[1 l-1]); j=j+1; end end k0=j-1; k=floor(k0/2); if k>=1 for m=1:k for t=p(2*m-1)+1:l s=POP(2*m-1,t); POP(2*m-1,t)=POP(2*m,t); POP(2*m,t)=s; end end for m=1:k0 for i=1:l Population1(POP(m,l+1),i)=POP(m,i); end end end function fitnessvalue=GA_fitnessvalue(x,p,w0,w) %使用惩罚法计算适应度值 %x为染色体 %p为背包问题中每个被选物体的价值 %w0为背包问题中背包总容积 %w为背包问题中每个被选物品的容积 l=length(x); for i=1:l a(i)=p(i).*x(i); end f=sum(a); b=min(w0,abs(sum(w)-w0)); for i=1:l wx(i)=w(i).*x(i); end if abs(sum(wx)-w0)>b*0.99 p=0.99;

背包问题(贪心算法)

算法分析与设计实验报告 第 4 次实验

}

附录:完整代码 #include #include #include struct node{ float value; float weight; }; float Value,curvalue=0; float Weight,curweight=0; //按价重比冒泡排序 void sort(node Node[],int M){ int i,j; node temp; for(i=0;i

贪心算法背包问题

算法设计与分析实验报告 题目:贪心算法背包问题 专业:JA V A技术xx——xxx班 学号: 姓名: 指导老师:

实验三:贪心算法背包问题 一、实验目的与要求 1、掌握背包问题的算法 2、初步掌握贪心算法 二、实验题: 问题描述:与0-1背包问题相似,给定n种物品和一个背包。物品i的重量是wi,其价值为vi,背包的容量为c。与0-1背包问题不同的是,在选择物品i装入背包时,背包问题的解决可以选择物品i的一部分,而不一定要全部装入背包,1< i < n。 三、实验代码 import java.awt.*; import java.awt.event.*; import javax.swing.*; public class er extends JFrame { private static final long serialVersionUID = -1508220487443708466L; private static final int width = 360;// 面板的宽度 private static final int height = 300;// 面板的高度 public int M; public int[] w; public int[] p; public int length; er() { // 初始Frame参数设置 this.setTitle("贪心算法"); setDefaultCloseOperation(EXIT_ON_CLOSE); setSize(width, height); Container c = getContentPane(); c.setLayout(new BoxLayout(c, BoxLayout.Y_AXIS)); setLocation(350, 150); // 声明一些字体样式 Font topF1 = new Font("宋体", Font.BOLD, 28); Font black15 = new Font("宋体", Font.PLAIN, 20); Font bold10 = new Font("宋体", Font.BOLD, 15); // 声明工具栏及属性设置 JPanel barPanel = new JPanel(); JMenuBar topBar = new JMenuBar(); topBar.setLocation(1, 1); barPanel.add(topBar); // 面板1和顶部标签属性设置 JPanel p1 = new JPanel(); JLabel topLabel = new JLabel("背包问题");

0-1背包问题的算法设计策略对比与讲解

算法设计与分析大作业 班级:电子154 姓名:吴志勇 学号: 1049731503279 任课老师:李瑞芳 日期: 2015.12.25

算法设计与分析课程论文 0-1背包问题的算法设计策略对比与分析 0 引言 对于计算机科学来说,算法的概念是至关重要的。在一个大型软件系统的开发中,设计出有效的算法将起到决定性的作用。通俗的讲,算法是解决问题的一种方法。也因此,《算法分析与设计》成为计算科学的核心问题之一,也是计算机科学与技术专业本科及研究生的一门重要的专业基础课。算法分析与设计是计算机软件开发人员必修课,软件的效率和稳定性取决于软件中所采用的算法;对于一般程序员和计算机专业学生,学习算法设计与分析课程,可以开阔编程思路,编写出优质程序。通过老师的解析,培养我们怎样分析算法的“好”于“坏”,怎样设计算法,并以广泛用于计算机科学中的算法为例,对种类不同难度的算法设计进行系统的介绍与比较。本课程将培养学生严格的设计与分析算法的思维方式,改变随意拼凑算法的习惯。本课程要求具备离散数学、程序设计语言、数据结构等先行课课程的知识。 1 算法复杂性分析的方法介绍 算法复杂性的高低体现在运行该算法所需要的计算机资源的多少上,所需的资源越多,该算法的复杂性越高;反之,所需资源越少,该算法的复杂性越低。对计算机资源,最重要的是时间与空间(即存储器)资源。因此,算法的复杂性有时间复杂性T(n)与空间复杂性S(n)之分。 算法复杂性是算法运行所需要的计算机资源的量,这个量应集中反映算法的效率,并从运行该算法的实际计算机中抽象出来,换句话说,这个量应该只依赖要解决的问题规模‘算法的输入和算法本身的函数。用C表示复杂性,N,I和A表示问题的规模、算法的输入和算法本身规模,则有如下表达式: C=F(N,I,A) T=F(N,I,A) S=F(N,I,A) 其中F(N,I,A)是一个三元函数。通常A隐含在复杂性函数名当中,因此表达式中一般不写A。 即:C=F(N,I) T=F(N,I) S=F(N,I) 算法复杂性中时间与空间复杂性算法相似,所以以下算法复杂性主要以时间复杂性为例: 算法的时间复杂性一般分为三种情况:最坏情况、最好情况和平均情况。下面描述算法复杂性时都是用的简化的复杂性算法分析,引入了渐近意义的记号O,Ω,θ,和o。 O表示渐近上界Ω表示渐近下界: θ表示同阶即:f(n)= O(g(n))且 f(n)= Ω(g(n)) 2 常见的算法分析设计策略介绍 2.1 递归与分治策略 分治法的设计思想是,将一个难以直接解决的大问题,分割成一些规模较小的相同问题,以便各个击破,分而治之。 直接或间接地调用自身的算法称为递归算法。用函数自身给出定义的函数称为递归函数。 由分治法产生的子问题往往是原问题的较小模式,这就为使用递归技术提供了方便。在这种情况下,反复应用分治手段,可以使子问题与原问题类型一致而其规模却不断缩小,最终使子问题缩小到很容易直接求出其解。这自然导致递归过程的产生。 分治与递归像一对孪生兄弟,经常同时应用在算法设计之中,并由此产生许多高效算法。 递归算法举例: 共11页第1页

c应用贪心算法求解背包问题

实验五应用贪心算法求解背包问题 学院:计算机科学与技术专业:计算机科学与技术 学号:班级:姓名: 、 实验内容: 背包问题指的是:有一个承重为W的背包和n个物品,它们各自的重量和价值分别是n ,假设W w i和v i(1 i n)w i 1i,求这些物品中最有价值的一个子集。如果每次选择某一个物品的时候,只能全部拿走,则这一问题称为离散(0-1)背包问题;如果每次可以拿走某一物品的任意一部分,则这一问题称为连续背包问题。 二、算法思想: 首先计算每种物品单位重量的价值Vi/Wi,然后,依贪心选择策略,将尽可能多的单位重量价值最高的物品装入背包。若将这种物品全部装入背包后,背包内的物品总重量未超过C,则选择单位重量价值次高的物品并尽可能多地装入背包。依此策略一直地进行下去,直到背包装满为止。 三、实验过程: #in elude using n amespace std; struct goodi nfo

{ float p; // 物品效益 float w; // 物品重量 float X; // 物品该放的数量 int flag; // 物品编号 };// 物品信息结构体 void Insertionsort(goodinfo goods[],int n)// 插入排序,按pi/wi 价值收益进行排序,一般教材上按冒泡排序 { int j,i; for(j=2;j<=n;j++) { goods[0]=goods[j]; i=j-1; while (goods[0].p>goods[i].p) { } goods[i+1]=goods[0]; } }// 按物品效益,重量比值做升序排列goods[i+1]=goods[i]; i--; void bag(goodinfo goods[],float M,int n) { float cu; int i,j;

贪心算法详解分析

贪心算法详解 贪心算法思想: 顾名思义,贪心算法总是作出在当前看来最好的选择。也就是说贪心算法并不从整体最优考虑,它所作出的选择只是在某种意义上的局部最优选择。当然,希望贪心算法得到的最终结果也是整体最优的。虽然贪心算法不能对所有问题都得到整体最优解,但对许多问题它能产生整体最优解。如单源最短路经问题,最小生成树问题等。在一些情况下,即使贪心算法不能得到整体最优解,其最终结果却是最优解的很好近似。 贪心算法的基本要素: 1.贪心选择性质。所谓贪心选择性质是指所求问题的整体最优解可以通过一系列局部最优的选择,即贪心选择来达到。这是贪心算法可行的第一个基本要素,也是贪心算法与动态规划算法的主要区别。 动态规划算法通常以自底向上的方式解各子问题,而贪心算法则通常以自顶向下的方式进行,以迭代的方式作出相继的贪心选择,每作一次贪心选择就将所求问题简化为规模更小的子问题。 对于一个具体问题,要确定它是否具有贪心选择性质,必须证明每一步所作的贪心选择最终导致问题的整体最优解。 2. 当一个问题的最优解包含其子问题的最优解时,称此问题具有最优子结构性质。问题的 最优子结构性质是该问题可用动态规划算法或贪心算法求解的关键特征。 贪心算法的基本思路: 从问题的某一个初始解出发逐步逼近给定的目标,以尽可能快的地求得更好的解。当达到算法中的某一步不能再继续前进时,算法停止。 该算法存在问题: 1. 不能保证求得的最后解是最佳的; 2. 不能用来求最大或最小解问题; 3. 只能求满足某些约束条件的可行解的范围。 实现该算法的过程: 从问题的某一初始解出发; while 能朝给定总目标前进一步do 求出可行解的一个解元素; 由所有解元素组合成问题的一个可行解; 用背包问题来介绍贪心算法: 背包问题:有一个背包,背包容量是M=150。有7个物品,物品可以分割成任意大小。要 求尽可能让装入背包中的物品总价值最大,但不能超过总容量。

遗传算法求解0-1背包问题(JAVA)

遗传算法求解0-1背包问题 一、问题描述 给定n种物品和容量为C的背包。物品i的重量是wi,其价值为vi。问应如何选择装入背包的物品,使得装入背包中物品的总价值最大? 二、知识表示 1、状态表示 (1)个体或染色体:问题的一个解,表示为n个比特的字符串,比特值为0表示不选该物品,比特值为1表示选择该物品。 (2)基因:染色体的每一个比特。 (3)种群:解的集合。 (4)适应度:衡量个体优劣的函数值。 2、控制参数 (1)种群规模:解的个数。 (2)最大遗传的代数 (3)交叉率:参加交叉运算的染色体个数占全体染色体的比例,取值范围一般为0.4~0.99。(4)变异率:发生变异的基因位数所占全体染色体的基因总位数的比例,取值范围一般为0.0001~0.1。 3、算法描述 (1)在搜索空间U上定义一个适应度函数f(x),给定种群规模N,交叉率Pc和变异率Pm,代数T; (2)随机产生U中的N个个体s1, s2, …, sN,组成初始种群S={s1, s2, …, sN},置代数计数器t=1; (3)计算S中每个个体的适应度f() ; (4)若终止条件满足,则取S中适应度最大的个体作为所求结果,算法结束。 (5)按选择概率P(xi)所决定的选中机会,每次从S中随机选定1个个体并将其染色体复制,共做N次,然后将复制所得的N个染色体组成群体S1; (6)按交叉率Pc所决定的参加交叉的染色体数c,从S1中随机确定c个染色体,配对进行交叉操作,并用产生的新染色体代替原染色体,得群体S2; (7)按变异率P m所决定的变异次数m,从S2中随机确定m个染色体,分别进行变异操作,并用产生的新染色体代替原染色体,得群体S3; (8)将群体S3作为新一代种群,即用S3代替S,t = t+1,转步3。 三、算法实现 1、主要的数据结构 染色体:用一维数组表示,数组中下标为i的元素表示第(i+1)个物品的选中状态,元素值为1,表示物品被选中,元素值为0表示物品不被选中。 种群:用二维数组表示,每一行表示一个染色体。 具有最大价值的染色体:由于每一个染色体经过选择、交叉、变异后都可能发生变化,所以对于产生的新的总群,需要记录每个物品的选中状态。同时保存该状态下物品的最大价值,如果新的总群能够产生更优的值,则替换具有最大价值的染色体。

贪心算法实现背包问题算法设计与分析实验报告

算法设计与分析实验报告 实验名称贪心算法实现背包问题评分 实验日期年月日指导教师 姓名专业班级学号 一.实验要求 1. 优化问题 有n个输入,而它的解就由这n个输入满足某些事先给定的约束条件的某个子集组成,而把满足约束条件的子集称为该问题的可行解。可行解一般来说是不唯一的。那些使目标函数取极值(极大或极小)的可行解,称为最优解。 2.贪心法求优化问题 算法思想:在贪心算法中采用逐步构造最优解的方法。在每个阶段,都作出一个看上去最优的决策(在一定的标准下)。决策一旦作出,就不可再更改。作出贪心决策的依据称为贪心准则(greedy criterion)。 3.一般方法 1)根据题意,选取一种量度标准。 2)按这种量度标准对这n个输入排序 3)依次选择输入量加入部分解中。如果当前这个输入量的加入,不满足约束条件,则不把此输入加到这部分解中。 procedure GREEDY(A,n) /*贪心法一般控制流程*/ //A(1:n)包含n个输入// solutions←φ //将解向量solution初始化为空/ for i←1 to n do x←SELECT(A) if FEASIBLE(solution,x) then solutions←UNION(solution,x) endif repeat return(solution) end GREEDY 4. 实现典型的贪心算法的编程与上机实验,验证算法的时间复杂性函数。 二.实验内容 1. 编程实现背包问题贪心算法。通过具体算法理解如何通过局部最优实现全局最优,

并验证算法的时间复杂性。 2.输入5个的图的邻接矩阵,程序加入统计prim算法访问图的节点数和边数的语句。 3.将统计数与复杂性函数所计算比较次数比较,用表格列出比较结果,给出文字分析。 三.程序算法 1.背包问题的贪心算法 procedure KNAPSACK(P,W,M,X,n) //P(1:n)和W(1;n)分别含有按 P(i)/W(i)≥P(i+1)/W(i+1)排序的n件物品的效益值 和重量。M是背包的容量大小,而x(1:n)是解向量 real P(1:n),W(1:n),X(1:n),M,cu; integer i,n; X←0 //将解向量初始化为零 cu←M //cu是背包剩余容量 for i←1 to n do if W(i)>cu then exit endif X(i) ←1 cu←cu-W(i) repeat if i≤n then X(i) ←cu/ W(i) endif end GREEDY-KNAPSACK procedure prim(G,) status←“unseen” // T为空 status[1]←“tree node” // 将1放入T for each edge(1,w) do status[w]←“fringe” // 找到T的邻接点 dad[w] ←1; //w通过1与T建立联系 dist[w] ←weight(1,w) //w到T的距离 repeat while status[t]≠“tree node” do pick a fringe u with min dist[w] // 选取到T最近的节点 status[u]←“tree node” for each edge(u,w) do 修改w和T的关系 repeat repeat 2.Prim算法

遗传算法求解y=x2 - 副本

初始遗传算法及一个简单的例子 遗传算法(Genetic Algorithms, GA)是一类借鉴生物界自然选择和自然遗传机制的随机化搜索算法。它模拟自然选择和自然遗传过程中发生的繁殖、交叉和基因突变现象,在每次迭代中都保留一组候选解,并按某种指标从解群中选取较优的个体,利用遗传算子(选择、交叉和变异)对这些个体进行组合,产生新一代的候选解群,重复此过程,直到满足某种收敛指标为止。 下面我以一个实例来详细表述遗传算法的过程 例:求下述二元函数的最大值: 2 =] y x x∈ ,0[ 31 1、编码: 用遗传算法求解问题时,不是对所求解问题的实际决策变量直接进行操作,而是对表示可行解的个体编码的操作,不断搜索出适应度较高的个体,并在群体中增加其数量,最终寻找到问题的最优解或近似最优解。因此,必须建立问题的可行解的实际表示和遗传算法的染色体位串结构之间的联系。在遗传算法中,把一个问题的可行解从其解空间转换到遗传算法所能处理的搜索空间的转换方法称之为编码。反之,个体从搜索空间的基因型变换到解空间的表现型的方法称之为解码方法。 编码是应用遗传算法是需要解决的首要问题,也是一个关键步骤。迄今为止人们已经设计出了许多种不同的编码方法。基本遗传算法使用的是二进制符号0和1所组成的二进制符号集{0,1},也就是说,把问题空间的参数表示为基于字符集{0,1}构成的染色体位串。每个个体的染色体中所包含的数字的个数L 称为染色体的长度或称为符号串的长度。一般染色体的长度L为一固定的数,如本例的编码为 s1 = 1 0 0 1 0 (17) s2 = 1 1 1 1 0 (30) s3 = 1 0 1 0 1 (21) s4 = 0 0 1 0 0 (4) 表示四个个体,该个体的染色体长度L=5。 2、个体适应度函数 在遗传算法中,根据个体适应度的大小来确定该个体在选择操作中被选定的概率。个体的适应度越大,该个体被遗传到下一代的概率也越大;反之,个体的适应度越小,该个体被遗传到下一代的概率也越小。基本遗传算法使用比例选择操作方法来确定群体中各个个体是否有可能遗传到下一代群体中。为了正确计算不同情况下各个个体的选择概率,要求所有个体的适应度必须为正数或为零,不能是负数。这样,根据不同种类的问题,必须预先确定好由目标函数值到个体适应度之间的转换规则,特别是要预先确定好目标函数值为负数时的处理方法。

人工智能之遗传算法求解01背包问题实验报告

人工智能之遗传算法求解0/1背包问题实验报告 Pb03000982 王皓棉 一、问题描述: 背包问题是著名的NP完备类困难问题, 在网络资源分配中有着广泛的应用,已经有很多人运用了各种不同的传统优化算法来解决这一问题,这些方法在求解较大规模的背包问题时,都存在着计算量大,迭代时间长的弱点。而将遗传算法应用到背包问题的求解,则克服了传统优化方法的缺点,遗传算法是借助了大自然的演化过程,是多线索而非单线索的全局优化方法,采用的是种群和随机搜索机制。 遗传算法(GA)是一类借鉴生物界自然选择和自然遗传机制的随机化的搜索算法,由美国J.Holland教授提出,其主要特点是群体搜索策略、群体中个体之间的信息交换和搜索不依赖于梯度信息。因此它尤其适用于处理传统搜索方法难于解决的复杂和非线性问题,可广泛应用于组合优化,机器学习,自适应控制,规划设计和人工生命领域。 GA是一种群体型操作,该操作以群体中的所有个体为对象。选择,交叉和变异是遗传算法的三个主要算子,他们构成了遗传算法的主要操作,使遗传算法具有了其它传统方法所没有的特性。遗传算法中包含了如下五个基本要素:1 .参数编码,2.初始群体的设置,3.适应度函数的设计, 4.遗传操作设计,5.控制参数设定,这个五个要素构成可遗传算法的核心内容。 遗传算法的搜索能力是由选择算子和交叉算子决定,变异算子则保证了算法能够搜索到问题空间的每一个点,从而使其具有搜索全局最优的能力.而遗传算法的高效性和强壮性可由Holland提出的模式定理和隐式并行性得以解释。 二、实验目的: 通过本实验,可以深入理解遗传算法,以及遗传算法对解决NP问题的作用。 三、算法设计: 1、确定种群规模M、惩罚系数 、杂交概率c p、变异概率m P、染色体长度n及最大 max. 进化代数gen x=1表 2、采用二进制n维解矢量X作为解空间参数的遗传编码,串T的长度等于n, i x=0表示不装入背包。例如X={0,1,0,1,0,0,1}表示第2,4,7示该物件装入背包, i 这三个物件被选入包中。

贪心算法实现01背包问题

贪心算法实现01背包问题 算法思想:贪心原则为单位价值最大且重量最小,不超过背包最大承重量为约束条件。也就是说,存在单位重量价值相等的两个包,则选取重量较小的那个背包。 具体实现过程是:首先可以设置一个备份pvu类型的数组,在不破环原数据的情况下,对此备份数组按单位重量价值从大到小的排序。依次设立两个指针i,j(其中i表示当前应该参与最佳pv值的元素指针,j表示符合约束条件的指针(单位重量价值PV最大,重量最小,不超过最大承重量约束) 代码实现如下: #include using namespace std; typedef struct { int v; int w; float pv; }pvu; void sortByPv(pvu [],int ); int zeroneBags(pvu[],int,int,int * ); void print(pvu a[],int n) { for (int i=0;i

相关文档
最新文档