蚁群算法(AntColonyOptimization,ACO)与TSP问题

对于小规模数据的TSP问题,我们可以使用动态规划快速的求解。

对于大规模数据的TSP问题,可以使用蚁群算法,模拟退火等近似算法进行求解。

蚁群算法是一种用来在图中寻找优化路径的机率型算法,最早Marco Dorigo提出。

它的灵感来源于蚁群寻找食物的过程,因为往往一只蚂蚁并没有太多“智能”的表现,而蚁群往往有“智能”的动作,比如大部分都趋向于食物

这是因为它们在移动的路径上会留下“信息素”,它们会更大概率沿着信息素更浓的路径行走,而路径越短,信息素就会越浓。

在解决TSP问题时,蚁群算法的流程如下:

  1. 初始化算法
  2. 派出一只蚂蚁,随机一个点作为蚂蚁的起点
  3. 对于蚂蚁当前所在的点,根据所有后继边的信息素浓度以及长度根据公式计算出访问每个后继节点的概率
  4. 用轮盘法随机出下一步走到哪个节点
  5. 重复3,4步,直到所有节点都访问了一次
  6. 计算回路长度,计算经过的边的信息素增加量
  7. 所有边上的信息素都会蒸发一定比例使算法收敛,增加经过的边的信息素
  8. 回到第2步,进行下一轮迭代

1.初始化问题:

初始化算法的时候需要设定一个初始信息素浓度,
需要注意这个浓度太大会导致新增的信息素没什么用,太小会导致过快结束算法,陷入局部最优解(类似于模拟退火的初始温度设定)
根据路径越长信息素浓度越低的规则,某只蚂蚁走过的回路长度为length的话,那么该蚂蚁对所走路径信息素浓度的贡献值为1/length
所以初始浓度设定为(M/length),M为蚂蚁数量

2.访问后继节点的概率计算:

算法的第三步需要计算当前节点到达后继节点的概率。

设定:α为信息素的重要程度,β为到达后继节点的边的长度,info[now][next]为信息素浓度,dist[now][next]为边长

那么到达一个后继节点的概率为: (info[now][next])^α/(dist[now][next])^β-----------公式一

假设蚂蚁现在处于A点,A点的后继节点为B,C,D

假设依据公式一所计算的结果,PB=0.5,PC=1.2,PD=0.2

那么:

选择节点B的概率为:pro_b = (PB)/(PB+PC+PD)=0.263

选择节点C的概率为:pro_c = (PC)/(PB+PC+PD)=0.632

选择节点D的概率为:pro_d = (PD)/(PB+PC+PD)=0.105

但是如果选择概率最高的节点作为下次抵达的节点,那么所有蚂蚁所作出的决策都是相同,这样就会失去探索新路径的机会,使得算法陷入停滞。

为了解决这个问题,我们采用轮盘法来做出抉择:

首先在[0,1]区间生成随机数RAND,然后进行迭代,RAND每次减去一个pro_*,当RAND减去一个pro_*后结果小于等于0,那么就选取节点*为下次抵达节点。

3.信号素的蒸发与增量

记录每只蚂蚁在跑图时,对于边edge[i][j]产生的信号素增量1/length[i][j],。当蚁群中的所以蚂蚁跑完后,对于边edge[i][j]的信号素浓度info[i][j]按照一定比例进行蒸发操作

设蒸发系数为rho(rho一般取值为0.5~0.8,蒸发系数越大收敛越快,同时准确率降低),那么修改后的info[i][j] = info[i][j]*(1-rho)

而后,将蚁群在跑图时,对于边edge[i][j]所产生的增量和phe[i][j]累加至info[i][j]

#include <bits/stdc++.h>
#include <iostream>
#define NS (25)
#define eps (1e-10)
#define M (80)
#define rho (0.5)  //信息素蒸发系数
#define alp (1)
#define bet (1)
#define Q (100)
#define Rand() ((double)rand() / RAND_MAX)

using namespace std;

int n, dis[NS][NS], path[NS], ans;

bool book[NS];

double info[NS][NS], phe[NS][NS], p[NS];

