ReadProblem.c
Go to the documentation of this file.
1 #include "LKH.h"
2 
3 /*
4  * The ReadProblem function reads the problem data in TSPLIB format from the
5  * file specified in the parameter file (PROBLEM_FILE).
6  *
7  * The following description of the file format is extracted from the TSPLIB
8  * documentation.
9  *
10  * The file consists of a specification part and a data part. The specification
11  * part contains information on the file format and on its contents. The data
12  * part contains explicit data.
13  *
14  * (1) The specification part
15  *
16  * All entries in this section are of the form <keyword> : <value>, where
17  * <keyword> denotes an alphanumerical keyword and <value> denotes
18  * alphanumerical or numerical data. The terms <string>, <integer> and <real>
19  * denote character string, integer or real data, respectively. The order of
20  * specification of the keywords in the data file is arbitrary (in principle),
21  * but must be consistent, i.e., whenever a keyword is specified, all
22  * necessary information for the correct interpretation of the keyword has to
23  * be known.
24  *
25  * Below is given a list of all available keywords.
26  *
27  * NAME : <string>e
28  * Identifies the data file.
29  *
30  * TYPE : <string>
31  * Specifies the type of data. Possible types are
32  * TSP Data for a symmetric traveling salesman problem
33  * ATSP Data for an asymmetric traveling salesman problem
34  * HCP Hamiltonian cycle problem data.
35  * HPP Hamiltonian path problem data (not available in TSPLIB)
36  * GTSP Data for a symmetric equality generalized TSP
37  * AGTSP Data for an asymmetric equality generalized TSP
38  *
39  * COMMENT : <string>
40  * Additional comments (usually the name of the contributor or the creator of
41  * the problem instance is given here).
42  *
43  * DIMENSION : < integer>
44  * The number of nodes.
45  *
46  * EDGE_WEIGHT_TYPE : <string>
47  * Specifies how the edge weights (or distances) are given. The values are:
48  * ATT Special distance function for problem att48 and att532
49  * CEIL_2D Weights are Euclidean distances in 2-D rounded up
50  * CEIL_3D Weights are Euclidean distances in 3-D rounded up
51  * EUC_2D Weights are Euclidean distances in 2-D
52  * EUC_3D Weights are Euclidean distances in 3-D
53  * EXPLICIT Weights are listed explicitly in the corresponding section
54  * GEO Weights are geographical distances in kilometers (TSPLIB).
55  * Coordinates are given in the form DDD.MM where DDD are the
56  * degrees and MM the minutes
57  * GEOM Weights are geographical distances in meters (used for the
58  * world TSP). Coordinates are given in decimal form
59  * GEO_MEEUS Weights are geographical distances in kilometers, computed
60  * according to Meeus' formula. Coordinates are given in the
61  * form DDD.MM where DDD are the degrees and MM the minutes
62  * GEOM_MEEUS Weights are geographical distances, computed according to
63  * Meeus' formula. Coordinates are given in decimal form
64  * MAN_2D Weights are Manhattan distances in 2-D
65  * MAN_3D Weights are Manhattan distances in 3-D
66  * MAX_2D Weights are maximum distances in 2-D
67  * MAX_3D Weights are maximum distances in 3-D
68  *
69  * EDGE-WEIGHT_FORMAT : <string>
70  * Describes the format of the edge weights if they are given explicitly.
71  * The values are
72  * FUNCTION Weights are given by a function (see above)
73  * FULL_MATRIX Weights are given by a full matrix
74  * UPPER_ROW Upper triangular matrix
75  * (row-wise without diagonal entries)
76  * LOWER_ROW Lower triangular matrix
77  * (row-wise without diagonal entries)
78  * UPPER_DIAG_ROW Upper triangular matrix
79  * (row-wise including diagonal entries)
80  * LOWER_DIAG_ROW Lower triangular matrix
81  * (row-wise including diagonal entries)
82  * UPPER_COL Upper triangular matrix
83  * (column-wise without diagonal entries)
84  * LOWER_COL Lower triangular matrix
85  * (column-wise without diagonal entries)
86  * UPPER_DIAG_COL Upper triangular matrix
87  * (column-wise including diagonal entries)
88  * LOWER_DIAG_COL Lower triangular matrix
89  * (column-wise including diagonal entries)
90  *
91  * EDGE_DATA_FORMAT : <string>
92  * Describes the format in which the edges of a graph are given, if the
93  * graph is not complete. The values are
94  * EDGE_LIST The graph is given by an edge list
95  * ADJ_LIST The graph is given by an adjacency list
96  *
97  * NODE_COORD_TYPE : <string>
98  * Specifies whether the coordinates are associated with each node
99  * (which, for example may be used for either graphical display or
100  * distance computations.
101  * The values are
102  * TWOD_COORDS Nodes are specified by coordinates in 2-D
103  * THREED_COORDS Nodes are specified by coordinates in 3-D
104  * NO_COORDS The nodes do not have associated coordinates
105  * The default value is NO_COORDS. In the current implementation, however,
106  * the value has no significance.
107  *
108  * DISPLAY_DATA_TYPE : <string>
109  * Specifies how a graphical display of the nodes can be obtained.
110  * The values are
111  * COORD_DISPLAY Display is generated from the node coordinates
112  * TWOD_DISPLAY Explicit coordinates in 2-D are given
113  * BO_DISPLAY No graphical display is psossible
114  *
115  * The default value is COORD_DISPLAY if node coordinates are specifies and
116  * NO_DISPLAY otherwise. In the current implementation, however, the value
117  * has no significance.
118  *
119  * GTSP_SETS : <integer>
120  * specifies the number of clusters in this instance.
121  *
122  * EOF
123  * Terminates input data. The entry is optional.
124  *
125  * (2) The data part
126  *
127  * Depending on the choice of specifications some additional data may be
128  * required. These data are given corresponding data sections following the
129  * specification part. Each data section begins with the corresponding
130  * keyword. The length of the sectionis either explicitly known form the
131  * format specification, or the section is terminated by an appropriate
132  * end-of-section identifier.
133  *
134  * NODE_COORD_SECTION :
135  * Node coordinates are given in this section. Each line is of the form
136  *
137  * <integer> <real> <real>
138  *
139  * if NODE_COORD_TYPE is TWOD_COORDS, or
140  *
141  * <integer> <real> <real> <real>
142  *
143  * if NODE_COORD_TYPE is THREED_COORDS. The integers give the number of the
144  * respective nodes. The real numbers are the associated coordinates.
145  *
146  * EDGE_DATA_SECTION :
147  * Edges of the graph are specified in either of the two formats allowed in
148  * the EDGE_DATA_FORAT entry. If a type is EDGE_LIST, then the edges are given
149  * as a sequence of lines of the form
150  *
151  * <integer> <integer>
152  *
153  * each entry giving the terminal nodes of some edge. The list is terminated
154  * by a -1. If the type is ADJ_LIST, the section consists of adjacency lists
155  * for nodes.
156  * The adjacency list of a node x is specified as
157  *
158  * <integer> <integer> ... <integer> -1
159  *
160  * where the first integer gives the number of node x and the following
161  * integers (terminated by -1) the numbers of the nodes adjacent to x.
162  * The list of adjacency lists are terminated by an additional -1.
163  *
164  * FIXED_EDGES_SECTION :
165  * In this section, edges are listed that are required to appear in each
166  * solution to the problem. The edges to be fixed are given in the form
167  * (per line)
168  *
169  * <integer> <integer>
170  *
171  * meaning that the edge (arc) from the first node to the second node has
172  * to be contained in a solution. This section is terminated by a -1.
173  *
174  * DISPLAY_DATA_SECTION :
175  * If DISPLAY_DATA_TYPE is TWOD_DISPLAY, the 2-dimensional coordinates from
176  * which a display can be generated are given in the form (per line)
177  *
178  * <integer> <real> <real>
179  *
180  * The integers specify the respective nodes and the real numbers give the
181  * associated coordinates. The contents of this section, however, has no
182  * significance in the current implementation.
183  *
184  * TOUR_SECTION :
185  * A tour is specified in this section. The tour is given by a list of
186  * integers giving the sequence in which the nodes are visited in the tour.
187  * The tour is terminated by a -1. Note: In contrast to the TSPLIB format,
188  * only one tour can be given in this section. The tour is used to limit
189  * the search (the last edge to be excluded in a non-gainful move must not
190  * belong to the tour). In addition, the Alpha field of its edges is set to
191  * -1.
192  *
193  * EDGE_WEIGHT_SECTION :
194  * The edge weights are given in the format specifies by the EDGE_WEIGHT_FORMAT
195  * entry. At present, all explicit data are integral and is given in one of the
196  * (self-explanatory) matrix formats, with explicitly known lengths.
197  *
198  * GTSP_SET_SECTION :
199  * This section defines which nodes belong to which clusters. This section
200  * contains exactly M entries, where M is the number of clusters.
201  * Each entry has the following format:
202  * m v1 v2 ... vk(m) -1, where m is the cluster number (clusters are numbered
203  * from 1 to M), and v1 v2 ... vk(m) are vertices comprising cluster m
204  * (vertices are numbered from 1 to N).
205  */
206 
207 static const char Delimiters[] = " :=\n\t\r\f\v\xef\xbb\xbf";
208 static void CheckSpecificationPart(void);
209 static char *Copy(char *S);
210 static void CreateNodes(void);
211 static void Read_DIMENSION(void);
212 static void Read_DISPLAY_DATA_SECTION(void);
213 static void Read_DISPLAY_DATA_TYPE(void);
214 static void Read_EDGE_DATA_FORMAT(void);
215 static void Read_EDGE_DATA_SECTION(void);
216 static void Read_EDGE_WEIGHT_FORMAT(void);
217 static void Read_EDGE_WEIGHT_SECTION(void);
218 static void Read_EDGE_WEIGHT_TYPE(void);
219 static void Read_FIXED_EDGES_SECTION(void);
220 static void Read_GTSP_SETS(void);
221 static void Read_GTSP_SET_SECTION(void);
222 static void Read_NAME(void);
223 static void Read_NODE_COORD_SECTION(void);
224 static void Read_NODE_COORD_TYPE(void);
225 static void Read_TOUR_SECTION(FILE ** File);
226 static void Read_TYPE(void);
227 static int TwoDWeightType(void);
228 static int ThreeDWeightType(void);
229 
231 {
232  int i, K;
233  char *Line, *Keyword;
234 
235  if (!(ProblemFile = fopen(ProblemFileName, "r")))
236  eprintf("Cannot open PROBLEM_FILE: \"%s\"", ProblemFileName);
237  if (TraceLevel >= 1)
238  printff("Reading PROBLEM_FILE: \"%s\" ... ", ProblemFileName);
239  FirstNode = 0;
242  Name = Copy("Unnamed");
245  Distance = 0;
246  C = 0;
247  c = 0;
248  while ((Line = ReadLine(ProblemFile))) {
249  if (!(Keyword = strtok(Line, Delimiters)))
250  continue;
251  for (i = 0; i < (int) strlen(Keyword); i++)
252  Keyword[i] = (char) toupper(Keyword[i]);
253  if (!strcmp(Keyword, "COMMENT"));
254  else if (!strcmp(Keyword, "DEMAND_SECTION"))
255  eprintf("Not implemented: %s", Keyword);
256  else if (!strcmp(Keyword, "DEPOT_SECTION"))
257  eprintf("Not implemented: %s", Keyword);
258  else if (!strcmp(Keyword, "DIMENSION"))
259  Read_DIMENSION();
260  else if (!strcmp(Keyword, "DISPLAY_DATA_SECTION"))
262  else if (!strcmp(Keyword, "DISPLAY_DATA_TYPE"))
264  else if (!strcmp(Keyword, "EDGE_DATA_FORMAT"))
266  else if (!strcmp(Keyword, "EDGE_DATA_SECTION"))
268  else if (!strcmp(Keyword, "EDGE_WEIGHT_FORMAT"))
270  else if (!strcmp(Keyword, "EDGE_WEIGHT_SECTION"))
272  else if (!strcmp(Keyword, "EDGE_WEIGHT_TYPE"))
274  else if (!strcmp(Keyword, "EOF"))
275  break;
276  else if (!strcmp(Keyword, "FIXED_EDGES_SECTION"))
278  else if (!strcmp(Keyword, "GTSP_SETS"))
279  Read_GTSP_SETS();
280  else if (!strcmp(Keyword, "GTSP_SET_SECTION"))
282  else if (!strcmp(Keyword, "NAME"))
283  Read_NAME();
284  else if (!strcmp(Keyword, "NODE_COORD_SECTION"))
286  else if (!strcmp(Keyword, "NODE_COORD_TYPE"))
288  else if (!strcmp(Keyword, "TOUR_SECTION"))
290  else if (!strcmp(Keyword, "TYPE"))
291  Read_TYPE();
292  else
293  eprintf("Unknown keyword: %s", Keyword);
294  }
295  Swaps = 0;
296 
297  /* Adjust parameters */
298  if (Seed == 0)
299  Seed = (unsigned) time(0);
300  if (Precision == 0)
301  Precision = 100;
302  if (InitialStepSize == 0)
303  InitialStepSize = 1;
304  if (MaxSwaps < 0)
306  if (KickType > Dimension / 2)
307  KickType = Dimension / 2;
308  if (Runs == 0)
309  Runs = 10;
310  if (MaxCandidates > Dimension - 1)
311  MaxCandidates = Dimension - 1;
312  if (ExtraCandidates > Dimension - 1)
314  if (SubproblemSize >= Dimension)
316  else if (SubproblemSize == 0) {
317  if (AscentCandidates > Dimension - 1)
319  if (InitialPeriod < 0) {
320  InitialPeriod = Dimension / 2;
321  if (InitialPeriod < 100)
322  InitialPeriod = 100;
323  }
324  if (Excess < 0)
325  Excess = 1.0 / Dimension;
326  if (MaxTrials == -1)
328  }
329 
330  if (CostMatrix == 0 && Dimension <= MaxMatrixDimension && Distance != 0
332  WeightType != GEO && WeightType != GEOM &&
334  Node *Ni, *Nj;
335  assert(CostMatrix =
336  (int *) calloc((size_t) Dimension * (Dimension - 1) / 2,
337  sizeof(int)));
338  Ni = FirstNode->Suc;
339  do {
340  Ni->C =
341  &CostMatrix[(size_t) (Ni->Id - 1) * (Ni->Id - 2) / 2] - 1;
342  if (ProblemType != HPP || Ni->Id < Dimension)
343  for (Nj = FirstNode; Nj != Ni; Nj = Nj->Suc)
344  Ni->C[Nj->Id] = Fixed(Ni, Nj) ? 0 : Distance(Ni, Nj);
345  else
346  for (Nj = FirstNode; Nj != Ni; Nj = Nj->Suc)
347  Ni->C[Nj->Id] = 0;
348  }
349  while ((Ni = Ni->Suc) != FirstNode);
351  c = 0;
352  }
353  if (Precision > 1 && (WeightType == EXPLICIT || ProblemType == ATSP)) {
354  int j, n = ProblemType == ATSP ? Dimension / 2 : Dimension;
355  for (i = 2; i <= n; i++) {
356  Node *N = &NodeSet[i];
357  for (j = 1; j < i; j++) {
358  while (N->C[j] * Precision / Precision != N->C[j]) {
359  printff("PRECISION (= %d) is too large. ", Precision);
360  if ((Precision /= 10) < 1)
361  Precision = 1;
362  printff("Changed to %d\n", Precision);
363  }
364  }
365  }
366  }
367  if (SubsequentMoveType == 0)
371  if (PatchingC > K)
372  PatchingC = K;
373  if (PatchingA > 1 && PatchingA >= PatchingC)
374  PatchingA = PatchingC > 2 ? PatchingC - 1 : 1;
375  if (NonsequentialMoveType == -1 ||
378  if (ProblemType == HCP || ProblemType == HPP)
379  MaxCandidates = 0;
380  if (TraceLevel >= 1) {
381  printff("done\n");
382  PrintParameters();
383  } else
384  printff("PROBLEM_FILE = %s\n",
386  fclose(ProblemFile);
389  if (InputTourFileName)
393  if (MergeTourFiles >= 1) {
394  free(MergeTourFile);
395  assert(MergeTourFile =
396  (FILE **) malloc(MergeTourFiles * sizeof(FILE *)));
397  for (i = 0; i < MergeTourFiles; i++)
399  }
400  free(LastLine);
401  LastLine = 0;
402 }
403 
404 static int TwoDWeightType()
405 {
406  return WeightType == EUC_2D || WeightType == MAX_2D ||
407  WeightType == MAN_2D || WeightType == CEIL_2D ||
408  WeightType == GEO || WeightType == GEOM ||
410  WeightType == ATT ||
412 }
413 
414 static int ThreeDWeightType()
415 {
416  return WeightType == EUC_3D || WeightType == MAX_3D ||
417  WeightType == MAN_3D || WeightType == CEIL_3D ||
419 }
420 
422 {
423  if (ProblemType == -1)
424  eprintf("TYPE is missing");
425  if (Dimension < 3)
426  eprintf("DIMENSION < 3 or not specified");
427  if (WeightType == -1 && ProblemType != ATSP && ProblemType != HCP)
428  eprintf("EDGE_WEIGHT_TYPE is missing");
429  if (WeightType == EXPLICIT && WeightFormat == -1)
430  eprintf("EDGE_WEIGHT_FORMAT is missing");
432  eprintf("Conflicting EDGE_WEIGHT_TYPE and EDGE_WEIGHT_FORMAT");
433  if (WeightType != EXPLICIT
434  && (WeightType != SPECIAL || CoordType != NO_COORDS)
435  && WeightType != -1 && WeightFormat != -1
436  && WeightFormat != FUNCTION)
437  eprintf("Conflicting EDGE_WEIGHT_TYPE and EDGE_WEIGHT_FORMAT");
438  if (ProblemType == ATSP && WeightType != EXPLICIT && WeightType != -1)
439  eprintf("Conflicting TYPE and EDGE_WEIGHT_TYPE");
441  eprintf("Conflicting TYPE and EDGE_WEIGHT_FORMAT");
443  && MaxCandidates > 0)
444  eprintf
445  ("Illegal EDGE_WEIGHT_TYPE for CANDIDATE_SET_TYPE = DELAUNAY");
446  if (CandidateSetType == NN && !TwoDWeightType()
447  && !ThreeDWeightType() && MaxCandidates > 0)
448  eprintf
449  ("Illegal EDGE_WEIGHT_TYPE for CANDIDATE_SET_TYPE = "
450  "NEAREST-NEIGHBOR");
453  eprintf
454  ("Illegal EDGE_WEIGHT_TYPE for CANDIDATE_SET_TYPE = QUADRANT");
456  && !ThreeDWeightType() && ExtraCandidates > 0)
457  eprintf
458  ("Illegal EDGE_WEIGHT_TYPE for EXTRA_CANDIDATE_SET_TYPE = "
459  "NEAREST-NEIGHBOR");
461  && !ThreeDWeightType()
462  && ExtraCandidates > 0)
463  eprintf
464  ("Illegal EDGE_WEIGHT_TYPE for EXTRA_CANDIDATE_SET_TYPE = "
465  "QUADRANT");
467  && !ThreeDWeightType())
468  eprintf
469  ("Illegal EDGE_WEIGHT_TYPE for INITIAL_TOUR_ALGORITHM = "
470  "QUICK-BORUVKA");
472  eprintf
473  ("Illegal EDGE_WEIGHT_TYPE for INITIAL_TOUR_ALGORITHM = "
474  "SIERPINSKI");
476  eprintf("Illegal EDGE_WEIGHT_TYPE for DELAUNAY specification");
478  eprintf("Illegal EDGE_WEIGHT_TYPE for KARP specification");
480  eprintf("Illegal EDGE_WEIGHT_TYPE for MOORE specification");
482  eprintf("Illegal EDGE_WEIGHT_TYPE for ROHE specification");
484  eprintf("Illegal EDGE_WEIGHT_TYPE for SIERPINSKI specification");
486  eprintf("Illegal EDGE_WEIGHT_TYPE for BORDERS specification");
487 }
488 
489 static char *Copy(char *S)
490 {
491  char *Buffer;
492 
493  if (!S || strlen(S) == 0)
494  return 0;
495  assert(Buffer = (char *) malloc(strlen(S) + 1));
496  strcpy(Buffer, S);
497  return Buffer;
498 }
499 
500 static void CreateNodes()
501 {
502  Node *Prev = 0, *N = 0;
503  int i;
504 
505  if (Dimension <= 0)
506  eprintf("DIMENSION is not positive (or not specified)");
507  if (ProblemType == ATSP)
508  Dimension *= 2;
509  else if (ProblemType == HPP) {
510  Dimension++;
512  eprintf("Dimension too large in HPP problem");
513  }
514  assert(NodeSet = (Node *) calloc(Dimension + 1, sizeof(Node)));
515  for (i = 1; i <= Dimension; i++, Prev = N) {
516  N = &NodeSet[i];
517  if (i == 1)
518  FirstNode = N;
519  else
520  Link(Prev, N);
521  N->Id = i;
522  if (MergeTourFiles >= 1)
523  assert(N->MergeSuc =
524  (Node **) calloc(MergeTourFiles, sizeof(Node *)));
525  }
526  Link(N, FirstNode);
527 }
528 
529 static void Read_NAME()
530 {
531  if (!(Name = Copy(strtok(0, Delimiters))))
532  eprintf("NAME: string expected");
533 }
534 
535 static void Read_DIMENSION()
536 {
537  char *Token = strtok(0, Delimiters);
538 
539  if (!Token || !sscanf(Token, "%d", &Dimension))
540  eprintf("DIMENSION: integer expected");
542 }
543 
545 {
546  Node *N;
547  int Id, i;
548 
550  if (ProblemType == HPP)
551  Dimension--;
552  if (!DisplayDataType || strcmp(DisplayDataType, "TWOD_DISPLAY"))
553  eprintf
554  ("DISPLAY_DATA_SECTION conflicts with DISPLAY_DATA_TYPE: %s",
556  if (!FirstNode)
557  CreateNodes();
558  N = FirstNode;
559  do
560  N->V = 0;
561  while ((N = N->Suc) != FirstNode);
562  N = FirstNode;
563  for (i = 1; i <= Dimension; i++) {
564  if (!fscanint(ProblemFile, &Id))
565  eprintf("Missing nodes in DIPLAY_DATA_SECTION");
566  if (Id <= 0 || Id > Dimension)
567  eprintf("(DIPLAY_DATA_SECTION) Node number out of range: %d",
568  Id);
569  N = &NodeSet[Id];
570  if (N->V == 1)
571  eprintf("(DIPLAY_DATA_SECTION) Node number occours twice: %d",
572  N->Id);
573  N->V = 1;
574  if (!fscanf(ProblemFile, "%lf", &N->X))
575  eprintf("Missing X-coordinate in DIPLAY_DATA_SECTION");
576  if (!fscanf(ProblemFile, "%lf", &N->Y))
577  eprintf("Missing Y-coordinate in DIPLAY_DATA_SECTION");
578  }
579  N = FirstNode;
580  do
581  if (!N->V)
582  break;
583  while ((N = N->Suc) != FirstNode);
584  if (!N->V)
585  eprintf("(DIPLAY_DATA_SECTION) No coordinates given for node %d",
586  N->Id);
587  if (ProblemType == HPP)
588  Dimension++;
589 }
590 
592 {
593  unsigned int i;
594 
595  if (!(DisplayDataType = Copy(strtok(0, Delimiters))))
596  eprintf("DISPLAY_DATA_TYPE: string expected");
597  for (i = 0; i < strlen(DisplayDataType); i++)
598  DisplayDataType[i] = (char) toupper(DisplayDataType[i]);
599  if (strcmp(DisplayDataType, "COORD_DISPLAY") &&
600  strcmp(DisplayDataType, "TWOD_DISPLAY") &&
601  strcmp(DisplayDataType, "NO_DISPLAY"))
602  eprintf("Unknown DISPLAY_DATA_TYPE: %s", DisplayDataType);
603 }
604 
606 {
607  unsigned int i;
608 
609  if (!(EdgeDataFormat = Copy(strtok(0, Delimiters))))
610  eprintf("EDGE_DATA_FORMAT: string expected");
611  for (i = 0; i < strlen(EdgeDataFormat); i++)
612  EdgeDataFormat[i] = (char) toupper(EdgeDataFormat[i]);
613  if (strcmp(EdgeDataFormat, "EDGE_LIST") &&
614  strcmp(EdgeDataFormat, "ADJ_LIST"))
615  eprintf("Unknown EDGE_DATA_FORMAT: %s", EdgeDataFormat);
617  eprintf("(EDGE_DATA_FORMAT)"
618  " cannot be used together with SUBPROBLEM_TOUR_FILE");
619 }
620 
622 {
623  Node *Ni, *Nj;
624  int i, j;
625 
627  if (!EdgeDataFormat)
628  eprintf("Missing EDGE_DATA_FORMAT specification");
629  if (!FirstNode)
630  CreateNodes();
631  if (ProblemType == HPP)
632  Dimension--;
633  if (!strcmp(EdgeDataFormat, "EDGE_LIST")) {
634  if (!fscanint(ProblemFile, &i))
635  i = -1;
636  while (i != -1) {
637  if (i <= 0
638  || i > (ProblemType != ATSP ? Dimension : Dimension / 2))
639  eprintf("(EDGE_DATA_SECTION) Node number out of range: %d",
640  i);
641  fscanint(ProblemFile, &j);
642  if (j <= 0
643  || j > (ProblemType != ATSP ? Dimension : Dimension / 2))
644  eprintf("(EDGE_DATA_SECTION) Node number out of range: %d",
645  j);
646  if (i == j)
647  eprintf("(EDGE_DATA_SECTION) Illgal edge: %d to %d", i, j);
648  if (ProblemType == ATSP) {
649  i += Dimension / 2;
650  j += Dimension / 2;
651  }
652  Ni = &NodeSet[i];
653  Nj = &NodeSet[j];
654  if (!Ni->CandidateSet) {
655  assert(Ni->CandidateSet =
656  (Candidate *) calloc(3, sizeof(Candidate)));
657  Ni->CandidateSet[0].To = Nj;
658  Ni->CandidateSet[0].Cost = 0;
659  Ni->CandidateSet[0].Alpha = 0;
660  Ni->V = 1;
661  } else if (!IsCandidate(Ni, Nj)) {
662  Ni->CandidateSet[Ni->V].To = Nj;
663  Ni->CandidateSet[Ni->V].Cost = 0;
664  Ni->CandidateSet[Ni->V].Alpha = Ni->V;
665  assert(Ni->CandidateSet =
666  (Candidate *) realloc(Ni->CandidateSet,
667  (++Ni->V +
668  1) * sizeof(Candidate)));
669  Ni->CandidateSet[Ni->V].To = 0;
670  }
671  if (!Nj->CandidateSet) {
672  assert(Nj->CandidateSet =
673  (Candidate *) calloc(3, sizeof(Candidate)));
674  Nj->CandidateSet[0].To = Ni;
675  Nj->CandidateSet[0].Cost = 0;
676  Nj->CandidateSet[0].Alpha = 0;
677  Nj->V = 1;
678  } else if (!IsCandidate(Nj, Ni)) {
679  Nj->CandidateSet[Nj->V].To = Ni;
680  Nj->CandidateSet[Nj->V].Cost = 0;
681  Nj->CandidateSet[Nj->V].Alpha = Nj->V;
682  assert(Nj->CandidateSet =
683  (Candidate *) realloc(Nj->CandidateSet,
684  (++Nj->V +
685  1) * sizeof(Candidate)));
686  Nj->CandidateSet[Nj->V].To = 0;
687  }
688  fscanint(ProblemFile, &i);
689  }
690  } else if (!strcmp(EdgeDataFormat, "ADJ_LIST")) {
691  Ni = FirstNode;
692  do
693  Ni->V = 0;
694  while ((Ni = Ni->Suc) != FirstNode);
695  if (!fscanint(ProblemFile, &i))
696  i = -1;
697  while (i != -1) {
698  if (i <= 0
699  || i > (ProblemType != ATSP ? Dimension : Dimension / 2))
700  eprintf("(EDGE_DATA_SECTION) Node number out of range: %d",
701  i);
702  if (ProblemType == ATSP)
703  i += Dimension / 2;
704  Ni = &NodeSet[i];
705  fscanint(ProblemFile, &j);
706  while (j != -1) {
707  if (j <= 0
708  || j > (ProblemType !=
709  ATSP ? Dimension : Dimension / 2))
710  eprintf
711  ("(EDGE_DATA_SECTION) Node number out of range: %d",
712  j);
713  if (i == j)
714  eprintf("(EDGE_DATA_SECTION) Illgal edge: %d to %d",
715  i, j);
716  if (ProblemType == ATSP)
717  j += Dimension / 2;
718  Nj = &NodeSet[j];
719  if (!Ni->CandidateSet) {
720  assert(Ni->CandidateSet =
721  (Candidate *) calloc(3, sizeof(Candidate)));
722  Ni->CandidateSet[0].To = Nj;
723  Ni->CandidateSet[0].Cost = 0;
724  Ni->CandidateSet[0].Alpha = 0;
725  Ni->V = 1;
726  } else if (!IsCandidate(Ni, Nj)) {
727  Ni->CandidateSet[Ni->V].To = Nj;
728  Ni->CandidateSet[Ni->V].Cost = 0;
729  Ni->CandidateSet[Ni->V].Alpha = Ni->V;
730  assert(Ni->CandidateSet =
731  (Candidate *) realloc(Ni->CandidateSet,
732  (++Ni->V +
733  1) * sizeof(Candidate)));
734  Ni->CandidateSet[Ni->V].To = 0;
735  }
736  if (!Nj->CandidateSet) {
737  assert(Nj->CandidateSet =
738  (Candidate *) calloc(3, sizeof(Candidate)));
739  Nj->CandidateSet[0].To = Ni;
740  Nj->CandidateSet[0].Cost = 0;
741  Nj->CandidateSet[0].Alpha = 0;
742  Nj->V = 1;
743  } else if (!IsCandidate(Nj, Ni)) {
744  Nj->CandidateSet[Nj->V].To = Ni;
745  Nj->CandidateSet[Nj->V].Cost = 0;
746  Nj->CandidateSet[Nj->V].Alpha = Nj->V;
747  assert(Nj->CandidateSet =
748  (Candidate *) realloc(Nj->CandidateSet,
749  (++Nj->V +
750  1) * sizeof(Candidate)));
751  Nj->CandidateSet[Nj->V].To = 0;
752  }
753  fscanint(ProblemFile, &j);
754  }
755  fscanint(ProblemFile, &i);
756  }
757  } else
758  eprintf("(EDGE_DATA_SECTION) No EDGE_DATA_FORMAT specified");
759  if (ProblemType == HPP)
760  Dimension++;
762 }
763 
765 {
766  unsigned int i;
767 
768  if (!(EdgeWeightFormat = Copy(strtok(0, Delimiters))))
769  eprintf("EDGE_WEIGHT_FORMAT: string expected");
770  for (i = 0; i < strlen(EdgeWeightFormat); i++)
771  EdgeWeightFormat[i] = (char) toupper(EdgeWeightFormat[i]);
772  if (!strcmp(EdgeWeightFormat, "FUNCTION"))
774  else if (!strcmp(EdgeWeightFormat, "FULL_MATRIX"))
776  else if (!strcmp(EdgeWeightFormat, "UPPER_ROW"))
778  else if (!strcmp(EdgeWeightFormat, "LOWER_ROW"))
780  else if (!strcmp(EdgeWeightFormat, "UPPER_DIAG_ROW"))
782  else if (!strcmp(EdgeWeightFormat, "LOWER_DIAG_ROW"))
784  else if (!strcmp(EdgeWeightFormat, "UPPER_COL"))
786  else if (!strcmp(EdgeWeightFormat, "LOWER_COL"))
788  else if (!strcmp(EdgeWeightFormat, "UPPER_DIAG_COL"))
790  else if (!strcmp(EdgeWeightFormat, "LOWER_DIAG_COL"))
792  else
793  eprintf("Unknown EDGE_WEIGHT_FORMAT: %s", EdgeWeightFormat);
794 }
795 
797 {
798  Node *Ni, *Nj;
799  int i, j, n, W;
800 
802  if (!FirstNode)
803  CreateNodes();
804  if (ProblemType != ATSP) {
805  assert(CostMatrix =
806  (int *) calloc((size_t) Dimension * (Dimension - 1) / 2,
807  sizeof(int)));
808  Ni = FirstNode->Suc;
809  do {
810  Ni->C =
811  &CostMatrix[(size_t) (Ni->Id - 1) * (Ni->Id - 2) / 2] - 1;
812  }
813  while ((Ni = Ni->Suc) != FirstNode);
814  } else {
815  n = Dimension / 2;
816  assert(CostMatrix = (int *) calloc((size_t) n * n, sizeof(int)));
817  for (Ni = FirstNode; Ni->Id <= n; Ni = Ni->Suc)
818  Ni->C = &CostMatrix[(size_t) (Ni->Id - 1) * n] - 1;
819  }
820  if (ProblemType == HPP)
821  Dimension--;
822  switch (WeightFormat) {
823  case FULL_MATRIX:
824  if (ProblemType == ATSP) {
825  n = Dimension / 2;
826  for (i = 1; i <= n; i++) {
827  Ni = &NodeSet[i];
828  for (j = 1; j <= n; j++) {
829  if (!fscanint(ProblemFile, &W))
830  eprintf("Missing weight in EDGE_WEIGHT_SECTION");
831  Ni->C[j] = W;
832  if (i != j && W > M)
833  M = W;
834  }
835  Nj = &NodeSet[i + n];
836  if (!Ni->FixedTo1)
837  Ni->FixedTo1 = Nj;
838  else if (!Ni->FixedTo2)
839  Ni->FixedTo2 = Nj;
840  if (!Nj->FixedTo1)
841  Nj->FixedTo1 = Ni;
842  else if (!Nj->FixedTo2)
843  Nj->FixedTo2 = Ni;
844  }
846  WeightType = -1;
847  } else
848  for (i = 1, Ni = FirstNode; i <= Dimension; i++, Ni = Ni->Suc) {
849  for (j = 1; j <= Dimension; j++) {
850  if (!fscanint(ProblemFile, &W))
851  eprintf("Missing weight in EDGE_WEIGHT_SECTION");
852  if (j < i)
853  Ni->C[j] = W;
854  }
855  }
856  break;
857  case UPPER_ROW:
858  for (i = 1, Ni = FirstNode; i < Dimension; i++, Ni = Ni->Suc) {
859  for (j = i + 1, Nj = Ni->Suc; j <= Dimension;
860  j++, Nj = Nj->Suc) {
861  if (!fscanint(ProblemFile, &W))
862  eprintf("Missing weight in EDGE_WEIGHT_SECTION");
863  Nj->C[i] = W;
864  }
865  }
866  break;
867  case LOWER_ROW:
868  for (i = 2, Ni = FirstNode->Suc; i <= Dimension; i++, Ni = Ni->Suc) {
869  for (j = 1; j < i; j++) {
870  if (!fscanint(ProblemFile, &W))
871  eprintf("Missing weight in EDGE_WEIGHT_SECTION");
872  Ni->C[j] = W;
873  }
874  }
875  break;
876  case UPPER_DIAG_ROW:
877  for (i = 1, Ni = FirstNode; i <= Dimension; i++, Ni = Ni->Suc) {
878  for (j = i, Nj = Ni; j <= Dimension; j++, Nj = Nj->Suc) {
879  if (!fscanint(ProblemFile, &W))
880  eprintf("Missing weight in EDGE_WEIGHT_SECTION");
881  if (i != j)
882  Nj->C[i] = W;
883  }
884  }
885  break;
886  case LOWER_DIAG_ROW:
887  for (i = 1, Ni = FirstNode; i <= Dimension; i++, Ni = Ni->Suc) {
888  for (j = 1; j <= i; j++) {
889  if (!fscanint(ProblemFile, &W))
890  eprintf("Missing weight in EDGE_WEIGHT_SECTION");
891  if (j != i)
892  Ni->C[j] = W;
893  }
894  }
895  break;
896  case UPPER_COL:
897  for (j = 2, Nj = FirstNode->Suc; j <= Dimension; j++, Nj = Nj->Suc) {
898  for (i = 1; i < j; i++) {
899  if (!fscanint(ProblemFile, &W))
900  eprintf("Missing weight in EDGE_WEIGHT_SECTION");
901  Nj->C[i] = W;
902  }
903  }
904  break;
905  case LOWER_COL:
906  for (j = 1, Nj = FirstNode; j < Dimension; j++, Nj = Nj->Suc) {
907  for (i = j + 1, Ni = Nj->Suc; i <= Dimension;
908  i++, Ni = Ni->Suc) {
909  if (!fscanint(ProblemFile, &W))
910  eprintf("Missing weight in EDGE_WEIGHT_SECTION");
911  Ni->C[j] = W;
912  }
913  }
914  break;
915  case UPPER_DIAG_COL:
916  for (j = 1, Nj = FirstNode; j <= Dimension; j++, Nj = Nj->Suc) {
917  for (i = 1; i <= j; i++) {
918  if (!fscanint(ProblemFile, &W))
919  eprintf("Missing weight in EDGE_WEIGHT_SECTION");
920  if (i != j)
921  Nj->C[i] = W;
922  }
923  }
924  break;
925  case LOWER_DIAG_COL:
926  for (j = 1, Nj = FirstNode; j <= Dimension; j++, Nj = Nj->Suc) {
927  for (i = j, Ni = Nj; i <= Dimension; i++, Ni = Ni->Suc) {
928  if (!fscanint(ProblemFile, &W))
929  eprintf("Missing weight in EDGE_WEIGHT_SECTION");
930  if (i != j)
931  Ni->C[j] = W;
932  }
933  }
934  break;
935  }
936  if (ProblemType == HPP)
937  Dimension++;
938 }
939 
941 {
942  unsigned int i;
943 
944  if (!(EdgeWeightType = Copy(strtok(0, Delimiters))))
945  eprintf("EDGE_WEIGHT_TYPE: string expected");
946  for (i = 0; i < strlen(EdgeWeightType); i++)
947  EdgeWeightType[i] = (char) toupper(EdgeWeightType[i]);
948  if (!strcmp(EdgeWeightType, "ATT")) {
949  WeightType = ATT;
952  } else if (!strcmp(EdgeWeightType, "CEIL_2D")) {
956  } else if (!strcmp(EdgeWeightType, "CEIL_3D")) {
960  } else if (!strcmp(EdgeWeightType, "EUC_2D")) {
961  WeightType = EUC_2D;
964  } else if (!strcmp(EdgeWeightType, "EUC_3D")) {
965  WeightType = EUC_3D;
968  } else if (!strcmp(EdgeWeightType, "EXPLICIT")) {
971  } else if (!strcmp(EdgeWeightType, "MAN_2D")) {
972  WeightType = MAN_2D;
975  } else if (!strcmp(EdgeWeightType, "MAN_3D")) {
976  WeightType = MAN_3D;
979  } else if (!strcmp(EdgeWeightType, "MAX_2D")) {
980  WeightType = MAX_2D;
983  } else if (!strcmp(EdgeWeightType, "MAX_3D")) {
984  WeightType = MAX_3D;
987  } else if (!strcmp(EdgeWeightType, "GEO")) {
988  WeightType = GEO;
991  } else if (!strcmp(EdgeWeightType, "GEOM")) {
992  WeightType = GEOM;
995  } else if (!strcmp(EdgeWeightType, "GEO_MEEUS")) {
999  } else if (!strcmp(EdgeWeightType, "GEOM_MEEUS")) {
1003  } else if (!strcmp(EdgeWeightType, "SPECIAL")) {
1004  WeightType = SPECIAL;
1006  } else if (!strcmp(EdgeWeightType, "XRAY1") ||
1007  !strcmp(EdgeWeightType, "XRAY2"))
1008  eprintf("EDGE_WEIGHT_TYPE not implemented: %s", EdgeWeightType);
1009  else
1010  eprintf("Unknown EDGE_WEIGHT_TYPE: %s", EdgeWeightType);
1011 }
1012 
1014 {
1015  Node *Ni, *Nj, *N, *NPrev = 0, *NNext;
1016  int i, j, Count = 0;
1017 
1018  eprintf("Not implemented: FIXED_EDGES_SECTION\n");
1020  if (!FirstNode)
1021  CreateNodes();
1022  if (ProblemType == HPP)
1023  Dimension--;
1024  if (!fscanint(ProblemFile, &i))
1025  i = -1;
1026  while (i != -1) {
1027  if (i <= 0
1028  || i > (ProblemType != ATSP ? Dimension : Dimension / 2))
1029  eprintf("(FIXED_EDGES_SECTION) Node number out of range: %d",
1030  i);
1031  fscanint(ProblemFile, &j);
1032  if (j <= 0
1033  || j > (ProblemType != ATSP ? Dimension : Dimension / 2))
1034  eprintf("(FIXED_EDGES_SECTION) Node number out of range: %d",
1035  j);
1036  if (i == j)
1037  eprintf("(FIXED_EDGES_SECTION) Illgal edge: %d to %d", i, j);
1038  Ni = &NodeSet[i];
1039  Nj = &NodeSet[ProblemType == ATSP ? j + Dimension / 2 : j];
1040  if (!Ni->FixedTo1)
1041  Ni->FixedTo1 = Nj;
1042  else if (!Ni->FixedTo2)
1043  Ni->FixedTo2 = Nj;
1044  else
1045  eprintf("(FIXED_EDGES_SECTION) Illegal fix: %d to %d", i, j);
1046  if (!Nj->FixedTo1)
1047  Nj->FixedTo1 = Ni;
1048  else if (!Nj->FixedTo2)
1049  Nj->FixedTo2 = Ni;
1050  else
1051  eprintf("(FIXED_EDGES_SECTION) Illegal fix: %d to %d", i, j);
1052  /* Cycle check */
1053  N = Ni;
1054  do {
1055  NNext = N->FixedTo1 != NPrev ? N->FixedTo1 : N->FixedTo2;
1056  NPrev = N;
1057  Count++;
1058  } while ((N = NNext) && N != Ni);
1059  if (N == Ni && Count != Dimension)
1060  eprintf("(FIXED_EDGES_SECTION) Illegal fix: %d to %d", i, j);
1061  if (!fscanint(ProblemFile, &i))
1062  i = -1;
1063  }
1064  if (ProblemType == HPP)
1065  Dimension++;
1066 }
1067 
1068 static void Read_GTSP_SETS()
1069 {
1070  char *Token = strtok(0, Delimiters);
1071 
1072  if (!Token || !sscanf(Token, "%d", &GTSPSets))
1073  eprintf("GTSP_SETS: integer expected");
1074  if (GTSPSets <= 1)
1075  eprintf("GTSP_SETS: not greater than 1");
1076 }
1077 
1079 {
1080  int Clusters = 0, n, Id;
1081  Cluster *Cl;
1082  Node *N, *Last = 0;
1083  char *Used;
1084 
1085  if (GTSPSets == 0)
1086  eprintf("Missing specification of GTSP_SETS");
1087  N = FirstNode;
1088  do
1089  N->V = 0;
1090  while ((N = N->Suc) != FirstNode);
1091  assert(Used = (char *) calloc(GTSPSets + 1, sizeof(char)));
1092  while (fscanf(ProblemFile, "%d", &Id) > 0) {
1093  if (Id < 1 || Id > GTSPSets)
1094  eprintf("(GTSP_SET_SECTION) Set number %d of of range", Id);
1095  if (Used[Id])
1096  eprintf("(GTSP_SET_SECTION) Set %d specified twice", Id);
1097  Used[Id] = 1;
1098  Cl = (Cluster *) calloc(1, sizeof(Cluster));
1099  Clusters++;
1100  Last = 0;
1101  for (;;) {
1102  fscanf(ProblemFile, "%d", &n);
1103  if (n == -1)
1104  break;
1105  if (n < 1 || n > DimensionSaved)
1106  eprintf("(GTSP_SET_SECTION) Node %d outside range", n);
1107  N = &NodeSet[n];
1108  if (N->V)
1109  eprintf("(GTSP_SET_SECTION) Node %d occurs in two sets", n);
1110  N->Next = 0;
1111  N->V = Id;
1112  Cl->Size++;
1113  if (!Cl->First)
1114  Cl->First = N;
1115  if (Last)
1116  Last->Next = N;
1117  Last = N;
1118  }
1119  if (LastCluster)
1120  LastCluster->Next = Cl;
1121  else
1122  FirstCluster = Cl;
1123  LastCluster = Cl;
1124  Last->Next = Cl->First;
1125  }
1126  for (Id = 1; Id <= DimensionSaved; Id++) {
1127  N = &NodeSet[Id];
1128  if (!N->V)
1129  eprintf("(GTSP_SET_SECTION) Node %d does not occur in any set",
1130  N->Id);
1131  }
1132  if (Clusters != GTSPSets)
1133  eprintf("(GTSP_SET_SECTION) Missing sets");
1134  free(Used);
1135 }
1136 
1138 {
1139  Node *N;
1140  int Id, i;
1141 
1144  eprintf("NODE_COORD_SECTION conflicts with NODE_COORD_TYPE: %s",
1145  NodeCoordType);
1146  if (!FirstNode)
1147  CreateNodes();
1148  N = FirstNode;
1149  if (ProblemType == HPP)
1150  Dimension--;
1151  for (i = 1; i <= Dimension; i++) {
1152  if (!fscanint(ProblemFile, &Id))
1153  eprintf("Missing nodes in NODE_COORD_SECTION");
1154  if (Id <= 0 || Id > Dimension)
1155  eprintf("(NODE_COORD_SECTION) Node number out of range: %d",
1156  Id);
1157  N = &NodeSet[Id];
1158  if (N->V == 1)
1159  eprintf("(NODE_COORD_SECTION) Node number occours twice: %d",
1160  N->Id);
1161  N->V = 1;
1162  if (!fscanf(ProblemFile, "%lf", &N->X))
1163  eprintf("Missing X-coordinate in NODE_COORD_SECTION");
1164  if (!fscanf(ProblemFile, "%lf", &N->Y))
1165  eprintf("Missing Y-coordinate in NODE_COORD_SECTION");
1166  if (CoordType == THREED_COORDS
1167  && !fscanf(ProblemFile, "%lf", &N->Z))
1168  eprintf("Missing Z-coordinate in NODE_COORD_SECTION");
1169  if (Name && !strcmp(Name, "d657")) {
1170  N->X = (float) N->X;
1171  N->Y = (float) N->Y;
1172  }
1173  }
1174  N = FirstNode;
1175  do
1176  if (!N->V && N->Id <= Dimension)
1177  break;
1178  while ((N = N->Suc) != FirstNode);
1179  if (!N->V)
1180  eprintf("(NODE_COORD_SECTION) No coordinates given for node %d",
1181  N->Id);
1182  if (ProblemType == HPP)
1183  Dimension++;
1184 }
1185 
1187 {
1188  unsigned int i;
1189 
1190  if (!(NodeCoordType = Copy(strtok(0, Delimiters))))
1191  eprintf("NODE_COORD_TYPE: string expected");
1192  for (i = 0; i < strlen(NodeCoordType); i++)
1193  NodeCoordType[i] = (char) toupper(NodeCoordType[i]);
1194  if (!strcmp(NodeCoordType, "TWOD_COORDS"))
1196  else if (!strcmp(NodeCoordType, "THREED_COORDS"))
1198  else if (!strcmp(NodeCoordType, "NO_COORDS"))
1199  CoordType = NO_COORDS;
1200  else
1201  eprintf("Unknown NODE_COORD_TYPE: %s", NodeCoordType);
1202 }
1203 
1204 static void Read_TOUR_SECTION(FILE ** File)
1205 {
1206  Node *First = 0, *Last = 0, *N;
1207  int i, k;
1208 
1209  if (TraceLevel >= 1) {
1210  printff("Reading ");
1211  if (File == &InitialTourFile)
1212  printff("INITIAL_TOUR_FILE: \"%s\" ... ", InitialTourFileName);
1213  else if (File == &InputTourFile)
1214  printff("INPUT_TOUR_FILE: \"%s\" ... ", InputTourFileName);
1215  else if (File == &SubproblemTourFile)
1216  printff("SUBPROBLEM_TOUR_FILE: \"%s\" ... ",
1218  else
1219  for (i = 0; i < MergeTourFiles; i++)
1220  if (File == &MergeTourFile[i])
1221  printff("MERGE_TOUR_FILE: \"%s\" ... ",
1222  MergeTourFileName[i]);
1223  }
1224  if (!FirstNode)
1225  CreateNodes();
1226  N = FirstNode;
1227  do
1228  N->V = 0;
1229  while ((N = N->Suc) != FirstNode);
1230  if (ProblemType == HPP)
1231  Dimension--;
1232  if (ProblemType == ATSP)
1233  Dimension /= 2;
1234  if (!fscanint(*File, &i))
1235  i = -1;
1236  for (k = 0; k <= GTSPSets && i != -1; k++) {
1237  if (i <= 0 || i > Dimension)
1238  eprintf("(TOUR_SECTION) Node number out of range: %d", i);
1239  N = &NodeSet[i];
1240  if (N->V == 1 && k != GTSPSets)
1241  eprintf("(TOUR_SECTION) Node number occours twice: %d", N->Id);
1242  N->V = 1;
1243  if (k == 0)
1244  First = Last = N;
1245  else {
1246  if (File == &InitialTourFile)
1247  Last->InitialSuc = N;
1248  else if (File == &InputTourFile)
1249  Last->InputSuc = N;
1250  else if (File == &SubproblemTourFile)
1251  (Last->SubproblemSuc = N)->SubproblemPred = Last;
1252  else
1253  for (i = 0; i < MergeTourFiles; i++)
1254  if (File == &MergeTourFile[i])
1255  Last->MergeSuc[i] = N;
1256  Last = N;
1257  }
1258  if (k < GTSPSets)
1259  fscanint(*File, &i);
1260  if (k == GTSPSets - 1)
1261  i = First->Id;
1262  }
1263  if (File == &SubproblemTourFile) {
1264  do {
1265  if (N->FixedTo1 &&
1266  N->SubproblemPred != N->FixedTo1
1267  && N->SubproblemSuc != N->FixedTo1)
1268  eprintf("Fixed edge (%d, %d) "
1269  "does not belong to subproblem tour", N->Id,
1270  N->FixedTo1->Id);
1271  if (N->FixedTo2 && N->SubproblemPred != N->FixedTo2
1272  && N->SubproblemSuc != N->FixedTo2)
1273  eprintf("Fixed edge (%d, %d) "
1274  "does not belong to subproblem tour", N->Id,
1275  N->FixedTo2->Id);
1276  } while ((N = N->Suc) != FirstNode);
1277  }
1278  if (ProblemType == HPP)
1279  Dimension++;
1280  if (ProblemType == ATSP)
1281  Dimension *= 2;
1282  if (TraceLevel >= 1)
1283  printff("done\n");
1284 }
1285 
1286 static void Read_TYPE()
1287 {
1288  unsigned int i;
1289 
1290  if (!(Type = Copy(strtok(0, Delimiters))))
1291  eprintf("TYPE: string expected");
1292  for (i = 0; i < strlen(Type); i++)
1293  Type[i] = (char) toupper(Type[i]);
1294  if (!strcmp(Type, "TSP"))
1295  ProblemType = TSP;
1296  else if (!strcmp(Type, "ATSP"))
1297  ProblemType = ATSP;
1298  else if (!strcmp(Type, "SOP")) {
1299  ProblemType = SOP;
1300  eprintf("TYPE: Type not implemented: %s", Type);
1301  } else if (!strcmp(Type, "HCP"))
1302  ProblemType = HCP;
1303  else if (!strcmp(Type, "CVRP")) {
1304  ProblemType = CVRP;
1305  eprintf("TYPE: Type not implemented: %s", Type);
1306  } else if (!strcmp(Type, "TOUR")) {
1307  ProblemType = TOUR;
1308  eprintf("TYPE: Type not implemented: %s", Type);
1309  } else if (!strcmp(Type, "HPP"))
1310  ProblemType = HPP;
1311  else if (!strcmp(Type, "GTSP")) {
1312  ProblemType = TSP;
1313  strcpy(Type, "TSP");
1314  } else if (!strcmp(Type, "AGTSP")) {
1315  ProblemType = ATSP;
1316  strcpy(Type, "ATSP");
1317  } else
1318  eprintf("Unknown TYPE: %s", Type);
1319 }
1320 
1321 /*
1322  The ReadTour function reads a tour from a file.
1323 
1324  The format is as follows:
1325 
1326  OPTIMUM = <real>
1327  Known optimal tour length. A run will be terminated as soon as a tour
1328  length less than or equal to optimum is achieved.
1329  Default: MINUS_INFINITY.
1330 
1331  TOUR_SECTION :
1332  A tour is specified in this section. The tour is given by a list of integers
1333  giving the sequence in which the nodes are visited in the tour. The tour is
1334  terminated by a -1.
1335 
1336  EOF
1337  Terminates the input data. The entry is optional.
1338 
1339  Other keywords in TSPLIB format may be included in the file, but they are
1340  ignored.
1341 */
1342 
1343 void ReadTour(char *FileName, FILE ** File)
1344 {
1345  char *Line, *Keyword, *Token;
1346  unsigned int i;
1347  int Done = 0;
1348 
1349  if (!(*File = fopen(FileName, "r")))
1350  eprintf("Cannot open tour file: \"%s\"", FileName);
1351  while ((Line = ReadLine(*File))) {
1352  if (!(Keyword = strtok(Line, Delimiters)))
1353  continue;
1354  for (i = 0; i < strlen(Keyword); i++)
1355  Keyword[i] = (char) toupper(Keyword[i]);
1356  if (!strcmp(Keyword, "COMMENT") ||
1357  !strcmp(Keyword, "DEMAND_SECTION") ||
1358  !strcmp(Keyword, "DEPOT_SECTION") ||
1359  !strcmp(Keyword, "DISPLAY_DATA_SECTION") ||
1360  !strcmp(Keyword, "DISPLAY_DATA_TYPE") ||
1361  !strcmp(Keyword, "EDGE_DATA_FORMAT") ||
1362  !strcmp(Keyword, "EDGE_DATA_SECTION") ||
1363  !strcmp(Keyword, "EDGE_WEIGHT_FORMAT") ||
1364  !strcmp(Keyword, "EDGE_WEIGHT_SECTION") ||
1365  !strcmp(Keyword, "EDGE_WEIGHT_TYPE") ||
1366  !strcmp(Keyword, "FIXED_EDGES_SECTION") ||
1367  !strcmp(Keyword, "NAME") ||
1368  !strcmp(Keyword, "NODE_COORD_SECTION") ||
1369  !strcmp(Keyword, "NODE_COORD_TYPE")
1370  || !strcmp(Keyword, "TYPE"));
1371  else if (strcmp(Keyword, "OPTIMUM") == 0) {
1372  if (!(Token = strtok(0, Delimiters)) ||
1373  !sscanf(Token, GainInputFormat, &Optimum))
1374  eprintf("[%s] (OPTIMUM): integer expected", FileName);
1375  } else if (strcmp(Keyword, "DIMENSION") == 0) {
1376  int Dim = 0;
1377  if (!(Token = strtok(0, Delimiters)) ||
1378  !sscanf(Token, "%d", &Dim))
1379  eprintf("[%s] (DIMENSION): integer expected", FileName);
1380  if (Dim != GTSPSets)
1381  eprintf
1382  ("[%s] (DIMENSION): does not match problem dimension",
1383  FileName);
1384  } else if (!strcmp(Keyword, "TOUR_SECTION")) {
1385  Read_TOUR_SECTION(File);
1386  Done = 1;
1387  } else if (!strcmp(Keyword, "EOF"))
1388  break;
1389  else
1390  eprintf("[%s] Unknown Keyword: %s", FileName, Keyword);
1391  }
1392  if (!Done)
1393  eprintf("Missing TOUR_SECTION in tour file: \"%s\"", FileName);
1394  fclose(*File);
1395 }
Definition: LKH.h:44
static void Read_EDGE_DATA_SECTION(void)
Definition: ReadProblem.c:621
static void Read_GTSP_SET_SECTION(void)
Definition: ReadProblem.c:1078
char * ProblemFileName
Definition: LKH.h:284
int IsCandidate(const Node *ta, const Node *tb)
Definition: IsCandidate.c:10
int Dimension
Definition: LKH.h:190
int Alpha
Definition: LKH.h:137
static void Read_FIXED_EDGES_SECTION(void)
Definition: ReadProblem.c:1013
static const char Delimiters[]
Definition: ReadProblem.c:207
int fscanint(FILE *f, int *v)
Definition: fscanint.c:13
int NonsequentialMoveType
Definition: LKH.h:237
FILE * InputTourFile
Definition: LKH.h:302
Definition: LKH.h:41
double Y
Definition: LKH.h:123
int MaxSwaps
Definition: LKH.h:227
static void Read_NODE_COORD_SECTION(void)
Definition: ReadProblem.c:1137
static char * Buffer
Definition: ReadLine.c:9
static void Read_EDGE_DATA_FORMAT(void)
Definition: ReadProblem.c:605
int ExtraCandidateSetType
Definition: LKH.h:290
Definition: LKH.h:44
int SubsequentMoveType
Definition: LKH.h:265
char * SubproblemTourFileName
Definition: LKH.h:284
Definition: LKH.h:47
int Precision
Definition: LKH.h:249
static void Read_DISPLAY_DATA_TYPE(void)
Definition: ReadProblem.c:591
Definition: LKH.h:41
int SubproblemSize
Definition: LKH.h:264
Definition: LKH.h:42
Definition: LKH.h:43
Definition: LKH.h:45
int GTSPSets
Definition: LKH.h:209
char * LastLine
Definition: LKH.h:214
#define GainInputFormat
Definition: GainType.h:23
Count
static int TwoDWeightType(void)
Definition: ReadProblem.c:404
int CoordType
Definition: LKH.h:290
void PrintParameters(void)
void printff(char *fmt,...)
Definition: printff.c:10
int Distance_MAN_2D(Node *Na, Node *Nb)
Definition: Distance.c:104
FILE * InitialTourFile
Definition: LKH.h:302
int Distance_GEOM_MEEUS(Node *Na, Node *Nb)
Definition: Distance.c:180
int SubproblemBorders
Definition: LKH.h:290
Definition: LKH.h:41
Definition: LKH.h:68
Definition: LKH.h:41
int MaxCandidates
Definition: LKH.h:224
Definition: LKH.h:41
int RohePartitioning
Definition: LKH.h:290
static void Read_TYPE(void)
Definition: ReadProblem.c:1286
int Id
Definition: LKH.h:69
char * EdgeWeightFormat
Definition: LKH.h:288
Definition: LKH.h:44
int WeightType
Definition: LKH.h:290
#define Link(a, b)
Definition: LKH.h:34
double X
Definition: LKH.h:123
Candidate * CandidateSet
Definition: LKH.h:119
Definition: LKH.h:43
Definition: LKH.h:41
int Distance_SPECIAL(Node *Na, Node *Nb)
Definition: LKH.h:162
Definition: LKH.h:48
Definition: LKH.h:44
FILE ** MergeTourFile
Definition: LKH.h:302
Node * FixedTo2
Definition: LKH.h:101
int KickType
Definition: LKH.h:217
CostFunction Distance
Definition: LKH.h:304
int * CostMatrix
Definition: LKH.h:189
int DelaunayPartitioning
Definition: LKH.h:290
static int ThreeDWeightType(void)
Definition: ReadProblem.c:414
Definition: LKH.h:44
double Z
Definition: LKH.h:123
Definition: LKH.h:44
GainType Optimum
Definition: LKH.h:241
Node * NodeSet
Definition: LKH.h:235
int MaxTrials
Definition: LKH.h:230
void ReadTour(char *FileName, FILE **File)
Definition: ReadProblem.c:1343
int Distance_ATT(Node *Na, Node *Nb)
Definition: Distance.c:24
Definition: LKH.h:47
int MergeTourFiles
Definition: LKH.h:231
Definition: LKH.h:41
Cluster * LastCluster
Definition: LKH.h:200
double Excess
Definition: LKH.h:192
int Distance_ATSP(Node *Na, Node *Nb)
Definition: Distance.c:14
static void Read_TOUR_SECTION(FILE **File)
Definition: ReadProblem.c:1204
int Swaps
Definition: LKH.h:272
int PatchingA
Definition: LKH.h:245
Definition: LKH.h:53
int ExtraCandidates
Definition: LKH.h:196
Node * InputSuc
Definition: LKH.h:108
Cluster * Next
Definition: LKH.h:164
Definition: LKH.h:43
int DimensionSaved
Definition: LKH.h:191
Node * Suc
Definition: LKH.h:89
char * DisplayDataType
Definition: LKH.h:288
Node ** MergeSuc
Definition: LKH.h:114
Node * FirstNode
Definition: LKH.h:201
static char * Copy(char *S)
Definition: ReadProblem.c:489
int Distance_CEIL_3D(Node *Na, Node *Nb)
Definition: Distance.c:36
static void Read_GTSP_SETS(void)
Definition: ReadProblem.c:1068
int MoorePartitioning
Definition: LKH.h:290
int Distance_CEIL_2D(Node *Na, Node *Nb)
Definition: Distance.c:30
Node * InitialSuc
Definition: LKH.h:109
int Distance_1(Node *Na, Node *Nb)
Definition: Distance.c:9
int TraceLevel
Definition: LKH.h:274
void eprintf(const char *fmt,...)
Definition: eprintf.c:8
Node * To
Definition: LKH.h:135
Definition: LKH.h:51
int * C
Definition: LKH.h:88
Definition: LKH.h:51
int Distance_GEOM(Node *Na, Node *Nb)
Definition: Distance.c:90
Definition: LKH.h:43
int PatchingC
Definition: LKH.h:247
int V
Definition: LKH.h:75
int KarpPartitioning
Definition: LKH.h:290
CostFunction C
Definition: LKH.h:304
#define Fixed(a, b)
Definition: LKH.h:23
unsigned Seed
Definition: LKH.h:259
int Runs
Definition: LKH.h:258
int Distance_GEO_MEEUS(Node *Na, Node *Nb)
Definition: Distance.c:167
static void Read_DIMENSION(void)
Definition: ReadProblem.c:535
int Distance_EUC_2D(Node *Na, Node *Nb)
Definition: Distance.c:42
char * ReadLine(FILE *InputFile)
Definition: ReadLine.c:23
void ReadProblem()
Definition: ReadProblem.c:230
Node * Next
Definition: LKH.h:96
int Distance_MAX_3D(Node *Na, Node *Nb)
Definition: Distance.c:122
int InitialTourAlgorithm
Definition: LKH.h:290
char * Name
Definition: LKH.h:288
int Distance_MAX_2D(Node *Na, Node *Nb)
Definition: Distance.c:115
int Distance_MAN_3D(Node *Na, Node *Nb)
Definition: Distance.c:109
char * Type
Definition: LKH.h:288
int Size
Definition: LKH.h:165
Cluster * FirstCluster
Definition: LKH.h:200
static void Read_NODE_COORD_TYPE(void)
Definition: ReadProblem.c:1186
char * EdgeDataFormat
Definition: LKH.h:288
int ProblemType
Definition: LKH.h:290
int Cost
Definition: LKH.h:136
int AscentCandidates
Definition: LKH.h:174
int SierpinskiPartitioning
Definition: LKH.h:290
int Distance_EUC_3D(Node *Na, Node *Nb)
Definition: Distance.c:48
static void Read_NAME(void)
Definition: ReadProblem.c:529
Node * FixedTo1
Definition: LKH.h:101
static void Read_EDGE_WEIGHT_FORMAT(void)
Definition: ReadProblem.c:764
int InitialStepSize
Definition: LKH.h:211
char ** MergeTourFileName
Definition: LKH.h:284
Definition: LKH.h:48
Definition: LKH.h:134
FILE * SubproblemTourFile
Definition: LKH.h:302
static void Read_EDGE_WEIGHT_SECTION(void)
Definition: ReadProblem.c:796
FILE * ProblemFile
Definition: LKH.h:302
static void CreateNodes(void)
Definition: ReadProblem.c:500
Definition: LKH.h:47
int WeightFormat
Definition: LKH.h:290
Definition: LKH.h:44
Definition: LKH.h:51
int M
Definition: LKH.h:218
static void CheckSpecificationPart(void)
Definition: ReadProblem.c:421
CostFunction c
Definition: LKH.h:304
int SubsequentPatching
Definition: LKH.h:269
Definition: LKH.h:44
int Distance_GEO(Node *Na, Node *Nb)
Definition: Distance.c:62
char * InitialTourFileName
Definition: LKH.h:284
char * EdgeWeightType
Definition: LKH.h:288
Definition: LKH.h:43
char * InputTourFileName
Definition: LKH.h:284
Definition: LKH.h:43
int MaxMatrixDimension
Definition: LKH.h:226
int MoveType
Definition: LKH.h:232
int InitialPeriod
Definition: LKH.h:210
char * NodeCoordType
Definition: LKH.h:288
static void Read_EDGE_WEIGHT_TYPE(void)
Definition: ReadProblem.c:940
int Distance_EXPLICIT(Node *Na, Node *Nb)
Definition: Distance.c:54
int CandidateSetType
Definition: LKH.h:290
static void Read_DISPLAY_DATA_SECTION(void)
Definition: ReadProblem.c:544
Node * First
Definition: LKH.h:163


glkh_solver
Author(s): Francisco Suarez-Ruiz
autogenerated on Mon Jun 10 2019 13:50:27