ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

C++模拟蚁群(二)

C++模拟蚁群(二) 目录一、数学基础一蚂蚁选择方向概率模型二轮盘赌抽取随机数三六角格与世界坐标四微分思想绘制圆使用SDL库要求掌握二、关键方法实现一参数设置二蚂蚁嗅探函数三、效果展示四、源码下载上一篇文章C模拟蚁群一介绍了使用SDL2库模拟绘制蚁群在正方形地板格找食物的场景。本文继续介绍将地板格改成正六边形实现模拟蚁群核心算法没有变理解和实现上难度有所提升。一、数学基础一蚂蚁选择方向概率模型推荐看一篇文章数学建模学习笔记一蚁群算法(MATLAB)我设置的场景是六边形砖块平铺蚂蚁只有6个方向且距离都相等设为1于是我对该模型进行了简化P k τ k α ⋅ 1 ∑ k 1 4 τ k α ⋅ 1 P_k\frac{\tau_k^\alpha \cdot 1}{\sum_{k1}^4 \tau_k^\alpha \cdot 1}Pk​∑k14​τkα​⋅1τkα​⋅1​其中α \alphaα是信息素重要程度我在程序里设置成2τ \tauτ是该方向上邻近的砖块所含的信息素浓度,P k P_kPk​就是蚂蚁选择方向k的概率。二轮盘赌抽取随机数轮盘赌是一种以转动轮盘上滚动的小球最终落入编号格子来决定赌注输赢的随机赌博游戏。假设蚂蚁6个方向都能走信息素浓度最大的那个方向肯定走的概率大。假设我有1个100面的骰子而6个方向信息素之和为200怎么办呢我需要掷一次骰子必然要选一个方向就需要做一个映射即1 ∼ 2 → 1 3 ∼ 4 → 2... 199 ∼ 200 → 100 1\sim2 \to13\sim4\to2...199\sim200\to1001∼2→13∼4→2...199∼200→100如果我掷取的数是3落在方向0的区间就可以选择方向0若没有落在方向0的区间我就依次检查有没有落在其他方向的数字区间。这样通过掷一次骰子我就能实现按各方向的信息素浓度对应一定的根据来选择前进方向了。三六角格与世界坐标推荐看我写的另一篇文章SDL2画六角格地板选学部分要求掌握在此不作赘述。四微分思想绘制圆使用SDL库要求掌握SDL2库没有专门的绘制圆的函数需要自己实现。我实现了一个高效算法有兴趣的请移步SDL2高效画实心圆的算法一。二、关键方法实现一参数设置所有参数统一在ant.h头文件中定义:staticdouble_INFO_1000;staticdouble_INFO_MAX_10000;//单个地板信息素上限防止无限累加staticdouble_INFO_DELTA_50;//信息素递减staticdouble_IMPORTANT_1.2;//信息素浓度重要程度staticdouble_EVADE_0.75;//挥发保留系数_INFO_DELT_代表蚂蚁每移动一格信息素浓度递减的数值也就是蚂蚁走的越远信息素浓度越小直到没有这样可以有效防止蚂蚁陷入局部最优解。_INFO_蚂蚁分别在找到食物和把食物放回家这2种状态下可以补充信息素回到_INFO_的数值。_IMPORTANT_就是数学模型里的α \alphaα于是概率方程就变成了P k τ k 1.2 ∑ k 0 5 τ k 1.2 P_k\frac{\tau_k^{1.2}}{\sum_{k0}^5 \tau_k^{1.2}}Pk​∑k05​τk1.2​τk1.2​​_EVADE_气味消散系数定义蚂蚁每移动1格为进行一次气味挥发地面上的所有信息素会变成原来的0.75倍。二蚂蚁嗅探函数//蚂蚁嗅探方向voidAnt::sniffDirection(){intrandD[6]{-1,-1,-1,-1,-1,-1};//随机方向存储器doubleinfoD[6]{};//各方向上信息素浓度^adoubleinfoSum0;//各方向上总浓度^aintcur0;//随机方向存储器尺寸指针for(intd0;d6;d){//遍历6个方向找要可用方向if(!(Foods::position[this-sy*Nthis-sx]||(Home::xthis-sxHome::ythis-sy))d(this-direction3)%6)continue;//不能是反方向回头路if(this-directionToDestination(d)){randD[cur]d;//标记可行方向if(this-food){infoD[cur]pow(Ground::getInfoHome(this-dx,this-dy),_IMPORTANT_);}else{infoD[cur]pow(Ground::getInfoFood(this-dx,this-dy),_IMPORTANT_);}infoSuminfoD[cur];cur;};}//end of forassert(cur);//断言必有可行方向if(infoSum0.5){//周围没有探索过this-directionrandD[rand()%cur];this-directionToDestination(this-direction);//随机方向}else{//轮盘赌doublerrand()*1.0/RAND_MAX*infoSum;//制取infoSum以内随机数doublet0;for(inti0;icur;i){//直到选出方向tinfoD[i];if(rt){this-directionrandD[i];this-directionToDestination(this-direction);break;}}}}三、效果展示实测对于N*N个地板格大概2/3 * N * N只蚂蚁演示效果最好。请看我上传的视频模拟蚁群四、源码下载C模拟蚁群需使用SDL、SDL-image库
返回列表