基因算法解决01背包问题

                                                                  

背包问题简述:
有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;
		}
	}

}


基因算法流程图:


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
遗传算法是一种常用于解决组合优化问题的算法,可以用来解决01背包问题。下面是一个使用Matlab实现的遗传算法解决01背包问题的代码示例: ```matlab % 01背包问题的遗传算法解决代码 function [bestSolution, bestFitness] = geneticAlgorithm01Knapsack(weights, values, capacity, populationSize, generations) % 初始化种群 population = initializePopulation(populationSize, length(weights)); % 进化过程 for generation = 1:generations % 计算适应度 fitness = calculateFitness(population, weights, values, capacity); % 选择 selectedPopulation = selection(population, fitness); % 交叉 offspringPopulation = crossover(selectedPopulation); % 变异 mutatedPopulation = mutation(offspringPopulation); % 更新种群 population = mutatedPopulation; end % 计算最佳解和最佳适应度 fitness = calculateFitness(population, weights, values, capacity); [bestFitness, bestIndex] = max(fitness); bestSolution = population(bestIndex, :); end % 初始化种群 function population = initializePopulation(populationSize, chromosomeLength) population = randi([0, 1], populationSize, chromosomeLength); end % 计算适应度 function fitness = calculateFitness(population, weights, values, capacity) populationSize = size(population, 1); fitness = zeros(populationSize, 1); for i = 1:populationSize chromosome = population(i, :); totalWeight = sum(chromosome .* weights); totalValue = sum(chromosome .* values); if totalWeight <= capacity fitness(i) = totalValue; end end end % 选择 function selectedPopulation = selection(population, fitness) populationSize = size(population, 1); selectedPopulation = zeros(populationSize, size(population, 2)); % 轮盘赌选择 cumulativeFitness = cumsum(fitness); totalFitness = sum(fitness); for i = 1:populationSize randomValue = rand() * totalFitness; selectedIndividualIndex = find(cumulativeFitness >= randomValue, 1); selectedPopulation(i, :) = population(selectedIndividualIndex, :); end end % 交叉 function offspringPopulation = crossover(selectedPopulation) populationSize = size(selectedPopulation, 1); offspringPopulation = zeros(populationSize, size(selectedPopulation, 2)); for i = 1:2:populationSize parent1 = selectedPopulation(i, :); parent2 = selectedPopulation(i+1, :); % 单点交叉 crossoverPoint = randi([1, length(parent1)-1]); offspring1 = [parent1(1:crossoverPoint), parent2(crossoverPoint+1:end)]; offspring2 = [parent2(1:crossoverPoint), parent1(crossoverPoint+1:end)]; offspringPopulation(i, :) = offspring1; offspringPopulation(i+1, :) = offspring2; end end % 变异 function mutatedPopulation = mutation(offspringPopulation) populationSize = size(offspringPopulation, 1); mutatedPopulation = offspringPopulation; % 每个个体的每个基因都有一定概率发生变异 mutationRate = 0.01; for i = 1:populationSize for j = 1:length(offspringPopulation(i, :)) if rand() < mutationRate mutatedPopulation(i, j) = 1 - mutatedPopulation(i, j); end end end end ``` 请注意,这只是一个简单的示例代码,具体的实现可能会有所不同。你可以根据自己的需求进行修改和优化。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值