ReadParameters.c
Go to the documentation of this file.
1 #include "LKH.h"
2 
3 /*
4  * The ReadParameters function reads the name of a parameter file from
5  * standard input and reads the problem parameters from this file.
6  *
7  * All entries of the parameter file are of the form <keyword >= <value>
8  * (or <keyword><whitespace><value>), where <keyword> denotes an alphanumeric
9  * keyword and <value> denotes alphanumeric or numeric data. Keywords are not
10  * case sensitive.
11  *
12  * The order of specifications in the file is arbitrary. The following
13  * specification is mandatory.
14  *
15  * PROBLEM_FILE = <string>
16  * Specifies the name of the problem file.
17  *
18  * Additional control information may be supplied in the following format:
19  *
20  * ASCENT_CANDIDATES = <integer>
21  * The number of candidate edges to be associated with each node during
22  * the ascent. The candidate set is complemented such that every candidate
23  * edge is associated with both its two end nodes.
24  * Default: 50.
25  *
26  * BACKBONE_TRIALS = <integer>
27  * The number of backbone trials in each run.
28  * Default: 0.
29  *
30  * BACKTRACKING = { YES | NO }
31  * Specifies whether a backtracking K-opt move is to be used as the first
32  * move in a sequence of moves (where K = MOVE_TYPE).
33  * Default: NO.
34  *
35  * CANDIDATE_FILE = <string>
36  * Specifies the name of a file to which the candidate sets are to be
37  * written. If, however, the file already exists, the candidate edges are
38  * read from the file. The first line of the file contains the number of
39  * nodes. Each of the following lines contains a node number, the number of
40  * the dad of the node in the minimum spanning tree
41  * (0, if the node has no dad), the number of candidate edges emanating
42  * from the node, followed by the candidate edges. For each candidate edge
43  * its end node number and alpha-value are given.
44  * It is possible to give more than one CANDIDATE_FILE specification. In this
45  * case the given files are read and the union of their candidate edges is
46  * used as candidate sets.
47  *
48  * CANDIDATE_SET_TYPE = { ALPHA | DELAUNAY [ PURE ] | NEAREST-NEIGHBOR |
49  * QUADRANT }
50  * Specifies the candidate set type.
51  * ALPHA is LKH's default type. It is applicable in general.
52  * The other four types can only be used for instances given by coordinates.
53  * The optional suffix PURE for the DELAUNAY type specifies that only
54  * edges of the Delaunay graph are used as candidates.
55  * Default: ALPHA.
56  *
57  * COMMENT <string>
58  * A comment.
59  *
60  * # <string>
61  * A comment.
62  *
63  * EOF
64  * Terminates the input data. The entry is optional.
65  *
66  * EXCESS = <real>
67  * The maximum alpha-value allowed for any candidate edge is set to
68  * EXCESS times the absolute value of the lower bound of a solution
69  * tour (determined by the ascent).
70  * Default: value of 1.0/DIMENSION.
71  *
72  * EXTRA_CANDIDATES = <integer> [ SYMMETRIC ]
73  * Number of extra candidate edges to be added to the candidate set
74  * of each node. Their candidate set type may be specified after the
75  * keyword EXTRA_CANDIDATE_SET_TYPE.
76  * The integer may be followed by the keyword SYMMETRIC, signifying
77  * that these extra candidate edges is to be complemented such
78  * that each of them is associated with both its two end nodes.
79  * Default: 0
80  *
81  * EXTRA_CANDIDATE_SET_TYPE = { NEAREST-NEIGHBOR | QUADRANT }
82  * The candidate set type of extra candidate edges.
83  * Default: QUADRANT
84  *
85  * GAIN23 = { YES | NO }
86  * Specifies whether the Gain23 function is used.
87  * Default: YES.
88  *
89  * GAIN_CRITERION = { YES | NO }
90  * Specifies whether Lin and Kernighan's gain criterion is used.
91  * Default: YES.
92  *
93  * INITIAL_PERIOD = <integer>
94  * The length of the first period in the ascent.
95  * Default: value of DIMENSION/2 (but at least 100).
96  *
97  * INITIAL_STEP_SIZE = <integer>
98  * The initial step size used in the ascent.
99  * Default: 1.
100  *
101  * INITIAL_TOUR_ALGORITHM = { BORUVKA | GREEDY | MOORE | NEAREST-NEIGHBOR |
102  * QUICK-BORUVKA | SIERPINSKI | WALK }
103  * Specifies the algorithm for obtaining an initial tour.
104  * Default: WALK.
105  *
106  * INITIAL_TOUR_FILE = <string>
107  * Specifies the name of a file containing a tour to be used as the
108  * initial tour in the search. The tour is given by a list of integers
109  * giving the sequence in which the nodes are visited in the tour.
110  * The tour is terminated by a -1.
111  * See also INITIAL_TOUR_FRACTION.
112  *
113  * INITIAL_TOUR_FRACTION = <real in [0;1]>
114  * Specifies the fraction of the initial tour to be constructed by means
115  * of INITIAL_TOUR_FILE edges.
116  * Default: 1.0
117  *
118  * INPUT_TOUR_FILE = <string>
119  * Specifies the name of a file containing a tour. The tour is used to
120  * limit the search (the last edge to be excluded in a non-gainful move
121  * must not belong to the tour). In addition, the Alpha field of its
122  * edges is set to zero. The tour is given by a list of integers giving
123  * the sequence in which the nodes are visited in the tour. The tour is
124  * terminated by a -1.
125  *
126  * KICK_TYPE = <integer>
127  * Specifies the value of K for a random K-swap kick. If KICK_TYPE is
128  * zero, then the LKH's special kicking strategy, WALK, is used.
129  * Default: 0.
130  *
131  * KICKS = <integer>
132  * Specifies the number of times to "kick" a tour found by Lin-Kernighan.
133  * Each kick is a random K-swap-kick move. However, KICKS is zero, then
134  * LKH's special kicking strategy, WALK, is used.
135  * Default: 1.
136  *
137  * MAX_BREADTH = <integer>
138  * The maximum number of candidate edges considered at each level of
139  * the search for a move.
140  * Default: INT_MAX.
141  *
142  * MAX_CANDIDATES = <integer> [ SYMMETRIC ]
143  * The maximum number of candidate edges to be associated with each node.
144  * The integer may be followed by the keyword SYMMETRIC, signifying
145  * that the candidate set is to be complemented such that every candidate
146  * edge is associated with both its two end nodes.
147  * If MAX_CANDIDATES is zero the candidate sets are made up of the
148  * edges represented in the CANDIDATE_FILEs, the INITIAL_TOUR_FILE,
149  * the INPUT_TOUR_FILE, the SUBPROBLEM_TOUR_FILE, and the MERGE_TOUR_FILEs.
150  * Default: 5.
151  *
152  * MAX_SWAPS = <integer>
153  * Specifies the maximum number of swaps (flips) allowed in any search
154  * for a tour improvement.
155  * Default: value of DIMENSION.
156  *
157  * MAX_TRIALS = <integer>
158  * The maximum number of trials in each run.
159  * Default: number of nodes (DIMENSION, given in the problem file).
160  *
161  * MERGE_TOUR_FILE = <string>
162  * Specifies the name of a tour to be merged. The edges of the tour are
163  * added to the candidate sets.
164  * It is possible to give more than two MERGE_TOUR_FILE specifications.
165  *
166  * MOVE_TYPE = <integer>
167  * Specifies the sequential move type to be used as submove in Lin-Kernighan.
168  * A value K >= 2 signifies that a sequential K-opt move is used.
169  * Default: 5.
170  *
171  * NONSEQUENTIAL_MOVE_TYPE = <integer>
172  * Specifies the nonsequential move type to be used. A value K >= 4
173  * signifies that attempts are made to improve a tour by nonsequential
174  * k-opt moves where 4 <= k <= K. Note, however, that the effect depends
175  * on the specifications of PATCHING_C and PATCHING_A.
176  * Default: value of (MOVE_TYPE + PATCHING_C + PATCHING_A - 1).
177  *
178  * OUTPUT_TOUR_FILE = <string>
179  * Specifies the name of a file where the best tour is to be written.
180  * Each time a trial has produced a new best tour, the tour is written
181  * to this file.
182  * The character '$' in the name has a special meaning. All occurrences
183  * are replaced by the cost of the tour.
184  *
185  * OPTIMUM = <integer>
186  * Known optimal tour length. If STOP_AT_OPTIMUM is YES, a run will be
187  * terminated if the tour length becomes equal to this value.
188  * Default: value of MINUS_INFINITY.
189  *
190  * PATCHING_A = <integer> [ RESTRICTED | EXTENDED ]
191  * The maximum number of disjoint alternating cycles to be used for
192  * patching. An attempt to patch cycles is made if the corresponding
193  * non-sequential move is gainful.
194  * The integer may be followed by the keyword RESTRICTED or EXTENDED.
195  * The keyword RESTRICTED signifies that gainful moves are only
196  * considered if all its inclusion edges are candidate edges.
197  * The keyword EXTENDED signifies that the non-sequential move need
198  * not be gainful if only all its inclusion edges are candidate edges.
199  * Default: 1.
200  *
201  * PATCHING_C = <integer> [ RESTRICTED | EXTENDED ]
202  * The maximum number of disjoint cycles to be patched in an attempt
203  * to find a feasible and gainful move. An attempt to patch cycles is
204  * made if the corresponding non-sequential move is gainful.
205  * The integer may be followed by the keyword RESTRICTED or EXTENDED.
206  * The keyword RESTRICTED signifies that gainful moves are only
207  * considered if all its inclusion edges are candidate edges.
208  * The keyword EXTENDED signifies that the non-sequential move need
209  * not be gainful if only all its inclusion edges are candidate edges.
210  * Default: 0.
211  *
212  * PI_FILE = <string>
213  * Specifies the name of a file to which penalties (Pi-values determined
214  * by the ascent) are to be written. If the file already exists, the
215  * penalties are read from the file, and the ascent is skipped.
216  * The first line of the file contains the number of nodes. Each of the
217  * following lines is of the form
218  * <integer> <integer>
219  * where the first integer is a node number, and the second integer is
220  * the Pi-value associated with the node.
221  * The file name "0" represents a file with all Pi-values equal to zero.
222  *
223  * POPULATION_SIZE = <integer>
224  * Specifies the maximum size of the population in the genetic algorithm.
225  * Default: 0.
226  *
227  * PRECISION = <integer>
228  * The internal precision in the representation of transformed distances:
229  * d[i][j] = PRECISION*c[i][j] + pi[i] + pi[j],
230  * where d[i][j], c[i][j], pi[i] and pi[j] are all integral.
231  * Default: 100 (which corresponds to 2 decimal places).
232  *
233  * RESTRICTED_SEARCH = { YES | NO }
234  * Specifies whether the following search pruning technique is used:
235  * The first edge to be broken in a move must not belong to the currently
236  * best solution tour. When no solution tour is known, it must not belong
237  * to the minimum spanning 1-tree.
238  * Default: YES.
239  *
240  * RUNS = <integer>
241  * The total number of runs.
242  * Default: 10.
243  *
244  * SEED = <integer>
245  * Specifies the initial seed for random number generation. If zero, the
246  * seed is derived from the system clock.
247  * Default: 1.
248  *
249  * STOP_AT_OPTIMUM = { YES | NO }
250  * Specifies whether a run is stopped, if the tour length becomes equal
251  * to OPTIMUM.
252  * Default: YES.
253  *
254  * SUBGRADIENT = { YES | NO }
255  * Specifies whether the Pi-values should be determined by subgradient
256  * optimization.
257  * Default: YES.
258  *
259  * SUBPROBLEM_SIZE = <integer> [ DELAUNAY | KARP | K-CENTER | K-MEANS | MOORE |
260  * ROHE | SIERPINSKI ] [ BORDERS ] [ COMPRESSED ]
261  * The number of nodes in a division of the original problem into subproblems.
262  * The division is made according to the tour given by SUBPROBLEM_TOUR_FILE.
263  * The value 0 signifies that no division is made.
264  * By default the subproblems are determined by subdividing the tour into
265  * segments of equal size. However, the integer may be followed by DELAUNAY,
266  * KARP, K-CENTER, K-MEANS, MOORE, ROHE or SIERPINSKI. DELAUNAY specifies that
267  * the Delaunay partitioning scheme is used, KARP that Karp's partitioning
268  * scheme is used, K-CENTER that a partitioning scheme based on K-center
269  * clustering, K-MEANS that a partitioning scheme based on K-means clustering
270  * is used, ROHE that Rohe's random rectange partitining scheme is used, and
271  * MOORE or SIERPINSKI that a partitioning scheme based on either a Moore or
272  * Sierpinski space-filling curve is used.
273  * The BORDERS specification signifies that the subproblems along the borders
274  * between subproblems are to be solved too.
275  * The COMPRESSED specification signifies that each subproblem is compressed by
276  * removing from the problem all nodes with two incident subproblem tour edges
277  * that belong to all tours to be merged (at least two MERGE_TOUR_FILEs should
278  * be given).
279  * Default: 0.
280  *
281  * SUBPROBLEM_TOUR_FILE = <string>
282  * Specifies the name of a file containing a tour to be used for dividing
283  * the original problem into subproblems. The approximate number of nodes
284  * in each is * given by SUBPROBLEM_SIZE.
285  * The tour is given by a list of integers giving the sequence in which the
286  * nodes are visited in the tour. The tour is terminated by a -1
287  *
288  * SUBSEQUENT_MOVE_TYPE = <integer>
289  * Specifies the move type to be used for all moves following the first move
290  * in a sequence of moves. The value K >= 2 signifies that a K-opt move is to
291  * be used. The value 0 signifies that all moves are of the same type
292  * (K = MOVE_TYPE).
293  * Default: 0.
294  *
295  * SUBSEQUENT_PATCHING = { YES | NO }
296  * Specifies whether patching is used for moves following the first move
297  * in a sequence of moves.
298  * Default: YES.
299  *
300  * TIME_LIMIT = <real>
301  * Specifies a time limit in seconds for each run.
302  * Default: value of DBL_MAX.
303  *
304  * TOUR_FILE = <string>
305  * Specifies the name of a file where the best tour is to be written.
306  * When a run has produced a new best tour, the tour is written to
307  * this file.
308  * The character '$' in the name has a special meaning. All occurrences
309  * are replaced by the cost of the tour.
310  *
311  * TRACE_LEVEL = <integer>
312  * Specifies the level of detail of the output given during the solution
313  * process. The value 0 signifies a minimum amount of output. The higher
314  * the value is the more information is given.
315  * Default: 1.
316  *
317  * List of abbreviations
318  * ---------------------
319  *
320  * A string value may be abbreviated to the first few letters of the string,
321  * if that abbreviation is unambiguous.
322  *
323  * Value Abbreviation
324  * ALPHA A
325  * BORDERS B
326  * BORUVKA B
327  * COMPRESSED C
328  * DELAUNAY D
329  * EXTENDED E
330  * GREEDY G
331  * KARP KA
332  * K-CENTER K-C
333  * K-MEANS K-M
334  * MOORE M
335  * NEAREST-NEIGHBOR N
336  * NO N
337  * PURE P
338  * QUADRANT Q
339  * QUICK-BORUVKA Q
340  * RESTRICTED R
341  * ROHE R
342  * SIERPINSKI S
343  * SYMMETRIC S
344  * WALK W
345  * YES Y
346  */
347 
348 static char Delimiters[] = "= \n\t\r\f\v\xef\xbb\xbf";
349 static char *GetFileName(char *Line);
350 static char *ReadYesOrNo(int *V);
351 #undef max
352 static size_t max(size_t a, size_t b);
353 
355 {
356  char *Line, *Keyword, *Token, *Name;
357  unsigned int i;
358 
362  AscentCandidates = 50;
363  BackboneTrials = 0;
364  Backtracking = 0;
368  DelaunayPure = 0;
369  Excess = -1;
370  ExtraCandidates = 0;
373  Gain23Used = 1;
374  GainCriterionUsed = 1;
375  InitialPeriod = -1;
376  InitialStepSize = 0;
378  InitialTourFraction = 1.0;
379  KarpPartitioning = 0;
381  KMeansPartitioning = 0;
382  Kicks = 1;
383  KickType = 0;
384  MaxBreadth = INT_MAX;
385  MaxCandidates = 5;
386  MaxPopulationSize = 0;
387  MaxTrials = -1;
388  MaxSwaps = -1;
389  MoorePartitioning = 0;
390  MoveType = 5;
393  PatchingA = 1;
394  PatchingC = 0;
395  PatchingAExtended = 0;
397  PatchingCExtended = 0;
399  Precision = 100;
400  RestrictedSearch = 1;
401  RohePartitioning = 0;
402  Runs = 0;
403  Seed = 1;
405  StopAtOptimum = 1;
406  Subgradient = 1;
407  SubproblemBorders = 0;
409  SubproblemSize = 0;
410  SubsequentMoveType = 0;
411  SubsequentPatching = 1;
412  TimeLimit = DBL_MAX;
413  TraceLevel = 1;
414 
415  if (ParameterFileName) {
416  if (!(ParameterFile = fopen(ParameterFileName, "r")))
417  eprintf("Cannot open PARAMETER_FILE: \"%s\"",
419  } else {
420  while (1) {
421  printff("PARAMETER_FILE = ");
422  if (!(ParameterFileName = GetFileName(ReadLine(stdin)))) {
423  do {
424  printff("PROBLEM_FILE = ");
426  } while (!ProblemFileName);
427  return;
428  } else if (!(ParameterFile = fopen(ParameterFileName, "r")))
429  printff("Cannot open \"%s\". Please try again.\n",
431  else
432  break;
433  }
434  }
435  while ((Line = ReadLine(ParameterFile))) {
436  if (!(Keyword = strtok(Line, Delimiters)))
437  continue;
438  if (Keyword[0] == '#')
439  continue;
440  for (i = 0; i < strlen(Keyword); i++)
441  Keyword[i] = (char) toupper(Keyword[i]);
442  if (!strcmp(Keyword, "ASCENT_CANDIDATES")) {
443  if (!(Token = strtok(0, Delimiters)) ||
444  !sscanf(Token, "%d", &AscentCandidates))
445  eprintf("ASCENT_CANDIDATES: integer expected");
446  if (AscentCandidates < 2)
447  eprintf("ASCENT_CANDIDATES: >= 2 expected");
448  } else if (!strcmp(Keyword, "BACKBONE_TRIALS")) {
449  if (!(Token = strtok(0, Delimiters)) ||
450  !sscanf(Token, "%d", &BackboneTrials))
451  eprintf("BACKBONE_TRIALS: integer expected");
452  if (BackboneTrials < 0)
453  eprintf("BACKBONE_TRIALS: non-negative integer expected");
454  } else if (!strcmp(Keyword, "BACKTRACKING")) {
455  if (!ReadYesOrNo(&Backtracking))
456  eprintf("BACKTRACKING: YES or NO expected");
457  } else if (!strcmp(Keyword, "CANDIDATE_FILE")) {
458  if (!(Name = GetFileName(0)))
459  eprintf("CANDIDATE_FILE: string expected");
460  if (CandidateFiles == 0) {
461  assert(CandidateFileName =
462  (char **) malloc(sizeof(char *)));
464  } else {
465  int i;
466  for (i = 0; i < CandidateFiles; i++)
467  if (!strcmp(Name, CandidateFileName[i]))
468  break;
469  if (i == CandidateFiles) {
470  assert(CandidateFileName =
471  (char **) realloc(CandidateFileName,
472  (CandidateFiles +
473  1) * sizeof(char *)));
474  CandidateFileName[CandidateFiles++] = Name;
475  }
476  }
477  } else if (!strcmp(Keyword, "CANDIDATE_SET_TYPE")) {
478  if (!(Token = strtok(0, Delimiters)))
479  eprintf("%s", "CANDIDATE_SET_TYPE: "
480  "ALPHA, DELAUNAY, NEAREST-NEIGHBOR, "
481  "or QUADRANT expected");
482  for (i = 0; i < strlen(Token); i++)
483  Token[i] = (char) toupper(Token[i]);
484  if (!strncmp(Token, "ALPHA", strlen(Token)))
486  else if (!strncmp(Token, "DELAUNAY", strlen(Token))) {
488  } else if (!strncmp(Token, "NEAREST-NEIGHBOR", strlen(Token)))
490  else if (!strncmp(Token, "QUADRANT", strlen(Token)))
492  else
493  eprintf("%s", "CANDIDATE_SET_TYPE: "
494  "ALPHA, DELAUNAY, NEAREST-NEIGHBOR, "
495  "or QUADRANT expected");
496  if (CandidateSetType == DELAUNAY) {
497  if ((Token = strtok(0, Delimiters))) {
498  for (i = 0; i < strlen(Token); i++)
499  Token[i] = (char) toupper(Token[i]);
500  if (strncmp(Token, "PURE", strlen(Token)))
501  eprintf("%s", "CANDIDATE_SET_TYPE (DELAUNAY): "
502  "PURE or no token expected");
503  DelaunayPure = 1;
504  }
505  }
506  } else if (!strcmp(Keyword, "COMMENT"))
507  continue;
508  else if (!strcmp(Keyword, "EOF"))
509  break;
510  else if (!strcmp(Keyword, "EXCESS")) {
511  if (!(Token = strtok(0, Delimiters)) ||
512  !sscanf(Token, "%lf", &Excess))
513  eprintf("EXCESS: real expected");
514  if (Excess < 0)
515  eprintf("EXCESS: non-negeative real expected");
516  } else if (!strcmp(Keyword, "EXTRA_CANDIDATES")) {
517  if (!(Token = strtok(0, Delimiters)) ||
518  !sscanf(Token, "%d", &ExtraCandidates))
519  eprintf("EXTRA_CANDIDATES: integer expected");
520  if (ExtraCandidates < 0)
521  eprintf("EXTRA_CANDIDATES: non-negative integer expected");
522  if ((Token = strtok(0, Delimiters))) {
523  for (i = 0; i < strlen(Token); i++)
524  Token[i] = (char) toupper(Token[i]);
525  if (strncmp(Token, "SYMMETRIC", strlen(Token)))
526  eprintf
527  ("(EXTRA_CANDIDATES) Illegal SYMMETRIC specification");
529  }
530  } else if (!strcmp(Keyword, "EXTRA_CANDIDATE_SET_TYPE")) {
531  if (!(Token = strtok(0, Delimiters)))
532  eprintf("%s", "EXTRA_CANDIDATE_SET_TYPE: "
533  "NEAREST-NEIGHBOR, or QUADRANT expected");
534  for (i = 0; i < strlen(Token); i++)
535  Token[i] = (char) toupper(Token[i]);
536  if (!strncmp(Token, "NEAREST-NEIGHBOR", strlen(Token)))
538  else if (!strncmp(Token, "QUADRANT", strlen(Token)))
540  else
541  eprintf("%s", "EXTRA_CANDIDATE_SET_TYPE: "
542  "NEAREST-NEIGHBOR or QUADRANT expected");
543  } else if (!strcmp(Keyword, "GAIN23")) {
544  if (!ReadYesOrNo(&Gain23Used))
545  eprintf("GAIN23: YES or NO expected");
546  } else if (!strcmp(Keyword, "GAIN_CRITERION")) {
548  eprintf("GAIN_CRITERION: YES or NO expected");
549  } else if (!strcmp(Keyword, "INITIAL_PERIOD")) {
550  if (!(Token = strtok(0, Delimiters)) ||
551  !sscanf(Token, "%d", &InitialPeriod))
552  eprintf("INITIAL_PERIOD: integer expected");
553  if (InitialPeriod < 0)
554  eprintf("INITIAL_PERIOD: non-negative integer expected");
555  } else if (!strcmp(Keyword, "INITIAL_STEP_SIZE")) {
556  if (!(Token = strtok(0, Delimiters)) ||
557  !sscanf(Token, "%d", &InitialStepSize))
558  eprintf("INITIAL_STEP_SIZE: integer expected");
559  if (InitialStepSize <= 0)
560  eprintf("INITIAL_STEP_SIZE: positive integer expected");
561  } else if (!strcmp(Keyword, "INITIAL_TOUR_ALGORITHM")) {
562  if (!(Token = strtok(0, Delimiters)))
563  eprintf("INITIAL_TOUR_ALGORITHM: "
564  "BORUVKA, GREEDY, MOORE, NEAREST-NEIGHBOR,\n"
565  "QUICK-BORUVKA, SIERPINSKI, or WALK expected");
566  for (i = 0; i < strlen(Token); i++)
567  Token[i] = (char) toupper(Token[i]);
568  if (!strncmp(Token, "BORUVKA", strlen(Token)))
570  else if (!strncmp(Token, "GREEDY", strlen(Token)))
572  else if (!strncmp(Token, "MOORE", strlen(Token)))
574  else if (!strncmp(Token, "NEAREST-NEIGHBOR", strlen(Token)))
576  else if (!strncmp(Token, "QUICK-BORUVKA", strlen(Token)))
578  else if (!strncmp(Token, "SIERPINSKI", strlen(Token)))
580  else if (!strncmp(Token, "WALK", strlen(Token)))
582  else
583  eprintf("INITIAL_TOUR_ALGORITHM: "
584  "BORUVKA, GREEDY, MOORE, NEAREST-NEIGHBOR,\n"
585  "QUICK-BORUVKA, SIERPINSKI or WALK expected");
586  } else if (!strcmp(Keyword, "INITIAL_TOUR_FILE")) {
587  if (!(InitialTourFileName = GetFileName(0)))
588  eprintf("INITIAL_TOUR_FILE: string expected");
589  } else if (!strcmp(Keyword, "INITIAL_TOUR_FRACTION")) {
590  if (!(Token = strtok(0, Delimiters)) ||
591  !sscanf(Token, "%lf", &InitialTourFraction))
592  eprintf("INITIAL_TOUR_FRACTION: real expected");
593  if (InitialTourFraction < 0 || InitialTourFraction > 1)
594  eprintf("INITIAL_TOUR_FRACTION: >= 0 or <= 1 expected");
595  } else if (!strcmp(Keyword, "INPUT_TOUR_FILE")) {
596  if (!(InputTourFileName = GetFileName(0)))
597  eprintf("INPUT_TOUR_FILE: string expected");
598  } else if (!strcmp(Keyword, "KICK_TYPE")) {
599  if (!(Token = strtok(0, Delimiters)) ||
600  !sscanf(Token, "%d", &KickType))
601  eprintf("KICK_TYPE: integer expected");
602  if (KickType != 0 && KickType < 4)
603  eprintf("KICK_TYPE: integer >= 4 expected");
604  } else if (!strcmp(Keyword, "KICKS")) {
605  if (!(Token = strtok(0, Delimiters)) ||
606  !sscanf(Token, "%d", &Kicks))
607  eprintf("KICKS: integer expected");
608  if (Kicks < 0)
609  eprintf("KICKS: non-negative integer expected");
610  } else if (!strcmp(Keyword, "MAX_BREADTH")) {
611  if (!(Token = strtok(0, Delimiters)) ||
612  !sscanf(Token, "%d", &MaxBreadth))
613  eprintf("MAX_BREADTH: integer expected");
614  if (MaxBreadth < 0)
615  eprintf("MAX_BREADTH: non-negative integer expected");
616  } else if (!strcmp(Keyword, "MAX_CANDIDATES")) {
617  if (!(Token = strtok(0, Delimiters)) ||
618  !sscanf(Token, "%d", &MaxCandidates))
619  eprintf("MAX_CANDIDATES: integer expected");
620  if (MaxCandidates < 0)
621  eprintf("MAX_CANDIDATES: non-negative integer expected");
622  if ((Token = strtok(0, Delimiters))) {
623  for (i = 0; i < strlen(Token); i++)
624  Token[i] = (char) toupper(Token[i]);
625  if (!strncmp(Token, "SYMMETRIC", strlen(Token)))
627  else
628  eprintf
629  ("(MAX_CANDIDATES) Illegal SYMMETRIC specification");
630  }
631  } else if (!strcmp(Keyword, "MAX_SWAPS")) {
632  if (!(Token = strtok(0, Delimiters)) ||
633  !sscanf(Token, "%d", &MaxSwaps))
634  eprintf("MAX_SWAPS: integer expected");
635  if (MaxSwaps < 0)
636  eprintf("MAX_SWAPS: non-negative integer expected");
637  } else if (!strcmp(Keyword, "MAX_TRIALS")) {
638  if (!(Token = strtok(0, Delimiters)) ||
639  !sscanf(Token, "%d", &MaxTrials))
640  eprintf("MAX_TRIALS: integer expected");
641  if (MaxTrials < 0)
642  eprintf("MAX_TRIALS: non-negative integer expected");
643  } else if (!strcmp(Keyword, "MERGE_TOUR_FILE")) {
644  if (!(Name = GetFileName(0)))
645  eprintf("MERGE_TOUR_FILE: string expected");
646  if (MergeTourFiles == 0) {
647  assert(MergeTourFileName =
648  (char **) malloc(sizeof(char *)));
650  } else {
651  int i;
652  for (i = 0; i < MergeTourFiles; i++)
653  if (!strcmp(Name, MergeTourFileName[i]))
654  break;
655  if (i == MergeTourFiles) {
656  assert(MergeTourFileName =
657  (char **) realloc(MergeTourFileName,
658  (MergeTourFiles +
659  1) * sizeof(char *)));
660  MergeTourFileName[MergeTourFiles++] = Name;
661  }
662  }
663  } else if (!strcmp(Keyword, "MOVE_TYPE")) {
664  if (!(Token = strtok(0, Delimiters)) ||
665  !sscanf(Token, "%d", &MoveType))
666  eprintf("MOVE_TYPE: integer expected");
667  if (MoveType < 2)
668  eprintf("MOVE_TYPE: >= 2 expected");
669  } else if (!strcmp(Keyword, "NONSEQUENTIAL_MOVE_TYPE")) {
670  if (!(Token = strtok(0, Delimiters)) ||
671  !sscanf(Token, "%d", &NonsequentialMoveType))
672  eprintf("NONSEQUENTIAL_MOVE_TYPE: integer expected");
673  if (NonsequentialMoveType < 4)
674  eprintf("NONSEQUENTIAL_MOVE_TYPE: >= 4 expected");
675  } else if (!strcmp(Keyword, "OPTIMUM")) {
676  if (!(Token = strtok(0, Delimiters)) ||
677  !sscanf(Token, GainInputFormat, &Optimum))
678  eprintf("OPTIMUM: integer expected");
679  } else if (!strcmp(Keyword, "OUTPUT_TOUR_FILE")) {
680  if (!(OutputTourFileName = GetFileName(0)))
681  eprintf("OUTPUT_TOUR_FILE: string expected");
682  } else if (!strcmp(Keyword, "PATCHING_A")) {
683  if (!(Token = strtok(0, Delimiters)) ||
684  !sscanf(Token, "%d", &PatchingA))
685  eprintf("PATCHING_A: integer expected");
686  if (PatchingA < 0)
687  eprintf("PATCHING_A: non-negative integer expected");
688  if ((Token = strtok(0, Delimiters))) {
689  for (i = 0; i < strlen(Token); i++)
690  Token[i] = (char) toupper(Token[i]);
691  if (!strncmp(Token, "RESTRICTED", strlen(Token)))
693  else if (!strncmp(Token, "EXTENDED", strlen(Token)))
694  PatchingAExtended = 1;
695  else
696  eprintf("%s", "(PATCHING_A) "
697  "Illegal RESTRICTED or EXTENDED specification");
698  }
699  } else if (!strcmp(Keyword, "PATCHING_C")) {
700  if (!(Token = strtok(0, Delimiters)) ||
701  !sscanf(Token, "%d", &PatchingC))
702  eprintf("PATCHING_C: integer expected");
703  if (PatchingC < 0)
704  eprintf("PATCHING_C: non-negative integer expected");
705  if ((Token = strtok(0, Delimiters))) {
706  for (i = 0; i < strlen(Token); i++)
707  Token[i] = (char) toupper(Token[i]);
708  if (!strncmp(Token, "RESTRICTED", strlen(Token)))
710  else if (!strncmp(Token, "EXTENDED", strlen(Token)))
711  PatchingCExtended = 1;
712  else
713  eprintf("%s", "(PATCHING_C) ",
714  "Illegal RESTRICTED or EXTENDED specification");
715  }
716  } else if (!strcmp(Keyword, "PI_FILE")) {
717  if (!(PiFileName = GetFileName(0)))
718  eprintf("PI_FILE: string expected");
719  } else if (!strcmp(Keyword, "POPULATION_SIZE")) {
720  if (!(Token = strtok(0, Delimiters)) ||
721  !sscanf(Token, "%d", &MaxPopulationSize))
722  eprintf("POPULATION_SIZE: integer expected");
723  } else if (!strcmp(Keyword, "PRECISION")) {
724  if (!(Token = strtok(0, Delimiters)) ||
725  !sscanf(Token, "%d", &Precision))
726  eprintf("PRECISION: integer expected");
727  } else if (!strcmp(Keyword, "PROBLEM_FILE")) {
728  if (!(ProblemFileName = GetFileName(0)))
729  eprintf("PROBLEM_FILE: string expected");
730  } else if (!strcmp(Keyword, "RESTRICTED_SEARCH")) {
732  eprintf("RESTRICTED_SEARCH: YES or NO expected");
733  } else if (!strcmp(Keyword, "RUNS")) {
734  if (!(Token = strtok(0, Delimiters)) ||
735  !sscanf(Token, "%d", &Runs))
736  eprintf("RUNS: integer expected");
737  if (Runs <= 0)
738  eprintf("RUNS: positive integer expected");
739  } else if (!strcmp(Keyword, "SEED")) {
740  if (!(Token = strtok(0, Delimiters)) ||
741  !sscanf(Token, "%u", &Seed))
742  eprintf("SEED: integer expected");
743  } else if (!strcmp(Keyword, "STOP_AT_OPTIMUM")) {
744  if (!ReadYesOrNo(&StopAtOptimum))
745  eprintf("STOP_AT_OPTIMUM: YES or NO expected");
746  } else if (!strcmp(Keyword, "SUBGRADIENT")) {
747  if (!ReadYesOrNo(&Subgradient))
748  eprintf("SUBGRADIENT: YES or NO expected");
749  } else if (!strcmp(Keyword, "SUBPROBLEM_TOUR_FILE")) {
751  eprintf("SUBPROBLEM_TOUR_FILE: string expected");
752  } else if (!strcmp(Keyword, "SUBPROBLEM_SIZE")) {
753  if (!(Token = strtok(0, Delimiters)) ||
754  !sscanf(Token, "%d", &SubproblemSize))
755  eprintf("SUBPROBLEM_SIZE: integer expected");
756  if (SubproblemSize < 3)
757  eprintf("SUBPROBLEM_SIZE: >= 3 expected");
758  if ((Token = strtok(0, Delimiters))) {
759  for (i = 0; i < strlen(Token); i++)
760  Token[i] = (char) toupper(Token[i]);
761  if (!strncmp(Token, "DELAUNAY", strlen(Token)))
763  else if (!strncmp(Token, "KARP", max(strlen(Token), 2)))
764  KarpPartitioning = 1;
765  else if (!strncmp
766  (Token, "K-CENTER", max(strlen(Token), 3)))
768  else if (!strncmp(Token, "K-MEANS", max(strlen(Token), 3)))
769  KMeansPartitioning = 1;
770  else if (!strncmp(Token, "MOORE", strlen(Token)))
771  MoorePartitioning = 1;
772  else if (!strncmp(Token, "ROHE", strlen(Token)))
773  RohePartitioning = 1;
774  else if (!strncmp(Token, "SIERPINSKI", strlen(Token)))
776  else if (!strncmp(Token, "BORDERS", strlen(Token)))
777  SubproblemBorders = 1;
778  else if (!strncmp(Token, "COMPRESSED", strlen(Token)))
780  else
781  eprintf
782  ("(SUBPROBLEM_SIZE) Illegal DELAUNAY, KARP, K-CENTER, "
783  "K-MEANS, MOORE, ROHE,\n SIERPINSKI, "
784  "BORDERS or COMPRESSED specification");
785  while ((Token = strtok(0, Delimiters))) {
786  for (i = 0; i < strlen(Token); i++)
787  Token[i] = (char) toupper(Token[i]);
788  if (!strncmp(Token, "BORDERS", strlen(Token)))
789  SubproblemBorders = 1;
790  else if (!strncmp(Token, "COMPRESSED", strlen(Token)))
792  else
793  eprintf
794  ("(SUBPROBLEM_SIZE) Illegal BORDERS or "
795  "COMPRESSED specification");
796  }
797  }
798  } else if (!strcmp(Keyword, "SUBSEQUENT_MOVE_TYPE")) {
799  if (!(Token = strtok(0, Delimiters)) ||
800  !sscanf(Token, "%d", &SubsequentMoveType))
801  eprintf("SUBSEQUENT_MOVE_TYPE: integer expected");
802  if (SubsequentMoveType != 0 && SubsequentMoveType < 2)
803  eprintf("SUBSEQUENT_MOVE_TYPE: 0 or >= 2 expected");
804  } else if (!strcmp(Keyword, "SUBSEQUENT_PATCHING")) {
806  eprintf("SUBSEQUENT_PATCHING: YES or NO expected");
807  } else if (!strcmp(Keyword, "TIME_LIMIT")) {
808  if (!(Token = strtok(0, Delimiters)) ||
809  !sscanf(Token, "%lf", &TimeLimit))
810  eprintf("TIME_LIMIT: real expected");
811  if (TimeLimit < 0)
812  eprintf("TIME_LIMIT: >= 0 expected");
813  } else if (!strcmp(Keyword, "TOUR_FILE")) {
814  if (!(TourFileName = GetFileName(0)))
815  eprintf("TOUR_FILE: string expected");
816  } else if (!strcmp(Keyword, "TRACE_LEVEL")) {
817  if (!(Token = strtok(0, Delimiters)) ||
818  !sscanf(Token, "%d", &TraceLevel))
819  eprintf("TRACE_LEVEL: integer expected");
820  } else
821  eprintf("Unknown keyword: %s", Keyword);
822  if ((Token = strtok(0, Delimiters)) && Token[0] != '#')
823  eprintf("Junk at end of line: %s", Token);
824  }
825  if (!ProblemFileName)
826  eprintf("Problem file name is missing");
827  if (SubproblemSize == 0 && SubproblemTourFileName != 0)
828  eprintf("SUBPROBLEM_SIZE specification is missing");
829  if (SubproblemSize > 0 && SubproblemTourFileName == 0)
830  eprintf("SUBPROBLEM_TOUR_FILE specification is missing");
831  fclose(ParameterFile);
832  free(LastLine);
833  LastLine = 0;
834 }
835 
836 static char *GetFileName(char *Line)
837 {
838  char *Rest = strtok(Line, "\n\t\r\f"), *t;
839 
840  if (!Rest)
841  return 0;
842  while (isspace(*Rest))
843  Rest++;
844  if (!Line) {
845  if (*Rest == '=')
846  Rest++;
847  }
848  while (isspace(*Rest))
849  Rest++;
850  for (t = Rest + strlen(Rest) - 1; isspace(*t); t--)
851  *t = '\0';
852  if (!strlen(Rest))
853  return 0;
854  assert(t = (char *) malloc(strlen(Rest) + 1));
855  strcpy(t, Rest);
856  return t;
857 }
858 
859 static char *ReadYesOrNo(int *V)
860 {
861  char *Token = strtok(0, Delimiters);
862 
863  if (Token) {
864  unsigned int i;
865  for (i = 0; i < strlen(Token); i++)
866  Token[i] = (char) toupper(Token[i]);
867  if (!strncmp(Token, "YES", strlen(Token)))
868  *V = 1;
869  else if (!strncmp(Token, "NO", strlen(Token)))
870  *V = 0;
871  else
872  Token = 0;
873  }
874  return Token;
875 }
876 
877 static size_t max(size_t a, size_t b)
878 {
879  return a > b ? a : b;
880 }
char * ProblemFileName
Definition: LKH.h:284
Definition: LKH.h:51
int Gain23Used
Definition: LKH.h:206
int NonsequentialMoveType
Definition: LKH.h:237
double InitialTourFraction
Definition: LKH.h:212
int MaxSwaps
Definition: LKH.h:227
int ExtraCandidateSetType
Definition: LKH.h:290
int SubsequentMoveType
Definition: LKH.h:265
Definition: LKH.h:53
char * SubproblemTourFileName
Definition: LKH.h:284
int CandidateSetSymmetric
Definition: LKH.h:290
int Precision
Definition: LKH.h:249
int SubproblemSize
Definition: LKH.h:264
int KMeansPartitioning
Definition: LKH.h:290
char * LastLine
Definition: LKH.h:214
int Kicks
Definition: LKH.h:216
#define GainInputFormat
Definition: GainType.h:23
int GainCriterionUsed
Definition: LKH.h:207
void printff(char *fmt,...)
Definition: printff.c:10
int SubproblemBorders
Definition: LKH.h:290
int MaxCandidates
Definition: LKH.h:224
int RohePartitioning
Definition: LKH.h:290
static char * GetFileName(char *Line)
int KCenterPartitioning
Definition: LKH.h:290
int KickType
Definition: LKH.h:217
#define MINUS_INFINITY
Definition: GainType.h:21
int DelaunayPartitioning
Definition: LKH.h:290
int PatchingAExtended
Definition: LKH.h:290
GainType Optimum
Definition: LKH.h:241
int MaxBreadth
Definition: LKH.h:221
int SubproblemsCompressed
Definition: LKH.h:290
int MaxTrials
Definition: LKH.h:230
char * OutputTourFileName
Definition: LKH.h:284
int MergeTourFiles
Definition: LKH.h:231
static int a
Definition: Random.c:41
double Excess
Definition: LKH.h:192
int PatchingA
Definition: LKH.h:245
Definition: LKH.h:53
int ExtraCandidates
Definition: LKH.h:196
int DelaunayPure
Definition: LKH.h:290
int RestrictedSearch
Definition: LKH.h:253
Definition: LKH.h:52
static char Delimiters[]
FILE * ParameterFile
Definition: LKH.h:302
int MoorePartitioning
Definition: LKH.h:290
int TraceLevel
Definition: LKH.h:274
void eprintf(const char *fmt,...)
Definition: eprintf.c:8
Definition: LKH.h:51
Definition: LKH.h:51
char * PiFileName
Definition: LKH.h:284
int Subgradient
Definition: LKH.h:262
int MaxPopulationSize
Definition: LKH.h:229
int PatchingC
Definition: LKH.h:247
int KarpPartitioning
Definition: LKH.h:290
unsigned Seed
Definition: LKH.h:259
static int b
Definition: Random.c:41
int Runs
Definition: LKH.h:258
char * TourFileName
Definition: LKH.h:284
int StopAtOptimum
Definition: LKH.h:260
char * ReadLine(FILE *InputFile)
Definition: ReadLine.c:23
int InitialTourAlgorithm
Definition: LKH.h:290
char * Name
Definition: LKH.h:288
char * ParameterFileName
Definition: LKH.h:284
static char * ReadYesOrNo(int *V)
double TimeLimit
Definition: LKH.h:273
int AscentCandidates
Definition: LKH.h:174
int SierpinskiPartitioning
Definition: LKH.h:290
Definition: LKH.h:52
int PatchingARestricted
Definition: LKH.h:290
int InitialStepSize
Definition: LKH.h:211
char ** MergeTourFileName
Definition: LKH.h:284
int Backtracking
Definition: LKH.h:177
int PatchingCRestricted
Definition: LKH.h:290
Definition: LKH.h:51
int SubsequentPatching
Definition: LKH.h:269
int CandidateFiles
Definition: LKH.h:188
char * InitialTourFileName
Definition: LKH.h:284
char * InputTourFileName
Definition: LKH.h:284
static size_t max(size_t a, size_t b)
char ** CandidateFileName
Definition: LKH.h:284
int MoveType
Definition: LKH.h:232
int InitialPeriod
Definition: LKH.h:210
int ExtraCandidateSetSymmetric
Definition: LKH.h:290
void ReadParameters()
int CandidateSetType
Definition: LKH.h:290
int BackboneTrials
Definition: LKH.h:176
Definition: LKH.h:52
int PatchingCExtended
Definition: LKH.h:290


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