Dip  0.92.4
VRP_Concorde.h
Go to the documentation of this file.
1 //===========================================================================//
2 // This file is part of the Decomp Solver Framework. //
3 // //
4 // Decomp is distributed under the Common Public License as part of the //
5 // COIN-OR repository (http://www.coin-or.org). //
6 // //
7 // Authors: Matthew Galati, SAS Institute Inc. (matthew.galati@sas.com) //
8 // Ted Ralphs, Lehigh University (ted@lehigh.edu) //
9 // Jiadong Wang, Lehigh University (jiw408@lehigh.edu) //
10 // //
11 // Copyright (C) 2002-2019, Lehigh University, Matthew Galati, and Ted Ralphs//
12 // All Rights Reserved. //
13 //===========================================================================//
14 
15 #ifndef VRP_CONCORDE_INCLUDED
16 #define VRP_CONCORDE_INCLUDED
17 
18 //---
19 //--- Interface class to Concorde (TSP solver)
20 //---
21 
22 // --------------------------------------------------------------------- //
23 #include "VRP_ConcordeI.h"
24 
25 // --------------------------------------------------------------------- //
26 #define VRP_CONCORDE_DEBUG 0
27 #define VRP_CONCORDE_SOLVER_TINY 1
28 //#define VRP_CONCORDE_SOLVER_TINY 0
29 
30 // --------------------------------------------------------------------- //
31 // --------------------------------------------------------------------- //
33  public:
34  int m_nEdges;
35  int m_nVerts;
36  int * m_edgeList;
37  int * m_edgeValue;
38 
39  //index on complete graph to index on complete graph minus d-to-d edges
40  //int * m_edgeMapCtoN;
41  //index on complete graph minus d-to-d edges to index on complete graph
42  //int * m_edgeMapNtoC;
43 
44  public:
46  m_nEdges (0),
47  m_nVerts (0),
48  m_edgeList (0),
49  m_edgeValue (0)
50  //m_edgeMapCtoN(0),
51  //m_edgeMapNtoC(0)
52 {};
53 
54  void clear(){
55  m_nEdges = 0;
56  m_nVerts = 0;
59  //UTIL_DELARR(m_edgeMapCtoN);
60  //UTIL_DELARR(m_edgeMapNtoC);
61  }
62 
63  void setEdgeValue(const double * edgeValue){
64 
65  }
66 
67  void init(const int nVerts,
68  const int nEdges){
69  m_nVerts = nVerts;
70  m_nEdges = nEdges;
71  if(nEdges > 0){
72  m_edgeList = new int[2 * m_nEdges];
73  m_edgeValue = new int[ m_nEdges];
74  //m_edgeMapCtoN = new int[ m_nEdges];
75  //m_edgeMapNtoC = new int[ m_nEdges];
76  //UtilFillN(m_edgeMapCtoN, m_nEdges, -1);
77  //UtilFillN(m_edgeMapNtoC, m_nEdges, -1);
79  //m_edgeMapCtoN && m_edgeMapNtoC,
80  "Error: Out of Memory");
81  }
82  }
83 
85  clear();
86  };
87 };
88 
89 // --------------------------------------------------------------------- //
90 // --------------------------------------------------------------------- //
91 class VRP_Concorde {
92  public:
93  const VRP_Instance * m_vrp; //ptr to vrp instance
94  ConcordeGraph m_cgExpand; //complete graph expanded
95  int * m_CCoptTour; //store optimal tour out of concorde
96  double m_CCoptVal; //store optimal obj out of concorde
97  //tmp storage of doubles (sz = num of original edges)
98  double * tmpDblNOrigE;
99  //tmp storage of doubles (sz = num of original edges)
101 
102  public:
104  m_vrp (0),
105  m_cgExpand ( ) ,
106  m_CCoptTour (0),
107  m_CCoptVal ( ) ,
108  tmpDblNOrigE( ) ,
109  tmpIntNOrigE( ) {}
110 
115  }
116 
117  public:
118 
120  void init(const VRP_Instance * vrp) {
121  m_vrp = vrp;
123  m_CCoptTour = new int[m_cgExpand.m_nVerts];
124  CoinAssertHint(m_CCoptTour, "Error: Out of Memory");
125 
126  const UtilGraphLib & graphLib = m_vrp->m_graphLib;
127  tmpDblNOrigE = new double[graphLib.n_edges];
128  tmpIntNOrigE = new int [graphLib.n_edges];
130  "Error: Out of Memory");
131  }
132 
133 
135  //---
136  //--- To represent a VRP graph as a TSP instance we need to
137  //--- create (nRoutes-1) additional dummy depots and their
138  //--- associated customer edges.
139  //---
140  //--- Original VRP graph has depot=0 and n_vertices-1 customers
141  //--- depot => 0
142  //--- C => {1,..,n_vertices-1}
143  //--- Now, we will shift the customers back to index:
144  //--- C => {0,..,n_vertices-2}
145  //--- and make the depot indices
146  //--- depot => n_vertices-1, .... n_vertices - 1 + nRoutes
147  //---
148  //--- We do not want or need edges between dummy depots. But, it
149  //--- actually makes the accounting easier to have them. So, we will
150  //--- include them and treat this like a complete graph but make the
151  //--- edge weights on depot-depot edges high (or just fix to 0).
152  //---
153  //--- NOTE: changed to remove depot-to-depot edges, now using
154  //--- a mapping for the book-keeping
155  //---
156  int i, j, edgeIndex;
157  const UtilGraphLib & graphLib = m_vrp->m_graphLib;
158  const int nRoutes = m_vrp->m_numRoutes;
159  int nCustomers = graphLib.n_vertices - 1;
160  int nVerts = nCustomers + nRoutes;
161  int nEdges = UtilNumEdgesU(nVerts);
162  int * edgeList = NULL;
163  //int * edgeMapCtoN = NULL;
164  //int * edgeMapNtoC = NULL;
165 
166  //---
167  //--- Assumption: a complete undirected graph,
168  //--- (i,j) = (j,i), i!=j (setup for i>j)
169  //--- Loop thru edges: i: 1 -> n-1, j: 0 -> i-1
170  //--- Number of edges: m = (n^2 - n)/2 - (nR^2 - nR)/2
171  //---
172  m_cgExpand.init(nVerts, nEdges);
173  edgeIndex = 0;
174  //edgeIndexC = 0;
175  edgeList = m_cgExpand.m_edgeList;
176  //edgeMapCtoN = m_cgExpand.m_edgeMapCtoN;
177  //edgeMapNtoC = m_cgExpand.m_edgeMapNtoC;
178  for(i = 1; i < nVerts; i++){
179  for(j = 0; j < i; j++){
180  //printf("(i=%d, j=%d) edgeIndexC:%d edgeIndex:%d",
181  // i,j,edgeIndexC,edgeIndex);
182  //if(i >= nCustomers && j >= nCustomers)
183  // printf(" --> depot edge");
184  //printf("\n");
185  //edgeMapCtoN[edgeIndexC] = edgeIndex;
186  //edgeMapNtoC[edgeIndex ] = edgeIndexC;
187  //exclude depot-to-depot edges
188  //if(i < nCustomers || j < nCustomers){
189  edgeList[2*edgeIndex ] = i;
190  edgeList[2*edgeIndex+1] = j;
191  CoinAssert(edgeIndex < nEdges);
192  edgeIndex++;
193  //}
194  //edgeIndexC++;
195  }
196  }
197  //TODO: or, open up less, except for m_edgeMapCtoN?
198  // m_cgExpand.m_nEdges = edgeIndex;
199  //assert(m_cgExpand.m_nEdges ==
200  // (UtilNumEdgesU(nVerts) - UtilNumEdgesU(nRoutes)));
201  }
202 
203  void setExpandedCost(const double * origGraphCost){
204  //---
205  //--- origGraphCost contains the costs based on original graph
206  //---
207  //--- Original VRP graph has depot=0 and n_vertices-1 customers
208  //--- depot => 0
209  //--- C => {1,..,n_vertices-1}
210  //---
211  const UtilGraphLib & graphLib = m_vrp->m_graphLib;
212  const int nOrigEdges = graphLib.n_edges;
213  const int nOrigVerts = graphLib.n_vertices;
214  const int nRoutes = m_vrp->m_numRoutes;
215  const int nEdges = m_cgExpand.m_nEdges;
216  const int nCustomers = nOrigVerts - 1;
217  double * origGraphCostDbl = tmpDblNOrigE;
218  int * origGraphCostInt = tmpIntNOrigE;
219  int * edgeValue = m_cgExpand.m_edgeValue;
220  int i;
221  //---
222  //--- offset the orig (reduced costs) costs so all positive
223  //---
224 #if VRP_CONCORDE_DEBUG > 0
225  for(i = 0; i < nOrigEdges; i++){
226  printf("origGraphCost[%d -> %s]: %10.5f\n",
227  i, UtilEdgeToStr(i).c_str(), origGraphCost[i]);
228  }
229 #endif
230  const double * minElement = min_element(origGraphCost,
231  origGraphCost + nOrigEdges);
232  const double offset = min(0.0, *minElement);
233 #if VRP_CONCORDE_DEBUG > 0
234  printf("minElement = %10.5f offset = %10.5f\n", *minElement, -offset);
235 #endif
236  memcpy(origGraphCostDbl, origGraphCost, nOrigEdges * sizeof(double));
237  if(offset < 0.0){
238  UtilAddOffsetArr(nOrigEdges, -offset, origGraphCostDbl);
239  }
240 
241  //---
242  //--- scale to integers (do something very simple)
243  //--- just multiply by 1.0e4 and then round
244  //--- this should avoid any kind of overflow and
245  //--- give accuracy at the 4th decimal place which should be
246  //--- sufficient
247  //--- NOTE: epsilon=1.0e-6, 1.0e-4 causes overflow issues
248  //---
249  //int scaleFactor =
250  UtilScaleDblToIntArr(nOrigEdges,
251  origGraphCostDbl,
252  origGraphCostInt, 1.0e-3);
253  //UtilScaleDblToIntArrCC(nOrigEdges,
254  // origGraphCostDbl,
255  // origGraphCostInt);
256 #if VRP_CONCORDE_DEBUG > 0
257  //printf("scaleFactor = %d\n", scaleFactor);
258  for(i = 0; i < nOrigEdges; i++){
259  printf("origGraphCost[%d]: %10.5f -> %10d\n",
260  i,
261  origGraphCostDbl[i],
262  origGraphCostInt[i]);
263  //CoinAssert(origGraphCostInt[i] < bigCost);
264  }
265 #endif
266 
267  //---
268  //--- find max edge length for "bigM" on depot-to-depot edges
269  //--- check for integer overflow
270  //---
271  int bigCost = 0;
272  double bigCostDbl = 0.0;
273  int maxEdgeLen = *max_element(origGraphCostInt,
274  origGraphCostInt+nOrigEdges);
275  bigCostDbl = ((double)maxEdgeLen+1.0) * (double)m_cgExpand.m_nVerts;
276  if((256*bigCostDbl) > (double)CCutil_MAXINT) {
277  printf("WARNING: Large edge lengths!!!!\n");
278  bigCost = CCutil_MAXINT / 256;
279  }
280  else
281  bigCost = (maxEdgeLen+1) * m_cgExpand.m_nVerts;
282 
283  while(maxEdgeLen > bigCost){
284  printf("maxEdgeLen=%d > bigCost=%d !!! SCALE BY 10\n",
285  maxEdgeLen, bigCost);
286  //scale by 10
287  for(i = 0; i < nOrigEdges; i++){
288  origGraphCostInt[i] /= 10;//and int will trunc it
289  }
290  maxEdgeLen /= 10;
291  }
292  assert(maxEdgeLen < bigCost);
293 
294  //---
295  //--- shift the customers back to index
296  //--- C => {0,..,n_vertices-2}
297  //--- and make the depot indices
298  //--- depot => n_vertices-1, .... n_vertices - 1 + nRoutes
299  //---
300  //--- set all depot to depot costs to a big number (DON'T NEED)
301  //--- and
302  //--- duplicate the original depot to customer edges for dummies
303  //---
304  int origDepot = 0;
305  int origCost = 0;
306  int u, v, d, d1, d2, origIndex, newIndex, custIndex, depot;
307  for(u = 1; u < nOrigVerts; u++){
308  for(v = 1; v < u; v++){
309  origIndex = UtilIndexU(u,v);
310  newIndex = UtilIndexU(u-1, v-1);
311 #if VRP_CONCORDE_DEBUG > 0
312  printf("origIndex: [%d -> %s] to newIndex: [%d -> %s]\n",
313  origIndex, UtilEdgeToStr(origIndex).c_str(),
314  newIndex, UtilEdgeToStr(newIndex).c_str());
315 #endif
316  CoinAssert(origGraphCostInt[origIndex] >= 0);
317  CoinAssert(origGraphCostInt[origIndex] < bigCost);
318  edgeValue[newIndex] = origGraphCostInt[origIndex];
319  }
320  }
321  for(u = 1; u <= nCustomers; u++){
322  //get the original cost of customer to depot
323  origIndex = UtilIndexU(u, origDepot);
324  origCost = origGraphCostInt[origIndex];
325  //in the concorde graph, the customers are 0..c-1
326  custIndex = u - 1;
327  //in the concorde graph, the depots are c..c+r-1
328  for(d = 0; d < nRoutes; d++){
329  depot = nCustomers + d;
330  //get the index in the concorde graph based on complete graph
331  //newIndex = edgeMapCtoN[UtilIndexU(custIndex, depot)];
332  newIndex = UtilIndexU(custIndex, depot);
333  CoinAssert(newIndex < nEdges);
334  //CoinAssert(origGraphCostInt[origIndex] < bigCost);
335 #if VRP_CONCORDE_DEBUG > 0
336  printf("(u:%d,0) origIndex=%d origCost=%d d=%d cInd=%d nInd=%d\n",
337  u, origIndex, origCost, d,
338  UtilIndexU(custIndex, depot), newIndex);
339 #endif
340  edgeValue[newIndex] = origCost;
341  }
342  }
343  for(d1 = 1; d1 < nRoutes; d1++){
344  for(d2 = 0; d2 < d1; d2++){
345  newIndex = UtilIndexU(nCustomers + d1,
346  nCustomers + d2);
347  edgeValue[newIndex] = bigCost;//bigCost (causing overflow)
348  }
349  }
350 
351  //#if VRP_CONCORDE_DEBUG > 0
352  //for(i = 0; i < nEdges; i++){
353  //printf("newGraphCostInt[%d -> %s]: %d\n",
354  // i, UtilEdgeToStr(i).c_str(), edgeValue[i]);
355  //printf("newGraphCostInt[%d -> (%d,%d)]: %d\n",
356  // i,
357  // edgeList[2*i],
358  // edgeList[2*i+1],
359  // edgeValue[i]);
360  //}
361  //#endif
362  }
363 
364  int solveTSP(vector<int> & vrpRouteInd,
365  vector<double> & vrpRouteEls,
366  double infinity){
367 
368 
369  //---
370  //--- NOTE: using this requires linking with Cplex right now
371  //---
372  //--- int CCtsp_solve_dat (int ncount,
373  //--- CCdatagroup * indat,
374  //--- int * in_tour,
375  //--- int * out_tour,
376  //--- double * in_val,
377  //--- double * optval,
378  //--- int * success,
379  //--- int * foundtour,
380  //--- char * name,
381  //--- double * timebound,
382  //--- int * hit_timebound,
383  //--- int silent,
384  //--- CCrandstate * rstate);
385  //---
386 
387  //---
388  //--- Description:
389  //--- SOLVES the TSP over the graph specfied in the edgelist.
390  //--- - elist is an array giving the ends of the edges (in pairs)
391  //--- - elen is an array giving the weights of the edges.
392  //--- - in_tour gives a starting tour in node node node format (it can
393  //--- be NULL)
394  //--- - out_tour will return the optimal tour (it can be NULL, if it is
395  //--- not NULL then it should point to an array of length at least
396  //--- ncount.
397  //--- - in_val can be used to specify an initial upperbound (it can be
398  //--- NULL)
399  //--- - optval will return the value of the optimal tour.
400  //--- - success will be set to 1 if the run finished normally,
401  //--- and set to if the search was terminated early (by hitting
402  //--- some predefined limit)
403  //--- - foundtour will be set to 1 if a tour has been found (if success
404  //--- is 0, then it may not be the optimal tour)
405  //--- - name specifes a char string that will be used to name various
406  //--- files that are written during the branch and bound search
407  //--- (if it is NULL, then "noname" will be used - this will
408  //--- cause problems in a multithreaded program, so specify a
409  //--- distinct name in that case).
410  //--- - silent will suppress most output if set to a nonzero value.
411  //---
412  int returnCode = 0;
413  int silent = 2;
414  int success, foundtour, hit_timebound;
415 
416  CCrandstate rstate;
417  int seed = 1;
418  CCutil_sprand(seed, &rstate);
419 
420 
421  //do this once
422  int i, d1, d2;
423  const UtilGraphLib & graphLib = m_vrp->m_graphLib;
424  int nRoutes = m_vrp->m_numRoutes;
425  int nOrigVerts = graphLib.n_vertices;
426  int nCustomers = nOrigVerts - 1;
427  double upbound = infinity;
428  double optval = infinity;
429 
430  //---
431  //--- try tiny first, switch if needed... if fails
432  //--- for now, full blown solver is overkill... ?
433  //---
434  int * lower = new int[m_cgExpand.m_nEdges];
435  int * upper = new int[m_cgExpand.m_nEdges];
436  int * xsol = new int[m_cgExpand.m_nEdges];
437  for(i = 0; i < m_cgExpand.m_nEdges; i++){
438  lower[i] = 0;
439  upper[i] = 1;
440  xsol[i] = 0;
441  }
442  for(d1 = 1; d1 < nRoutes; d1++){
443  for(d2 = 0; d2 < d1; d2++){
444  upper[UtilIndexU(nCustomers + d1, nCustomers + d2)] = 0;
445  }
446  }
447  returnCode = CCtiny_bnc_msp (m_cgExpand.m_nVerts,
451  -1,//depot
452  lower,
453  upper,
454  &upbound,
456  &optval,
457  xsol,
458  1, //checkresult (make option)
459  1000); //nodelimit
460 
461  assert(returnCode != CC_TINYTSP_ERROR);
462  assert(returnCode != CC_TINYTSP_INFEASIBLE);
463  bool useFullSolver = false;
464  if(returnCode == CC_TINYTSP_SEARCHLIMITEXCEEDED){
465  printf("Search limit exceeded - let's go to full solver\n");
466  useFullSolver = true;
467  }
468 
469  delete [] lower;
470  delete [] upper;
471 
472  if(useFullSolver){
473  CCdatagroup dataGroup;
478  -1, &dataGroup);
479  char nameC[100];
480  string name = UtilStringRandom(10);
481  strcpy(nameC, name.c_str());
482 
483 #if VRP_CONCORDE_DEBUG > 0
484  printf("CONCORDE GRAPH:\n");
485  printf(" nVerts=%d nEdges=%d\n",
488  for(i = 0; i < m_cgExpand.m_nEdges; i++){
489  printf("(%4d,%4d) val:%4d\n",
490  m_cgExpand.m_edgeList[2*i],
491  m_cgExpand.m_edgeList[2*i+1],
493  }
494 #endif
495 
496  returnCode = CCtsp_solve_dat(m_cgExpand.m_nVerts,
497  &dataGroup,
498  NULL, //in_tour
499  m_CCoptTour,
500  NULL, //in_val,
501  &m_CCoptVal,
502  &success,
503  &foundtour,
504  nameC,
505  NULL, //timebound
506  &hit_timebound,
507  silent,
508  &rstate);
509  CoinAssert((success == 1) && (foundtour == 1));
510  }
511 
512 #if VRP_CONCORDE_DEBUG > 0
513  printf("Optimal Route:\n");
514 #endif
515 
516 
517  if(!useFullSolver){
518  vector<int> edgeListSol;
519  for(i = 0; i < m_cgExpand.m_nEdges; i++){
520  if(xsol[i]){
521 #if VRP_CONCORDE_DEBUG > 0
522  printf("(%d,%d) wt:%d\n",
523  m_cgExpand.m_edgeList[2*i],
524  m_cgExpand.m_edgeList[2*i+1],
526 #endif
527  edgeListSol.push_back(m_cgExpand.m_edgeList[2*i]);
528  edgeListSol.push_back(m_cgExpand.m_edgeList[2*i+1]);
529  }
530  }
531  createVrpRouteFromTspEdgeList(edgeListSol,
532  vrpRouteInd,
533  vrpRouteEls);
534  }
535  else{
538  vrpRouteInd,
539  vrpRouteEls);
540  }
541  return returnCode;
542  }
543 
544  void createVrpRouteFromTspEdgeList(vector<int> & tspEdgeList,
545  vector<int> & vrpRouteInd,
546  vector<double> & vrpRouteEls){
547 
548  int i, u, v;
549  int nVerts = m_vrp->m_graphLib.n_vertices;
550  int nCustomers = m_vrp->m_graphLib.n_vertices - 1;
551  int * depotEdges = tmpIntNOrigE;
552 
553  //---
554  //--- keep track of depot edges separate for 1-routes (els=2.0)
555  //---
556  UtilFillN(depotEdges, nVerts, 0);
557 #if VRP_CONCORDE_DEBUG > 0
558  printf("Optimal Route:\n");
559 #endif
560  for(i = 0; i < m_cgExpand.m_nVerts; i++){
561  //for(i = 0; i < tspRouteLen-1; i++){
562  u = tspEdgeList[2*i];
563  v = tspEdgeList[2*i+1];
564  u = u >= nCustomers ? 0 : u+1;
565  v = v >= nCustomers ? 0 : v+1;
566  CoinAssert((u + v) > 0);
567  if(u == 0){
568  depotEdges[v]++; //(0,v) depot edge
569  }
570  else if(v == 0){
571  depotEdges[u]++; //(u,0) depot edge
572  }
573  else{
574  vrpRouteInd.push_back(UtilIndexU(u,v));
575 #if VRP_CONCORDE_DEBUG > 0
576  printf("(%d,%d) -> %d\n", u, v, UtilIndexU(u,v));
577 #endif
578  }
579  }
580  UtilFillN(vrpRouteEls, vrpRouteInd.size(), 1.0);
581 
582  for(v = 1; v < nVerts; v++){
583  if(depotEdges[v]){
584  CoinAssert(depotEdges[v] >= 0);
585  CoinAssert(depotEdges[v] <= 2);
586  vrpRouteInd.push_back(UtilIndexU(v, 0));
587  vrpRouteEls.push_back(static_cast<double>(depotEdges[v]));
588 #if VRP_CONCORDE_DEBUG > 0
589  printf("%d D(%d,%d) -> %d\n",
590  depotEdges[v], v, 0, UtilIndexU(v,0));
591 #endif
592  }
593  }
594  }
595 
596  void createVrpRouteFromTspRoute(const int * tspRoute,
597  const int tspRouteLen,
598  vector<int> & vrpRouteInd,
599  vector<double> & vrpRouteEls){
600 
601  int i, u, v;
602  int nVerts = m_vrp->m_graphLib.n_vertices;
603  int nCustomers = m_vrp->m_graphLib.n_vertices - 1;
604  int * depotEdges = tmpIntNOrigE;
605 
606  //---
607  //--- keep track of depot edges separate for 1-routes (els=2.0)
608  //---
609  UtilFillN(depotEdges, nVerts, 0);
610 #if VRP_CONCORDE_DEBUG > 0
611  printf("Optimal Route Nodes:");
612  for(i = 0; i < tspRouteLen; i++){
613  printf("%d ", tspRoute[i]);
614  }
615  printf("\nOptimal Route Edges:\n");
616 #endif
617  for(i = 0; i < tspRouteLen-1; i++){
618  u = tspRoute[i] >= nCustomers ? 0 : tspRoute[i] +1;
619  v = tspRoute[i+1] >= nCustomers ? 0 : tspRoute[i+1]+1;
620  CoinAssert((u + v) > 0);
621  if(u == 0){
622  depotEdges[v]++; //(0,v) depot edge
623  }
624  else if(v == 0){
625  depotEdges[u]++; //(u,0) depot edge
626  }
627  else{
628  vrpRouteInd.push_back(UtilIndexU(u,v));
629  }
630 #if VRP_CONCORDE_DEBUG > 0
631  printf("(%d,%d) -> %d\n", u, v, UtilIndexU(u,v));
632 #endif
633  }
634  u = tspRoute[tspRouteLen-1] >= nCustomers ? 0
635  : tspRoute[tspRouteLen-1]+1;
636  v = tspRoute[0] >= nCustomers ? 0 : tspRoute[0] + 1;
637  CoinAssert((u + v) > 0);
638  if(u == 0){
639  depotEdges[v]++; //(0,v) depot edge
640  }
641  else if(v == 0){
642  depotEdges[u]++; //(u,0) depot edge
643  }
644  else{
645  vrpRouteInd.push_back(UtilIndexU(u,v));
646  }
647 #if VRP_CONCORDE_DEBUG > 0
648  printf("(%d,%d) -> %d\n", u, v, UtilIndexU(u,v));
649 #endif
650  UtilFillN(vrpRouteEls, vrpRouteInd.size(), 1.0);
651 
652  for(v = 1; v < nVerts; v++){
653  if(depotEdges[v]){
654  CoinAssert(depotEdges[v] >= 0);
655  CoinAssert(depotEdges[v] <= 2);
656  vrpRouteInd.push_back(UtilIndexU(v, 0));
657  vrpRouteEls.push_back(static_cast<double>(depotEdges[v]));
658 #if VRP_CONCORDE_DEBUG > 0
659  printf("%d D(%d,%d) -> %d\n",
660  depotEdges[v], v, 0, UtilIndexU(v,0));
661 #endif
662  }
663  }
664  }
665 
666  void createTSPLIBFile(const string fileName){
667  ofstream os;
668  int i, j, edgeIndex;
669  const int nVerts = m_cgExpand.m_nVerts;
670  const int * edgeValue = m_cgExpand.m_edgeValue;
671 
672  printf("Open File %s\n", fileName.c_str());
673 
674  UtilOpenFile(os, fileName);
675  os << "NAME: " << fileName << "\n"
676  << "TYPE: TSP\n"
677  << "DIMENSION: " << nVerts << "\n"
678  << "EDGE_WEIGHT_TYPE: EXPLICIT\n"
679  << "EDGE_WEIGHT_FORMAT: LOWER_DIAG_ROW\n"
680  << "EDGE_WEIGHT_SECTION\n";
681  os << " 0\n";
682  edgeIndex = 0;
683  for(i = 1; i < nVerts; i++){
684  for(j = 0; j < i; j++){
685  os << edgeValue[edgeIndex] << " ";
686  edgeIndex++;
687  }
688  os << " 0\n";
689  }
690  os << "EOF\n";
691 
692  os.close();
693  }
694 
695 
696 };
697 
698 
699 #endif
int UtilIndexU(const int i, const int j)
Definition: UtilMacros.h:134
int * m_CCoptTour
Definition: VRP_Concorde.h:95
std::string UtilStringRandom(int iLength)
Definition: UtilMacros.h:384
int * m_edgeValue
Definition: VRP_Concorde.h:37
void createVrpRouteFromTspRoute(const int *tspRoute, const int tspRouteLen, vector< int > &vrpRouteInd, vector< double > &vrpRouteEls)
Definition: VRP_Concorde.h:596
#define CC_TINYTSP_INFEASIBLE
Definition: VRP_ConcordeI.h:25
int * tmpIntNOrigE
Definition: VRP_Concorde.h:100
ConcordeGraph m_cgExpand
Definition: VRP_Concorde.h:94
int * m_edgeList
Definition: VRP_Concorde.h:36
#define CC_TINYTSP_SEARCHLIMITEXCEEDED
Definition: VRP_ConcordeI.h:24
int UtilNumEdgesU(const int n)
Definition: UtilMacros.h:128
void init(const int nVerts, const int nEdges)
Definition: VRP_Concorde.h:67
#define UTIL_DELARR(x)
Definition: UtilMacros.h:29
#define CoinAssertHint(expression, hint)
Definition: CoinError.hpp:184
double m_CCoptVal
Definition: VRP_Concorde.h:96
void UtilOpenFile(ifstream &fs, const char *fileName)
Definition: UtilMacros.h:526
UtilGraphLib m_graphLib
Data for an instance from VRPLIB.
Definition: VRP_Instance.h:31
int solveTSP(vector< int > &vrpRouteInd, vector< double > &vrpRouteEls, double infinity)
Definition: VRP_Concorde.h:364
const VRP_Instance * m_vrp
Definition: VRP_Concorde.h:93
int CCtsp_solve_dat(int ncount, CCdatagroup *indat, int *in_tour, int *out_tour, double *in_val, double *optval, int *success, int *foundtour, char *name, double *timebound, int *hit_timebound, int silent, CCrandstate *rstate)
void createVrpRouteFromTspEdgeList(vector< int > &tspEdgeList, vector< int > &vrpRouteInd, vector< double > &vrpRouteEls)
Definition: VRP_Concorde.h:544
std::string UtilEdgeToStr(const int index)
Definition: UtilMacros.h:246
#define CC_TINYTSP_MINIMIZE
Definition: VRP_ConcordeI.h:22
void UtilAddOffsetArr(const int arrLen, T offset, T *arr)
Definition: UtilMacros.h:352
void UtilFillN(T *to, const int size, const T value)
Definition: UtilMacros.h:158
int CCutil_graph2dat_matrix(int ncount, int ecount, int *elist, int *elen, int defaultlen, CCdatagroup *dat)
void setEdgeValue(const double *edgeValue)
Definition: VRP_Concorde.h:63
void buildExpandedCompleteGraph()
Definition: VRP_Concorde.h:134
#define CCutil_MAXINT
Definition: VRP_ConcordeI.h:26
#define CoinAssert(expression)
Definition: CoinError.hpp:183
#define CC_TINYTSP_ERROR
Definition: VRP_ConcordeI.h:23
void CCutil_sprand(int seed, CCrandstate *r)
void init(const VRP_Instance *vrp)
Definition: VRP_Concorde.h:120
int CCtiny_bnc_msp(int ncount, int ecount, int *elist, int *elen, int depot, int *lower, int *upper, double *upperbound, int objsense, double *optval, int *xsol, int checkresult, int searchlimit)
void createTSPLIBFile(const string fileName)
Definition: VRP_Concorde.h:666
int UtilScaleDblToIntArr(const int arrLen, const double *arrDbl, int *arrInt, const double oneDbl, int *oneInt, const double epstol=UtilEpsilon)
double * tmpDblNOrigE
Definition: VRP_Concorde.h:98
void setExpandedCost(const double *origGraphCost)
Definition: VRP_Concorde.h:203