蚁群算法求解旅行商问题(附c和matlab源代码)

前几天写了个模拟退火算法的程序,然后又陆陆续续看了很多群智能算法,发现很多旅行商问题都采用蚁群算法来求解,于是开始写蚁群算法的模板。网上关于蚁群算法的理论很多就不再这里赘述了,下面直接上代码和进行简单的比较。

c代码:

1 #ifndef _CITY_H
2 #define _CITY_H
3 struct CITY
4 {
5     int id;
6     double x, y;
7 };
8 #endif // !_CITY_H

CITY.h

 1 #ifndef _OPTION_H
 2 #define _OPTION_H
 3 const int MAXN = 210;
 4 int m = 50; /* 蚂蚁数量 */
 5 double Q = 10;  /* 常系数 */
 6 double alpha = 1;  /* 信息素重要程度因子 */
 7 double beta = 5;   /* 启发函数重要程度因子 */
 8 double rho = 0.2;  /* 信息素挥发因子 */
 9 int iter = 1;  /* 迭代次数初值 */
10 int iter_max = 200;  /* 最大迭代次数 */
11 #endif // !_OPTION_H

OPTION.h

  1 #include <cstdio>
  2 #include <cmath>
  3 #include <ctime>
  4 #include <set>
  5 #include <vector>
  6 #include <windows.h>
  7 #include "CITY.h"
  8 #include "OPTION.h"
  9 using namespace std;
 10
 11 const double eps = 1e-4;
 12 const double inf = (1 << 30);
 13 const double rand_max = 32767;
 14 CITY    citys[MAXN];           /* 保存城市坐标和编号信息 */
 15 int     city_count = 0;        /* 保存城市数量 */
 16 double  D[MAXN][MAXN];           /* 城市之间的距离矩阵 */
 17 double  Heu_F[MAXN][MAXN];     /* 启发函数,Heu_F = 1./D (D为保存城市间距离的矩阵) */
 18 double  Tau[MAXN][MAXN];       /* 信息素矩阵 */
 19 int     Table[MAXN][MAXN];     /* 路径记录表 */
 20 int        Route_best[MAXN][MAXN];/* 各代最佳路径 */
 21 double  Length_best[MAXN];     /* 各代最佳路径的长度 */
 22 char    *file = NULL;          /* 数据文件 */
 23 time_t  st, ed;                   /* 记录开始结束时间 */
 24
 25 void put_help();
 26 void input();
 27 void cal_dist();
 28 void travel();
 29 int gen_int();      /* 随机生成城市编号 */
 30 double gen_rand();  /* 生成0~1之间的随机数 */
 31 void show_result();
 32
 33 int main(int argc, char **argv)
 34 {
 35
 36     srand(static_cast<int>(time(NULL)));
 37     if (argc == 1) {
 38         put_help();
 39         goto end;
 40     }
 41     /* get the parameters */
 42     file = argv[1];
 43     if (argc > 2)
 44     {
 45         for (int i = 2; i < argc; i += 2) {
 46             if (strcmp(argv[i], "-m") == 0) {
 47                 m = atoi(argv[i + 1]);
 48             }
 49             else if (strcmp(argv[i], "-Q") == 0) {
 50                 Q = atof(argv[i + 1]);
 51             }
 52             else if (strcmp(argv[i], "-a") == 0){
 53                 alpha = atof(argv[i + 1]);
 54             }
 55             else if (strcmp(argv[i], "-b") == 0) {
 56                 beta = atof(argv[i + 1]);
 57             }
 58             else if (strcmp(argv[i], "-r") == 0) {
 59                 rho = atof(argv[i + 1]);
 60             }
 61             else if (strcmp(argv[i], "-i") == 0) {
 62                 iter_max = atoi(argv[i + 1]);
 63             }
 64         }
 65     }
 66     file = argv[1];
 67     freopen(file, "r", stdin);
 68     input();
 69     cal_dist();
 70     st = clock();
 71     travel();
 72     ed = clock();
 73     show_result();
 74     end:
 75     return 0;
 76 }
 77
 78 void put_help()
 79 {
 80     puts("用法: ACA 数据文件绝对路径 <参数设置> ");
 81     puts("格式: ACA C:\\Users\\Administrator\\Desktop\\data.txt");
 82     puts("输入数据格式: 每行为城市的坐标");
 83     puts("  1 2");
 84     puts("  3 1");
 85     puts("  5 6");
 86     puts("参数选项 ");
 87     puts("  -m <int>          蚂蚁数量, 默认 50");
 88     puts("  -Q <double>       常系数, 默认 10");
 89     puts("  -a <double>       信息素重要程度因子, 默认1");
 90     puts("  -b <double>       启发函数重要程度因子, 默认5");
 91     puts("  -r <double>       信息素挥发因子, 默认0.2");
 92     puts("  -i <int  >        最大迭代次数, 默认200");
 93 }
 94
 95 void input()
 96 {
 97     double x, y;
 98     while (~scanf("%lf%lf", &x, &y)) {
 99         ++city_count;
100         citys[city_count].id = city_count;
101         citys[city_count].x = x;
102         citys[city_count].y = y;
103     }
104     puts("Data input success!");
105 }
106
107 void cal_dist()
108 {
109     for (int i = 1; i <= city_count; ++i) {
110         for (int j = 1; j <= city_count; ++j) {
111             D[i][j] = sqrt((citys[i].x - citys[j].x)*(citys[i].x - citys[j].x)
112                 + (citys[i].y - citys[j].y)*(citys[i].y - citys[j].y));
113             if (i == j)
114                 D[i][j] = eps;
115             Heu_F[i][j] = 1 / D[i][j];
116         }
117     }
118 }
119
120 int gen_int()
121 {
122     return rand() % city_count + 1;
123 }
124
125 void travel()
126 {
127     for (int i = 1; i <= city_count; ++i)
128         for (int j = 1; j <= city_count; ++j)
129             Tau[i][j] = 1;
130     while (iter <= iter_max) {
131         /* 随机产生各个蚂蚁的起点城市 */
132         for (int i = 1; i <= m; ++i)
133             Table[i][1] = gen_int();
134         /* 逐个蚂蚁路径选择 */
135         for (int i = 1; i <= m; ++i) {
136             set<int> allow; /* 待访问城市集合 */
137             vector<int> v_tabu;  /* 禁忌表 */
138             for (int k = 1; k <= city_count; ++k) {
139                 if (k == Table[i][1])
140                     v_tabu.push_back(k);
141                 else
142                     allow.insert(k);
143             }
144             for (int j = 2; j <= city_count; ++j) {
145                 double P[MAXN];
146                 P[0] = 0;
147                 int  allow_count = allow.size();
148                 auto k_it = allow.begin();
149                 auto tabu_it = v_tabu.end();
150                 --tabu_it;
151                 /* 计算城市间转移概率 */
152                 for (int k = 1; k <= allow_count; ++k) {
153                     P[k] = pow(Tau[*tabu_it][*k_it],alpha)
154                         *pow(Heu_F[*tabu_it][*k_it],beta);
155                     P[k] += P[k - 1];
156                     ++k_it;
157                 }
158                 /* 轮盘赌法选择下一个访问城市 */
159                 for (int k = 1; k <= allow_count; ++k) {
160                     P[k] /= P[allow_count];
161                 }
162                 double t_rand = gen_rand();
163                 int k;
164                 for (k = 1; k <= allow_count; ++k) {
165                     if (P[k] >= t_rand)
166                         break;
167                 }
168                 auto allow_it = allow.begin();
169                 int cnt = 0;
170                 while (cnt < k-1) {
171                     ++cnt;
172                     ++allow_it;
173                 }
174                 Table[i][j] = *allow_it;
175                 v_tabu.push_back(Table[i][j]);
176                 allow.erase(Table[i][j]);
177             }
178         }
179         /* 计算每个蚂蚁的路径距离 */
180         double Length[MAXN];
181         memset(Length, 0, sizeof Length);
182         for (int i = 1; i <= m; ++i) {
183             int Route[MAXN];
184             for (int j = 1; j <= city_count; ++j) {
185                 Route[j] = Table[i][j];
186             }
187             for (int j = 1; j <= city_count - 1; ++j) {
188                 Length[i] = Length[i] + D[Route[j]][Route[j + 1]];
189             }
190             Length[i] = Length[i] + D[Route[city_count]][Route[1]];
191         }
192         /* 计算最短路径距离和求最短路径 */
193         if (iter == 1) {
194             double min_Length = static_cast<double>(inf);
195             for (int i = 1; i <= city_count; ++i) {
196                 if (Length[i] < min_Length) {
197                     min_Length = Length[i];
198                     for (int j = 1; j <= city_count; ++j) {
199                         Route_best[iter][j] = Table[i][j];
200                     }
201                 }
202             }
203             Length_best[iter] = min_Length;
204         }
205         else {
206             double min_Length = static_cast<double>(inf);
207             for (int i = 1; i <= city_count; ++i) {
208                 if (Length[i] < min_Length) {
209                     min_Length = Length[i];
210                     for (int j = 1; j <= city_count; ++j) {
211                         Route_best[iter][j] = Table[i][j];
212                     }
213                 }
214             }
215             Length_best[iter] = min_Length;
216             if (Length_best[iter-1] < min_Length) {
217                 Length_best[iter] = Length_best[iter - 1];
218                 for (int j = 1; j <= city_count; ++j) {
219                     Route_best[iter][j] = Route_best[iter-1][j];
220                 }
221             }
222         }
223         /* 更新信息素 */
224         double Delta_Tau[MAXN][MAXN];
225         for (int i = 1; i <= m; ++i) {
226             for (int j = 1; j <= city_count - 1; ++j) {
227                 Delta_Tau[Table[i][j]][Table[i][j + 1]]
228                     = Delta_Tau[Table[i][j]][Table[i][j + 1]] + Q / Length[i];
229             }
230             Delta_Tau[Table[i][city_count]][Table[i][1]]
231                 = Delta_Tau[Table[i][city_count]][Table[i][1]] + Q / Length[i];
232         }
233         for (int i = 1; i <= city_count; ++i)
234             for (int j = 1; j <= city_count; ++j)
235                 Tau[i][j] = (1 - rho)*Tau[i][j] + Delta_Tau[i][j];
236         /* 迭代次数加1,清空路径记录表 */
237         ++iter;
238         memset(Table, 0, sizeof Table);
239     }
240 }
241
242 double gen_rand()
243 {
244     return rand() / rand_max;
245 }
246
247 void show_result()
248 {
249     printf("求得的最短路径长度为: %lf\n", Length_best[iter_max]);
250     printf("最短路径为: ");
251     for (int i = 1; i <= city_count; ++i) {
252         printf("%d ", Route_best[iter_max][i]);
253     }
254     puts("");
255     printf("程序运行时间: %lf s\n", static_cast<double>(ed - st) / CLOCKS_PER_SEC);
256 }

