基因算法解决01背包问题
2015-12-18 19:26
411 查看
背包问题简述:
有m个物体,每个物体价值为v[i],重量为w[i],有一个背包,最多能盛重量为W的物体,
求背包能盛的最大的价值。
基因算法:
编码:编码长度为物体的个数,1表示放进包,0表示不放进包
适应度:包里物品的价值和
交叉:两个随机,采用多点交叉,交叉点的个数是随机的,交叉的位置是随机的
编译:同样两个随机
交叉概率:0.8
变异概率:0.15
个体类(一个个体就是问题的一个解):
import java.util.Arrays;
/**
* 0 1背包中的个体,一个个体对应基因算法的一个解
* @author founder
*/
public class Individual {
//基因序列,数组的大小为物体的个数,gene[i]=1表示选择,gene[i]=0表示不选择
public int[] gene;
public double fitness; //个体的适应度
public double selectProbability; //选择概率
public double accumulateProbability; //累积的选择概率
public Individual(Individual ind){
this.gene = new int[ind.gene.length];
this.gene = Arrays.copyOf(ind.gene, ind.gene.length);
this.fitness = ind.fitness;
this.selectProbability = ind.selectProbability;
this.accumulateProbability = ind.accumulateProbability;
}
public Individual(){
}
}
全部代码如下,evaluate给出每个解的评估,crossover交叉操作,mutation编译操作,迭代次数为100,种群大小为50。
代码实现了两种选择算子,轮盘赌算法和二进制锦标赛算法
:
import java.util.Arrays; import java.util.Random; /** * 基因算法解决0 1背包问题,背包问题简述: * 有m个物体,每个物体价值为v[i],重量为w[i],有一个背包,最多能盛重量为W的物体, * 求背包能盛价值最大的物体 * @author founder */ public class BinPacking { public int[] bin_values; //价值向量 public int[] bin_weights; //重量向量 public int bin_capacity; //背包可以承受的总重量 public int bin_objNum; public int gene_N; //种群大小 public double gene_cross_prob = 0.8; public double gene_mutation_prob = 0.15; public Individual[] population; public Random random; /** * 构造函数 * @param num 物体个数 * @param gene_N 种群大小 */ public BinPacking(){ this.bin_objNum = 7; //物体个数 this.gene_N = 40; //种群中的个体个数 population = new Individual[gene_N]; int[] bin_values = {10,40,30,50,35,40,30}; this.bin_values = bin_values; int[] bin_weights = {35,30,60,50,40,10,25}; this.bin_weights = bin_weights; this.bin_capacity = 150; this.random = new Random(System.currentTimeMillis()); } /** * 随机产生大小为N的种群 * Random.nextInt(n)从0(包含)到n(不包含)均匀分布的整数 */ public void generateInitPopulation(){ for(int i=0;i<this.gene_N;i++){ Individual ind = new Individual(); ind.gene = new int[this.bin_objNum]; for(int j=0;j<ind.gene.length;j++){ ind.gene[j] = random.nextInt(2); } population[i] = ind; } } /** * 计算每个个体的适应度,顺便计算整个种群的适应度 * @param Individual[] inds,一整个种群 * @return 种群总的适应度,所有个体的适应度的和(用来计算选择概率) */ public void evaluate(){ int totalFitness = 0; for(int i=0;i<this.population.length;i++){ //计算每个个体的适应度以及种群的总适应度 Individual ind = this.population[i]; int weight = 0; ind.fitness = 0; for(int j=0;j<ind.gene.length;j++){ if(ind.gene[j]==1){ ind.fitness += bin_values[j]; weight += bin_weights[j]; } } if(weight > bin_capacity){ ind.fitness = 1; } totalFitness += ind.fitness; } double lastcf = 0.0; for(int i=0;i<this.population.length;i++){ //计算每个个体的选择概率,以及累加选择概率(轮盘赌) this.population[i].selectProbability = this.population[i].fitness/totalFitness; this.population[i].accumulateProbability = lastcf + this.population[i].selectProbability; lastcf = this.population[i].accumulateProbability; } } /** * 使用轮盘赌算法选择大小为N的种群 */ public void select(){ Individual[] newInds = new Individual[this.gene_N]; for(int i=0;i<this.gene_N;i++){ //选择的次数即为种群的大小 double prob = random.nextDouble(); if(prob<this.population[0].accumulateProbability){ newInds[i] = new Individual(this.population[0]); }else{ for(int j=0;j<this.population.length-1;j++){ if(prob>=this.population[j].accumulateProbability && prob<this.population[j+1].accumulateProbability){ newInds[i] = new Individual(this.population[j+1]); } } } } this.population = newInds; } /** * 轮盘赌选择算法的另一种选择方法:二进制竞赛 * 随机选择两个,适应度大的作为下一代,适应度小的丢弃 */ public void binaryCompetitionSelect(){ Individual[] newInds = new Individual[this.gene_N]; for(int i=0;i<newInds.length;i++){ int first = random.nextInt(this.gene_N); int second = random.nextInt(this.gene_N); if(this.population[first].fitness>=this.population[second].fitness){ newInds[i] = new Individual(this.population[first]); }else{ newInds[i] = new Individual(this.population[second]); } } this.population = newInds; } /** * 交叉操作,以某概率,交叉概率设置为0.8 */ public void crossover(){ int first = -1; for(int i=0;i<this.population.length;i++){ double prob = random.nextDouble(); if(prob<this.gene_cross_prob){ if(first<0){ first = i; }else{ exchange(first, i); first = -1; } } } } /** * 交换两个个体的部分基因(随机个基因),两个随机: * 1、交换点的个数是随机的 * 2、交换的位置是随机的 */ public void exchange(int first,int second){ int exNum = random.nextInt(population.length); //产生交换的基因数 for(int i=0;i<exNum;i++){ //每次选择一个基因进行交换,一共exNum个。 int pos = random.nextInt(this.bin_objNum); //int temp = population[first].gene[pos]; Individual ind = population[first]; int temp = ind.gene[pos]; population[first].gene[pos] = population[second].gene[pos]; population[second].gene[pos] = temp; } } /** * 变异操作 */ public void mutation(){ for(int i=0;i<this.population.length;i++){ if(random.nextDouble()<this.gene_mutation_prob){ //进行变异操作,随机个点,随机位置 int mutNum = random.nextInt(this.population.length); for(int j=0;j<mutNum;j++){ int pos = random.nextInt(this.bin_objNum); this.population[i].gene[pos] = 1-this.population[i].gene[pos]; } } } } public static void startBP(){ BinPacking bp = new BinPacking(); bp.generateInitPopulation(); for(int i=0;i<50;i++){ bp.evaluate(); //bp.select(); bp.binaryCompetitionSelect(); bp.crossover(); bp.mutation(); } bp.evaluate(); Arrays.sort(bp.population, new IndCom()); System.out.println(bp.population[0].fitness); for(int i=0;i<bp.population[0].gene.length;i++){ System.out.print(bp.population[0].gene[i]+" "); } } public static void main(String[] args) { startBP(); } }
用于对Individual排序的比较器:
import java.util.Comparator; public class IndCom implements Comparator<Individual>{ @Override public int compare(Individual o1, Individual o2) { if(o2.fitness>o1.fitness){ return 1; }else if(o2.fitness<o1.fitness){ return -1; }else{ return 0; } } }
基因算法流程图:
相关文章推荐
- Xcode 5集成GoogleTest Frame
- PANIC : Error configuring AvalonLogSystem :
- 博客第一笔
- 安装和使用cocoaPods
- 经典并查集(原文作者gemire)
- 数据库安装配置文件总结(mysql,SQL Server,oracle,Mongodb,DB2)
- Struts OGNL and ValueStack
- 史上最详细的CocoaPods安装教程
- 第10周 纸上谈兵:“知原理”检验题目
- Fragment笔记
- 【个人重构】数据库设计之深度思考
- [Servlet&JSP] 使用JDBC连接数据库
- hdu 1722(gcd)
- ios学习----- mjRefresh使用指南
- Fragment+ViewPager实现仿微信点击和滑动切换界面
- git重新初始化远程仓库
- 一个较好的资料收编网站
- 最全面的前端开发指南
- Objective-c语言_SNottification(通知)
- 1014 装箱问题