遗传算法解决背包问题(java)
遗传算法作为当今一个比较热门的研究方向,在解决最优化问题上有着良好的作用。遗传算法利用基因编码,对其进行生成、杂交、变异、选择等操作,产生不同的基因序列,使解一步一步向最优解逼近。
背包问题(Knapsack problem)是一种组合优化的NP完全问题。问题可以描述为:给定一组物品,每种物品都有自己的重量和价格,在限定的总重量内,我们如何选择,才能使得物品的总价格最高。问题的名称来源于如何选择最合适的物品放置于给定背包中。相似问题经常出现在商业、组合数学,计算复杂性理论、密码学和应用数学等领域中。也可以将背包问题描述为决定性问题,即在总重量不超过W的前提下,总价值是否能达到V。
已知n个物体的容积及其价值分别为w_i 和c_i (i=1,2, …,n),背包的总容量为v。问:选择哪些物品 装入背包可以使背包在满足容量限制的前提下总价值最大?
问题
可选择的物品有50件,其价值c和重量v分别为
c={220,208,198,192,180,180,165,162,160,158,155,130,125122,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}
w={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}
背包的总量不能超过1000,求解背包所能装下的最大的价值是多少
遗传算法解决思路
利用遗传算法时,可以随机生成一个长度为50的0-1序列,其中1表示对应位置的物品装进背包,0表示对应物品不装进背包,需要注意的是,生成的序列有可能超过背包的总重量,不满足约束条件,此时需要对序列进行操作。可行的操作有两种,第一种是对于不满足约束条件的序列进行抛弃,第二种是对其进行贪心算子变换,具体操作如下:
- 对所有 x_1=1 的物品,按它们的价值密度排序,形成队列b(i);
- 依次放入价值密度最大的物品,并判断是否有超出背包限定的范围;
- 如果超出,则将价值密度序列中从这个位置之后的所有商品置0;
代码
染色体类
import java.util.Random;
public class Chromosome {
public boolean[] gene;
private int fitness;
private int bag=1000;
public int getFitness() {
return fitness;
}
public void setFitness(int fitness) {
this.fitness = fitness;
}
/*
构造染色体
*/
public Chromosome(int n){
if (n<0){
return;
}
initSize(n);
for(int i=0;i<n;i++){
gene[i]=Math.random()>=0.5;
}
getFitness();
}
public Chromosome(){
}
public void initSize(int n){
if (n<0){
return;
}
this.gene=new boolean[n];
}
/*
染色体变异
*/
public void mutation(int size,double rate){
Random random=new Random();
for(int i=0;i<size;i++){
if(random.nextDouble()<rate){
boolean t=gene[i];
t=!t;
gene[i]=t;
}
}
}
}
遗传算法
import java.util.*;
public class GeneticAlgorith {
public List<Chromosome> population=new ArrayList<Chromosome>();//存放所有的种群基因
private int popSize; //种群规模N
private int chromoLength;//每条染色体数目m;
private double mutationRate=0.01;//基因突变概率pm
private double crossoverRate=0.6;//交叉概率pc
private int bagMax=1000;
private int generation;//种群代数t
private int iterNum=10000;//最大迭代次数
// private int stepmax=3;//最长步长
private int [] charge={
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};
private int [] weight={
80,