main.cpp

matlab代码:

  1 %% 清空环境变量
  2 clear all
  3 clc
  4 %% 导入数据
  5 citys = [1304        2312
  6         3639        1315
  7         4177        2244
  8         3712        1399
  9         3488        1535
 10         3326        1556
 11         3238        1229
 12         4196        1004
 13         4312         790
 14         4386         570
 15         3007        1970
 16         2562        1756
 17         2788        1491
 18         2381        1676
 19         1332         695
 20         3715        1678
 21         3918        2179
 22         4061        2370
 23         3780        2212
 24         3676        2578
 25         4029        2838
 26         4263        2931
 27         3429        1908
 28         3507        2367
 29         3394        2643
 30         3439        3201
 31         2935        3240
 32         3140        3550
 33         2545        2357
 34         2778        2826
 35         2370        2975
 36 ];
 37 %% 计算城市间相互距离
 38 n = size(citys,1);
 39 D = zeros(n,n);
 40 for i = 1:n
 41     for j = 1:n
 42         if i ~= j
 43             D(i,j) = sqrt(sum((citys(i,:) - citys(j,:)).^2));
 44         else
 45             D(i,j) = 1e-4;
 46         end
 47     end
 48 end
 49 %% 初始化参数
 50 m = 50;                              % 蚂蚁数量
 51 alpha = 1;                           % 信息素重要程度因子
 52 beta = 5;                            % 启发函数重要程度因子
 53 rho = 0.2;                           % 信息素挥发因子
 54 Q = 1;                               % 常系数
 55 Eta = 1./D;                          % 启发函数
 56 Tau = ones(n,n);                     % 信息素矩阵
 57 Table = zeros(m,n);                  % 路径记录表
 58 iter = 1;                            % 迭代次数初值
 59 iter_max = 200;                      % 最大迭代次数
 60 Route_best = zeros(iter_max,n);      % 各代最佳路径
 61 Length_best = zeros(iter_max,1);     % 各代最佳路径的长度
 62 Length_ave = zeros(iter_max,1);      % 各代路径的平均长度
 63 %% 迭代寻找最佳路径
 64 tic
 65 while iter <= iter_max
 66     % 随机产生各个蚂蚁的起点城市
 67       start = zeros(m,1);
 68       for i = 1:m
 69           temp = randperm(n);
 70           start(i) = temp(1);
 71       end
 72       Table(:,1) = start;
 73       % 构建解空间
 74       citys_index = 1:n;
 75       % 逐个蚂蚁路径选择
 76       for i = 1:m
 77           % 逐个城市路径选择
 78          for j = 2:n
 79              tabu = Table(i,1:(j - 1));           % 已访问的城市集合(禁忌表)
 80              allow_index = ~ismember(citys_index,tabu);
 81              allow = citys_index(allow_index);  % 待访问的城市集合
 82              P = allow;
 83              % 计算城市间转移概率
 84              for k = 1:length(allow)
 85                  P(k) = Tau(tabu(end),allow(k))^alpha * Eta(tabu(end),allow(k))^beta;
 86              end
 87              P = P/sum(P);
 88              % 轮盘赌法选择下一个访问城市
 89              Pc = cumsum(P);
 90             target_index = find(Pc >= rand);
 91             target = allow(target_index(1));
 92             Table(i,j) = target;
 93          end
 94       end
 95       % 计算各个蚂蚁的路径距离
 96       Length = zeros(m,1);
 97       for i = 1:m
 98           Route = Table(i,:);
 99           for j = 1:(n - 1)
