前几天在做孔群加工问题,各种假设到最后就是求解旅行商问题了,因为原本就有matlab代码模板所以当时就改了城市坐标直接用了,发现运行速度惨不忍睹,最后用上了两个队友的电脑一起跑。这次模拟结束后在想用c语言来实现的话应该可以提高不少效率。关于模拟退火和旅行商问题的介绍我就不赘述了,网上各路大神说的都很详细,我下面就把c语言和matlab代码先附上。

c语言:

 #ifndef _OPTION_H
 #define _OPTION_H
 /*
 * T0 表示 初始温度
 * Tf 表示 结束时的温度
 * alpha 表示 温度衰减系数
 * T 表示 当前温度
 * Markov_length 表示 Markov链长度
 */
 ;
 double alpha = 0.99;
 ;
 ;
 double T = T0;
 #endif // !_OPTION_H

OPTION.h

 #ifndef _CITY_H
 #define _CITY_H
 struct CITY
 {
     int    id;
     double x;
     double y;
 };
 #endif

CITY.h

 #include <cstdio>
 #include <cmath>
 #include <windows.h>
 #include <ctime>
 #include <algorithm>
 #include "OPTION.h"
 #include "CITY.h"
 using namespace std;
 typedef unsigned int UINT;
 typedef long long LL;

  << );
 ;
 ][];     /* 城市之间的距离矩阵 */
 ];          /* 产生的新解 */
 ];          /* 当前解 */
 ];         /* 冷却中得到的最优解 */
 double new_dist;           /* 新解的路径距离 */
 double cur_dist;           /* 当前解对应路径距离 */
 double best_dist;           /* 冷却过程中得到的最优解 */
 CITY citys[];           /* 保存城市坐标和编号信息 */
 ;        /* 保存城市数量 */
 char *file = NULL;         /* 数据文件 */
 time_t st, ed;               /* 记录开始结束时间 */

 void put_help();
 double init_rand();
 void input();
 void cal_dist();
 void init();
 void cool();
 void disp_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 += ) {
             ) {
                 T0 = atof(argv[i + ]);
                 T = T0;
             }
             ) {
                 Tf = atof(argv[i + ]);
             }
             ){
                 alpha = atof(argv[i + ]);
             }
             ) {
                 Markov_length = atoi(argv[i + ]);
             }
         }
     }
     freopen(file, "r", stdin);
     input();
     st = clock();
     cal_dist();
     init();
     cool();
     ed = clock();
     disp_result();
     end:
     ;
 }

 double init_rand()
 {
     return rand() / rand_max;
 }

 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) {
             dist[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));
         }
     }
 }

 void init()
 {
     cur_dist = inf;
     best_dist = inf;
     ; i <= city_count; ++i) {
         new_sol[i] = i;
         cur_sol[i] = i;
         best_sol[i] = i;
     }
 }

 void cool()
 {
     while (T >= Tf) {
         ; i <= Markov_length; ++i) {
             ;
             ;
              || ind2 ==  ) {
                 ind1 = static_cast<int>(ceil(city_count*init_rand()));
                 ind2 = static_cast<int>(ceil(city_count*init_rand()));
             }
             swap(new_sol[ind1], new_sol[ind2]);
             /* 检查是否满足约束 */
             /* 计算距离 */
             new_dist = ;
             ; i <= city_count - ; ++i) {
                 new_dist = new_dist + dist[new_sol[i]][new_sol[i + ]];
             }
             new_dist += dist[new_sol[city_count]][new_sol[]];
             /* 若新解距离小于当前最优距离,则接受新解;否则以一定概率接受新解 */
             if (new_dist < cur_dist) {
                 cur_dist = new_dist;
                 ; i <= city_count; ++i)
                     cur_sol[i] = new_sol[i];
                 if (new_dist < best_dist) {
                     best_dist = new_dist;
                     ; i <= city_count; ++i)
                         best_sol[i] = new_sol[i];
                 }
             }
             else {
                 if (init_rand() < exp(-(new_dist - cur_dist) / T)) {
                     cur_dist = new_dist;
                     ; i <= city_count; ++i)
                         cur_sol[i] = new_sol[i];
                 }
                 else{
                     ; i <= city_count; ++i)
                         new_sol[i] = cur_sol[i];
                 }
             }
         }
         T = T*alpha;
     }
 }

 void put_help()
 {
     puts("Usage: SA data_source <param_option> ");
     puts("example: SA C:\\Users\\Administrator\\Desktop\\data.txt");
     puts("Format of data file: the coordinates of the cities.");
     puts("example:");
     puts("  1 2");
     puts("  3 1");
     puts("  5 6");
     puts("Set of param: ");
     puts("  -T0 <double>      Start temperature");
     puts("  -Tf <double>      Final temperature");
     puts("  -a <double>       Cooling coefficient (0 < a < 1)");
     puts("  -M <int>          Length of Markov chain");
 }

 void disp_result()
 {
     printf("最短路径长度为: %lf\n",best_dist);
     printf("最优解为: ");
     ; i <= city_count; ++i){
         printf("%d ", best_sol[i]);
     }
     puts("");
     printf("求解用时为: %lf s\n", static_cast<double>(ed - st)/CLOCKS_PER_SEC);
 }

