tsp42.gms : TSP solution with subtour elimination

Description

This model solves a Symmetric TSP using a simple algorithm
that adds cuts to exclude subtours found in the previous
solution. The data set is dantzig42 from TSPLIB.


Large Model of Type : MIP


Category : GAMS Model library


Main file : tsp42.gms

$title TSP Solution with Subtour Elimination (TSP42,SEQ=213)

$onText
This model solves a Symmetric TSP using a simple algorithm
that adds cuts to exclude subtours found in the previous
solution. The data set is dantzig42 from TSPLIB.


Dantzig, G B, Fulkerson, and Johnson, Solution of a Large-Scale
Traveling-Salesman Problem. Operations Research 2 (1954), 393-410.

optimal solution: 699

Keywords: mixed integer linear programming, traveling salesman problem, iterative
          subtour elimination, cut generation
$offText

$eolCom //

option optCr = 0, limRow = 0, limCol = 0, solPrint = off;

Set i 'cities'
      / c1  'Manchester, N.H.',     c2  'Montpelier, Vt.',      c3  'Detroit, Mich.'
        c4  'Cleveland, Ohio',      c5  'Charleston, W.Va.',    c6  'Louisville, Ky.'
        c7  'Indianapolis, Ind.',   c8  'Chicago, Ill.',        c9  'Milwaukee, Wis.'
        c10 'Minneapolis, Minn.',   c11 'Pierre, S.D.',         c12 'Bismarck, N.D.'
        c13 'Helena, Mont.',        c14 'Seattle, Wash.',       c15 'Portland, Ore.'
        c16 'Boise, Idaho',         c17 'Salt Lake City, Utah', c18 'Carson City, Nevada'
        c19 'Los Angeles, Calif.',  c20 'Phoenix, Ariz.',       c21 'Santa Fe, N.M.'
        c22 'Denver, Colo.',        c23 'Cheyenne, Wyo.',       c24 'Omaha, Neb.'
        c25 'Des Moines, Iowa',     c26 'Kansas City, Mo.',     c27 'Topeka, Kans.'
        c28 'Oklahoma City, Okla.', c29 'Dallas, Tex.',         c30 'Little Rock, Ark.'
        c31 'Memphis, Tenn.',       c32 'Jackson, Miss.',       c33 'New Orleans, La.'
        c34 'Birmingham, Ala.',     c35 'Atlanta, Ga.',         c36 'Jacksonville, Fla.'
        c37 'Columbia, S.C.',       c38 'Raleigh, N.C.',        c39 'Richmond, Va.'
        c40 'Washington, D.C.',     c41 'Boston, Mass.',        c42 'Portland, Me.'      /;

Alias (i,j,k);

