蚁群算法求解旅行商问题(附c和matlab源代码)
前几天写了个模拟退火算法的程序,然后又陆陆续续看了很多群智能算法,发现很多旅行商问题都采用蚁群算法来求解,于是开始写蚁群算法的模板。网上关于蚁群算法的理论很多就不再这里赘述了,下面直接上代码和进行简单的比较。
c代码:
#ifndef _CITY_H
#define _CITY_H
struct CITY
{
int id;
double x, y;
};
#endif // !_CITY_H
CITY.h
#ifndef _OPTION_H #define _OPTION_H ; ; /* 蚂蚁数量 */ ; /* 常系数 */ ; /* 信息素重要程度因子 */ ; /* 启发函数重要程度因子 */ double rho = 0.2; /* 信息素挥发因子 */ ; /* 迭代次数初值 */ ; /* 最大迭代次数 */ #endif // !_OPTION_H
OPTION.h
#include <cstdio>
#include <cmath>
#include <ctime>
#include <set>
#include <vector>
#include <windows.h>
#include "CITY.h"
#include "OPTION.h"
using namespace std;
;
<< );
;
CITY citys[MAXN]; /* 保存城市坐标和编号信息 */
; /* 保存城市数量 */
double D[MAXN][MAXN]; /* 城市之间的距离矩阵 */
double Heu_F[MAXN][MAXN]; /* 启发函数,Heu_F = 1./D (D为保存城市间距离的矩阵) */
double Tau[MAXN][MAXN]; /* 信息素矩阵 */
int Table[MAXN][MAXN]; /* 路径记录表 */
int Route_best[MAXN][MAXN];/* 各代最佳路径 */
double Length_best[MAXN]; /* 各代最佳路径的长度 */
char *file = NULL; /* 数据文件 */
time_t st, ed; /* 记录开始结束时间 */
void put_help();
void input();
void cal_dist();
void travel();
int gen_int(); /* 随机生成城市编号 */
double gen_rand(); /* 生成0~1之间的随机数 */
void show_result();
int main(int argc, char **argv)
{
srand(static_cast<int>(time(NULL)));
) {
put_help();
goto end;
}
/* get the parameters */
file = argv[];
)
{
; i < argc; i += ) {
) {
m = atoi(argv[i + ]);
}
) {
Q = atof(argv[i + ]);
}
){
alpha = atof(argv[i + ]);
}
) {
beta = atof(argv[i + ]);
}
) {
rho = atof(argv[i + ]);
}
) {
iter_max = atoi(argv[i + ]);
}
}
}
file = argv[];
freopen(file, "r", stdin);
input();
cal_dist();
/*for (int i = 1; i <= city_count; ++i) {
for (int j = 1; j <= city_count; ++j) {
printf("%lf ", Heu_F[i][j]);
}
puts("");
}*/
st = clock();
travel();
ed = clock();
show_result();
end:
;
}
void put_help()
{
puts("用法: ACA 数据文件绝对路径 <参数设置> ");
puts("格式: ACA C:\\Users\\Administrator\\Desktop\\data.txt");
puts("输入数据格式: 每行为城市的坐标");
puts(" 1 2");
puts(" 3 1");
puts(" 5 6");
puts("参数选项 ");
puts(" -m <int> 蚂蚁数量, 默认 50");
puts(" -Q <double> 常系数, 默认 10");
puts(" -a <double> 信息素重要程度因子, 默认1");
puts(" -b <double> 启发函数重要程度因子, 默认5");
puts(" -r <double> 信息素挥发因子, 默认0.2");
puts(" -i <int > 最大迭代次数, 默认200");
}
void input()
{
double x, y;
while (~scanf("%lf%lf", &x, &y)) {
++city_count;
citys[city_count].id = city_count;
citys[city_count].x = x;
citys[city_count].y = y;
}
puts("Data input success!");
}
void cal_dist()
{
; i <= city_count; ++i) {
; j <= city_count; ++j) {
D[i][j] = sqrt((citys[i].x - citys[j].x)*(citys[i].x - citys[j].x)
+ (citys[i].y - citys[j].y)*(citys[i].y - citys[j].y));
if (i == j)
D[i][j] = eps;
Heu_F[i][j] = / D[i][j];
}
}
}
int gen_int()
{
;
}
void travel()
{
; i <= city_count; ++i)
; j <= city_count; ++j)
Tau[i][j] = ;
while (iter <= iter_max) {
/* 随机产生各个蚂蚁的起点城市 */
; i <= m; ++i)
Table[i][] = gen_int();
/* 逐个蚂蚁路径选择 */
; i <= m; ++i) {
set<int> allow; /* 待访问城市集合 */
vector<int> v_tabu; /* 禁忌表 */
; k <= city_count; ++k) {
])
v_tabu.push_back(k);
else
allow.insert(k);
}
; j <= city_count; ++j) {
double P[MAXN];
P[] = ;
int allow_count = allow.size();
auto k_it = allow.begin();
auto tabu_it = v_tabu.end();
--tabu_it;
/* 计算城市间转移概率 */
; k <= allow_count; ++k) {
P[k] = pow(Tau[*tabu_it][*k_it],alpha)
*pow(Heu_F[*tabu_it][*k_it],beta);
//printf("%lf %lf %d %d\n", Tau[*tabu_it][*k_it], Heu_F[*tabu_it][*k_it], *tabu_it, *k_it);
P[k] += P[k - ];
//printf("%lf\n", P[k]);
++k_it;
}
/* 轮盘赌法选择下一个访问城市 */
; k <= allow_count; ++k) {
P[k] /= P[allow_count];
}
double t_rand = gen_rand();
int k;
; k <= allow_count; ++k) {
if (P[k] >= t_rand)
break;
}
auto allow_it = allow.begin();
;
) {
++cnt;
++allow_it;
}
Table[i][j] = *allow_it;
v_tabu.push_back(Table[i][j]);
allow.erase(Table[i][j]);
}
}
/* 计算每个蚂蚁的路径距离 */
double Length[MAXN];
memset(Length, , sizeof Length);
; i <= m; ++i) {
int Route[MAXN];
; j <= city_count; ++j) {
Route[j] = Table[i][j];
}
; j <= city_count - ; ++j) {
Length[i] = Length[i] + D[Route[j]][Route[j + ]];
}
Length[i] = Length[i] + D[Route[city_count]][Route[]];
}
/*for (int i = 1; i <= m; ++i) {
printf("%lf\n", Length[i]);
}*/
/* 计算最短路径距离和求最短路径 */
) {
double min_Length = static_cast<double>(inf);
; i <= m; ++i) {
if (Length[i] < min_Length) {
min_Length = Length[i];
; j <= city_count; ++j) {
Route_best[iter][j] = Table[i][j];
}
}
}
Length_best[iter] = min_Length;
}
else {
double min_Length = static_cast<double>(inf);
; i <= m; ++i) {
if (Length[i] < min_Length) {
min_Length = Length[i];
; j <= city_count; ++j) {
Route_best[iter][j] = Table[i][j];
}
}
}
Length_best[iter] = min_Length;
] < min_Length) {
Length_best[iter] = Length_best[iter - ];
; j <= city_count; ++j) {
Route_best[iter][j] = Route_best[iter-][j];
}
}
}
/* 更新信息素 */
double Delta_Tau[MAXN][MAXN];
memset(Delta_Tau, , sizeof Delta_Tau);
; i <= m; ++i) {
; j <= city_count - ; ++j) {
Delta_Tau[Table[i][j]][Table[i][j + ]]
= Delta_Tau[Table[i][j]][Table[i][j + ]] + Q / Length[i];
}
Delta_Tau[Table[i][city_count]][Table[i][]]
= Delta_Tau[Table[i][city_count]][Table[i][]] + Q / Length[i];
}
; i <= city_count; ++i)
; j <= city_count; ++j)
Tau[i][j] = ( - rho)*Tau[i][j] + Delta_Tau[i][j];
/*for (int i = 1; i <= city_count; ++i) {
for (int j = 1; j <= city_count; ++j)
printf("%lf ", Tau[i][j]);
puts("");
}*/
/* 迭代次数加1,清空路径记录表 */
++iter;
memset(Table, , sizeof Table);
}
}
double gen_rand()
{
return rand() / rand_max;
}
void show_result()
{
printf("求得的最短路径长度为: %lf\n", Length_best[iter_max]);
printf("最短路径为: ");
; i <= city_count; ++i) {
printf("%d ", Route_best[iter_max][i]);
}
puts("");
printf("程序运行时间: %lf s\n", static_cast<double>(ed - st) / CLOCKS_PER_SEC);
}
main.cpp
matlab代码:
%% 清空环境变量
clear all
clc
%% 导入数据
citys = [
];
%% 计算城市间相互距离
n = size(citys,);
D = zeros(n,n);
:n
:n
if i ~= j
D(i,j) = sqrt(sum((citys(i,:) - citys(j,:)).^));
else
D(i,j) = 1e-;
end
end
end
%% 初始化参数
m = ; % 蚂蚁数量
alpha = ; % 信息素重要程度因子
beta = ; % 启发函数重要程度因子
rho = 0.2; % 信息素挥发因子
Q = ; % 常系数
Eta = ./D; % 启发函数
Tau = ones(n,n); % 信息素矩阵
Table = zeros(m,n); % 路径记录表
iter = ; % 迭代次数初值
iter_max = ; % 最大迭代次数
Route_best = zeros(iter_max,n); % 各代最佳路径
Length_best = zeros(iter_max,); % 各代最佳路径的长度
Length_ave = zeros(iter_max,); % 各代路径的平均长度
%% 迭代寻找最佳路径
tic
while iter <= iter_max
% 随机产生各个蚂蚁的起点城市
start = zeros(m,);
:m
temp = randperm(n);
start(i) = temp();
end
Table(:,) = start;
% 构建解空间
citys_index = :n;
% 逐个蚂蚁路径选择
:m
% 逐个城市路径选择
:n
tabu = Table(i,:(j - )); % 已访问的城市集合(禁忌表)
allow_index = ~ismember(citys_index,tabu);
allow = citys_index(allow_index); % 待访问的城市集合
P = allow;
% 计算城市间转移概率
:length(allow)
P(k) = Tau(tabu(end),allow(k))^alpha * Eta(tabu(end),allow(k))^beta;
end
P = P/sum(P);
% 轮盘赌法选择下一个访问城市
Pc = cumsum(P);
target_index = find(Pc >= rand);
target = allow(target_index());
Table(i,j) = target;
end
end
% 计算各个蚂蚁的路径距离
Length = zeros(m,);
:m
Route = Table(i,:);
:(n - )
Length(i) = Length(i) + D(Route(j),Route(j + ));
end
Length(i) = Length(i) + D(Route(n),Route());
end
% 计算最短路径距离及平均距离
[min_Length,min_index] = min(Length);
Length_best(iter) = min_Length;
Length_ave(iter) = mean(Length);
Route_best(iter,:) = Table(min_index,:);
else
[min_Length,min_index] = min(Length);
Length_best(iter) = min(Length_best(iter - ),min_Length);
Length_ave(iter) = mean(Length);
if Length_best(iter) == min_Length
Route_best(iter,:) = Table(min_index,:);
else
Route_best(iter,:) = Route_best((iter-),:);
end
end
% 更新信息素
Delta_Tau = zeros(n,n);
% 逐个蚂蚁计算
:m
% 逐个城市计算
:(n - )
Delta_Tau(Table(i,j),Table(i,j+)) = Delta_Tau(Table(i,j),Table(i,j+)) + Q/Length(i);
end
Delta_Tau(Table(i,n),Table(i,)) = Delta_Tau(Table(i,n),Table(i,)) + Q/Length(i);
end
Tau = (-rho) * Tau + Delta_Tau;
% 迭代次数加1,清空路径记录表
iter = iter + ;
Table = zeros(m,n);
end
toc
%% 结果显示
[Shortest_Length,index] = min(Length_best);
Shortest_Route = Route_best(index,:);
disp(['最短距离:' num2str(Shortest_Length)]);
disp([)])]);
%% 绘图
figure()
plot([citys(Shortest_Route,);citys(Shortest_Route(),)],...
[citys(Shortest_Route,);citys(Shortest_Route(),)],'o-');
grid on
:size(citys,)
text(citys(i,),citys(i,),[' ' num2str(i)]);
end
text(citys(Shortest_Route(),),citys(Shortest_Route(),),' 起点');
text(citys(Shortest_Route(end),),citys(Shortest_Route(end),),' 终点');
xlabel('城市位置横坐标')
ylabel('城市位置纵坐标')
title(['蚁群算法优化路径(最短距离:' num2str(Shortest_Length) ')'])
figure()
plot(:iter_max,Length_best,:iter_max,Length_ave,'r:')
legend('最短距离','平均距离')
xlabel('迭代次数')
ylabel('距离')
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源代码)的更多相关文章
- ACS蚁群算法求解对称TSP旅行商问题的JavaScript实现
本来以为在了解蚁群算法的基础上实现这道奇怪的算法题并不难,结果实际上大相径庭啊.做了近三天时间,才改成现在这能勉强拿的出手的模样.由于公式都是图片,暂且以截图代替那部分内容吧,mark一记. 1 蚁群 ...
- 利用HTML5 Canvas和Javascript实现的蚁群算法求解TSP问题演示
HTML5提供了Canvas对象,为画图应用提供了便利. Javascript可执行于浏览器中, 而不须要安装特定的编译器: 基于HTML5和Javascript语言, 可随时编写应用, 为算法測试带 ...
- 蚁群算法求解TSP问题
一.蚁群算法简介 蚁群算法是对自然界蚂蚁的寻径方式进行模似而得出的一种仿生算法:蚂蚁在运动过程中,能够在它所经过的路径上留下信息素(pheromone)的物质进行信息传递,而且蚂蚁在运动过程中能够感知 ...
- 蚁群算法(Java)tsp问题
1.理论概述 1.1.TSP问题 旅行商问题,即TSP问题(旅行推销员问题.货郎担问题),是数学领域中著名问题之一.假设有一个旅行商人要拜访n个城市,他必须选择所要走的路径,路径的限制是每个城市只 ...
- 蚁群算法MATLAB解VRP问题
Excel exp12_3_2.xls内容: ANT_VRP函数: function [R_best,L_best,L_ave,Shortest_Route,Shortest_Length]=ANT ...
- 蚁群算法和简要matlab来源
1 蚁群算法原理 从1991由意大利学者 M. Dorigo,V. Maniezzo 和 A. Colorni 通过模拟蚁群觅食行为提出了一种基于群体的模拟进化算法--蚁群优化.极大关注,蚁群算法的特 ...
- 蚁群算法简介(part3: 蚁群算法之更新信息素)
信息素的局部更新策略 每只蚂蚁在构造出一条从起点到终点的路径后,蚁群算法还要求根据路径的总长度来更新这条路径所包含的每条边上信息素的浓度(在旅行商问题中每座城市是图中的一个节点,城市两两间有一条边 ...
- 蚁群算法简介(part2: 蚁群算法之构造路径)
蚁群算法主要可以分为以下几个步骤:首先,蚁群中的每只蚂蚁都根据地面上信息素浓度的大小找出一条从原点通向终点的遍历所有城市一次的路径(构造路径):然后每只蚂蚁沿着自己刚刚找到的路径回溯,在路径经过的各个 ...
- 基于粒子群算法求解求解TSP问题(JAVA)
一.TSP问题 TSP问题(Travelling Salesman Problem)即旅行商问题,又译为旅行推销员问题.货郎担问题,是数学领域中著名问题之一.假设有一个旅行商人要拜访n个城市,他必须选 ...
随机推荐
- java 使用递归获取指定文件路径目录,删除指定的文件后缀(可扩展,根据具体需要的删除的后缀进行配置)~~
在工作开发过程中,每次用SVN提交代码全选择的时候,发现会产生很多不需要的文件后缀垃圾文件,感觉挺烦人的,一个一个删太麻烦了,如果产生多种后缀文件时,那删起来多费劲,是吧?想想,就写了一段程序通过递归 ...
- webservice wsdl axis2报错 Provider com.bea.xml.stream.MXParserFactory not found
错误信息: Exception in thread "main" javax.xml.stream.FactoryConfigurationError: Provider com. ...
- sellsa
我看见天空很蓝 就像你在我身边的温暖 生命有太多遗憾 人越成长越觉得孤单 我很想飞 多远都不会累 才明白爱得越深心就会越痛 我只想飞 在我的天空飞 我知道你会在我身边 回忆的画面 记录的语言 爱始终是 ...
- EI目录下载地址及保护密码
EI目录下载地址:http://www.elsevier.com/solutions/engineering-village/content EI工作薄保护密码:AAAAABABAABD
- Protocol buffers 介绍
Protocol buffers和mxl一样在序列化数据结构时很灵活.高效和智能,但是它的优势在于定义文件更小,读取速度更快,使用更加简单.目前protocol buffers支持C++.java和p ...
- EBS中配置OAF
配置EBS的OAF作者 redqq 16:09 | 静态链接网址 | 最新回复 (0) | 引用 (0) | ERP学习 载jdev 9.03.5带Oracle Applications Extens ...
- ASP.NET MVC WEBAPI第一次接触
asp.net 的MVC4 WEBAPI的出现已经有段时间了.最近因为做自己的一些小玩儿,要做一个API,正好可以学习一下这个WEBAPI. WEBAPI项目的创建我就不啰嗦,先来看看webapi的路 ...
- php 之跨域上传图片
因为要将所有上传的图片上传到一台独立的图片服务器上面,js上传时存在跨域问题,网上找到这种,通过php curl方式,将图片重新发送到另外一台服务器上保存,并返回图片路径!这种方式存在一定问题:1,上 ...
- Windows下用Python 3.4+自带的venv模块创建虚拟环境
Python 3.4+自带了venv模块,用于创建虚拟环境,每个虚拟环境都可以安装一套独立的第三方模块. 本文在Windows 10上操作. 1.创建一个虚拟环境: D:\>mkdir test ...
- JSON与XML优缺点对比分析
本文从各个方面向大家对比展示了json和xml的优缺点,十分的全面细致,有需要的小伙伴可以参考下. 1. 定义介绍 1.1 XML定义 扩展标记语言 (Extensible Markup Langua ...