main.cpp

用法根据帮助了解

-T0  设置初始温度

-Tf  设置结束温度

-a   设置降温系数

-M   设置Markov链长度

数据文件的路径为绝对路径,内容格式为每行对应记录一个城市的坐标(坐标为二维欧氏空间)

matlab代码:

 clear
     clc
     a = 0.99;    % 温度衰减函数的参数
     t0 = ; tf = ; t = t0;
     Markov_length = ;    % Markov链长度
     coordinates = [

 ];
 tic
     amount = size(coordinates,);     % 城市的数目
     % 通过向量化的方法计算距离矩阵
     dist_matrix = zeros(amount, amount);
     coor_x_tmp1 = coordinates(:,) * ones(,amount);
     coor_x_tmp2 = coor_x_tmp1';
     coor_y_tmp1 = coordinates(:,) * ones(,amount);
     coor_y_tmp2 = coor_y_tmp1';
     dist_matrix = sqrt((coor_x_tmp1-coor_x_tmp2).^ + ...
                     (coor_y_tmp1-coor_y_tmp2).^);

     sol_new = :amount;         % 产生初始解
 % sol_new是每次产生的新解;sol_current是当前解;sol_best是冷却中的最好解;
     E_current = inf;E_best = inf;         % E_current是当前解对应的回路距离;
 % E_new是新解的回路距离;
 % E_best是最优解的
     sol_current = sol_new; sol_best = sol_new;
     p = ;

     while t>=tf
         :Markov_length        % Markov链长度
             % 产生随机扰动
             if (rand < 0.5)    % 随机决定是进行两交换还是三交换
                 % 两交换
                 ind1 = ; ind2 = ;
                 while (ind1 == ind2)
                     ind1 = ceil(rand.*amount);
                     ind2 = ceil(rand.*amount);
                 end
                 tmp1 = sol_new(ind1);
                 sol_new(ind1) = sol_new(ind2);
                 sol_new(ind2) = tmp1;
             else
                 % 三交换
                 ind1 = ; ind2 = ; ind3 = ;
                 while (ind1 == ind2) || (ind1 == ind3) ...
                     || (ind2 == ind3) || (abs(ind1-ind2) == )
                     ind1 = ceil(rand.*amount);
                     ind2 = ceil(rand.*amount);
                     ind3 = ceil(rand.*amount);
                 end
                 tmp1 = ind1;tmp2 = ind2;tmp3 = ind3;
                 % 确保ind1 < ind2 < ind3
                 if (ind1 < ind2) && (ind2 < ind3)
                     ;
                 elseif (ind1 < ind3) && (ind3 < ind2)
                     ind2 = tmp3;ind3 = tmp2;
                 elseif (ind2 < ind1) && (ind1 < ind3)
                     ind1 = tmp2;ind2 = tmp1;
                 elseif (ind2 < ind3) && (ind3 < ind1)
                     ind1 = tmp2;ind2 = tmp3; ind3 = tmp1;
                 elseif (ind3 < ind1) && (ind1 < ind2)
                     ind1 = tmp3;ind2 = tmp1; ind3 = tmp2;
                 elseif (ind3 < ind2) && (ind2 < ind1)
                     ind1 = tmp3;ind2 = tmp2; ind3 = tmp1;
                 end

                 tmplist1 = sol_new((ind1+):(ind2-));
                 sol_new((ind1+):(ind1+ind3-ind2+)) = ...
                     sol_new((ind2):(ind3));
                 sol_new((ind1+ind3-ind2+):ind3) = ...
                     tmplist1;
             end

             %检查是否满足约束

             % 计算目标函数值(即内能)
             E_new = ;
              : (amount-)
                 E_new = E_new + ...
                     dist_matrix(sol_new(i),sol_new(i+));
             end
             % 再算上从最后一个城市到第一个城市的距离
             E_new = E_new + ...
                 dist_matrix(sol_new(amount),sol_new());

             if E_new < E_current
                 E_current = E_new;
                 sol_current = sol_new;
                 if E_new < E_best
 % 把冷却过程中最好的解保存下来
                     E_best = E_new;
                     sol_best = sol_new;
                 end
             else
                 % 若新解的目标函数值小于当前解的,
                 % 则仅以一定概率接受新解
                 if rand < exp(-(E_new-E_current)./t)
                     E_current = E_new;
                     sol_current = sol_new;
                 else
                     sol_new = sol_current;
                 end
             end
         end
         t=t.*a;        % 控制参数t(温度)减少为原来的a倍
     end
 toc
     disp('最优解为:')
     disp(sol_best)
     disp('最短距离:')
     disp(E_best)

