Click here to Skip to main content
15,889,651 members
Articles / Programming Languages / C++/CLI
Article

Solution to Travelling Salesman Problem

Rate me:
Please Sign up or sign in to vote.
1.54/5 (18 votes)
21 Jan 20052 min read 192.8K   5.4K   32   21
Solution to a Travelling Salesman problem using Hamiltonian circuit, the efficieny is O(n^4) and I think it gives the optimal solution.

Introduction

Hereby, I am giving a program to find a solution to a Traveling Salesman Problem using Hamiltonian circuit, the efficiency is O (n^4) and I think it gives the optimal solution. Though I have provided enough comments in the code itself so that one can understand the algorithm that I m following, here I give the pseudocode.

Problem Statement

Find the order of cities in which a salesman should travel in order to start from a city, reaching back the same city by visiting all rest of the cities each only once and traveling minimum distance for the same.

ALT statement: Find a Hamiltonian circuit with minimum circuit length for the given graph.

Notations

G: Symmetric weighted undirectional graph with,

  • Number of vertices = No. of cities
  • Number of links = Number of paths
  • Weight of the link = Distance of the path.

Algorithm

MIN_CKT_LENGTH=INFINITY
for each vertex V in the graph G
  for each vertex V_N in the graph G such that V and V_N are different
   mark all vertices unvisited
   mark V as visited 
     for staring vertex as V and succeeding vertex as V_N, find circuit 
          such that path staring from V_N in that circut yeilds minimum 
          pathlength from V_N for all unvisited vertices by 
          visiting each vertex.( this path is obtained by greedy method).
       if currently obtained circuit length <= MIN_CKT_LENGTH then
         set MIN_CKT_LENGTH=newly obtained value
         copy the new circuit as hamiltonion circuit
       end if
     end for V_N
   end for V

code segment:

//for each vertex, S_V as a staring node

for(int S_V_id=0;S_V_id<n;S_V_id++)

{ 
      //for each and non start vertex as i
      for(i=0;i<n;i++)
      { 
          //set all to unvisited
          set_visited(ALL,FALSE);
          // set staring vertex as visited
          set_visited(S_V_id,TRUE);
          //reset/init minimum circuit
          reset_min_circuit(S_V_id);
          // obtain circuit for combination of S_V and i
          new_circuit_length=get_valid_circuit(S_V_id,i);
          // if newer length is less than the previously
          //calculated min then set it as min and set the
          //current circuit in hamiltonion circuit
          if(new_circuit_length<=min_circuit_length)
                SET_HAM_CKT(min_circuit_length=new_circuit_length);
       }

}

Example

Inputs

infinity: 999
no. of cities: 4
no. of paths: 6

 S D Dist
path0: 0 1 2
path1: 0 2 4
path2: 0 3 3
path3: 1 2 3
path4: 1 3 6
path5: 2 3 1

Algorithm proceeds as follows:

VV_NV_N-pathckt_length, ckt
(started with INFI,-)
MIN_CKT_LENGTH, HAM_CKT
(started with INFI,-)
011-2-39,0-1-2-3-0*9,0-1-2-3-0
 22-3-113,0-2-3-1-09,0-1-2-3-0
 33-2-19,0-3-2-1-0*9,0-3-2-1-0
100-3-29,1-0-3-2-1*9,1-0-3-2-1
 22-3-09,1-2-3-0-1*9,1-2-3-0-1
 33-2-013,1-3-2-0-19,1-2-3-0-1
200-1-313,2-0-1-3-29,1-2-3-0-1
 11-0-39,2-1-0-3-2*9,2-1-0-3-2
 33-0-19,2-3-0-1-2*9,2-3-0-1-2
300-1-29,3-0-1-2-3*9,3-0-1-2-3
 11-0-213,3-1-0-2-39,3-0-1-2-3
 22-1-09,3-2-1-0-3*9,3-2-1-0-3

Comments

This might be the overrun for lower values of vertex count but for large values of n, it's surely less than the exhaustive search as n increases n^4 < n! for n>6.

The optimality is the issue with this problem and as far as I am concerned, I think this algorithm yields the optimal Hamiltonian circuit if it exists at all.