/*初始化过程:关于信息素的更新,
首先是初始化算法的时候需要设定一个初始信息素浓度,
这个浓度太大会导致新增的信息素没什么用,太小会导致过快结束算法,陷入局部最优解。
根据路径越长信息素浓度越低的规则,某只蚂蚁走过的回路长度为length的话,那么该蚂蚁对所走路径信息素浓度的贡献值为1/length
所以初始浓度设定为(Q*M/length)Q为常数用于精确计算结果,M为蚂蚁数量
*/
void init() //初始化算法
{
    int a = 1, len = 0;
    book[1] = 1;
    for (int c = 1; c < n; c += 1)
    {
        int mn = INT_MAX, nxt = 0;
        for (int i = 1; i <= n; i += 1)
            if (!book[i] && dis[a][i] < mn)
                mn = dis[a][i], nxt = i;
        len += dis[a][nxt], a = nxt, book[a] = 1;
    }
    len += dis[a][1], ans = len;
    for (int i = 1; i <= n; i += 1)
        for (int j = 1; j <= n; j += 1)
            info[i][j] = (double)Q * M / len;
}

inline double Pow(double a, int b)
{
    if(b==0)
        return 1;
    double res = 1;
    while(b > 0)
    {
        if(b & 1)
        {
            res = res*a;
        }
        a *= a;
        b /= 2;
    }
    return res;
}

/*
1.随机一个节点作为蚂蚁的起始节点
2.对于当前点,依据信息素浓度和与后继节点的边长计算访问该后继节点的概率
3.轮盘法随机出下一个到达的节点
4.重复2,3直到所有节点均被访问一次
*/
void run()
{
    int a = rand() % n + 1, s = a, len = 0;
    memset(book + 1, 0, sizeof(bool) * n), book[a] = 1;
    for (int c = 1; c < n; c += 1)
    {
        double tot = 0;
        for (int i = 1; i <= n; i += 1)
            if (book[i]) p[i] = 0;
            else
            {
                p[i] = Pow(info[a][i], alp) / Pow(dis[a][i], bet);
                tot += p[i];
            }
        if (tot < eps) return;
        for (int i = 1; i <= n; i += 1) p[i] /= tot;
        double r = Rand();
        for (int i = 1; i <= n; r -= p[i], i += 1)  //轮盘法
            if (!book[i] && r <= p[i])
            {
                len += dis[a][i], a = i, book[a] = 1, path[c] = i;
                break;
            }
    }
    // dt[][]为边上的信息素增量
    len += dis[a][s], phe[a][s] += (double)Q / len, ans = min(ans, len);
    for (int i = 1; i < n; i += 1)
        phe[s][path[i]] += (double)Q / len, s = path[i];
}

int main(int argc, char const* argv[])
{
    //cout << (0xfffffff) << endl;
    cin >> n;
    srand((unsigned) time(0));
    for (int i = 1; i <= n; i += 1)
        for (int j = 1; j <= n; j += 1)
            //IN(dis[i][j]);
            cin >> dis[i][j];
    init();
    for (int c = 1; c <= 700; c += 1)
    {
        for (int i = 1; i <= n; i += 1)
            for (int j = 1; j <= n; j += 1)
                phe[i][j] = 0;
        for (int j = 1; j <= M; j += 1) run();
        for (int i = 1; i <= n; i += 1)
            for (int j = 1; j <= n; j += 1)
                info[i][j] = info[i][j] * (1-rho) + phe[i][j];
    }
    printf("%d\n", ans);
    return 0;
}

原文地址:https://www.cnblogs.com/alan-W/p/12094215.html

时间: 2024-08-28 15:30:23

蚁群算法(AntColonyOptimization,ACO)与TSP问题的相关文章

蚁群算法解决TSP问题

一.论述 1.算法来源 蚁群算法的基本原理来源于自然界蚂蚁觅食的最短路径原理,根据昆虫学家的观察,发现自然界的蚂蚁虽然视觉不发达,但它可以在没有任何提示的情况下找到从食物源到巢穴的最短路径,并且能在环境发生变化(如原有路径上有了障碍物)后,自适应地搜索新的最佳路径. 2.单个蚂蚁寻找路径 正反馈: 单个的蚂蚁为了避免自己迷路,它在爬行时,同时也会释放一种特殊的分泌物--信息素(Pheromone),而且它也能觉察到一定范围内的其它蚂蚁所分泌的信息素,并由此影响它自己的行为.当一条路上的信息素越来

蚁群算法求解TSP问题