tsp.m

铛铛铛铛,接下来比较两个代码的运行时间。我们以以下31个城市的坐标为测试数据:

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语言同学的测试结果

接下来是matlab同学的:

从结果上看,c代码的运行速度远快过matlab代码。

由于matlab代码里考虑了二交换和三交换,在c代码里我偷工减料只写了二交换,所以在最后对对比结果会有影响,但是这个影响微乎其微,我就忽略不计了(。。)

在以上各三次的结果中matlab代码求得的最短距离可能优于c代码的结果,但这并不说明,matlab写的精度较高,毕竟模拟退火是个概率算法。而且用跑一个matlab代码的时间去跑c代码,足以求出更优解吧。

就说到这里了,想到那几天在机房没日没夜跑结果,我去厕所哭会儿。

模拟退火算法求解旅行商问题(附c和matlab源代码)的更多相关文章

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

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

  2. 【智能算法】用模拟退火(SA, Simulated Annealing)算法解决旅行商问题 (TSP, Traveling Salesman Problem)

    喜欢的话可以扫码关注我们的公众号哦,更多精彩尽在微信公众号[程序猿声] 文章声明 此文章部分资料和代码整合自网上,来源太多已经无法查明出处,如侵犯您的权利,请联系我删除. 01 什么是旅行商问题(TS ...

  3. 模拟退火算法Python编程(2)约束条件的处理

    1.最优化与线性规划 最优化问题的三要素是决策变量.目标函数和约束条件. 线性规划(Linear programming),是研究线性约束条件下线性目标函数的极值问题的优化方法,常用于解决利用现有的资 ...

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

    HTML5提供了Canvas对象,为画图应用提供了便利. Javascript可执行于浏览器中, 而不须要安装特定的编译器: 基于HTML5和Javascript语言, 可随时编写应用, 为算法測试带 ...

  5. 模拟退火算法(SA)求解TSP 问题(C语言实现)

    这篇文章是之前写的智能算法(遗传算法(GA).粒子群算法(PSO))的补充.其实代码我老早之前就写完了,今天恰好重新翻到了,就拿出来给大家分享一下,也当是回顾与总结了. 首先介绍一下模拟退火算法(SA ...

  6. Matlab随笔之模拟退火算法

    问题描述: 我方有一个基地,经度和纬度为( 70,40).假设我方飞机的速度为 1000 公里/小时. 我方派一架飞机从基地出发,侦察完敌方所有目标,再返回原来的基地.在敌方每一目 标点的侦察时间不计 ...

  7. 模拟退火算法SA原理及python、java、php、c++语言代码实现TSP旅行商问题,智能优化算法,随机寻优算法,全局最短路径

    模拟退火算法SA原理及python.java.php.c++语言代码实现TSP旅行商问题,智能优化算法,随机寻优算法,全局最短路径 模拟退火算法(Simulated Annealing,SA)最早的思 ...

  8. 模拟退火算法Python编程(3)整数规划问题

    1.整数规划问题 整数规划问题在工业.经济.国防.医疗等各行各业应用十分广泛,是指规划中的变量(全部或部分)限制为整数,属于离散优化问题(Discrete Optimization). 线性规划问题的 ...

  9. 贪心算法:旅行商问题(TSP)

    TSP问题(Traveling Salesman Problem,旅行商问题),由威廉哈密顿爵士和英国数学家克克曼T.P.Kirkman于19世纪初提出.问题描述如下: 有若干个城市,任何两个城市之间 ...

随机推荐

  1. Spark Streaming源码解读之State管理之UpdataStateByKey和MapWithState解密

    本期内容 : UpdateStateByKey解密 MapWithState解密 Spark Streaming是实现State状态管理因素: 01. Spark Streaming是按照整个Bach ...

  2. 萌萌的websocket原理解析

    转载自:http://www.zhihu.com/question/20215561 一.WebSocket是HTML5出的东西(协议),也就是说HTTP协议没有变化,或者说没关系,但HTTP是不支持 ...

  3. 过渡transitioin

    一,什么是过渡(transition)? 1,transition 允许 CSS 元素的属性值在一定的时间区间内平滑地过渡. 2,可以在不使用 Flash 动画或 JavaScript 的情况下,在元 ...

  4. Nodejs+Express创建HTTPS服务器

    为了使我的Nodejs服务器提供HTTPS服务,学习了一下如何利用express创建https服务器,现记录如下.(一点一点的积累与掌握吧) 1. Http与Https 介绍 HTTP: 超文本传输协 ...

  5. ConnectionString属性尚未初始化

    问题前因:使用动软代码生成的三成模板然后复制到相应的类库 动软生成的 sql帮助类 推荐的是DBsqlhelp 期间引用了:BLl层:Maticsoft.Common.dll DAl层:Maticso ...

  6. Nodejs学习(二)-express生成器

    1.安装生成器 sudo npm install express-generator -g 2.做ln链接,这个我就不介绍了,可以参照上个随笔,指向/usr/local/bin就行. 3.生成项目文件 ...

  7. c#接口容易被忽视的问题

    今天在看"并发集合"的时候,接口IProducerConsumerCollection<T> 有一个方法是TryAdd(),表示"试图"去添加,然后 ...

  8. SQL Server中Rowcount与@@Rowcount的用法

    rowcount的用法: rowcount的作用就是用来限定后面的sql在返回指定的行数之后便停止处理,比如下面的示例, set rowcount 10select * from 表A 这样的查询只会 ...

  9. leetcode-javascript

    1. Largest Number For example, given [3, 30, 34, 5, 9], the largest formed number is 9534330. // wro ...

  10. Perl语言

    Perl是高级.通用.直译式.动态的程序语言家族.最初设计者拉里·沃尔(Larry Wall)为了让在UNIX上进行报表处理的工作变得更方便,决定开发一个通用的脚本语言,而在1987年12月18日发表 ...