Hereby I ask you people to evaluate my algorithm for different sets of test cases. In case of failure, please inform me with the set of input values, answer found by my code and the actual optimal answer.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Engineer
India India
Engg Student

Comments and Discussions

 
Questionthanks Pin
saeedmag4-Jul-12 6:47
saeedmag4-Jul-12 6:47 
QuestionSome question. Pin
Spas22110-Jan-12 2:29
Spas22110-Jan-12 2:29 
QuestionDocumentation Pin
garzon326-Jun-11 10:00
garzon326-Jun-11 10:00 
Questionheuristic Pin
Tamas Bege15-Dec-10 3:07
Tamas Bege15-Dec-10 3:07 
GeneralTHANKSSSSSSSSSS Pin
hamid_ss28-May-10 11:53
hamid_ss28-May-10 11:53 
GeneralMinor change !! Pin
patson3318-Mar-10 14:01
patson3318-Mar-10 14:01 
GeneralAlgorithm is not optimal Pin
KHDev4u10-Mar-06 12:20
KHDev4u10-Mar-06 12:20 
Sorry to report, but I have several examples of your algorithm not finding the optimal solution, even for small test cases. Not that it isn't everyone's dream to find a polynomial algorithm for an NP-Complete problem (in this case, it's NP-HARD!). I think every good computer scientist delves into the problem at one point or another and comes out with a better understanding of what makes NP-Complete problems "hard." Smile | :)

That being said, here is proof of non-optimality.

I modified your program to input data in a standard way. In matrix form:
(num nodes)
(dist0to0) (dist0to1) ... (dist0toN)
(dist1to0) (dist1to1) ... (dist1toN)
...
(distNto0) (distNto1) ... (distNtoN)

It makes sure to keep the distance from a node to itself as INFI. Then check out this simple test case (based on 10 points in a Euclidean space):

10
   0  583  584  201  291  526  337  327  180  304
 583    0 1030  633  854   90  389  353  405  638
 584 1030    0  420  362 1010  645  892  712  860
 201  633  420    0  254  601  277  475  293  504
 291  854  362  254    0  807  528  617  463  516
 526   90 1010  601  807    0  384  269  347  554
 337  389  645  277  528  384    0  389  247  570
 327  353  892  475  617  269  389    0  184  286
 180  405  712  293  463  347  247  184    0  325
 304  638  860  504  516  554  570  286  325    0


Your program came up with:
Minimum circuit length is: 3063
Circuit is:
<8> <1> <5> <7> <9> <0> <3> <4> <2> <6> <8>

Here is a better tour (probably optimal) found by a simple backtracking algo:
TOUR (2889): 0 4 2 3 6 1 5 7 9 8 0

Here is a much larger example.

rbg443 data from http://www.iwr.uni-heidelberg.de/groups/comopt/software/TSPLIB95/atsp/rbg443.atsp.gz[^].

The best known tour is 2720 (see http://www.informatik.uni-heidelberg.de/groups/comopt/software/TSPLIB95/ATSP.html[^]).

Just strip the header from the rbg443 data file (everything else is in the right format).

tsm < ../final/rbg443.txt
Enter no. of cities(MAX:2000):Enter paths:< source_id destination_id distance >
ids varying from 0 to 442
........................................................................................................................
........................................................................................................................
........................................................................................................................
...................................................................................


Minimum circuit length is: 3758
Circuit is:
<375> <189> <86> <395> <442> <423> <427> <392> <422> <441> <437> <436> <434> <414> <402> <433> <428> <426> <432> <409>
<404> <311> <415> <431> <413> <199> <251> <376> <313> <439> <430> <418> <412> <429> <425> <424> <420> <111> <212> <101>
<19> <364> <2> <140> <139> <34> <116> <95> <294> <81> <378> <417> <390> <142> <97> <239> <416> <252> <75> <388> <411>
<266> <293> <353> <410> <383> <317> <315> <408> <440> <393> <391> <385> <407> <291> <241> <270> <406> <389> <381> <405>
<275> <274> <373> <374> <368> <358> <403> <365> <233> <401> <380> <253> <310> <352> <400> <338> <82> <333> <399> <320>
<325> <357> <258> <286> <398> <89> <331> <397> <355> <123> <246> <319> <175> <396> <316> <394> <225> <269> <156> <387> <185>
<228> <386> <77> <256> <384> <152> <382> <261> <100> <435> <27> <314> <308> <377> <206> <148> <369> <113> <41> <62> <262>
<273> <178> <367> <354> <245> <366> <249> <237> <363> <205> <125> <438> <110> <362> <379> <69> <361> <278> <271> <360>
<240> <106> <267> <257> <234> <192> <191> <359> <283> <323> <356> <40> <183> <351> <226> <171> <350> <55> <349> <332>
<10> <107> <254> <93> <105> <302> <348> <312> <371> <347> <264> <255> <346> <318> <370> <49> <85> <306> <345> <54> <231>
<344> <149> <28> <343> <244> <232> <342> <421> <52> <277> <341> <372> <22> <337> <141> <218> <121> <45> <83> <51> <340>
<48> <272> <339> <265> <25> <336> <229> <126> <58> <335> <94> <39> <334> <243> <50> <71> <330> <248> <236> <329> <215>
<146> <145> <328> <227> <32> <144> <0> <99> <168> <98> <14> <90> <16> <327> <207> <238> <326> <263> <304> <324> <64> <103>
<322> <117> <76> <102> <321> <172> <279> <47> <143> <419> <23> <91> <181> <31> <84> <247> <137> <78> <219> <124> <122>
<309> <186> <153> <138> <56> <307> <20> <88> <305> <182> <37> <303> <1> <169> <87> <33> <79> <3> <118> <26> <301> <242>
<108> <73> <24> <60> <96> <80> <300> <15> <44> <57> <5> <42> <250> <176> <46> <299> <35> <104> <29> <298> <65> <61> <17>
<297> <74> <296> <18> <295> <292> <290> <260> <289> <288> <287> <285> <284> <282> <281> <280> <276> <268> <259> <235>
<230> <224> <223> <222> <221> <220> <217> <216> <214> <213> <211> <210> <209> <208> <204> <203> <202> <201> <200> <198>
<197> <196> <195> <194> <193> <190> <188> <187> <184> <180> <179> <177> <174> <173> <170> <112> <167> <166> <165> <164>
<163> <162> <161> <160> <159> <158> <157> <155> <154> <151> <150> <147> <136> <135> <134> <133> <132> <131> <130> <129>
<128> <127> <120> <119> <115> <114> <109> <92> <72> <70> <68> <67> <66> <63> <59> <53> <43> <38> <36> <30> <21> <13> <12>
<11> <9> <8> <7> <6> <4> <375>

Your solution of 3758 is not close to best known tour of 2720. A greedy algorithm based on Prim's shortest path finds a tour of around 3305.

Here is the modified version of the code (I only modified the input / output -- use diff to see what I changed):

<br />
/*<br />
+-------Program to solve travelling salesman problem------------------+<br />
| by:                                                                 |<br />
| 								      |<br />
| Omkar Joshi                                                         |<br />
| 21 Male                                                             |<br />
| Mubai,India.                                                        |<br />
|                                                                     |<br />
| efficiency: O(n^4)                                                  |<br />
| optimality: I think yes!!!!!!                                       |<br />
| but still under test for different graphs                           |<br />
| so PLEASE:::send me the test cases along with the optimal solution  |<br />
| where my algorithm fails to give the optimal solution.              |<br />
| Free to use and/or distribute for non-commercial purposes.          |<br />
+---------------------------------------------------------------------+<br />
*/<br />
/*<br />
example:<br />
	  2<br />
    [0]-------[1]<br />
     | \4     /|<br />
     |	 \  /  |<br />
    3|    /\   |3<br />
     | 6/    \ |<br />
    [3]-------[2]<br />
	  1<br />
<br />
    inputs:<br />
    infinity:999<br />
    no. of cities: 4<br />
    no. of paths:6<br />
<br />
	  S D Dist<br />
    path0:0 1 2<br />
    path0:0 2 4<br />
    path0:0 3 3<br />
    path0:1 2 3<br />
    path0:1 3 6<br />
    path0:2 3 1<br />
*/<br />
<br />
#include<stdio.h><br />
#include<stdlib.h><br />
#define ALL -1<br />
#define MAXCITIES 2000<br />
<br />
enum BOOL{FALSE,TRUE};<br />
long*visited;//visited nodes set here<br />
long*min_circuit;//min inner circuit for given node as start node at position indexed 0<br />
long*ham_circuit;//optimal circuit with length stored at position indexed 0<br />
long min_circuit_length;//min circuit lenth for given start node<br />
<br />
int n;//city count<br />
long matrix[MAXCITIES][MAXCITIES];//nondirectional nXn symmetric matrix<br />
//to store path distances as sourceXdestination<br />
long INFI;// INFINITY value to be defined by user<br />
<br />
// function resets minimum circuit for a given start node<br />
//with setting its id at index 0 and setting furthr node ids to -1<br />
void reset_min_circuit(int s_v_id)<br />
{<br />
	min_circuit[0]=s_v_id;<br />
	for(int i=1;i<n;i++)	min_circuit[i]=-1;<br />
}<br />
<br />
// marks given node id with given flag<br />
// if id==ALL it marks all nodes with given flag<br />
void set_visited(int v_id,BOOL flag)<br />
{<br />
	if(v_id==ALL)	for(int i=0;i<n;i++)	visited[i]=flag;<br />
	else		visited[v_id]=flag;<br />
}<br />
<br />
// function sets hamiltonion circuit for a given path length<br />
//with setting it at index 0 and setting furthr nodes from current min_circuit<br />
void SET_HAM_CKT(long pl)<br />
{<br />
	ham_circuit[0]=pl;<br />
	for(int i=0;i<n;i++)       ham_circuit[i+1]=min_circuit[i];<br />
	ham_circuit[n+1]=min_circuit[0];<br />
}<br />
<br />
//function sets a valid circuit by finiding min inner path for a given<br />
//combination start vertex and next vertex to start vertex such that<br />
// the 2nd vertex of circuits is always s_n_v and start and dest node is<br />
//always s_v for all possible values of s_n_v, and then returns the<br />
// valid circuit length for this combination<br />
<br />
long get_valid_circuit(int s_v,int s_n_v)<br />
{<br />
	int next_v,min,v_count=1;<br />
	long path_length=0;<br />
	min_circuit[0]=s_v;<br />
	min_circuit[1]=s_n_v;<br />
	set_visited(s_n_v,TRUE);<br />
	path_length+=matrix[s_v][s_n_v];<br />
	for(int V=s_n_v;v_count<n-1;v_count++)<br />
	{       	min=INFI;<br />
			for(int i=0;i<n;i++)<br />
				if(	matrix[V][i]<INFI && !visited[i]<br />
					&& matrix[V][i]<=min<br />
				  )<br />
					min=matrix[V][next_v=i];<br />
		set_visited(next_v,TRUE);<br />
		V=min_circuit[v_count+1]=next_v;<br />
		path_length+=min;<br />
	}<br />
	path_length+=matrix[min_circuit[n-1]][s_v];<br />
	return(path_length);<br />
}<br />
<br />
int main()<br />
{<br />
	//printf("Make sure that infinity value < sum of all path distances\nSet Infinity at (signed long):");<br />
	//scanf("%ld",&INFI);<br />
	INFI=(1<<28)-1;<br />
<br />
	int pathcount,i,j,source,dest,nxt;<br />
	long dist=0;<br />
	long new_circuit_length=INFI;<br />
	printf("Enter no. of cities(MAX:%d):",MAXCITIES);<br />
	scanf("%d",&n);<br />
	if (n > MAXCITIES){<br />
		printf("ERROR: Number of cities is more than max of %d\n", MAXCITIES);<br />
		return -1;<br />
	}<br />
<br />
	printf("Enter paths:< source_id destination_id distance >\n ids varying from 0 to %d\n",n-1);<br />
	//init all matrix distances to infinity<br />
	for(i=0;i<n;i++)<br />
		for(j=0;j<n;j++)<br />
			matrix[i][j]=INFI;<br />
<br />
	//Read in distance values for all possible paths in matrix (except from a node to itself).<br />
	for (i=0;i<n;i++){<br />
		for(j=0;j<n;j++){<br />
			scanf("%d",&nxt);<br />
			if (i != j){ matrix[i][j]=nxt; }<br />
		}<br />
	}<br />
<br />
/*******<br />
	//printf("Enter path count:");<br />
	//scanf("%d",&pathcount);<br />
<br />
	//populate the matrix<br />
	for(i=0;i<pathcount;i++)<br />
	{<br />
		printf("[path %d]:",i);<br />
		scanf("%d %d %ld",&source,&dest,&dist);<br />
		if(source!=dest)<br />
		     matrix[source][dest]=matrix[dest][source]=dist;<br />
	}<br />
*******/<br />
<br />
	visited=new long[n];<br />
	min_circuit=new long[n];<br />
	ham_circuit=new long[n+2];<br />
	min_circuit_length=INFI;<br />
	// algorithm<br />
	//for each vertex, S_V as a staring node<br />
	for(int S_V_id=0;S_V_id<n;S_V_id++)<br />
	{<br />
		printf("."); fflush(stdout);<br />
	        //for each and non start vertex as i<br />
		for(i=0;i<n;i++)<br />
		{       //set all to unvisited<br />
			set_visited(ALL,FALSE);<br />
			// set staring vertex as visited<br />
			set_visited(S_V_id,TRUE);<br />
			//reset/init minimum circuit<br />
			reset_min_circuit(S_V_id);<br />
			// obtain circuit for combination of S_V and i<br />
			new_circuit_length=get_valid_circuit(S_V_id,i);<br />
			// if newer length is less than the previously<br />
			//calculated min then set it as min and set the<br />
			//current circuit in hamiltonion circuit<br />
			if(new_circuit_length<=min_circuit_length)<br />
				SET_HAM_CKT(min_circuit_length=new_circuit_length);<br />
		}<br />
	}<br />
	printf("\n");<br />
// if any circuit found<br />
if(min_circuit_length<INFI)<br />
{<br />
	printf("\n\nMinimum circuit length is: %ld\nCircuit is:\n",min_circuit_length);<br />
	for(i=1;i<n+2;i++)	printf("<%ld> ",ham_circuit[i]);<br />
	printf("\n");<br />
}<br />
else	printf("\n\nNo hamiltonian circuit !");<br />
delete []visited;<br />
delete []min_circuit;<br />
delete []ham_circuit;<br />
}<br />


Your algorithm is an interesting approach though. New ideas for an old problem usually provide some insight.

Best,
-Kevin
GeneralRe: Algorithm is not optimal Pin
omkar joshi11-Mar-06 0:00
omkar joshi11-Mar-06 0:00 
GeneralRe: Algorithm is not optimal Pin
sirb27-Nov-11 0:28
sirb27-Nov-11 0:28 
QuestionP = NP? Pin
Cap'n Code22-Jan-05 6:21
Cap'n Code22-Jan-05 6:21 
AnswerRe: P = NP? Pin
Rui A. Rebelo22-Jan-05 7:39
Rui A. Rebelo22-Jan-05 7:39 
GeneralRe: P = NP? Pin
omkar joshi22-Jan-05 21:03
omkar joshi22-Jan-05 21:03 
AnswerRe: P = NP? Pin
omkar joshi22-Jan-05 21:03
omkar joshi22-Jan-05 21:03 
AnswerRe: P = NP? Pin
jbstjohn24-Jun-05 5:43
jbstjohn24-Jun-05 5:43 
GeneralRe: P = NP? Pin
Paul Conrad1-Jul-05 7:23
professionalPaul Conrad1-Jul-05 7:23 
GeneralRe: P = NP? Pin
Anonymous29-Aug-05 10:21
Anonymous29-Aug-05 10:21 
GeneralRe: P = NP? Pin
omkar joshi24-Jan-06 1:54
omkar joshi24-Jan-06 1:54 
GeneralRe: P = NP? Pin
omkar joshi24-Jan-06 1:27
omkar joshi24-Jan-06 1:27 
GeneralRe: P = NP? Pin
omkar joshi24-Jan-06 1:43
omkar joshi24-Jan-06 1:43 
GeneralRe: P = NP? Pin
jbstjohn9-Feb-06 4:16
jbstjohn9-Feb-06 4:16 
GeneralRe: P = NP? Pin
vishal_chauhan8-May-07 3:26
vishal_chauhan8-May-07 3:26 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.