0、问题梗概

旅行商问题(TravelingSalesmanProblem,TSP)是一个经典的组合优化问题。经典的TSP可以描述为:一个商品推销员要去若干个城市推销商品,该推销员从一个城市出发,需要经过所有城市后,回到出发地。应如何选择行进路线,以使总的行程最短。

1、随机数据的初始概率密度函数

2、程序运行数据

运行次数 时间(维数23) 时间(维数33)
1 3.06541 ms 26.9593 ms
2 3.65156 ms 48.6972 ms
3 2.66832 ms 43.5297 ms
4 6.78412 ms 44.7827 ms
5 9.77699 ms 24.6574 ms
6 4.44002 ms 24.3777 ms
7 9.36337 ms 20.4059 ms
8 7.22274 ms 45.9999 ms
9 8.77502 ms 41.7881 ms
10 8.07504 ms 66.3793 ms

维度 23 的平均执行时间为 6.4 毫秒,维度 33 的平均执行时间为 38.8 毫秒。

3、代码分析

I)使用数据类型

using mat_d = vector<vector<double>>;
using path_t = vector<pair<size_t, size_t>>;

II) 随机数据的初始概率密度函数

double F(double x)
{return (5 / 6.0) * (1 + pow(x, 4));
}
// use Acceptance-Rejection Method
// max from 0 to 1 in function F is 5/3
double GetRnd()
{double u1, u2;while (true){u1 = rand() % MAX_DIST;u2 = rand() % MAX_DIST;if (u2 <= (3 / 5.0) * F(u1))return u1;}
}

III) 任务路径树

// Task tree node represents each reduction matrix
class TaskTree
{private:double bound;int index_row, index_col;
​
public:mat_d mat;path_t path;TaskTree(const mat_d &m, const path_t &p = {}, const double b = 0);void PrintMat();void ReduceMinElem();void FindMinPath();bool PathCompleted() { return path.size() == mat.size(); }double GetBound() { return bound; }int GetRowIndex() { return index_row; }int GetColIndex() { return index_col; }
};

IV) 选取路径中最小元素后进行规约操作

// Minimum statute
void TaskTree::ReduceMinElem()
{for (size_t i = 0; i < mat.size(); i++){double minelem_row = INF;for (size_t j = 0; j < mat.size(); j++){if (minelem_row > mat[i][j]){minelem_row = mat[i][j];}}for (size_t j = 0; j < mat.size(); j++){if (mat[i][j] != INF){mat[i][j] -= minelem_row;}}if (minelem_row != INF)bound += minelem_row;}for (size_t i = 0; i < mat.size(); i++){double minelem_col = INF;for (size_t j = 0; j < mat.size(); j++){if (minelem_col > mat[j][i]){minelem_col = mat[j][i];}}for (size_t j = 0; j < mat.size(); j++){if (mat[j][i] != INF){mat[j][i] -= minelem_col;}}if (minelem_col != INF)bound += minelem_col;}FindMinPath();
}

V) 寻找最小元素过程

// Find the shortest path possible
void TaskTree::FindMinPath()
{index_row = -1;index_col = -1;double max_sum = -1;for (size_t i = 0; i < mat.size(); i++){for (size_t j = 0; j < mat.size(); j++){if (mat[i][j] == 0){double min_row = INF, min_col = INF;for (size_t k = 0; k < mat.size(); k++){if (k != j && mat[i][k] < min_row)min_row = mat[i][k];if (k != i && mat[k][j] < min_col)min_col = mat[k][j];}double max_sum_tmp = min_row + min_col;if (max_sum_tmp > max_sum){index_row = i;index_col = j;max_sum = max_sum_tmp;}}}}path.push_back(make_pair(index_row, index_col));
}

VI) 左子树情况为选取最小元素加入路径,右子树情况为不选取该元素

// Subtree containing the selected path
shared_ptr<TaskTree> SetLeft(const mat_d &m, const path_t &path, const double bound, const int index_row, const int index_col)
{mat_d mat = m;map<size_t, size_t> pathTest;for (size_t i = 0; i < path.size() - 1; i++){pathTest[path[i].first] = path[i].second;}size_t pos = index_col;while (pathTest.find(pos) != pathTest.end()){pos = pathTest[pos];if (pos == index_row){return nullptr;}}for (size_t i = 0; i < mat.size(); i++){mat[index_row][i] = INF;mat[i][index_col] = INF;}mat[index_col][index_row] = INF;
​return make_shared<TaskTree>(mat, path, bound);
}
// Does not contain the subtree of the selected path
shared_ptr<TaskTree> SetRight(const mat_d &m, const path_t &p, const double bound, const int index_row, const int index_col)
{mat_d mat = m;mat[index_row][index_col] = INF;
​path_t path = p;path.pop_back();return make_shared<TaskTree>(mat, path, bound);
}