100               Length(i) = Length(i) + D(Route(j),Route(j + 1));
101           end
102           Length(i) = Length(i) + D(Route(n),Route(1));
103       end
104       % 计算最短路径距离及平均距离
105       if iter == 1
106           [min_Length,min_index] = min(Length);
107           Length_best(iter) = min_Length;
108           Length_ave(iter) = mean(Length);
109           Route_best(iter,:) = Table(min_index,:);
110       else
111           [min_Length,min_index] = min(Length);
112           Length_best(iter) = min(Length_best(iter - 1),min_Length);
113           Length_ave(iter) = mean(Length);
114           if Length_best(iter) == min_Length
115               Route_best(iter,:) = Table(min_index,:);
116           else
117               Route_best(iter,:) = Route_best((iter-1),:);
118           end
119       end
120       % 更新信息素
121       Delta_Tau = zeros(n,n);
122       % 逐个蚂蚁计算
123       for i = 1:m
124           % 逐个城市计算
125           for j = 1:(n - 1)
126               Delta_Tau(Table(i,j),Table(i,j+1)) = Delta_Tau(Table(i,j),Table(i,j+1)) + Q/Length(i);
127           end
128           Delta_Tau(Table(i,n),Table(i,1)) = Delta_Tau(Table(i,n),Table(i,1)) + Q/Length(i);
129       end
130       Tau = (1-rho) * Tau + Delta_Tau;
131     % 迭代次数加1,清空路径记录表
132     iter = iter + 1;
133     Table = zeros(m,n);
134 end
135 toc
136 %% 结果显示
137 [Shortest_Length,index] = min(Length_best);
138 Shortest_Route = Route_best(index,:);
139 disp([‘最短距离:‘ num2str(Shortest_Length)]);
140 disp([‘最短路径:‘ num2str([Shortest_Route Shortest_Route(1)])]);
141 %% 绘图
142 figure(1)
143 plot([citys(Shortest_Route,1);citys(Shortest_Route(1),1)],...
144      [citys(Shortest_Route,2);citys(Shortest_Route(1),2)],‘o-‘);
145 grid on
146 for i = 1:size(citys,1)
147     text(citys(i,1),citys(i,2),[‘   ‘ num2str(i)]);
148 end
149 text(citys(Shortest_Route(1),1),citys(Shortest_Route(1),2),‘       起点‘);
150 text(citys(Shortest_Route(end),1),citys(Shortest_Route(end),2),‘       终点‘);
151 xlabel(‘城市位置横坐标‘)
152 ylabel(‘城市位置纵坐标‘)
153 title([‘蚁群算法优化路径(最短距离:‘ num2str(Shortest_Length) ‘)‘])
154 figure(2)
155 plot(1:iter_max,Length_best,‘b‘,1:iter_max,Length_ave,‘r:‘)
156 legend(‘最短距离‘,‘平均距离‘)
157 xlabel(‘迭代次数‘)
158 ylabel(‘距离‘)
159 title(‘各代最短距离与平均距离对比‘)