蚁群算法的第一个算法就是蚂蚁系统,而蚂蚁系统有三种基本模型分别是 蚁周模型.蚁密模型.蚁量模型.三种模型的实现大致相同,主要区别是在信息素 的更新方式上.在用蚂蚁系统解决T SP问题时,蚁量模型和蚁密模型是蚂蚁在构建 一条合法路径的过程中进行信息素的更新的,当蚂蚁走过一条边之后,就对该边进 行信息素的更新,即为局部更新方式.而蚁周模型是在所有蚂蚁都构建了一条合 法路径之后才对各边进行信息素更新的,也即全局更新方式. 并且这三种模型中蚂蚁在自己所走过的路线上释放的信息素的量也是有所 不同的,在蚁密

ACS蚁群算法求解对称TSP旅行商问题的JavaScript实现

本来以为在了解蚁群算法的基础上实现这道奇怪的算法题并不难,结果实际上大相径庭啊.做了近三天时间,才改成现在这能勉强拿的出手的模样.由于公式都是图片,暂且以截图代替那部分内容吧,mark一记. 蚁群算法解TSP问题的javascript实现 目录(又是神奇的手动目录..) 1 蚁群算法 (1)        蚁群AS算法简介 (2)        蚁群AS算法过程 (3)        蚁群AS算法TSP问题应用 (4)        蚁群算法应用于TSP步骤 2 蚁群系统(Ant Colony

智能算法---蚁群算法

智能算法---蚁群算法 1 蚁群算法及其基本思想 蚁群算法是一种智能优化算法,通过蚁群优化求解复杂问题,ACO在离散优化问题方面有比较好的优越性. 基本思想(以旅行商问题为例) 设置多只蚂蚁,分头并行搜索. 每只蚂蚁完成一次周游后,在行进的路上释放信息素,信息素量与解的质量成正比. 蚂蚁路径的选择根据信息素强度大小(初始信息素量设为相等),同时考虑两点之间的距离,采用随机的局部搜索策略.这使得距离较       短的边,其上的信息素量较大,后来的蚂蚁选择该边的概率也较大. 每只蚂蚁只能走合法路线

基本蚁群算法

//=====================================================================//基本蚁群算法源代码//使用的城市数据是eil51.tsp//=====================================================================// AO.cpp : 定义控制台应用程序的入口点.#pragma once#include "stdafx.h"#include <ios

蚁群算法简介及应用

蚂蚁几乎没有视力,但他们却能够在黑暗的世界中找到食物,而且能够找到一条从洞穴到食物的最短路径.它们是如何做到的呢? 简介 由来 蚁群算法是一种用来寻找优化路径的概率型算法.它由Marco Dorigo于1992年在他的博士论文中提出,其灵感来源于蚂蚁在寻找食物过程中发现路径的行为. 这种算法具有分布计算.信息正反馈和启发式搜索的特征,本质上是进化算法中的一种启发式全局优化算法. 思想 将蚁群算法应用于解决优化问题的基本思路为:用蚂蚁的行走路径表示待优化问题的可行解,整个蚂蚁群体的所有路径构成待优

智能算法:蚁群算法

作为一种现代智能算法,蚁群算法不需要任何先验知识,最初只是随机地选择搜索路径,随着对解空间的了解,搜索更加具有规律性,并逐渐得到全局最优解.目前,蚁群算法已被成功地应用于求解旅行商问题.车辆调度问题以及指派问题等... 求解TSP: %% 第22章 蚁群算法的优化计算——旅行商问题(TSP)优化 %% 清空环境变量 clear all clc %% 导入数据 load citys_data.mat %% 计算城市间相互距离 n = size(citys,1); D = zeros(n,n); f

蚁群算法求解迷宫最优路径问题

本段程序的基本思想是利用蚁群算法中的蚁周模型,来对全局的迷宫图进行信息素的跟新 和为每一只蚂蚁选择下一个方格. 一共会进行RcMax = 2000轮模拟(理论上模拟的次数越多结果 会越接近真实值),而在每一轮中会排除 M = 10只蚂蚁进行探路.同时在算法的回溯思想上采用的 是栈的数据结构来实现的.当栈最终为空时则表示无解.但同时这段程序的一缺点就是:由于我没在 算法中对每一轮的每只探路蚂蚁采用多线程的模式,所以整体的运行效率还不是很高.如读者有好的 思想或建议,请留言. #include<io

蚁群算法

今天真机调试的时候莫名其妙遇到了这样的一个问题: This product type must be built using a provisioning profile, however no provisioning profile matching both the identity "iPhone Developer" and the bundle identifier..... 具体如下图所示: 十分蛋疼, 发现不管是从网上下的demo, 还是自己的过程.凡事真机测试的时候都