粒子群算法--背包问题
来源:互联网 发布:舆情监控软件下载 编辑:程序博客网 时间:2024/05/21 10:48
粒子群算法,即PSO,关于PSO的入门介绍请参看博文:http://www.cnblogs.com/maybe2030/p/5043356.html
PSO的核心是如下两个公式:
V表示粒子的速度,X表示粒子的位置,Pi为当前粒子找到的最优位置,Pj为整个粒子群找到的最优位置。c1、c2为正常数,称为加速因子,一般取0-1之间的某个值。w称为惯性因子,其取值直接关系到PSO的搜索能力,若w取值较大,则PSO搜索范围增加,有比较强的全局搜索能力,若w取值较小,则PSO的搜索范围变小,局部搜索增强。w的取值可以固定在0-1之间的某个值,也可以根据要解决的问题模型自行设计,进行线性变换或正态分布变换等。rand()为[0, 1]之间的随机数。PSO算法就是根据这两个公式,不断迭代、更新整个粒子群的速度、位置信息,直到迭代完成为止。
以下是PSO算法的总流程:
这里还是以01背包问题为例,介绍PSO算法在求解背包问题上的应用。关于背包问题的描述,请参看我的另一篇博文遗传算法--背包问题。
代码如下:(scala语言实现)
package main.scalaimport scala.collection.mutable.ArrayBufferimport scala.io.Sourceimport scala.util.Random// 种群中个体定义class Individual(indivi_bit:Int){ var individual_bit = indivi_bit // 个体中的位数,即背包中物品的数量 var knapsack_data:ArrayBuffer[(Int, Int)] = null // 背包数据的引用 var p_vec = new Array[Int](individual_bit) // 当前位置向量 var v_vec = new Array[Double](individual_bit) // 当前速度向量 var weight_all = 0 // 当前总重量 var fitness = 0 // 当前适应度值 var p_best:Array[Int] = new Array[Int](individual_bit) // 当前个体搜索到的最优位置信息 var best_fitness = 0 // 当前个体搜索到的最优位置的适应度值 var best_fitness_weight = 0 // 当前个体搜索到的最优位置的适应度值对应的总重量 var weight_limit = 1000 // 限重 def this(data:ArrayBuffer[(Int, Int)]) { this(data.length) this.knapsack_data = data this.init } // 计算适应度 def calcFitness() = { weight_all = 0 fitness = 0 for(i <- 0 until individual_bit) { p_vec(i) match { case 0 => case _ => { weight_all = weight_all + knapsack_data(i)._1 fitness = fitness + knapsack_data(i)._2 } } } if(weight_all > weight_limit) fitness = 0 } // 初始化 def init = { for(i <- 0 until individual_bit) { p_vec(i) = new Random().nextInt(2) v_vec(i) = new Random().nextDouble() } p_vec.copyToArray(p_best) calcFitness() best_fitness = fitness best_fitness_weight = weight_all } def updateCurBestInfo() = { if(fitness > best_fitness) { best_fitness = fitness best_fitness_weight = weight_all p_vec.copyToArray(p_best) } } // 复制个体 def copyTo(to:Individual) = { to.individual_bit = this.individual_bit to.knapsack_data = this.knapsack_data to.weight_all = this.weight_all to.fitness = this.fitness to.best_fitness = this.best_fitness to.best_fitness_weight = this.best_fitness_weight to.weight_limit = this.weight_limit if(to.p_vec == null) to.p_vec = this.p_vec.clone() else this.p_vec.copyToArray(to.p_vec) if(to.v_vec == null) to.v_vec = this.v_vec.clone() else this.v_vec.copyToArray(to.v_vec) if(to.p_best == null) to.p_best = this.p_best.clone() else this.p_best.copyToArray(to.p_best) }}object PSODemo{ val KNAPSACK_DATA_FILE = "knapsack.data" val PSO_NUM = 20 // 种群数 val ITERATE_NUM = 30 // 迭代计算次数 val w = 0.8 // 惯性系数 val c1 = 0.7 // 加速因子1 val c2 = 0.7 // 加速因子2 var gbest:Individual = null // 最优个体 // 读取背包问题的初始数据 def readKnapsackData(path:String) = { val list = new ArrayBuffer[(Int, Int)]() for(line <- Source.fromFile(path).getLines()) { val strs = line.split(" ") list += ((strs(0).toInt, strs(1).toInt)) } list } // 初始化粒子群 def InitPsoPopulation(data:ArrayBuffer[(Int, Int)]) = { val population = new Array[Individual](PSO_NUM) for(i <- 0 until PSO_NUM) { population(i) = new Individual(data) } population } // 更新粒子群中的最优个体 def updateBestIndividual(pso:Array[Individual]) = { var population_best_fitness = 0 var individual_id = -1 for(i <- 0 until PSO_NUM) { if(population_best_fitness < pso(i).best_fitness) { population_best_fitness = pso(i).best_fitness individual_id = i } } if(individual_id >= 0) pso(individual_id).copyTo(gbest) } // 更新粒子群中的每个个体 def updateEachIndividual(pso:Array[Individual]) = { for(i <- 0 until PSO_NUM) { val v_new = pso(i).v_vec.clone() // 新的速度信息 val p_new = pso(i).p_vec.clone() // 新的位置信息 val r1 = new Random().nextDouble() val r2 = new Random().nextDouble() for(j <- 0 until pso(i).individual_bit) { v_new(j) = w * pso(i).v_vec(j) + c1 * r1 * (pso(i).p_best(j) - pso(i).p_vec(j)) + c2 * r2 * (gbest.p_best(j) - pso(i).p_vec(j)) val p_tmp = pso(i).p_vec(j) + v_new(j) if(p_tmp < 0.5) p_new(j) = 0 else p_new(j) = 1 } v_new.copyToArray(pso(i).v_vec) p_new.copyToArray(pso(i).p_vec) // 计算适应度 pso(i).calcFitness() // 更新该个体当前最优位置信息 pso(i).updateCurBestInfo() } } def main(args: Array[String]):Unit = { // 每个元素为 (weight, value) val knapsack_data = readKnapsackData(KNAPSACK_DATA_FILE) gbest = new Individual(knapsack_data.length) // 初始化粒子群,每个个体为 (位置向量, 速度向量) val pso = InitPsoPopulation(knapsack_data) // 开始迭代计算 for(i <- 0 to ITERATE_NUM) { // 更新最优个体 updateBestIndividual(pso) println("第" + i + "代,最优个体:" + gbest.p_best.mkString(",") + ",总重量:" + gbest.best_fitness_weight + ",总价值:" + gbest.best_fitness) // 更新每个个体的位置信息、速度信息 updateEachIndividual(pso) } }}
每一行数据代表一个物品,其中,第1个值表示物品的重量weight,第2个值表示物品的价值value,背包最大承重量为1000。
源码就是整个PSO流程的最好说明,源码中已给出了比较详尽的注释。在PSODemo.updateEachIndividual()接口中,更新种群中每个粒子的速度、位置信息,其计算方式即按照上述的两个公式来计算。
这里有一个问题,PSO在解决背包问题时,用粒子的位置向量表示背包问题的一个解,即每个粒子的位置向量是一个01数组,其中,数组的每个元素取值只有取0或取1两种情况,但根据公式更新时,位置+速度后的结果可能是0.x或1.x,甚至有可能是-0.x,出现这种情况时,需要把连续的取值给离散化为取0、或取1。代码中我采用了一种比较粗暴的方式,若计算结果<0.5,取0,否则取1。这种离散化方式其实效果很差,求解时收敛很快,很容易陷入局部最优。当然,也可以采用其他的离散化方式来改善PSO算法的性能,比如进行异或、同或等,这就要具体问题具体分析了。从这也可以看出,PSO算法比较适合求解连续性优化问题,如函数优化等,这种离散化问题用PSO求解不是很合适。
- 粒子群算法--背包问题
- 粒子群算法总结+背包问题
- 粒子群算法解决TSP问题
- 粒子群算法求解优化问题(MATLAB)
- 粒子群算法解决函数优化问题
- 蚁群算法--背包问题
- 粒子群PSO算法
- 粒子群算法介绍
- 粒子群算法(PSO)
- 粒子群优化算法
- pso粒子群算法
- PSO 粒子群算法
- 粒子群优化算法
- 粒子群优化算法
- 粒子群优化算法
- 粒子群优化算法
- 粒子群算法
- 粒子群算法二
- cxf和spring整合出现的问题: com.sun.xml.internal.ws.fault.ServerSOAPFaultException: Client received SOAP Faul
- 解决ADB响应失败的N种方法!
- SuperTextView遇到的坑
- 20170611 JS实现数字反转
- STL sort 函数实现详解
- 粒子群算法--背包问题
- Tesseract OCR 引擎-概述
- Android -----有序广播
- 【DPDK】虚拟机开发环境配置
- Windows核心编程第二章笔记
- Android开发数据存储基础整理
- LeetCode-72. Edit Distance
- Multimodal Memory Modelling for Video Captioning
- poj-2757-最长上升子序列-C语言-动态规划入门