Table d(i,j)
        c1  c2  c3  c4  c5  c6  c7  c8  c9 c10 c11 c12 c13 c14 c15 c16 c17 c18 c19 c20 c21
   c2    8
   c3   39  45
   c4   37  47   9
   c5   50  49  21  15
   c6   61  62  21  20  17
   c7   58  60  16  17  18   6
   c8   59  60  15  20  26  17  10
   c9   62  66  20  25  31  22  15   5
   c10  81  81  40  44  50  41  35  24  20
   c11 103 107  62  67  72  63  57  46  41  23
   c12 108 117  66  71  77  68  61  51  46  26  11
   c13 145 149 104 108 114 106  99  88  84  63  49  40
   c14 181 185 140 144 150 142 135 124 120  99  85  76  35
   c15 187 191 146 150 156 142 137 130 125 105  90  81  41  10
   c16 161 170 120 124 130 115 110 104 105  90  72  62  34  31  27
   c17 142 146 101 104 111  97  91  85  86  75  51  59  29  53  48  21
   c18 174 178 133 138 143 129 123 117 118 107  83  84  54  46  35  26  31
   c19 185 186 142 143 140 130 126 124 128 118  93 101  72  69  58  58  43  26
   c20 164 165 120 123 124 106 106 105 110 104  86  97  71  93  82  62  42  45  22
   c21 137 139  94  96  94  80  78  77  84  77  56  64  65  90  87  58  36  68  50  30
   c22 117 122  77  80  83  68  62  60  61  50  34  42  49  82  77  60  30  62  70  49  21
   c23 114 118  73  78  84  69  63  57  59  48  28  36  43  77  72  45  27  59  69  55  27
   c24  85  89  44  48  53  41  34  28  29  22  23  35  69 105 102  74  56  88  99  81  54
   c25  77  80  36  40  46  34  27  19  21  14  29  40  77 114 111  84  64  96 107  87  60
   c26  87  89  44  46  46  30  28  29  32  27  36  47  78 116 112  84  66  98  95  75  47
   c27  91  93  48  50  48  34  32  33  36  30  34  45  77 115 110  83  63  97  91  72  44
   c28 105 106  62  63  64  47  46  49  54  48  46  59  85 119 115  88  66  98  79  59  31
   c29 111 113  69  71  66  51  53  56  61  57  59  71  96 130 126  98  75  98  85  62  38
   c30  91  92  50  51  46  30  34  38  43  49  60  71 103 141 136 109  90 115  99  81  53
   c31  83  85  42  43  38  22  26  32  36  51  63  75 106 142 140 112  93 126 108  88  60
   c32  89  91  55  55  50  34  39  44  49  63  76  87 120 155 150 123 100 123 109  86  62
   c33  95  97  64  63  56  42  49  56  60  75  86  97 126 160 155 128 104 128 113  90  67
   c34  74  81  44  43  35  23  30  39  44  62  78  89 121 159 155 127 108 136 124 101  75
   c35  67  69  42  41  31  25  32  41  46  64  83  90 130 164 160 133 114 146 134 111  85
   c36  74  76  61  60  42  44  51  60  66  83 102 110 147 185 179 155 133 159 146 122  98
   c37  57  59  46  41  25  30  36  47  52  71  93  98 136 172 172 148 126 158 147 124 121
   c38  45  46  41  34  20  34  38  48  53  73  96  99 137 176 178 151 131 163 159 135 108
   c39  35  37  35  26  18  34  36  46  51  70  93  97 134 171 176 151 129 161 163 139 118
   c40  29  33  30  21  18  35  33  40  45  65  87  91 117 166 171 144 125 157 156 139 113
   c41   3  11  41  37  47  57  55  58  63  83 105 109 147 186 188 164 144 176 182 161 134
   c42   5  12  55  41  53  64  61  61  66  84 111 113 150 186 192 166 147 180 188 167 140

   +   c22 c23 c24 c25 c26 c27 c28 c29 c30 c31 c32 c33 c34 c35 c36 c37 c38 c39 c40 c41
   c23   5
   c24  32  29
   c25  40  37   8
   c26  36  39  12  11
   c27  32  36   9  15   3
   c28  36  42  28  33  21  20
   c29  47  53  39  42  29  30  12
   c30  61  62  36  34  24  28  20  20
   c31  64  66  39  36  27  31  28  28   8
   c32  71  78  52  49  39  44  35  24  15  12
   c33  76  82  62  59  49  53  40  29  25  23  11
   c34  79  81  54  50  42  46  43  39  23  14  14  21
   c35  84  86  59  52  47  51  53  49  32  24  24  30   9
   c36 105 107  79  71  66  70  70  60  48  40  36  33  25  18
   c37  97  99  71  65  59  63  67  62  46  38  37  43  23  13  17
   c38 102 103  73  67  64  69  75  72  54  46  49  54  34  24  29  12
   c39 102 101  71  65  65  70  84  78  58  50  56  62  41  32  38  21   9
   c40  95  97  67  60  62  67  79  82  62  53  59  66  45  38  45  27  15   6
   c41 119 116  86  78  84  88 101 108  88  80  86  92  71  64  71  54  41  32  25
   c42 124 119  90  87  90  94 107 114  77  86  92  98  80  74  77  60  48  38  32   6;

Set lt(i,j) 'lower triangular';
lt(i,j)$(ord(i) > ord(j)) = yes;

Free   Variable z;
Binary Variable x(i,j);

Equation twomatch(i), obj;

obj..         z =e= sum(lt(i,j), d(i,j)*x(i,j));