ACA.m

【运行结果比较】

测试数据选用和模拟退火的测试相同:

1304        2312
3639        1315
4177        2244
3712        1399
3488        1535
3326        1556
3238        1229
4196        1004
4312         790
4386         570
3007        1970
2562        1756
2788        1491
2381        1676
1332         695
3715        1678
3918        2179
4061        2370
3780        2212
3676        2578
4029        2838
4263        2931
3429        1908
3507        2367
3394        2643
3439        3201
2935        3240
3140        3550
2545        2357
2778        2826
2370        2975

c版ACA:

可选择设置的相关参数:

运行结果:

matlab版ACA:

运行结果:

从时间效率上看,c运行时间比matlab的运行时间少了2/3,在运行之前就想到了,也没什么惊讶的,而且代码被我写搓了,继续优化可以更快。。。

然而多次运行c版的程序发现它貌似比matlab更容易陷入局部最优跳不出来,求得的路径长度基本都比matlab求出的路径长(。。。),百思不得其解,唯一能想到的是c++的伪随机数还不够“随机”导致陷入局部最优,还希望有大神解答下。

时间: 2024-11-03 14:29:06

蚁群算法求解旅行商问题(附c和matlab源代码)的相关文章

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

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

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

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

利用HTML5 Canvas和Javascript实现的蚁群算法求解TSP问题演示

