蚁群算法--背包问题
来源:互联网 发布:缩小毛孔的精华 知乎 编辑:程序博客网 时间:2024/05/16 11:34
蚁群算法,简称ACO,其入门性介绍请参看博文:http://www.cnblogs.com/Leo_wl/p/5665715.html
ACO在提出之时主要用来解决旅行商问题(即TSP,不清楚的可以百度TSP)。旅行商问题也是一个经典的NP完全问题,比较传统的解法有贪心算法等,在问题规模增长时,传统算法的求解效率大大降低。ACO的灵感来源于蚂蚁搜寻食物的过程,对于寻路问题有天然的优势,在旅行商问题上的成功应用证明了这点。
ACO最核心的两个公式如下:
第一个公式计算蚂蚁选择下一个要去的地点的概率。第二个公式计算蚂蚁走过每个地点后,每个地点上残留的信息素。对于不同的问题模型,这两个公式中参数含义不一样,具体计算时,过程相似,细节不同。
本文主要讨论ACO应用在求解简单的01背包问题上。关于背包问题的描述,参看我的博文遗传算法--背包问题。
说了这么多,直接上代码,代码就是最好的讲解:(scala语言实现)
package main.scalaimport scala.collection.mutable.HashSetimport scala.collection.mutable.ArrayBufferimport scala.io.Source// 定义蚂蚁class Ant(val knapsack_data:ArrayBuffer[(Int, Int)]){ val item_num = knapsack_data.length // 背包中物品数量 val iter_all_item_set = new HashSet[Int]() // 每次迭代所有物品的集合(均保留下标id) val iter_legal_selected_set = new HashSet[Int]() // 每次迭代所选的合法物品集合 var pheromones:Array[Double] = _ // 物品信息素值的引用 val LIMIT_WIGHT = 1000 // 背包的总重量限重 var iter_selected_weight = 0 // 每次迭代所选物品的总重量 var iter_selected_value = 0 // 每次迭代所选物品的总价值 def this(data:ArrayBuffer[(Int, Int)], pher:Array[Double]) = { this(data) pheromones = pher } // 根据信息素计算选择概率,选取下一个概率最大的爬行位置(物品) private def select() = { var sum = 0.0 for(id <- iter_all_item_set) { sum += (pheromones(id) * knapsack_data(id)._2 / knapsack_data(id)._1) } // 每个物品被选中的概率集 (概率,下标id) val probabys = iter_all_item_set.map(id => { val Pj = (pheromones(id) * knapsack_data(id)._2.toDouble / knapsack_data(id)._1) / sum (Pj, id) }).toArray var max = (0.0, 0) for(i <- probabys) { if(i._1 > max._1) { max = i } } max._2 } // 每次迭代前的处理工作 def before_each_iter() = { iter_selected_weight = 0 iter_selected_value = 0 iter_all_item_set.clear() iter_legal_selected_set.clear() for(i <- 0 until item_num) { iter_all_item_set += i } } // 蚂蚁爬行,从起始点开始,选取一条路径,即生成一个所选物品序列 def go() = { while(iter_all_item_set.nonEmpty) { // 选取下一个概率最大的物品 val pos = select() if(iter_selected_weight + knapsack_data(pos)._1 <= LIMIT_WIGHT) { iter_selected_weight += knapsack_data(pos)._1 iter_selected_value += knapsack_data(pos)._2 // 若不超过总重量,加入到合法序列中 iter_legal_selected_set += pos } iter_all_item_set -= pos } } def resultString() = { val ret = new ArrayBuffer[Int]() for(i <- 0 until item_num) { ret += { if(iter_legal_selected_set(i)) 1 else 0 } } ret.mkString(",") }}object ACODemo{ val KNAPSACK_DATA_FILE = "knapsack.data" val INIT_PHERO = 1.1 // 每个物品上信息素初始值 val ITER_RESERVE_PHERO_RATE = 0.7 // 每次迭代每个物品上信息素的保留率 val ANTS_NUM = 20 // 蚂蚁数量 val ITER_NUM = 30 // 迭代计算次数 // 读取背包问题的初始数据 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 initAnts(data:ArrayBuffer[(Int, Int)], pher:Array[Double]) = { val _ants = new ArrayBuffer[Ant]() for(i <- 0 until ANTS_NUM) { _ants += new Ant(data, pher) } _ants } // 找出最优的蚂蚁个体 def findBestAnt(ants:ArrayBuffer[Ant]) = { var best = ants(0) for(ant <- ants) if(ant.iter_selected_value > best.iter_selected_value) best = ant best } // 更新所有物品的信息素 def updatePheromones(pheromones:Array[Double], ants:ArrayBuffer[Ant], data:ArrayBuffer[(Int, Int)]) = { for(i <- 0 until pheromones.length) { // 计算每个物品的信息素增量 var increment = 0.0 for(ant <- ants) { val delta = { if(ant.iter_legal_selected_set(i)) data(i)._2.toDouble / ant.iter_selected_value else 0.0 } increment += delta } // 更新该物品的信息素 pheromones(i) = ITER_RESERVE_PHERO_RATE * pheromones(i) + increment } } def main(args: Array[String]) = { // 背包数据,每个元素为(weight value) val data = readKnapsackData(KNAPSACK_DATA_FILE) val pheromones = Array.fill(data.length)(INIT_PHERO) // 所有物品的信息素值 val ants = initAnts(data, pheromones) for(i <- 0 until ITER_NUM) { for(j <- 0 until ANTS_NUM) { ants(j).before_each_iter() ants(j).go() } val best_ant = findBestAnt(ants) println("第" + i + "代,总重量:" + best_ant.iter_selected_weight + ",总价值:" + best_ant.iter_selected_value + ",物品序列:" + best_ant.resultString()) updatePheromones(pheromones, ants, data) } }}
首先从文件“knapsack.data”中读取背包物品数据,背包物品的数据组织方式参看我另一篇博文粒子群算法--背包问题。然后初始化物品上的全局信息素、初始化蚁群,接着开始不断的迭代计算,直到迭代结束。
如何设计选择概率的计算方式和信息素的更新方式,直接影响到ACO算法性能,优化ACO通常从这两方面入手。本文在计算物品的选择概率时,只针对未选物品,已选物品的概率均为0。在更新物品的信息素时,每只蚂蚁都会影响到该物品的信息素变化,只要蚂蚁的选择路径中加入了该物品,更新时都要考虑进去。
经测试,本文中的ACO处理01背包问题,拥有较快的解收敛速度,能够比较快速的找到一个优质解。
阅读全文
0 0
- 蚁群算法--背包问题
- 粒子群算法--背包问题
- 粒子群算法总结+背包问题
- 背包问题的算法
- 递归算法 背包问题
- “背包问题”的算法
- 背包问题的算法
- 背包问题的算法
- 背包问题的算法
- 背包问题的算法
- 背包问题的算法
- 背包问题的算法
- 背包问题的算法
- 背包问题的算法
- 背包问题的算法
- 背包问题的算法
- 背包问题的算法
- 背包问题的算法
- ZOJ--1048:Financial Management
- byte为什么要与上0xff?进行与int运算
- python的GUI编程(Tkinter库)(一)
- 从神经网络说起:深度学习初学者不可不知的25个术语和概念
- VS2015 中的MFC对话框动态布局
- 蚁群算法--背包问题
- SyntaxError missing) after argument list
- 使用Navicat实现MySQL数据库 表结构同步
- python写算法题:leetcode: 10. Regular Expression Matching
- Tomcat配置内存大小
- Java设计模式之 静态代理和动态代理
- FCN 全卷积网络训练
- 机器学习之支持向量机SVM
- dubbo-admin-2.5.4在Jdk8和Tomcat8下部署失败的解决方案