VII) 对旅行商问题解决进行二次封装

// Problem-solving tree
class Task
{private:map<size_t, size_t> bestpath;list<shared_ptr<TaskTree>> tour;mat_d origin_mat;double best;shared_ptr<TaskTree> root;
​
public:Task(const size_t size, double (*pf)() = GetRnd);Task(const char *filename, const size_t size);void RunTask();void PrintPath();
};

VIII) 解决问题过程,核心思路优先考虑左子树以加快收敛过程

void Task::RunTask()
{tour.push_front(root);// root->PrintMat();while (tour.size() != 0){shared_ptr<TaskTree> head = tour.front();tour.pop_front();if (head->GetBound() > best){continue;}if (head->PathCompleted()){best = head->GetBound();bestpath.clear();for (size_t i = 0; i < origin_mat.size(); i++){bestpath[head->path[i].first] = head->path[i].second;}continue;}if (head->GetRowIndex() == -1 && head->GetColIndex() == -1){continue;}shared_ptr<TaskTree> left = SetLeft(head->mat, head->path, head->GetBound(), head->GetRowIndex(), head->GetColIndex());shared_ptr<TaskTree> right = SetRight(head->mat, head->path, head->GetBound(), head->GetRowIndex(), head->GetColIndex());if (left != nullptr){if (left->path.size() < origin_mat.size()){if (left->GetBound() < right->GetBound()){tour.push_front(right);tour.push_front(left);}else{tour.push_front(left);tour.push_front(right);}
#if 0
                cout << "bound: " << tour.front()->GetBound() << endl;
                head->PrintMat();
#endif}else{tour.push_front(left);}}else{tour.push_front(right);}}PrintPath();
}

IX) 打印总体路径

void Task::PrintPath()
{cout << "Best path: 1 => ";size_t begin = 0;while (bestpath[begin] != 0){cout << bestpath[begin] + 1 << " => ";begin = bestpath[begin];}cout << "1" << endl;cout << "best tour: " << best << endl;
}

X) 主函数

int main()
{const auto start_time = high_resolution_clock::now();srand(time(NULL));const size_t nDim1 = 6, nDim2 = 33;
#if 0
    Task t1("input.txt", nDim1);
    t1.RunTask();
#endif
#if 1Task t2(nDim2);t2.RunTask();
#endifconst auto end_time = high_resolution_clock::now();PrintTime(start_time, end_time);
}

4、代码总评

Best path: 1 => 29 => 12 => 32 => 23 => 11 => 15 => 24 => 14 => 5 => 8 => 17 => 25 => 26 => 33 => 20 => 18 => 9 => 13 => 16 => 31 => 30 => 3 => 21 => 2 => 19 => 10 => 28 => 27 => 22 => 4 => 7 => 6 => 1
best tour: 239
Time: 19.0621 ms

智能指针设计在一定程度上简化了内存管理,避免了内存泄漏的问题。 一个显着的优点是尽可能多地使用指针,而不是重新创建对象,这样整个程序占用的内存很少。 从算法设计的角度来看,优先考虑左子树(即路径),这使得代码更加高效。

完整代码: https://github.com/KCNyu/Program_MSU-BIT/blob/master/C%2B%2B_LECTURE/TSP/TSP.cpp

