一:问题描述
给定n种物品,物品i(1≤i≥n)的体积为wi,价值为vi,将这n种物品放入容量为C的背包之中。在放入背包的物品总体积小于C的情况下,求放入背包物品的最大价值。
二:基本实现原理
1:编码
问题可以表示为一个n位的二进制码,第i位表示物品i,数值为0表示物品没有选中,1表示选中物品。
2:种群
种群是个体的集合
3:适应度
适应度在0-1背包问题中表示的是背包中的总价值的大小,总价值越大个体的适应度越大。
4:选择
从种群中选出部分个体之后进行重组或交叉,产生的新个体依据适应度函数进行优胜劣汰,选出优良个体。
5:交叉
不同的个体之间随机的进行杂交,其基因进行再次重组。其后产生新的具有不同适应度的新个体。
6:变异
变异指单个个体的基因按照小概率进行变化的方法。本题中采用的变异方法随机产生变异点,并进行了以下两种变异类型。
1) 变异点进行0和1的状态翻转。此方法趋于常规,但无甚缺点。
2) 变异点变为1,如果超出背包容积,则变为0。此方法更易产生较大的解,但如若初始种群产生的不好,则随后的变异绝不会产生最优解。
三:算法实现
1:初始化
初始化工作包括输入算法的参数,产生初始化种群,种群差异性越明显越好。
2:功能
行数共有以下几种功能:
1)数据结构初始化
2)种群初始化工作
3)选择操作
4)计算适应度函数功能
5)交叉操作
6)变异操作
7)产生随机数功能
8)最优解记录功能,将进化的每一个种群的最大值与之前产生的最优解进行比较,更大则替换之,否则不替换。
3:终止条件
在遗传一定大的代数时,可以认为产生过了优秀的个体,即最优解(或接近最优解)。
4:算法步骤
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) 按变异率Pm所决定的变异次数m,从S2中随机确定m个染色体,分别进行变异操作,并用产生的新染色体代替原染色体,得群体S3;
8) 将群体S3作为新一代种群,即用S3代替S,t=t+1,转步3;
5:编程设计
1) 类的设计:
1:class Global {
publicfinal static int M =200; //种群的规模
publicfinal static int T = 1000; //遗传的最大代数
publicfinal static double pc = 0.8; //交叉率
publicfinal static double pv = 0.05; //变异率
}
2:class MaxValue{
publicstatic int[] have = null; //最大解选择到的物品
publicstatic int max_value = 0; //最大解的价值
}
3:public class GasolvePackage
2)
类的功能:
Global类中定义的相当于全局变量。
MaxValue类中记录最优解,have数组记录选择的到的物品,max_value记录最优解得价值
GasolvePackage类有遗传算法的各种函数
3)
函数设计:此中具体介绍一下两种最主要的部分
1:GasolvePackage类的构造器
public GasolvePackage(){
try{
BufferedReaderread=newBufferedReader(newInputStreamReader(newFileInputStream("input.txt")));
Stringa=newString();
Stringb=newString();
package_rj=Integer.parseInt(read.readLine().trim()); //读取背包容积
a=read.readLine(); //读取物品体积行
tiji=strArr_to_intArr(a.split(" "));
b=read.readLine(); //读取物品价值行
value =strArr_to_intArr(b.split(" "));
num=value.length;
MaxValue.have=new int[Global.M];
read.close();
}
catch(Exception e)
{
System.out.println("请检查输入文件中的错误");
}
}
private int[]strArr_to_intArr(String[] strArr){ //将字符数组转化为数字数组
int size = strArr.length;
int[] int_arr = new int[size];
for(int i = 0; i < size; i++){
int_arr[i]= Integer.valueOf(strArr[i]);
}
return int_arr;
}
此中主要从文本中输入背包容积,各个物品的体积以及各个物品的价值。
2:
public int[][] variation(int[][]cross_zq){ //变异算法
int i = 0;
int row_id = 0;
int col_id = 0;
Randomrand =newRandom();
int variation_num = (int)(Global.pv * Global.M