算法报告-旅行商问题模板讲解

算法报告-旅行商问题模板讲解
算法报告-旅行商问题模板讲解

《算法设计与课程设计》

题目: TSP问题多种算法策略

班级:计算机技术14

学号:

姓名:

指导老师:

完成日期:

成绩:

旅行商问题的求解方法

摘要

旅行商问题(TSP 问题)时是指旅行家要旅行n 个城市然后回到出发城市,要求各个城市经历且仅经历一次,并要求所走的路程最短。该问题又称为货郎担问题、邮递员问题、售货员问题,是图问题中最广为人知的问题。本文主要介绍用动态规划法、贪心法、回溯法和深度优先搜索策略求解TSP 问题,其中重点讨论动态规划法和贪心法,并给出相应求解程序。

关键字:旅行商问题;动态规划法;贪心法;回溯法;深度优先搜索策略 1引言

旅行商问题(TSP)是组合优化问题中典型的NP-完全问题,是许多领域内复杂工程优化问题的抽象形式。研究TSP 的求解方法对解决复杂工程优化问题具有重要的参考价值。关于TSP 的完全有效的算法目前尚未找到,这促使人们长期以来不断地探索并积累了大量的算法。归纳起来,目前主要算法可分成传统优化算法和现代优化算法。在传统优化算法中又可分为:最优解算法和近似方法。最优解算法虽然可以得到精确解,但计算时间无法忍受,因此就产生了各种近似方法,这些近似算法虽然可以较快地求得接近最优解的可行解,但其接近最优解的程度不能令人满意。但限于所学知识和时间限制,本文重点只讨论传统优化算法中的动态规划法、贪心法、回溯法和深度优先搜索策略。 2正文

2.1动态规划法

2.1.1动态规划法的设计思想

动态规划法将待求解问题分解成若干个相互重叠的子问题,每个子问题对应决策过程的一个阶段,一般来说,子问题的重叠关系表现在对给定问题求解的递推关系(也就是动态规划函数)中,将子问题的解求解一次并填入表中,当需要再次求解此子问题时,可以通过查表获得该子问题的解而不用再次求解,从而避免了大量重复计算。

2.1.2 TSP 问题的动态规划函数

假设从顶点i 出发,令'(,)d i V 表示从顶点i 出发经过'V 中各个顶点一次且仅一次,最后回到出发点i 的最短路径长度,开始时,{}'V V i =-,于是,TSP 问

题的动态规划函数为:

{}{}{}''(,)min (,)()

(,)()ik ki d i V c d k V k k V d k c k i =+-∈=≠

2.1.3算法分析