twomatch(k).. sum(lt(i,k), x(i,k)) + sum(lt(k,j),x(k,j)) =e= 2;

Model match / obj, twomatch /;

solve match minimizing z using mip;

* display x.l;

* dynamic number of cuts
Set
   cycle          / cycle1*cycle50 /
   t     'tours'  / t1*t100 /
   cutindex(cycle,t) 'dynamic set for addressing cuts';

Equation cut(cycle,t) 'actual cuts';

Parameter
   cutcoeff(cycle,t,i,j) 'coefficients in cuts'
   cutlength(cycle,t)    'rhs for cuts';

cut(cutindex).. sum((i,j), cutcoeff(cutindex,i,j)*x(i,j)) =l= cutlength(cutindex) - 1;

Model tsp / obj, twomatch, cut /;

* used to find and display tours
Set
   s(i,j)      'current solution'
   tour(t,i,j) 'subtours'
   tt(t)       'current subtour'
   first(i,j)  'first (i,j) in S'
   reach(i,j)  "(i,j)'s connected to tour(tt)";

Scalar
   proceed
   done / 0 /;

Parameter results;  // for reporting
results('relaxed','obj')        = z.l;
results('relaxed','total equs') = match.numEqu;

Parameter solutions(*,i,j);
solutions('relaxed',i,j) = x.l(i,j);

loop(cycle,
*  initialization
   tour(t,i,j) = no;
   s(i,j)      = no;
   first(i,j)  = no;
   reach(i,j)  = no;
   done  = 0;
   tt(t) = no;
   tt(t)$(ord(t) = 1) = 1;         // initialize tt(1) = yes
   s(i,j) = yes$(x.l(i,j) > 0.5);  // initialize to current solution

   while(not done,
*     pick any (i,j) from remaining solutions
      first(i,j) = no;
      loop((i,j)$(card(first) = 0), first(i,j) = s(i,j););
*     display first;

*     this is he beginning of a new subtour
      tour(tt,first) = yes;
      s(first)       =  no;

      proceed = 1;
      while(proceed,
*        find (i,j)'s connected to tour(tt)
*        note that the loop over tt is just syntax: tt contains one element
         reach(i,j) = no;
         loop((tt,k),
            reach(s(i,j))$tour(tt,k,j) = yes;
            reach(s(i,j))$tour(tt,i,k) = yes;
            reach(s(i,j))$tour(tt,k,i) = yes;
            reach(s(i,j))$tour(tt,j,k) = yes;
         );
*        display tour, s, reach;

*        if reach = empty then we can stop the while loop
         if(card(reach) = 0, proceed = 0;);

*        add them to the current subtour
*        note that the loop over tt is just syntax: tt contains one element
         loop(tt, tour(tt,reach) = yes;);
         s(reach) = no;
      );
*     display tour;

*     if no remaining solutions, we are done
      if(card(s) = 0, done = 1;);

*     new subtour
      tt(t) = tt(t-1);   // t := t + 1
   );
   cutindex(cycle,t)$(sum(tour(t,i,j),1) > 0.5) = yes;

*  check
   option tour:0:1:1;
*  display tour;
   loop(cutindex(cycle,t),
      abort$(sum(tour(t,i,j),1) < 2.5) "subtour with 1 or 2 points";
   );
   if(sum(cutindex(cycle,t),1) > 1.5,
      cutcoeff(cycle,tour(t,i,j))$cutindex(cycle,t) = 1;
      cutlength(cutindex(cycle,t)) = sum(tour(t,i,j),1);

      option cutindex:0:1:1, cutcoeff:0:1:1;
*     display cutindex, cutcoeff, cutlength;

      solve tsp minimizing z using mip;
*     display x.l;

      results(cycle,'obj') = z.l;
      results(cycle,'cuts added') = sum(cutindex(cycle,t), 1);
      results(cycle,'total equs') = tsp.numEqu;
*     display results;

      solutions(cycle,i,j) = x.l(i,j);
   else
      display "Optimal solution found!";
      done = 1;
      solutions('optimal',i,j) = x.l(i,j);
   );
);

option x:0:0:1;

display x.l, results;