HTML5提供了Canvas对象,为绘图应用提供了便利. Javascript可运行于浏览器中, 而不需要安装特定的编译器: 基于HTML5和Javascript语言, 可随时编写应用, 为算法测试带来便利. 针对TSP问题, 编写了Ant colony algorithm, 用于演示该算法, tsp_ant_colony_algorithm.html代码如下: <html> <head> <meta charset = "utf-8" / > &l

蚁群算法求解TSP问题

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

蚁群算法简介及应用

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

智能算法---蚁群算法

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

蚁群算法和简要matlab来源

1 蚁群算法原理 从1991由意大利学者 M. Dorigo,V. Maniezzo 和 A. Colorni 通过模拟蚁群觅食行为提出了一种基于群体的模拟进化算法--蚁群优化.极大关注,蚁群算法的特点: ① 其原理是一种正反馈机制或称增强型学习系统; 它通过[最优路径上蚂蚁数量的添加→信息素强度添加→后来蚂蚁选择概率增大→最优路径上蚂蚁数量更大添加]达到终于收敛于最优路径上L ② 它是一种通用型随机优化方法, 它吸收了蚂蚁的行为特(内在搜索机制) , 它是使用人工蚂蚁仿真(也称蚂蚁系统) 来求

智能算法:蚁群算法

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

基于自适应蚁群算法的无人飞行器航迹规划

为求解无人飞行器航迹规划问题,提出自适应蚁群算法,区别于标准蚁群算法的全部搜索模式,该算法采用局部搜索模式.首先根据起始节点与目标节点的相对位置 关系选择相应的搜索模式,然后计算各个待选节点的转移概率,最后按照轮盘赌规则选择下一个节点.仿真结果表明,自适应蚁群算法具有搜寻节点数少.速度快等 优点,在降低了航迹代价的同时,减小了计算时间.此外,自适应蚁群算法可以避免奇异航迹段的出现,从而保证所获的航迹实际可飞,表明所提算法整体性能明显 较标准蚁群算法优异. 此资料( 基于自适应蚁群算法的无人飞行器