分支定界法求解旅行商问题相关推荐

  1. MATLAB实战系列(二十九)-头脑风暴优化(BSO)算法求解旅行商问题(TSP)-交叉算子

    前言 代码明细可参见 MATLAB实战系列(八)-头脑风暴优化(BSO)算法求解旅行商问题(TSP)(附MATLAB代码) 交叉算子的实现机制 我们还是以求解TSP问题为例,8个城市的坐标如下所示. ...

  2. 模拟退火算法求解旅行商问题(python实现)

    模拟退火算法求解旅行商问题 文章目录 模拟退火算法求解旅行商问题 一.模拟退火算法原理 二.旅行商问题 1.求解思路 2.代码 总结 旅行商问题(TSP 问题).假设有一个旅行商人要拜访全国31个省会 ...

  3. 计算机设计大赛国奖作品_5. 模拟退火求解旅行商问题

    计算机设计大赛国奖作品_5. 模拟退火求解旅行商问题 本系列是2021年中国大学生计算机设计大赛作品"环境监测无人机航线优化"的相关文档,获得2021年西北赛区一等奖,国赛三等奖. ...

  4. 【MVO TSP】基于matlab灰狼算法求解旅行商问题【含Matlab源码 1327期】

    一.获取代码方式 获取代码方式1: 完整代码已上传我的资源:[TSP]基于matlab灰狼算法求解旅行商问题[含Matlab源码 1327期] 点击上面蓝色字体,直接付费下载,即可. 获取代码方式2: ...

  5. MATLAB实现分支定界法求解整数规划

    利用MATLAB实现分支定界法求解整数规划 classdef Model < matlab.mixin.CopyablepropertiesintconlbubsolverAineqbineqA ...

  6. 【GA TSP】基于matlab遗传算法求解旅行商问题【含Matlab源码 1337期】

    一.获取代码方式 获取代码方式1: 完整代码已上传我的资源:[TSP]基于matlab遗传算法求解旅行商问题[含Matlab源码 1337期] 点击上面蓝色字体,直接付费下载,即可. 获取代码方式2: ...

  7. 【路径规划-TSP问题】基于粒子群结合蚁群算法求解旅行商问题附matlab代码

    1 内容介绍 一种基于粒子群优化的蚁群算法求解TSP问题的方法.该方法在求解TSP问题时,利用粒子群优化的思想,对蚁群算法的参数取值进行优化并选择.在粒子群算法中,将蚁群算法的5个参数(q,α,β,ρ ...

  8. pso解决tsp matlab,计算智能课程设计_粒子群优化算法求解旅行商问题_Matlab实现.doc...

    计算智能课程设计_粒子群优化算法求解旅行商问题_Matlab实现.doc 摘要:TSP是一个典型的NPC问题.本文首先介绍旅行商问题和粒子群优化算法的基本概念.然后构造一种基于交换子和交换序[1]概念 ...

  9. 【PSO TSP】基于matlab GUI粒子群算法求解旅行商问题【含Matlab源码 1334期】

    ⛄一.TSP简介 旅行商问题,即TSP问题(Traveling Salesman Problem)又译为旅行推销员问题.货郎担问题,是数学领域中著名问题之一.假设有一个旅行商人要拜访n个城市,他必须选 ...

  10. 单目标应用:瞪羚优化算法GOA求解旅行商问题TSP(提供Matlab代码)

    一.瞪羚优化算法 瞪羚优化算法(Gazelle Optimization Algorithm,GOA)由Agushaka等人于2022年提出,该算法模拟了瞪羚逃避捕食者的行为,思路新颖,性能高效. 瞪 ...

最新文章

  1. 计算机应用基础第三章操作步骤,最新江西三校生计算机应用基础模拟操作题集锦(超实用!)...
  2. Oracle数据库的数据统计(Analyze)
  3. 【Network】高性能 UDP 服务应该怎么搞?
  4. BZOJ4591 SHOI2015超能粒子炮·改(卢卡斯定理+数位dp)
  5. 【高并发】怎么演示公平锁和非公平锁?
  6. seaborn_Seaborn Kdeplot –综合指南
  7. eclipse adt bundle不显示Android SDK菜单
  8. PHP 互联网架构师成长之路*「swoole」终极指南
  9. oppo小布机器人_OPPO小布助手2.0强势来袭 三大版块迎来重大升级
  10. python负数的处理
  11. 概率统计Python计算:全概率公式
  12. 抖音同款 抖音 城堡 微信背景图,抖音城堡微信背景图
  13. SDUT ACM 多项式求和(基于C语言)
  14. 【Fracturing amp; Destruction】Unity3D的物体爆裂、炸裂、碎裂效果
  15. accept()函数
  16. python中的对象是什么意思_python中什么是对象
  17. 【创建Vue手脚架项目】
  18. mysql为什么会慢
  19. c语言的four是什么意思,【转】一些变态的编程语言
  20. 「工具」三分钟了解一款在线流程绘制工具:Whimsical

热门文章

  1. jQuery实现下拉菜单[代码+详细讲解+效果图]
  2. VBScript 教程
  3. ecshop二次开发之模板整合
  4. 从四大造字法看文字所承载的文化_汉语汉字所承载的文化信息最好能举例说明...
  5. 仿vista桌面小工具
  6. kali linux启动盘工具,白话kali linux USB启动盘的制作(快捷版)
  7. java 主板序列号_Java获得硬盘和主板的序列号
  8. mysql-front源码_MySQL-Front
  9. 服务器搬迁方案_服务器数据迁移方案
  10. 2109-全国大学生电子设计竞赛-F-纸张数识别(内含arduino代码以及题解)