(1)for (i=1; i

d[i][0]=c[i][0];

(2)for (j=1; j< n-12 -1; j++)

for (i=1; i

if (子集V[j]中不包含i)

对V[j]中的每个元素k ,计算V[m] == V[j]-k;

d[i][j]=min(c[i][k]+d[k][m]);

(3)对V[n-12 -1]中的每一个元素k ,计算V[m] == V[n-12 -1]-k;

d[0][ n-12 -1]=min(c[0][k]+d[k][m]);

(4)输出最短路径长度d[0][ n-12 -1];

2.1.4时间复杂性

T()(2)n n O n =?

动态规划法求解TSP 问题,把原来的时间复杂性是O(n!)的排列问题,转化为组合问题,从而降低了算法的时间复杂性,但它仍需要指数时间。

2.2贪心法

2.2.1贪心法的设计思想

贪心法在解决问题的策略上目光短浅,只根据当前已有的信息就做出选择,而且一旦做出了选择,不管将来有什么结果,这个选择都不会改变。换言之,贪心法并不是从整体最优考虑,它所做出的选择只是在某种意义上的局部最优。这种局部最优选择并不总能获得整体最优解,但通常能获得近似最优解。

2.2.2最近邻点策略求解TSP 问题

贪心法求解TSP 问题的贪心策略是显然的,至少有两种贪心策略是合理的:最近邻点策略和最短链接策略。本文仅重点讨论最近邻点策略及其求解过程。 最近邻点策略:从任意城市出发,每次在没有到过的城市中选择距离已选择的城市中最近的一个,直到经过了所有的城市,最后回到出发城市。

2.2.3算法分析

1.P={ };

2.V=V-{u0}; u=u0; //从顶点u0出发

3.循环直到集合P 中包含n-1条边

3.1查找与顶点u 邻接的最小代价边(u, v)并且v 属于集合V ;

3.2 P=P+{(u, v)};

3.3 V=V-{v};

3.4 u=v; //从顶点v 出发继续求解

2.2.4时间复杂性

2

T O n

()

但需注意,用最近邻点贪心策略求解TSP问题所得的结果不一定是最优解。当图中顶点个数较多并且各边的代价值分布比较均匀时,最近邻点策略可以给出较好的近似解,不过,这个近似解以何种程度近似于最优解,却难以保证。

2.3回溯法

2.3.1回溯法的设计思想

回溯法(探索与回溯法)是一种选优搜索法,按选优条件向前搜索,以达到目标。但当探索到某一步时,发现原先选择并不优或达不到目标,就退回一步重新选择,这种走不通就退回再走的技术为回溯法,而满足回溯条件的某个状态的点称为“回溯点”。

若已有满足约束条件的部分解,不妨设为(x1,x2,x3,……xi),I

2.3.2 算法分析(回溯法+深度优先搜索策略)

因为是采用回溯法来做,肯定是递归,然后还需要现场清理。

要设置一个二维数组来标识矩阵内容,然后回溯还需要设计

一个二维标记数组来剪枝,设定一个目标变量,初始为无穷大,

后续如果有比目标变量值小的就更新。剪枝的条件就是如果走到当前节点的耗费值>=目标变量,就直接不再往下面走,向上走。

深度优先= 递归

递归基:如果到达叶子节点的上一个节点,那么就进行是否更新的判断

递归步:如果没有到达叶子节点,就进行剪枝操作,判断能否进入下一个节点,如果能,更新最优值

2.3.3 关键实现(回溯法+深度优先搜索策略)

1 //递归基:如果已经遍历到叶子节点的上一层节点,i标识递归深度

if(i == g_n)

{

//判断累加和是否超过最大值,如果有0,应该排除;满足这个条件,才打印if((g_iArr[pArr[i-1]][pArr[i]] != 0) && (g_iArr[pArr[g_n]][1] != 0) && (g_iCurResult + g_iArr[pArr[i-1]][pArr[i]] + g_iArr[pArr[g_n]][1] < g_iResult ))

{

g_iResult = g_iCurResult + g_iArr[pArr[i-1]][pArr[i]] + g_iArr[pArr[g_n]][1];

//用当前最优路径去更新最优路径,防止下一次没有

for(int k = 1 ; k <= g_n ; k++)

{

g_iBestPath[k] = pArr[k];

2 //递归步:判断能否进入子树,需要尝试每一个节点

else

{

//尝试不同的组合

for(int j = i ; j <= g_n ; j++)

{

//判断能否进入子树:如果当前值+下一个连线值的和< 最优值,就进入,0要pass

if( (g_iArr[pArr[i-1]][pArr[j]] != 0) && (g_iCurResult + g_iArr[ pArr[i-1] ][ pArr[j] ] < g_iResult) )

3 //交换i与j,则i为当前可以尝试的范围

//为完成后面k个元素的排列,逐一对数组第n-k~n个元素互换。数组第一个元素为1,生成后面n-1个元素的排列

//数组第一个元素与第二个元素互换,第一个元素为2,第2个元素为1,生成后面的n-1个元素的排列...

swap(&pArr[i],&pArr[j]);

//更新当前累加值,是i-1与i的

g_iCurResult += g_iArr[ pArr[i-1] ][ pArr[i] ];

//递归

backTrace(i+1,pArr);

//回溯,清空累加值;能够走到这里,说明上述结果不是最优解,需要向求解树上一层回退

g_iCurResult -= g_iArr[pArr[i-1]][ pArr[i] ];

swap(&pArr[i],&pArr[j]);

*/

2.3.4时间复杂性

T = O(n!), 该方法并没有有效的提高时间效率。

3结论

本文主要重点讨论了动态规划法、贪心法、回溯法和深度优先搜索策略求解TSP问题算法,并附录给出了相应程序,并通过对比得到动态规划法和贪心法相对更有优势,下面对这两种方法进行详述和进一步对比。

3.1动态规划法思想

动态规划法中对于顶点元素生成的子集本文中用字符串形式存储,然后再用递归方法按照子集中元素个数从小到大开始赋值。因为后面元素个数较多的子集与前面比其元素个数少1的子集间有一定对应关系,所以用递归方式,可以简便很多。个人觉得这算本文的一大特色。另,在计算d[i][j] =min(c[i][k]+d[k][j-1])时,获得d[k][j-1]的过程比较困难,运用字符串后,我们就可以首先找到指定字

符,然后去掉该字符,返回剩余字符串,在与V[]逐个比较,找到与其相等的V[]中元素对应下标,此下标即为j-1;具体求解过程可参考附录源程序,有详细说明。在求解最佳路径所经过城市顺序时,本文是通过边查找d[i][j]边记录路径的,这样可以省掉很多麻烦,另,路径也是采用字符串形式的数组,数组规模与存储城市间距离的c[][]数组相同,由于很多元素均不需赋值,这样做可能会浪费内存空间,但是目前还没找到更好地求解方法。

3.2贪心法思想

贪心法中,由于贪心法相对动态规划法要简单很多,每次在查找最近城市时所得的顶点均为最后该法最佳路径所经过的城市编号,规模相对较小,容易确定,操作相对简单,所以本文用数组V[]存放最佳路径所经过的城市编号顺序相对来说方便很多。另外,本文用path[]整型数组存放所经路径的长度,最后相加即可得最短路径。

3.3两者比较

动态规划法相对贪心法来说虽然要精确些,但代码相对繁杂很多,对时间和空间要求很多,仅适用于城市数量较小的情况。贪心法虽然比较简单,实现起来比较容易,但不是很精确,当图中顶点个数较多并且各边的代价值分布比较均匀时,贪心法可以给出较好的近似解,不过,这个近似解以何种程度近似于最优解,却难以保证。

另外,动态规划法有一个明显的缺点,就是出发城市只能是第0个城市(城市从0开始编号),若出发城市改变,则必须以该城市为第0个城市顺序给其他城市编号,输入城市间距离。由于若出发城市任意,编码的难度大大增加,所以最后不得已放弃,但这大大地限制了程序的通用性。而对于贪心法,本文很好地避免了这个问题,一旦城市编号确定,可以从任意城市出发,这也是本文中贪心法优于动态规划法的一点。

3.4优点

本文程序优点,各个子函数功能分隔很明显,没有大量集中在一个函数里面,而是分成了几个不同功能的小函数,这样程序可阅读性提高。另外,程序中有详细注释,程序中变量取名都是根据变量的性质和所代表的含义命名的,也相应提高了程序的可读性。

对于动态规划法,城市个数可以在算法时间允许的范围内任意,于这点来说,通用性较好;对于贪心法,出发城市可以任意,城市个数也可以任意,通用性较好。

3.5 建议

当城市个数较少时,用动态规划法求出最优解;当城市个数较多并且各边的代价值分布比较均匀时,贪心法可以给出较好的近似解。

4参考文献

(1)《计算机算法分析与设计》第二版,王晓东编著,电子工业出版社

(2)Java语言与面向对象程序设计(第2版)印旻、王行言编著,清华大学出版社

(3)求解TSP算法,周康、强小利、同小军、许进,计算机工程与应用

(4)《算法设计与分析》,王红梅编著,清华大学出版社

(5)《ACM/ICPC算法训练教程》,余立功主编,清华大学出版社

6附录

6.1动态规划法

6.1.1源代码

package Tsp;

import java.util.Scanner;

public class TSPDP {

String[] V;// 顶点生成的子集,这里把每一个子集用一个字符串表示

int[][] c;// 顶点间距离

int[][] d;// 存放迭代结果

int N; // 城市个数

String[][] path;// 用于存放每种选择下经过的城市

static int IFINITE = 99999;// 无穷大距离表示城市自己到达自己时,距离无穷大,不作为考虑因素

// 构造函数

public TSPDP() {

initialC();

initialV1();

}

// 初始化数组c[],即顶点间距离

public void initialC() {

Scanner in = new Scanner(System.in);

System.out.println("请输入城市个数:(注意根据实际情况城市个数不可小于1!)");

N = in.nextInt();

if (N <= 1) {

System.out.println("不符合要求,请认真核对!");

System.exit(0);// 输入错误,结束!

}

System.out.println("请输入城市相邻城市间距离(城市从0开始编号,且出发城市为第0个城市!): ");

c = new int[N][N];// 为c分配空间

for (int i = 0; i < N; i++)

for (int j = 0; j < N; j++) {

c[i][j] = in.nextInt(); // 输入时,按城市编号从小到大,如若两城市间没有公路相连,则距离为无穷大。本城市与本城市间距离也为无穷大。

}

}

// 初始化顶点生成的子集的对外调用函数

public void initialV1() {

V = new String[(int) Math.pow(2, N - 1)];// 为V分配空间

initialV(0, 0);

}

// 具体的初始化顶点生成的子集

// 本程序使用递归调用方法初始化V,并按照数字大小顺序排序。。另,子集使用字符型形式存放的

// 我们是按照子集中元素个数从小到大逐个添加的,后面的子集是前面对应子集加上一个元素组成的,故用递归

public void initialV(int m, int len) {// m代表下一个即将初始化的V数组的元素的下标;len是最后一个初始化的元素的长度

if (m > (int) Math.pow(2, N - 1) - 1)

return;// 如果全部顶点已初始化完成,则返回。

if (m == 0)

V[m++] = "";// 初始化出发顶点,即V[0]

else {

int i = m - 1;

while (i >= 0 && V[i].length() == len)

// 找与最后一个初始化的V[m-1]子集内元素个数相同的集合,把指针i指向满足条件的集合

i--;

i++;// 把指针i指向满足条件的第一个集合

while (i < m) {

int ch;// 用于表示下一个即将加入子集的数字

if (i == 0)

ch = 0;// 如果i指向V中第一个元素

else {

String chStr = "" + V[i].charAt(V[i].length() - 1);// 找出V[i]中最后一个数字

ch = Integer.parseInt(chStr);// 转换成整型

}

// 比ch大而又比N-1(因为这里顶点是从0开始的)小的数字应该加在子集中

while (ch < N - 1)

V[m++] = V[i] + (++ch);

i++;// 对已存在的自己逐个扫描添加

}

}

initialV(m, V[m - 1].length());// 递归调用

}

// 判断自己V[j]中是否存在指定元素,即行号i

boolean exclude(int i, int j) {

String str = "" + i;// 把i转换成字符串

if (V[j].contains(str))

// {System.out.println(i + "i");

return false;// 如若存在,则返回false

else

return true;

}

// 获得子集V[j]中除指定元素k外的元素,用字符串形式表示

public String getSubString(int k, int j) {

if (V[j].length() == 1)

return "";// 如果子集中只有一个元素,则返回空串

else {

if (k == 0)

return V[j].substring(1, V[j].length());// 如果k是第一个元素,则返回其后面的元素

else if (k == V[j].length() - 1)

return V[j].substring(0, V[j].length() - 1);// 如果k是最后一个元素,则返回其前面的元素

else

return (V[j].substring(0, k) + V[j].substring(k + 1,

V[j].length()));// 返回除k外的元素

}

}

// 找出V[]中与str相同元素的下标号,即找出上一个子集

public int stringEqual(String str) {

// if(str.equals(""))return 0;

int i = 0;

while (i < V.length) {

if (V[i].equals(str))

return i;

i++;

}

return -1;// 如若没找到,则返回错误符号-1

}

// 求最小距离

public int min(int i, int j) {

int k = 0;// 用于记录V[j]中元素个数

String vStr = "" + V[j].charAt(k);// 铭记V[j].charAt(k)得到的是字符型,转换成整形后是字母对应的ASC码!!!!

int v = Integer.parseInt(vStr);// 把位置k处的字符转换成整形

String str = getSubString(k, j);// 获得V[j]中除位置k处外的字符串

// System.out.println("min" + str + stringEqual(str) + v);

if (stringEqual(str) == -1)

System.exit(0);

int min = c[i][v] + d[v][stringEqual(str)];// 先把最小的距离赋值给从V[j]中第一个顶点出发的距离

// System.out.println(min);

// //stringEqual(str)表示返回与上面获得的字符串相同的V中元素的下标,即找上一个子集

path[i][j] = path[v][stringEqual(str)] + i;

k++;

// 寻找最小距离

while (k < V[j].length()) {

vStr = "" + V[j].charAt(k);

v = Integer.parseInt(vStr);

str = getSubString(k, j);

if (min > c[i][v] + d[v][stringEqual(str)]) {

min = c[i][v] + d[v][stringEqual(str)];

path[i][j] = path[v][stringEqual(str)] + i;

}

k++;

}

// V[j].substring(beginIndex, endIndex)

// System.out.println(path[i][j]);

return min;// 返回最小值

}

// 处理函数

public void dynamic() {

d = new int[N][(int) Math.pow(2, N - 1)];// 分配空间

path = new String[N][(int) Math.pow(2, N - 1)];

for (int i = 1; i < N; i++) {// 初始化第一列

d[i][0] = c[i][0];

path[i][0] = "0" + i;// 初始化第一个元素,即为出发城市顶点

// System.out.print(d[i][0] + " ");

}

// 初始化后面的元素

int j = 1;

for (; j < (int) Math.pow(2, N - 1) - 1; j++)

for (int i = 1; i < N; i++) {

if (exclude(i, j))// 判断V子集中是否包含当前顶点,即V[j]中是否包含i

{

// System.out.println("done!" + i + " " + j);

d[i][j] = min(i, j);// 寻找最小距离

}

}

d[0][j] = min(0, j);// 初始化组后一列

}

// 输出中间结果,各个数组,用于调试程序

public void print() {

System.out.println("显示定点生成子集:");

for (int i = 0; i < (int) Math.pow(2, N - 1); i++)

System.out.print(V[i] + " ");

// for(int i = 0 ; i < c.length ; )

System.out.println();

System.out.println("打印代价矩阵:");

for (int i = 0; i < N; i++) {

for (int j = 0; j < N; j++)

System.out.print(c[i][j] + " ");

System.out.println();

}

System.out.println("动态规划表填表结果:");

for (int i = 0; i < N; i++) {

for (int j = 0; j < (int) Math.pow(2, N - 1); j++)

System.out.print(d[i][j] + " ");

System.out.println();

}

}

// 输出最短路径

public void printShortestPath() {

// 输出所经城市

System.out.print("经过城市:");

String str = path[0][(int) Math.pow(2, N - 1) - 1];

// System.out.println(str);

System.out.print(str.charAt(str.length() - 1));

for (int i = str.length() - 2; i >= 0; i--) {

System.out.print("->" + str.charAt(i));

}

System.out.println("会有最短路径");

System.out.println("最短路径为:" + d[0][(int) Math.pow(2, N - 1) - 1]);

}

// 主函数

public static void main(String[] args) {

TSPDP TSP = new TSPDP();

TSP.dynamic();// 求最短路径

TSP.print();//打印中间结果,测试和理解用

TSP.printShortestPath();// 输出最短路径

}

}

// 测试数据

/*

* 99999 3 6 7

* 5 99999 2 3

* 6 4 99999 2

* 3 7 5 99999

*/

6.1.2结果

(1)

(2)

(3)

(4)

6.2贪心法

6.2.1源代码

/*

* TSP:贪心法之最近邻点策略求解

*/

package Tsp;

import java.util.Scanner;

public class TSPGreedy {

int[] V;// 存放旅行所经过的城市顶点

int[][] c;// 存放每两座城市间的距离,注意:若路径不存在或同一城市间距离为无穷大

int[] path;// 存放旅行所经过的每两座城市间的距离

int N;// 城市个数

int shortestPath;// 表示最短路径

int u0;// 出发城市编号

static int IFINITE = 99999;// 无穷大距离表示城市自己到达自己时,距离无穷大,不作为考虑因素

public TSPGreedy() {

initialC();

}

// 得到最短路径

public int getShortestPath() {

for (int i = 0; i < N; i++) {

shortestPath += path[i];

}

return shortestPath;

}

// 初始化数组c[],即顶点间距离

public void initialC() {

Scanner in = new Scanner(System.in);

System.out.println("请输入城市个数:(注意根据实际情况城市个数不可小于1!)");

N = in.nextInt();

if (N <= 1) {

System.out.println("不符合要求,请认真核对!");

System.exit(0);// 输入错误,结束!

}

System.out.println("请输入城市相邻城市间距离(城市从0开始编号,且出发城市为第0个城市!): ");

c = new int[N][N];// 为c分配空间

for (int i = 0; i < N; i++)

for (int j = 0; j < N; j++) {

c[i][j] = in.nextInt(); // 输入时,按城市编号从小到大,如若两城市间没有公路相连,则距离为无穷大。本城市与本城市间距离也为无穷大。

}

}

public void tspGreedy() {

Scanner in = new Scanner(System.in);

System.out.println("请输入出发城市编号(注意城市从0开始编号,请按照输入城市间距离即初始化c[][]时顺序计算):");

u0 = in.nextInt();

V = new int[N + 1];

path = new int[N];

int k = 0;

V[k] = u0;

while (k < N) {

int min = IFINITE;

k++;

for (int i = 0; i < N; i++) {

int mark = 0;

for (int j = 0; j < k; j++)

if (V[j] == i)

mark = 1;

if (mark == 0 && c[V[k - 1]][i] < min) {

min = c[V[k - 1]][i];

V[k] = i;

}

}

path[k - 1] = min;

}

V[k] = u0;

path[k - 1] = c[V[k - 1]][V[k]];

}

// 输出最短路径下所经城市,两城市间距离和最短路径

public void print() {

shortestPath = 0;

System.out.println("按照下列方式旅游会使所走路程最短:");

for (int i = 0; i < N; i++) {

System.out.println("从" + V[i] + "->" + V[i + 1] + ",所经路程为:"

+ path[i]);

shortestPath += path[i];

}

System.out.println("总路程为:" + shortestPath);

}

public static void main(String[] args) {

TSPGreedy tg = new TSPGreedy();

tg.tspGreedy();

//tg.print();

}

}

/*

* 99999 3 3 2 6

* 3 99999 7 3 2

* 3 7 99999 2 5

* 2 3 2 99999 3

* 6 2 5 3 99999

*/

6.2.2结果

(1)

(2)

(3)

(4)

6.3回溯法(回溯法+深度优先搜索策略)

6.3.1源代码

#include

#include

using namespace std;

const int MAXSIZE = 100;

const int MAX = 1000000000;

int g_iArr[MAXSIZE][MAXSIZE];//邻接矩阵

int g_iResult;//存放最优解

int g_iPath[MAXSIZE];//存放最优路径上

int g_n;//元素个数

int g_iCurResult;//当前累加路径和

int g_iBestPath[MAXSIZE];//还需要设置一个数组,用来保存最优解

void swap(int* pI,int* pJ)

{

int iTemp = *pI;

*pI= *pJ;

*pJ = iTemp;

}

void printResult(int n,int* pArr)

{

cout<<"最短距离为:"<

cout<

cout<<"最优路线为:"<

for(int i = 1 ; i <= n ; i++)

{

if( i != 1)

{

cout<<"->"<

}

else

{

cout<

}

}

cout<<"->1"<

}

//可以做成字符串全排列的性质track(int i,int* pArr,int* pResult),其中pArr是用于存放最优解的路径

void backTrace(int i,int* pArr)

{//递归基:如果已经遍历到叶子节点的上一层节点

if(i == g_n)

{

//判断累加和是否超过最大值,如果有0,应该排除;满足这个条件,才打印

if((g_iArr[pArr[i-1]][pArr[i]] != 0) && (g_iArr[pArr[g_n]][1] != 0) && (g_iCurResult + g_iArr[pArr[i-1]][pArr[i]] + g_iArr[pArr[g_n]][1] < g_iResult ))

{

g_iResult = g_iCurResult + g_iArr[pArr[i-1]][pArr[i]] + g_iArr[pArr[g_n]][1];

//用当前最优路径去更新最优路径,防止下一次没有

for(int k = 1 ; k <= g_n ; k++)

{

g_iBestPath[k] = pArr[k];

}

}

}//递归步:判断能否进入子树,需要尝试每一个节点

else

{

//尝试不同的组合

for(int j = i ; j <= g_n ; j++)

{

//判断能否进入子树:如果当前值+下一个连线值的和 < 最优值,就进入,0要pass if( (g_iArr[pArr[i-1]][pArr[j]] != 0) && (g_iCurResult + g_iArr[ pArr[i-1] ][ pArr[j] ] < g_iResult) )

{

//交换i与j,则i为当前可以尝试的范围

//为完成后面k个元素的排列,逐一对数组第n-k~n个元素呼唤。数组第一个元素为1,生成后面n-1个元素的排列

//数组第一个元素与第二个元素互换,第一个元素为2,第2个元素为1,生成后面的n-1个元素的排列...

swap(&pArr[i],&pArr[j]);

//更新当前累加值,是i-1与i的

g_iCurResult += g_iArr[ pArr[i-1] ][ pArr[i] ];

//递归

backTrace(i+1,pArr);

//回溯,清空累加值;能够走到这里,说明上述结果不是最优解,需要向求解树上一层回退

g_iCurResult -= g_iArr[pArr[i-1]][ pArr[i] ];

swap(&pArr[i],&pArr[j]);

}

}

}

}

void process()

TSP问题求解实验报告

TSP问题求解 (一)实验目的 熟悉和掌握遗传算法的原理,流程和编码策略,并利用遗传求解函数优化问题,理解求解TSP问题的流程并测试主要参数对结果的影响。 (二)实验原理 巡回旅行商问题 给定一组n个城市和俩俩之间的直达距离,寻找一条闭合的旅程,使得每个城市刚好经过一次且总的旅行距离最短。TSP问题也称为货郎担问题,是一个古老的问题。最早可以追溯到1759年Euler提出的骑士旅行的问题。1948年,由美国兰德公司推动,TSP成为近代组合优化领域的典型难题。TSP是一个具有广泛的应用背景和重要理论价值的组合优化问题。近年来,有很多解决该问题的较为有效的算法不断被推出,例如Hopfield神经网络方法,模拟退火方法以及遗传算法方法等。 TSP搜索空间随着城市数n的增加而增大,所有的旅程路线组合数为(n-1)!/2。在如此庞大的搜索空间中寻求最优解,对于常规方法和现有的计算工具而言,存在着诸多计算困难。借助遗传算法的搜索能力解决TSP问题,是很自然的想法。

基本遗传算法可定义为一个8元组: (SGA)=(C,E,P0,M,Φ,Г,Ψ,Τ) C ——个体的编码方法,SGA使用固定长度二进制符号串编码方法; E ——个体的适应度评价函数; P0——初始群体; M ——群体大小,一般取20—100; Ф——选择算子,SGA使用比例算子; Г——交叉算子,SGA使用单点交叉算子; Ψ——变异算子,SGA使用基本位变异算子; Т——算法终止条件,一般终止进化代数为100—500; 问题的表示 对于一个实际的待优化问题,首先需要将其表示为适合于遗传算法操作的形式。用遗传算法解决TSP,一个旅程很自然的表示为n个城市的排列,但基于二进制编码的交叉和变异操作不能适用。 路径表示是表示旅程对应的基因编码的最自然,最简单的表示方法。它在编码,解码,存储过程中相对容易理解和实现。例如:旅程(5-1-7-8-9-4-6-2-3)可以直接表示为(5 1 7 8 9 4 6 2 3) (三)实验内容 N>=8。

旅行商问题概述_郭靖扬

旅行商问题(TravelingSalesmanProblem,简称TSP)是一个著名的组合优化问题:给定n个城市,有一个旅行商从某一城市出发,访问每个城市各一次后再回到原出发城市,要求找出的巡回路径最短。如果用图论来描述,那就是已知带权图G= (C,L),寻出总权值最小的Hamilton圈。其中C={c1,c2,…,cn}表示n个城市的集合,L={lij|ci,cj∈C}是集合C中元素(城市)两两连接的集合,每一条边lij,都存在与之对应的权值dij,实际应用中dij可以表示距离、费用、时间、油量等。 TSP的描述虽然简单, 解决起来却很困难。最简单思路是用穷举法把所有可能的巡回路径全部列出来,最短的一个就是最优解,但这样只能处理很小规模的问题。旅行商问题属于 NP-complete问题, 是NP(non-deterministicpoly-nominal)问题中最难的一类,不能在多项式时间内求解。如果有n座城市,那么巡游路径共有(n-1)!/2条,计算的时间和(n-1)!成正比。当 城市数n=20,巡回路径有1.2×1018种,n=100, 巡回路径就有多达4.6×10155种,而据估计宇宙中基本粒子数“仅仅只有”1087个。 尽管如此,随着算法研究的逐步深入和计算机技术飞速提高,对TSP问题的研究不断取得进展。70年来,被征服的TSP规模从几十个城市增加到上万个城市。目前的最高记录是在2004年5月,找到的巡游瑞典24978个城镇的最优路径 (sw24978), 花费了84.8个CPU年。图1展示了TSP的研究进展,最近的二三十年时间里,被攻克的TSP规模高速增长,差不多是每十年增加一个数量级。照这样发展下去的话,再过20年就能解决上百万个城市的TSP,有专家甚至已经为此准备好了数据:全球190,4711个城市的坐标。当然,能不能达到这 个目标,有赖于未来计算技术的发展。 图1TSP的发展 字母后面的数字表示城市数,“sw24978”就是瑞典的 24978个城镇。 一、应用 旅行商问题具有重要的实际意义和工程背景。它一开始 是为交通运输而提出的,比如飞机航线安排、送邮件、快递服务、设计校车行进路线等等。实际上其应用范围扩展到了许多其他领域,下面举几个实例。 印制电路板转孔是TSP应用的经典例子,在一块电路板上打成百上千个孔,转头在这些孔之间移动,相当于对所有的孔进行一次巡游。把这个问题转化为TSP,孔相当于城市,孔到孔之间的移动时间就是距离。 为了避免大气干扰,使光学系统达到其衍射极限分辨率,欧美发达国家提出发展空间光干涉仪和综合孔径望远镜的计划。美国航空航天局有一个卫星群组成空间天文台(Space-basedObservatories)的计划, 用来探测宇宙起源和外星智慧生命。欧洲空间局也有类似的Darwin计划。对天体成像的时候,需要对两颗卫星的位置进行调整,如何控制卫星,使消耗的燃料最少,可以用TSP来求解。这里把天体看作城市,距离就是卫星移动消耗的燃料。 美国国家卫生协会在人类基因排序工作中用TSP方法绘制放射性杂交图。把DNA片断作为城市,它们之间的相似程度作为城市间的距离。法国科学家已经用这种办法作出了老鼠的放射性杂交图。 此外,旅行商问题还有电缆和光缆布线、晶体结构分析、数据串聚类等多种用途。更重要的是,它提供了一个研究组合优化问题的理想平台。很多组合优化问题,比如背包问题、分配问题、车间调度问题,和TSP同属NP-complete类,它们都是同等难度的,如果其中一个能用多项式确定性算法解决,那么其他所有的NP-complete类问题也能用多项式确定性算法解决。很多方法本来是从TSP发展起来的,后来推广到其他NP-complete类问题上去。 二、TSP求解方法 求解旅行商问题的方法可以分为两大类,一类是精确算法,目的是要找到理论最优解;另一类是近似算法,不强求最优解,只要找到“足够好”的满意解就可以了。 (一)精确算法 如前面所述,穷举法和全局搜索算法属于精确算法,但 旅行商问题概述 郭靖扬 (电子科技大学光电信息学院, 四川成都610054) 【摘要】旅行商问题是组合优化的经典问题,应用广泛,而且长期以来被作为NP-complete问题的理想研究平台。文章介绍 了旅行商问题的基础知识、应用,以及常用的求解方法。 【关键词】旅行商问题;组合优化;NP-complete;k-opt;智能算法【中图分类号】TP182【文献标识码】A【文章编号】1008-1151(2006)08-0229-02大众科技 DAZHONGKEJI2006年第8期(总第94期) No.8,2006 (CumulativelyNo.94) 【收稿日期】2006-03-18【作者简介】郭靖扬(1980-),四川宜宾人,电子科技大学光电信息学院硕士研究生。 229--

TSP问题的解决方案

《算法设计与分析》实验报告一 学号:姓名: 日期:20161230 得分: 一、实验内容: TSP问题 二、所用算法的基本思想及复杂度分析: 1、蛮力法 1)基本思想 借助矩阵把问题转换为矩阵中点的求解。首先构造距离矩阵,任意节点到自身节点的距离为无穷大。在第一行找到最小项a[1][j],从而跳转到第j行,再找到最小值a[j][k],再到第k行进行查找。。。然后构造各行允许数组row[n]={1,1…1},各列允许数组colable[n]={0,1,1….1},其中1表示允许访问,即该节点未被访问;0表示不允许访问,即该节点已经被访问。如果改行或该列不允许访问,跳过该点访问下一节点。程序再发问最后一个节点前,所访问的行中至少有1个允许访问的节点,依次访问这些节点找到最小的即可;在访问最后一个节点后,再次访问,会返回k=0,即实现访问源节点,得出一条简单回路。 2)复杂度分析 基本语句是访问下一个行列中最小的点,主要操作是求平方,假设有n个点,则计算的次 页脚内容1

数为n^2-n。T(n)=n*(n-1)=O(n^2)。 2、动态规划法 1)基本思想 假设从顶点s出发,令d(i, V’)表示从顶点i出发经过V’(是一个点的集合)中各个顶点一次且仅一次,最后回到出发点s的最短路径长度。 推导:(分情况来讨论) ①当V’为空集,那么d(i, V’),表示从i不经过任何点就回到s了,如上图的城市3->城市0(0 为起点城市)。此时d(i, V’)=Cis(就是城市i 到城市s 的距离)、 ②如果V’不为空,那么就是对子问题的最优求解。你必须在V’这个城市集合中,尝试每一个, 并求出最优解。 d(i, V’)=min{Cik +d(k, V’-{k})} 注:Cik表示你选择的城市和城市i的距离,d(k, V’-{k})是一个子问题。 综上所述,TSP问题的动态规划方程就出来了: 2)复杂度分析 和蛮力法相比,动态规划求解tsp问题,把原来时间复杂性O(n!)的排列转化为组合问题,从而降低了时间复杂度,但仍需要指数时间。 3、回溯法 1)基本思想 页脚内容2

模拟退火算法的旅行商问题

人工智能原理 实验报告 模拟退火算法解决TSP问题

目录 1 旅行商问题和模拟退火算法........................................... 错误!未定义书签。 旅行商问题................................................................... 错误!未定义书签。 旅行商问题的描述................................................. 错误!未定义书签。 模拟退火算法............................................................... 错误!未定义书签。 基本思想................................................................. 错误!未定义书签。 2 TSP模拟退火算法的实现................................................ 错误!未定义书签。 TSP算法实现............................................................... 错误!未定义书签。 TSP算法描述......................................................... 错误!未定义书签。 TSP算法流程......................................................... 错误!未定义书签。 TSP的C实现 .............................................................. 错误!未定义书签。 加载数据文件......................................................... 错误!未定义书签。 计算总距离的函数................................................. 错误!未定义书签。 交换城市的函数..................................................... 错误!未定义书签。 执行模拟退火的函数............................................. 错误!未定义书签。 实验结果......................................................................... 错误!未定义书签。 小结................................................................................. 错误!未定义书签。3源代码................................................................................ 错误!未定义书签。

货郎担问题或旅行商问题动态规划算法

#include #include #define maxsize 20 int n; int cost[maxsize][maxsize]; int visit[maxsize]={1}; //表示城市0已经被加入访问的城市之中 int start = 0; //从城市0开始 int imin(int num, int cur) { int i; if(num==1) //递归调用的出口 return cost[cur][start]; //所有节点的最后一个节点,最后返回最后一个节点到起点的路径 int mincost = 10000; for(i=0; i

{ /*if(mincost <= cost[cur][i]+cost[i][start]) { continue; //其作用为结束本次循环。即跳出循环体中下面尚未执行的语句。区别于break } */ visit[i] = 1; //递归调用时,防止重复调用 int value = cost[cur][i] + imin(num-1, i); if(mincost > value) { mincost = value; } visit[i] = 0;//本次递归调用完毕,让下次递归调用 } } return mincost;

} int main() { int i,j; // int k,e,w; n=4; int cc[4][4]={{0,10,15,20}, {5,0,9,10}, {6,13,0,12}, {8,8,9,0}}; for(i=0; i

实验报告:遗传算法在解决旅行商问题的应用

实验报告:用遗传算法解决旅行商问题的简单实现 实验目的:编写程序实现用遗传算法解决旅行商问题,研究遗传算法的工作原理和收敛性质。 实验者: 问题描述:TSP是一个具有广泛应用背景和重要理论价值的组合优化难题,TSP问题可以简单的描述为:已知N个城市之间的相互距离.现有一个旅行商必须遍历这N个城市,并且每个城市只能访一次,最后必须返回出发城市。如何安排他对这些城市的访问次序,可使旅行路线的总长度最短? 本次实验的目标问题中国大陆31个大城市的公路旅行商问题,数据来源是《中国大城市公路里程表》(后附)。 需求分析:TSP已经被证明是一个NP—Hard问题,即找不到一种算法能在多项式时间内求得问题的最优解。利用遗传算法,在一定时间内求得近似最优解的可能性比较大。实验目标是: 1)设计用遗传算法解决TSP问题的程序; 2)求出该TSP问题的(近似)最短路程; 3)求得相应的城市遍历序列; 4)检查算法收敛性,求解决该问题的(近似)最优遗传参数。 算法分析: 1.算法基本流程

2.编码策略与初始群体设定 TSP的一般编码策略主要有二进制表示、次序表示、路径表示、矩阵表示和边表示等。而路径编码是最直观的方式,以城市序号作为遗传基因。在本实验中,我们用一个N维向量来表示一个个体,N是城市总数,元素表示城市遍历顺序,以最后一个到达的城市为结束。则群体用一个N * POP的矩阵表示,POP为群体中的人口(个体数)。初始群体在空间中自动生成。 3.适应度函数及结束条件 适应度函数采用题目的目标函数——路径的总路程(包括回到出发点)。适应度越低,个体越优秀。由于暂时无法先验估计收敛性和目标结果,所以以一个参数,最大遗传代数MAXGEN作为程序结束控制。 4.遗传算子设计 遗传算子的设计方法主要有两大类:自然算法和贪心算法。自然算法是以大自然的进化规律为依据,大体采用“优胜劣汰”的机制来进行遗传;贪心算法则是以迅速收敛为目标,对个体进行更严格的选择和遗传处理。

[精品文档]旅行商问题

算法设计与分析实验报告实验三旅行商问题 院系: 班级:计算机科学与技术 学号: 姓名: 任课教师: 成绩: 湘潭大学 2016年5月

实验三旅行商问题 一. 实验内容 分别编程实现回溯法和分支限界法求TSP问题的最优解,分析比较两种算法的时间复杂度并验证分析结果。 二.实验目的 1、掌握回溯法和分支限界法解决问题的一般步骤,学会使用回溯法和分支限界法解决实际问题; 2、理解回溯法和分支限界法的异同及各自的适用范围。 三. 算法描述 旅行商问题的回溯法算法可描述如下: Template Class Traveling{ friend Type TSP(int ** , int[],int ,Type); Private; Void Backtrack(int i); Int n, //图G的顶点数 *x; //当前解 *bestx; //当前最优解 Type **a, //图G的邻接矩阵 cc, //当前费用 bestc,//当前最优解 NoEdge; //无边标记 }; Template Void Traveling : : backtrack(int i) {if(i ==n){

if(a[x[n-1]][x[n]]!=NoEdge&&a[x[n]][1]!=NoEdge&& (cc+a[x[n-1]][x[n]]+a[x[n]][1] +a[x[n]][1] Type TSP(Type**a, int v[], int n, Type NoEdge) {Traveling Y; //初始化Y Y.x = new int [n+1]; //置x为单位排列 For(int i = 1;i <= n;i++) Y.x[i] = i; Y.a = a; Y.n = n;

TSP实验报告

2012 年第一学期研究生课程考核 (实验报告、研究报告) 考核科目:算法分析与复杂性理论 学生所在学院:计算机科学与技术学院 学生所在学科:计算机应用技术 姓名: 学号: 学生类别:研究生

一、实验目的 1.通过TSP算法的具体实现,加深对算法复杂分析的理解。 2.通过TSP算法的具体实现,提高对NP完全问题的认识。 3.通过TSP算法的具体实现,理解不确定性算法。 4.通过TSP算法的具体实现,理解不确定性算法。 二、实验环境 实验平台:Visual C++ 6.0 编程语言:C++ 编程电脑配置: 三、实验内容描述 TSP(Travelling Salesman Problem)又称货郎担或巡回售货员问题,在运筹学、管理科学及工程实际中具有广泛的用途。及工程实际中具有广泛的用途。TSP问题是组合优化中的著名难题,一直受到人们的极大关注。由于其NP难题性质,至今尚未完全解决。此问题可以抽象描述为: 给出一个n个顶点网络(有向或无向),要求找出一个包含所有n个顶点的具有最小耗费的环路。其中,任何一个包含所有n个顶点的环路被称作一个旅行。 对于旅行商问题,顶点表示旅行商所要旅行的城市(包括起点)。边上权值给出了在两个城市旅行所需的路程。旅行表示当旅行商游览了所有城市后再回到出发点时所走的路线。 四、实验原理

许多研究表明,应用蚁群优化算法求解TSP问题优于模拟退火法、遗传算法、神经网络算法、禁忌算法等多种优化方法。 为说明该算法,引人如下的标记: m表示蚁群中蚂蚁的数量; 表示城市i和城市j之间的距离;表示t时刻位于城 市i的蚂蚁数,显然应满足,表示t时刻在ij连线上的信息数 量。在算法的初始时刻,将m只蚂蚁随机地放到n座城市上,此时各路径上的信息量相等,设。每只蚂蚁根据路径上保留的信息量独立地选择下一个城市。在时刻t,蚂蚁k从城市i转移到城市j 的概率为 其中,表示蚂蚁走下一步允许选择的所有城市,列表纪录了当前蚂蚁k所走过的城市,当所有n个城市都加入到中时,蚂 蚁k便完成了一次循环,此时蚂蚁走所走过的路径便是问题的一个解。是一个启发式因子,表示蚂蚁从城市i转移到城市j的期望程度,在蚂蚁算法中,通 常取 城市ij之间距离的倒数。α和β分别表示路径上信息量和启发示因子的重要程度。 当所有蚂蚁完成一次循环后,各路径上的信息量要根据下面的公式进行调整:

TSP问题算法分析

T S P问题算法分析集团企业公司编码:(LL3698-KKI1269-TM2483-LUI12689-ITT289-

算法第二次大作业 TSP问题算法分析 021251班 王昱(02125029) 一.问题描述 “TSP问题”常被称为“旅行商问题”,是指一名推销员要拜访多个地点时,如何找到在拜访每个地点一次后再回到起点的最短路径。 TSP问题在本实验中的具体化:从A城市出发,到达每个城市并且一个城市只允许访问一次,最后又回到原来的城市,寻找一条最短距离的路径。 二.算法描述 2.1分支界限法 2.1.1算法思想 分支限界法常以广度优先或以最小耗费(最大效益)优先的方式搜索问题的解空间树。 在分支限界法中,每一个活结点只有一次机会成为扩展结点。活结点一旦成为扩展结点,就一次性产生其所有儿子结点。在这些儿子结点中,导致不可行解或导致非最优解的儿子结点被舍弃,其余儿子结点被加入活结点表中。 此后,从活结点表中取下一结点成为当前扩展结点,并重复上述结点扩展过程。这个过程一直持续到找到所需的解或活结点表为空时为止。

2.1.2算法设计说明 设求解最大化问题,解向量为X=(x1,…,xn),xi的取值范围为Si,|Si|=ri。在使用分支限界搜索问题的解空间树时,先根据限界函数估算目标函数的界[down,up],然后从根结点出发,扩展根结点的r1个孩子结点,从而构成分量x1的r1种可能的取值方式。 对这r1个孩子结点分别估算可能的目标函数bound(x1),其含义:以该结点为根的子树所有可能的取值不大于bound(x1),即: bound(x1)≥bound(x1,x2)≥…≥bound(x1,…,xn) 若某孩子结点的目标函数值超出目标函数的下界,则将该孩子结点丢弃;否则,将该孩子结点保存在待处理结点表PT中。 再取PT表中目标函数极大值结点作为扩展的根结点,重复上述。 直到一个叶子结点时的可行解X=(x1,…,xn),及目标函数值 bound(x1,…,xn)。 2.2A*算法 算法思想 对于某一已到达的现行状态,如已到达图中的n节点,它是否可能成为最佳路径上的一点的估价,应由估价函数f(n)值来决定。假设g*(n)函数值表示从起始节点s到任意一个节点n的一条最佳路径上的实际耗散值。h*(n)函数值表示从任意节点n到目标节点ti的最佳路径的实际耗散值。其中ti是一个可能的目标节点。f*(n)函数值表示从起始s,通过某一指定的n到达目标节点ti的一条最佳路径的实际耗散值,并有 f*(n)=g*(n)+h*(n)。

TSP实验报告

(实验报告、研究报告) 考核科目:算法分析与复杂性理论 学生所在学院:计算机科学与技术学院 学生所在学科:计算机应用技术 姓名: 学号: 学生类别:研究生 一、实验目的 1.通过TSP算法的具体实现,加深对算法复杂分析的理解。

2.通过TSP算法的具体实现,提高对NP完全问题的认识。 3.通过TSP算法的具体实现,理解不确定性算法。 4.通过TSP算法的具体实现,理解不确定性算法。 二、实验环境 实验平台:Visual C++ 编程语言:C++ 编程电脑配置: 三、实验内容描述 TSP(Travelling Salesman Problem)又称货郎担或巡回售货员问题,在运筹学、管理科学及工程实际中具有广泛的用途。及工程实际中具有广泛的用途。TSP问题是组合优化中的著名难题,一直受到人们的极大关注。由于其NP难题性质,至今尚未完全解决。此问题可以抽象描述为: 给出一个n个顶点网络(有向或无向),要求找出一个包含所有n个顶点的具有最小耗费的环路。其中,任何一个包含所有n个顶点的环路被称作一个旅行。 对于旅行商问题,顶点表示旅行商所要旅行的城市(包括起点)。边上权值给出了在两个城市旅行所需的路程。旅行表示当旅行商游览了所有城市后再回到出发点时所走的路线。 四、实验原理 许多研究表明,应用蚁群优化算法求解TSP问题优于模拟退火法、遗传算法、神经网络算法、禁忌算法等多种优化方法。

为说明该算法,引人如下的标记: m表示蚁群中蚂蚁的数量; 表示城市i和城市j之间的距离;表示t时刻位于城市i的蚂蚁数,显然应满足,表示t时刻在ij连线上的信息数量。在算法的初始时刻,将m只蚂蚁随机地放到n座城市上,此时各路径上的信息量相等,设。每只蚂蚁根据路径上保留的信息量独立地选择下一个城市。在时刻t,蚂蚁k从城市i转移到城市j 的概率为 其中,表示蚂蚁走下一步允许选择的所有城市,列表纪录了当前蚂蚁k所走过的城市,当所有n个城市都加入到中时,蚂蚁k便完成了一次循环,此时蚂蚁走所走过的路径便是问题的一个解。是一个启发式因子,表示蚂蚁从城市i转移到城市j的期望程度,在蚂蚁算法中, 通常取 城市ij之间距离的倒数。α和β分别表示路径上信息量和启发示因子的重要程度。 当所有蚂蚁完成一次循环后,各路径上的信息量要根据下面的公式进行调整: 其中表示路径上信息的蒸发系数;表示信息的保留系数;表示本次循环路径ij上信息的增量。表示第k只蚂蚁在本次循环中留在路

Tsp问题的几种算法的分析

摘要 本文分析比较了tsp问题的动态规划算法,分支界限法,近似等算法。分析了旅行商问题的时间度特点,针对启发式算法求解旅行商问题中存在的一些问题提出了改进算法。此算法将群体分为若干小子集,并用启发式交叉算子,以较好利用父代个体的有效信息,达到快速收敛的效果,实验表明此算法能提高寻优速度,解得质量也有所提高。 关键词:旅行商问题TSP Abstract this paper analyzed the time complexity of traveling salesman problem,then put forward some imprivement towards the genetic algorithm for solving this problen: divding the population into some small parent individual well.so it can quickly get into convergence, the experimental result indicates the impwoved algorithm can accelerate the apeed of finding solution and improve the precision. Keywords traveling salesman problem; genetic algorithm; subset; henristic crossover operator

目录 1、摘要--------------------------------------------------------------1 2、Abstract---------------------------------------------------------1 3、Tsp问题的提法------------------------------------------------2 4、回溯法求Tsp问题--------------------------------------------3 5、分支限界法求Tsp问题--------------------------------------7 6、近似算法求解Tsp问题-------------------------------------10 7、动态规划算法解Tsp问题----------------------------------12

基于Boltzmann机的求解TSP问题的实验报告

姓名学号 实验成 绩 华中师范大学计算机科学系 实验报告书 实验题目:基于Boltzmann Machine的模拟退火算法解决TSP问题课程名称:智能计算 主讲教师:沈显君 辅导教师: 课程编号: 班级:2011级硕士 实验时间:2011.12.27

实验题目 基于Boltzmann Machine的模拟退火算法解决TSP问题 实验环境 操作系统:Microsoft Windows XP Professional 编程平台:Microsoft Visual C++ 6.0 TSP问题 旅行商问题(TSP,Traveling Salesman Problem)是著名的组合优化问题之一。可以描述如下:设n为城市数目,D=[d ij]为n*n的矩阵,d ij表示从城市i到城市j的距离,其中i,j=0,1,…,n-1,则TSP的解就是从某一城市出发经过所有城市恰好一次最后回到出发点的最短路径。 Boltzmann Machine 波尔兹曼机(Boltzmann Machine)是一种多层网络,由输入层,输出层和隐层构成,隐单元之间相互连接。网络状态按照概率分布变化,网络中单元状态可取0,1两种值,每个单元的状态的转换是一随机函数。如把状态的0或1看成拒绝或接受某一假设,则两者的连接强度可理解为两个假设之间的一致程度。 模拟退火(Simulated Annealing) 模拟退火算法借鉴了金属制品加工的退火过程,即为了提高金属制品的韧性和硬度将金属制品缓慢加热到一定温度,保持足够时间,然后以适宜速度冷却。 金属制品中的原子结构代表一种状态,每个状态对应一个能量,这是由原子

算法报告-旅行商问题模板讲解

《算法设计与课程设计》 题目: TSP问题多种算法策略 班级:计算机技术14 学号: 姓名: 指导老师: 完成日期: 成绩:

旅行商问题的求解方法 摘要 旅行商问题(TSP 问题)时是指旅行家要旅行n 个城市然后回到出发城市,要求各个城市经历且仅经历一次,并要求所走的路程最短。该问题又称为货郎担问题、邮递员问题、售货员问题,是图问题中最广为人知的问题。本文主要介绍用动态规划法、贪心法、回溯法和深度优先搜索策略求解TSP 问题,其中重点讨论动态规划法和贪心法,并给出相应求解程序。 关键字:旅行商问题;动态规划法;贪心法;回溯法;深度优先搜索策略 1引言 旅行商问题(TSP)是组合优化问题中典型的NP-完全问题,是许多领域内复杂工程优化问题的抽象形式。研究TSP 的求解方法对解决复杂工程优化问题具有重要的参考价值。关于TSP 的完全有效的算法目前尚未找到,这促使人们长期以来不断地探索并积累了大量的算法。归纳起来,目前主要算法可分成传统优化算法和现代优化算法。在传统优化算法中又可分为:最优解算法和近似方法。最优解算法虽然可以得到精确解,但计算时间无法忍受,因此就产生了各种近似方法,这些近似算法虽然可以较快地求得接近最优解的可行解,但其接近最优解的程度不能令人满意。但限于所学知识和时间限制,本文重点只讨论传统优化算法中的动态规划法、贪心法、回溯法和深度优先搜索策略。 2正文 2.1动态规划法 2.1.1动态规划法的设计思想 动态规划法将待求解问题分解成若干个相互重叠的子问题,每个子问题对应决策过程的一个阶段,一般来说,子问题的重叠关系表现在对给定问题求解的递推关系(也就是动态规划函数)中,将子问题的解求解一次并填入表中,当需要再次求解此子问题时,可以通过查表获得该子问题的解而不用再次求解,从而避免了大量重复计算。 2.1.2 TSP 问题的动态规划函数 假设从顶点i 出发,令'(,)d i V 表示从顶点i 出发经过'V 中各个顶点一次且仅一次,最后回到出发点i 的最短路径长度,开始时,{}'V V i =-,于是,TSP 问

人工智能TSP旅行商问题实验报告剖析

人工智能实验三实验报告 班级:姓名:学号: 一实验题目 TSP问题的遗传算法实现 旅行商问题(Traveling Salesman Problem, TSP),又译为旅行推销员问题、货担郎问题,简称为TSP问题,是最基本的路线问题。假设有n个可直达的城市,一销售商从其中的某一城市出发,不重复地走完其余n-1个城市并回到原出发点,在所有可能的路径中求出路径长度最短的一条。 应用遗传算法求解30/10个节点的TSP(旅行商问题)问题,求问题的最优解。 二实验目的 1 熟悉和掌握遗传算法的基本概念和基本思想; 2 理解和掌握遗传算法的各个操作算子,能够用选定的编程语言设计简单的遗传优化系统; 3 通过实验培养学生利用遗传算法进行问题求解的基本技能。 三实验要求 1 掌握遗传算法的基本原理、各个遗传操作和算法步骤; 2 要求求出问题最优解,若得不出最优解,请分析原因; 3 对实验中的几个算法控制参数进行仔细定义,并能通过实验选择参数的最佳值; 4 要求界面显示每次迭代求出的局部最优解和最终求出的全局最优解。 四数据结构 请说明染色体个体和群体的定义方法。 struct RanSeTi //染色体的个体的定义方法 { int city[cities]; //基因的排列(即城市的顺序,路径的组织) int adapt; //记录适应度 double p; //记录其在种群中的幸存概率 } RanSeTi [num], RanSeTi temp[num]; //用数组来存储染色体群体方法 五实验算法 1 说明算法中对染色体的编码方法,适应度函数定义方法 1)染色体的编码方法: 即为染色体个体定义过程中生成的基因排列(路径中城市的顺序)

旅行商问题的几种求解算法比较

旅行商问题的几种求解算法比较 作者: (xxx学校) 摘要:TSP问题是组合优化领域的经典问题之一,吸引了许多不同领域的研究工作者,包括数学,运筹学,物理,生物和人工智能等领域,他是目前优化领域里的热点.本文从动态规划法,分支界限法,回溯法分别来实现这个题目,并比较哪种更优越,来探索这个经典的NP(Nondeterministic Polynomial)难题. 关键词:旅行商问题求解算法比较 一.引言 旅行商问题(Travelling Salesman Problem),是计算机算法中的一个经典的难解问题,已归为NP一完备问题类.围绕着这个问题有各种不同的求解方法,已有的算法如动态规划法,分支限界法,回溯法等,这些精确式方法都是指数级(2n)[2,3]的,根本无法解决目前的实际问题,贪心法是近似方法,而启发式算法不能保证得到的解是最优解,甚至是较好的解释.所以我认为很多问题有快速的算法(多项式算法),但是,也有很多问题是无法用算法解决的.事实上,已经证明很多问题不可能在多项式时间内解决出来.但是,有很多很重要的问题他们的解虽然很难求解出来,但是他们的值却是很容易求可以算出来的.这种事实导致了NP完全问题.NP表示非确定的多项式,意思是这个问题的解可以用非确定性的算法"猜"出来.如果我们有一个可以猜想的机器,我们就可以在合理的时间内找到一个比较好的解.NP-完全问题学习的简单与否,取决于问题的难易程度.因为有很多问题,它们的输出极其复杂,比如说人们早就提出的一类被称作NP-难题的问题.这类问题不像NP-完全问题那样时间有限的.因为NP-问题由上述那些特征,所以很容易想到一些简单的算法――把全部的可行解算一遍.但是这种算法太慢了(通常时间复杂度为O(2^n))在很多情况下是不可行的.现在,没有知道有没有那种精确的算法存在.证明存在或者不存在那种精确的算法这个沉重的担子就留给了新的研究者了,或许你就是成功者. 本篇论文就是想用几种方法来就一个销售商从几个城市中的某一城市出发,不重复地走完其余N—1个城市,并回到原出发点,在所有可能的路径中求出路径长度最短的一条,比较是否是最优化,哪种结果好. 二.求解策略及优化算法 动态规划法解TSP问题 我们将具有明显的阶段划分和状态转移方程的规划称为动态规划,这种动态规划是在研究多阶段决策问题时推导出来的,具有严格的数学形式,适合用于理论上的分析.在实际应用中,许多问题的阶段划分并不明显,这时如果刻意地划分阶段法反而麻烦.一般来说,只要该问题可以划分成规模更小的子问题,并且原问题的最优解中包含了子问题的最优解(即满足最优子化原理),则可以考虑用动态规划解决.所以动态规划的实质是分治思想和解决冗余,因此,动态规划是一种将问题实例分解为更小的,相似的子问题,并存储子问题的解而避免计算重复的子问题,以解决最优化问题的算法策略. 旅行商问题(TSP问题)其实就是一个最优化问题,这类问题会有多种可能的解,每个解都有一个值,而动态规划找出其中最优(最大或最小)值的解.若存在若干个取最优值的解的话,它只取其中的一个.在求解过程中,该方法也是通过求解局部子问题的解达到全局最优解,但与分治法和贪心法不同的是,动态规划允许这些子问题不独立,(亦即各子问题可包含公共的子子问题)也允许其通过自身子问题的解作出选择,该方法对每一个子问题只解一次,并将结果保存起来,避免每次碰到时都要重复计算. 关于旅行商的问题,状态变量是gk(i,S),表示从0出发经过k个城市到达i的最短距离,S为包含k 个城市的可能集合,动态规划的递推关系为:

TSP问题《运筹学》综合性实验报告

华北科技学院基础部综合性实验 实验报告 课程名称运筹学B 实验学期 2011 至 2012 学年第 2 学期学生所在系部基础部 年级 09 专业班级计算B091班 学生姓名张成林学号 200909014101 任课教师孙士国 实验成绩

《 运筹学B 》课程综合性实验报告 开课实验室: 数学应用实验室 2012 年 6 月 13 日 实验题目 TSP 问题 一、实验目的 1)领会TSP 问题的理论和方法。 2)会编制上述方法的基于lingo 语言的计算程序,并用来求解有关问题。 3)熟悉求解TSP 问题的有关方法和理论。 4)针对所给问题编制程序,并上机计算其所需要的结果。 二、设备与环境 Lingo11.0 软件等 三、实验内容及要求 TSP 问题1 设有一个售货员从10个城市中的某一个城市出发,去其它9个城市推销产品。10个城市相互距离如下表。要求每个城市到达一次仅一次后,回到原出发城市。问他应如何选择旅行路线,使总路程最短。 城市 1 2 3 4 5 6 7 8 9 10 1 0 7 4 5 8 6 12 13 11 18 2 7 0 3 10 9 14 5 14 17 17 3 4 3 0 5 9 10 21 8 27 12 4 5 10 5 0 14 9 10 9 23 16 5 8 9 9 14 7 8 7 20 19 6 6 14 10 9 7 0 13 5 25 13 7 12 5 21 10 8 13 0 23 21 18 8 13 14 8 9 7 5 23 0 18 12 9 11 17 27 23 20 25 21 18 0 16 10 18 17 12 16 19 13 18 12 16 0 1.问题分析与建模: 设城市之间距离用矩阵d 来表示,其中d 为下三角矩阵,ij d 表示城市i 与城市j 之间的距离。设0--1矩阵s 用来表示经过的各城市之间的路线。设 ?? ?=j i j i s ij 到城市若从城市到城市若不从城市1 则该TSP 问题转化为如下线性模型: ∑∑=-== n i i j ij ij d s Z 21 1 min 112..2 2,3,,01j j ik ji k i j i ij s s t s s i n s ><>?=??+==???=?∑∑∑ 或

遗传算法求解TSP问题实验报告推荐文档

人工智能实验报告 实验六遗传算法实验II 一、实验目的: 熟悉和掌握遗传算法的原理、流程和编码策略,并利用遗传求解函数优化问题,理解求解TSP 问题的流程并测试主要参数对结果的影响。 二、实验原理: 旅行商问题,即TSP问题(Traveling Salesman Problem)是数学领域中著名问题之一。假设有一个旅行商人要拜访n个城市,他必须选择所要走的路径,路经的限制是每个城市只能拜访一次,而且最后要回到原来出发的城市。路径的选择目标是要求得的路径路程为所有路径之中的最小值。TSP问题是一个组合优化问题。该问题可以被证明具有NPC计算复杂性。因此,任何能使该问题的求解得以简化的方法,都将受到高度的评价和关注。 遗传算法的基本思想正是基于模仿生物界遗传学的遗传过程。它把问题的参数用基因代表,把问题的解用染色体代表(在计算机里用二进制码表示),从而得到一个由具有不同染色体的个体组成的群体。这个群体在问题特定的环境里生存竞争,适者有最好的机会生存和产生后代。后代随机化地继承了父代的最好特征,并也在生存环境的控制支配下继续这一过程。群体的染色体都将逐渐适应环境,不断进化,最后收敛到一族最适应环境的类似个体,即得到问题最优的解。要求利用遗传算法求解TSP问题的最短路径。 三、实验内容: 1、参考实验系统给出的遗传算法核心代码,用遗传算法求解TSP的优化问题,分析遗传算法求解不同规模TSP问题的算法性能。 2、对于同一个TSP问题,分析种群规模、交叉概率和变异概率对算法结果的影响。 3、增加1种变异策略和1种个体选择概率分配策略,比较求解同一TSP问题时不同变异策略及不同个体选择分配策略对算法结果的影响。 4、上交源代码。 四、实验报告要求: 1、画出遗传算法求解TSP问题的流程图。 开始初始化种群(随机产生城市坐标)确定种群规模、迭代次数、个体选择方式、交叉概率、变异概率等 计算染色体适应度值(城市之间的欧氏距离)按某个选择概率选择个体YES个体交叉个体变异P<迭代总次数N输入适应度最高的结

用遗传算法解决旅行商问题

用遗传算法解决旅行商问题 姓名:王晓梅 学号:1301281 班级:系统工程6班

一、问题背景 有一个销售员,要到n 个城市推销商品,他要找出一个包含所有n 个城市的具有最短路程的环路。 现在假设有10个城市,他们之间的距离如下。 { 0, 107, 241, 190, 124, 80, 316, 76, 152, 157}, { 107, 0, 148, 137, 88, 127, 336, 183, 134, 95}, { 241, 148, 0, 374, 171, 259, 509, 317, 217, 232}, { 190, 137, 374, 0, 202, 234, 222, 192, 248, 42}, { 124, 88, 171, 202, 0, 61, 392, 202, 46, 160}, { 80, 127, 259, 234, 61, 0, 386, 141, 72, 167}, { 316, 336, 509, 222, 392, 386, 0, 233, 438, 254}, { 76, 183, 317, 192, 202, 141, 233, 0, 213, 188}, { 152, 134, 217, 248, 46, 72, 438, 213, 0, 206}, { 157, 95, 232, 42, 160, 167, 254, 188, 206, 0} 将这10个城市分别编码为0,1,2,3,4,5,6,7,8,9。要求走完这10个城市,目标是使走的距离最短。 二、建立模型 ),...,1,(1) ,...,1,(1. .)(min 11 11n j j i n i j i t s j i n j ij n i ij ij n i n j ij x x d x =≠==≠=≠∑∑∑∑====

相关文档
最新文档