Scippy

SCIP

Solving Constraint Integer Programs

graph_load.c
Go to the documentation of this file.
1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2 /* */
3 /* This file is part of the program and library */
4 /* SCIP --- Solving Constraint Integer Programs */
5 /* */
6 /* Copyright (C) 2002-2022 Konrad-Zuse-Zentrum */
7 /* fuer Informationstechnik Berlin */
8 /* */
9 /* SCIP is distributed under the terms of the ZIB Academic License. */
10 /* */
11 /* You should have received a copy of the ZIB Academic License */
12 /* along with SCIP; see the file COPYING. If not visit scipopt.org. */
13 /* */
14 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
15 
16 /**@file graph_load.c
17  * @brief Methods for loading Steiner problems in .stp format
18  * @author Thorsten Koch
19  * @author Daniel Rehfeldt
20  *
21  * This file includes methods for reading a Steiner problem in .stp format.
22  *
23  * A list of all interface methods can be found in graph.h.
24  *
25  */
26 
27 /*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
28 /*lint -esym(750,GRPHLOAD_C) -esym(766,errno.h) */
29 
30 #define GRPHLOAD_C
31 
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <string.h>
35 #include <ctype.h>
36 #include <errno.h> /* errno */
37 #include <assert.h>
38 #include <stdarg.h> /* message: va_list etc */
39 #include "reduce.h"
40 
41 #if defined(_MSC_VER)
42 #include <io.h>
43 #endif
44 
45 #if defined(_WIN32) || defined(_WIN64) || defined(_MSC_VER)
46 #ifndef R_OK
47 #define R_OK 1
48 #endif
49 #else
50 #include <unistd.h> /* R_OK */
51 #endif
52 
53 #include "portab.h"
54 #include "graph.h"
55 
56 #define MSG_FATAL 0
57 #define MSG_ERROR 1
58 #define MSG_WARN 2
59 #define MSG_INFO 3
60 #define MSG_DEBUG 4
61 
62 #ifdef WITH_UG
63 #define VERBOSE MSG_WARN
64 #else
65 #define VERBOSE MSG_INFO
66 #endif
67 
68 /* Try to get the maximum length of a path.
69  *
70  * WARNING: if a path found or build during the scanning process is
71  * longer than defined below, the program will probably
72  * crash, because scanf() will overwrite some memory.
73  */
74 #if defined(PATH_MAX) /* Found this on SCO UNIX */
75 #define MAX_PATH_LEN PATH_MAX
76 #elif defined(_MAX_PATH) /* Watcom C on MSDOS */
77 #define MAX_PATH_LEN _MAX_PATH
78 #elif defined(_POSIX_PATH_MAX) /* Maybe POSIX */
79 #define MAX_PATH_LEN _POSIX_PATH_MAX
80 #else
81 #define MAX_PATH_LEN 1024
82 #endif
83 
84 /* Extension separators
85  */
86 #define EXTSEP '.'
87 
88 #define MAX_LINE_LEN 1024
89 #define MAX_KEYWORD_LEN 64
90 #define MAX_STRING_LEN 256
91 #define MAX_ARGUMENTS 8
92 
93 struct key
94 {
95  const char* keyword;
96  int sw_code;
97  const char* format;
98 };
99 
100 #define KEY_SECTION 0001
101 #define KEY_EOF 9999
102 #define KEY_END 9998
103 
104 #define KEY_COMMENT_NAME 1001
105 #define KEY_COMMENT_DATE 1002
106 #define KEY_COMMENT_CREATOR 1003
107 #define KEY_COMMENT_PROBLEM 1004
108 #define KEY_COMMENT_REMARK 1005
109 
110 #define KEY_GRAPH_NODES 2001
111 #define KEY_GRAPH_EDGES 2002
112 #define KEY_GRAPH_E 2003
113 #define KEY_GRAPH_A 2004
114 #define KEY_GRAPH_AA 2005
115 #define KEY_GRAPH_OBSTACLES 2006
116 #define KEY_GRAPH_HOPLIMIT 2007
117 
118 #define KEY_TERMINALS_END 3001
119 #define KEY_TERMINALS_TERMINALS 3002
120 #define KEY_TERMINALS_T 3003
121 #define KEY_TERMINALS_TP 3004
122 #define KEY_TERMINALS_ROOT 3005
123 #define KEY_TERMINALS_ROOTP 3006
124 #define KEY_TERMINALS_TG 3007
125 #define KEY_TERMINALS_GROUPS 3008
126 #define KEY_TERMINALS_TR 3009
127 #define KEY_TERMINALS_TF 3010
128 #define KEY_TERMINALS_TL 3011
129 #define KEY_TERMINALS_TB 3012
130 #define KEY_TERMINALS_RB 3013
131 
132 #define KEY_COORDINATES_DD 4001
133 #define KEY_COORDINATES_DDD 4002
134 #define KEY_COORDINATES_DDDD 4003
135 #define KEY_COORDINATES_DDDDD 4004
136 #define KEY_COORDINATES_DDDDDD 4005
137 #define KEY_COORDINATES_DDDDDDD 4006
138 #define KEY_COORDINATES_DDDDDDDD 4007
139 
140 #define KEY_COORDINATES_END 4011
141 #define KEY_COORDINATES_GRID 4012
142 
143 #define KEY_SOLUTION_VALUE 4021
144 #define KEY_SOLUTION_DATE 4022
145 #define KEY_SOLUTION_TIME 4023
146 #define KEY_SOLUTION_STEINER 4024
147 #define KEY_SOLUTION_S 4025
148 
149 #define KEY_PRESOLVE_DATE 5001
150 #define KEY_PRESOLVE_FIXED 5002
151 #define KEY_PRESOLVE_LOWER 5003
152 #define KEY_PRESOLVE_UPPER 5004
153 #define KEY_PRESOLVE_TIME 5005
154 #define KEY_PRESOLVE_EA 5006
155 #define KEY_PRESOLVE_EC 5007
156 #define KEY_PRESOLVE_ED 5008
157 #define KEY_PRESOLVE_ES 5009
158 
159 
160 #define KEY_NODEWEIGHTS_NW 6000
161 #define KEY_NODEWEIGHTS_END 6001
162 
163 #define KEY_MAXDEGS_MD 8000
164 
165 #define KEY_OBSTACLES_RR 9000
166 #define KEY_OBSTACLES_END 9001
167 
168 #define KEY_HOPCONS_LIM 10000
169 #define KEY_HOPCONS_FACTOR 10001
170 
171 #define KEY_TREE_S 11000
172 
173 #define KEY_BUDGET_B 12000
174 
175 
176 static const struct key keyword_table[] =
177  {
178  /*
179  * *** The keywords MUST be sorted alphabetically ! ***
180  */
181  { ".eof", KEY_EOF, NULL },
182  { ".section", KEY_SECTION, NULL },
183 
184  { "budget.b", KEY_BUDGET_B, "n" },
185  { "budget.end", KEY_END, NULL },
186 
187  { "comment.creator", KEY_COMMENT_CREATOR, "s" },
188  { "comment.date", KEY_COMMENT_DATE, "s" },
189  { "comment.end", KEY_END, NULL },
190  { "comment.name", KEY_COMMENT_NAME, "s" },
191  { "comment.problem", KEY_COMMENT_PROBLEM, "s" },
192  { "comment.remark", KEY_COMMENT_REMARK, "s" },
193 
194  { "coordinates.dd", KEY_COORDINATES_DD, "nnn" },
195  { "coordinates.ddd", KEY_COORDINATES_DDD, "nnnn" },
196  { "coordinates.dddd", KEY_COORDINATES_DDDD, "nnnnn" },
197  { "coordinates.ddddd", KEY_COORDINATES_DDDDD, "nnnnnn" },
198  { "coordinates.dddddd", KEY_COORDINATES_DDDDDD, "nnnnnnn" },
199  { "coordinates.ddddddd", KEY_COORDINATES_DDDDDDD, "nnnnnnnn" },
200  { "coordinates.dddddddd", KEY_COORDINATES_DDDDDDDD, "nnnnnnnnn" },
201  { "coordinates.end", KEY_COORDINATES_END, NULL },
202  { "coordinates.grid", KEY_COORDINATES_GRID, NULL },
203 
204  { "graph.a", KEY_GRAPH_A, "nnn" },
205  { "graph.aa", KEY_GRAPH_AA, "nnnn" },
206  { "graph.e", KEY_GRAPH_E, "nnn" },
207  { "graph.edges", KEY_GRAPH_EDGES, "n" },
208  { "graph.end", KEY_END, NULL },
209  { "graph.hoplimit", KEY_GRAPH_HOPLIMIT, "n" },
210  { "graph.nodes", KEY_GRAPH_NODES, "n" },
211  { "graph.obstacles", KEY_GRAPH_OBSTACLES, "n" },
212 
213  { "hopconstraint.limit", KEY_HOPCONS_LIM, "n" },
214  { "hopconstraint.factor", KEY_HOPCONS_FACTOR, "nn" },
215 
216  { "maximumdegrees.end", KEY_END, NULL },
217  { "maximumdegrees.md", KEY_MAXDEGS_MD, "n" },
218 
219  { "nodeweights.end", KEY_NODEWEIGHTS_END, NULL },
220  { "nodeweights.nw", KEY_NODEWEIGHTS_NW, "n" },
221 
222  { "obstacles.end", KEY_OBSTACLES_END, NULL },
223  { "obstacles.rr", KEY_OBSTACLES_RR, "nnnn" },
224 
225  { "presolve.date", KEY_PRESOLVE_DATE, "s" },
226  { "presolve.ea", KEY_PRESOLVE_ED, "nnnn" },
227  { "presolve.ec", KEY_PRESOLVE_EC, "nnn" },
228  { "presolve.ed", KEY_PRESOLVE_ED, "nnn" },
229  { "presolve.end", KEY_END, NULL },
230  { "presolve.es", KEY_PRESOLVE_ES, "nn" },
231  { "presolve.fixed", KEY_PRESOLVE_FIXED, "n" },
232  { "presolve.lower", KEY_PRESOLVE_LOWER, "n" },
233  { "presolve.orgnodes", KEY_EOF, "n" },
234  { "presolve.time", KEY_PRESOLVE_TIME, "n" },
235  { "presolve.upper", KEY_PRESOLVE_UPPER, "n" },
236 
237  { "solution.date", KEY_SOLUTION_DATE, "s" },
238  { "solution.end", KEY_END, NULL },
239  { "solution.s", KEY_SOLUTION_S, "n" },
240  { "solution.steiner", KEY_SOLUTION_STEINER, "n" },
241  { "solution.time", KEY_SOLUTION_TIME, "n" },
242  { "solution.value", KEY_SOLUTION_VALUE, "n" },
243 
244  { "terminals.end", KEY_TERMINALS_END, NULL },
245  { "terminals.groups", KEY_TERMINALS_GROUPS, "n" },
246  { "terminals.rb", KEY_TERMINALS_RB, "nnn" },
247  { "terminals.root", KEY_TERMINALS_ROOT, "n" },
248  { "terminals.rootp", KEY_TERMINALS_ROOTP, "n" },
249  { "terminals.t", KEY_TERMINALS_T, "n" },
250  { "terminals.tb", KEY_TERMINALS_TB, "nnn" },
251  { "terminals.terminals", KEY_TERMINALS_TERMINALS, "n" },
252  { "terminals.tf", KEY_TERMINALS_TF, "n" },
253  { "terminals.tg", KEY_TERMINALS_TG, "nn" },
254  { "terminals.tl", KEY_TERMINALS_TL, "n" },
255  { "terminals.tp", KEY_TERMINALS_TP, "nn" },
256  { "terminals.tr", KEY_TERMINALS_TR, "nn" },
257 
258  { "tree.s", KEY_TREE_S, NULL },
259  };
260 
261 struct section
262 {
263  const char* name;
264  const char* extension;
265  const int flag;
266  int mark;
267 };
268 
269 #define FLAG_OPTIONAL 1
270 #define FLAG_REQUIRED 2
271 
272 #define SECTION_MISSING 0
273 #define SECTION_EXISTEND 1
274 
275 /* Extension NULL = no separate file possible !
276  */
277 static struct section section_table[] =
278  {
279  { "", "stp", FLAG_REQUIRED, SECTION_EXISTEND },
280 
281  /*
282  * *** The section names MUST be sorted alphabetically ! ***
283  */
284  { "budget", "bgt", FLAG_OPTIONAL, SECTION_MISSING },
285  { "comment", NULL, FLAG_OPTIONAL, SECTION_MISSING },
286  { "coordinates", "crd", FLAG_OPTIONAL, SECTION_MISSING },
287  { "graph", "grp", FLAG_REQUIRED, SECTION_MISSING },
288  { "maximumdegrees", "mdg", FLAG_OPTIONAL, SECTION_MISSING },
289  { "nodeweights", "nwg", FLAG_OPTIONAL, SECTION_MISSING },
290  { "obstacles", "obs", FLAG_OPTIONAL, SECTION_MISSING },
291  { "presolve", "prs", FLAG_OPTIONAL, SECTION_MISSING },
292  { "solution", "slt", FLAG_OPTIONAL, SECTION_MISSING },
293  { "terminals", "trm", FLAG_OPTIONAL, SECTION_MISSING },
294  { "tree", "tre", FLAG_OPTIONAL, SECTION_MISSING },
295  };
296 
297 typedef struct current_file
298 {
299  char filename[MAX_PATH_LEN];
300  int line;
301  FILE* fp;
302  struct section* section;
303 } CURF;
304 
305 typedef union parameter
306 {
307  double n; /* Could be long long */
308  char s[MAX_STRING_LEN];
309 } PARA;
310 
311 /*---------------------------------------------------------------------------*/
312 /*--- Name : String to Lower ---*/
313 /*--- Function : Converts a string to lower case. ---*/
314 /*--- Arguments: Pointer to string. ---*/
315 /*--- Returns : The argument, but now pointing to a lower case string. ---*/
316 /*---------------------------------------------------------------------------*/
317 static
318 char* strlower(
319  char* s
320  )
321 {
322  char* t;
323 
324  for( t = s; *s != '\0'; s++ )
325  *s = (char)tolower(*s);
326 
327  return t;
328 }
329 
330 
331 /** checks input graph and return possible read error */
332 static
334  SCIP* scip, /**< SCIP data structure */
335  int nterms, /**< number of terminals */
336  GRAPH* graph /**< graph */
337 )
338 {
339  if( graph_typeIsSpgLike(graph) )
340  {
341  SCIP_Bool isInfeas;
342 
343  if( nterms != graph->terms )
344  {
345  SCIPerrorMessage("wrong number of terminals specified %d vs %d \n\n", graph->terms, nterms);
346  return SCIP_READERROR;
347  }
348 
349  // todo do that properly
350  SCIP_CALL( reduce_unconnectedInfeas(scip, TRUE, graph, &isInfeas) );
351 
352  if( isInfeas )
353  {
354  SCIPerrorMessage("unconnected terminal node found \n\n");
355  return SCIP_READERROR;
356  }
357  }
358 
359  if( !graph_validInput(scip, graph) )
360  {
361  return SCIP_READERROR;
362  }
363 
364  if( graph_hasMultiEdges(scip, graph, TRUE) )
365  {
366  return SCIP_READERROR;
367  }
368 
369 
370  return SCIP_OKAY;
371 }
372 
373 
374 /*---------------------------------------------------------------------------*/
375 /*--- Name : Print Message ---*/
376 /*--- Function : Prints a message on stderr. ---*/
377 /*--- Arguments: Type of message, Info about filename and line number, ---*/
378 /*--- printf format string and parameters to be printed. ---*/
379 /*--- Returns : Nothing ---*/
380 /*---------------------------------------------------------------------------*/
381 static void message(
382  unsigned int type,
383  const CURF* curf,
384  const char* msg,
385  ...)
386 {
387  va_list params;
388 
389  const char* intro[] = { "Fatal Error", "Error ", "Warning ",
390  "Info ", "Debug "
391  };
392  const char* header = "*** %s File \"%s\" line %05d: ";
393 
394  assert(type < sizeof(intro) / sizeof(char*));
395  assert(curf != NULL);
396  assert(curf->filename != NULL);
397  assert(curf->line >= 0);
398  assert(msg != NULL);
399 
400  va_start(params, msg);
401 
402  if (type <= VERBOSE)
403  {
404  (void)fprintf(stderr, header, intro[type], curf->filename, curf->line);
405  (void)vfprintf(stderr, msg, params);
406  (void)fputc('\n', stderr);
407  }
408  va_end(params);
409 }
410 
411 /*---------------------------------------------------------------------------*/
412 /*--- Name : Key Compare ---*/
413 /*--- Function : Compares the key with an element of the list. ---*/
414 /*--- Parameter: Pointer to key, pointer to element ---*/
415 /*--- Returns : <0 : key<elem, =0 : key=elem, >0 : key>elem ---*/
416 /*---------------------------------------------------------------------------*/
417 static int key_cmp(
418  const void* key,
419  const void* elem)
420 {
421  assert(key != NULL);
422  assert(elem != NULL);
423  assert(((const struct key*)elem)->keyword != NULL);
424 
425  return(strcmp((const char*)key, ((const struct key*)elem)->keyword));
426 }
427 
428 /*---------------------------------------------------------------------------*/
429 /*--- Name : Section Compare ---*/
430 /*--- Function : Compares the key with an section name. ---*/
431 /*--- Parameter: Pointer to key, pointer to section ---*/
432 /*--- Returns : <0 : key<sec, =0 : key=sec, >0 : key>sec ---*/
433 /*---------------------------------------------------------------------------*/
434 static int sec_cmp(
435  const void* key,
436  const void* section)
437 {
438  assert(key != NULL);
439  assert(section != NULL);
440  assert(((const struct section*)section)->name != NULL);
441 
442  return(strcmp((const char*)key, ((const struct section*)section)->name));
443 }
444 
445 /*---------------------------------------------------------------------------*/
446 /*--- Name : Get Arguments ---*/
447 /*--- Function : Extract the arguments following a keyword. ---*/
448 /*--- Parameter: Current file info, argument format string, input line, ---*/
449 /*--- pointer to array of MAX_ARGUMENTS PARA's. ---*/
450 /*--- Returns : 0 for success and < 0 for failure. ---*/
451 /*---------------------------------------------------------------------------*/
452 static int get_arguments(
453  const CURF* curf,
454  const char* format,
455  const char* s,
456  PARA* para)
457 {
458  const char* err_missmatch_v = "Wrong Syntax";
459  const char* msg_hello_ss = "get_arguments(\"%s\", \"%s\")";
460 
461  int missmatch = FALSE;
462  int i;
463  int decimal_spaces;
464  SCIP_Bool is_negative;
465  assert(format != NULL);
466  assert(s != NULL);
467  assert(para != NULL);
468 
469  message(MSG_DEBUG, curf, msg_hello_ss, format, s);
470 
471  /* We try until we run out of input or have enough arguments.
472  */
473  while((*s != '\0') && (*format != '\0') && !missmatch)
474  {
475  missmatch = TRUE;
476 
477  switch(*format)
478  {
479  case 'n' : /* Numeric */
480  /* Go to next digit.
481  */
482  while((*s != '\0') && !isdigit(*s) && (*s != '.') && (*s != '-') )
483  {
484  s++;
485  }
486  /* Something left ?
487  */
488  if (*s != '\0')
489  {
490  assert(isdigit(*s) || (*s == '.') || (*s == '-'));
491 
492  /* Get it.
493  */
494  para->n = 0;
495  decimal_spaces = -1;
496  is_negative = FALSE;
497  while(isdigit(*s) || (*s == '.') || (*s == '-'))
498  {
499  if( *s == '.' )
500  decimal_spaces = 0;
501  else if( *s == '-' )
502  is_negative = TRUE;
503  else if( decimal_spaces != -1 )
504  para->n = para->n + pow(10.0, (double) -(++decimal_spaces)) * (*s - '0');
505  else
506  para->n = para->n * 10 + (*s - '0');
507  s++;
508  }
509  if( is_negative )
510  para->n = (-1) * para->n;
511  missmatch = FALSE;
512  }
513  break;
514  case 's' : /* String */
515  /* Go to the beginning of the string.
516  */
517  while((*s != '\0') && (*s != '\"'))
518  s++;
519 
520  /* Someting left ?
521  */
522  if (*s != '\0')
523  {
524  assert(*s == '\"');
525 
526  /* Get the String.
527  */
528  i = 0;
529  s++;
530 
531  while((*s != '\0') && (*s != '\"') && (i < MAX_STRING_LEN - 1))
532  para->s[i++] = *s++;
533 
534  para->s[i] = '\0';
535  missmatch = FALSE;
536  }
537  break;
538  case 'b' : /* Bool */
539  case 'd' : /* Date */
540  default :
541  /* CONSTCOND */
542  assert(FALSE);
543  break;
544  }
545  if (missmatch)
546  message(MSG_WARN, curf, err_missmatch_v);
547  else
548  {
549  para++;
550  format++;
551 
552  }
553  }
554  return((*format == '\0') ? SUCCESS : FAILURE);
555 }
556 
557 /*---------------------------------------------------------------------------*/
558 /*--- Name : Open File ---*/
559 /*--- Function : Opens a file, processes the file header and secures it's ---*/
560 /*--- the right file. ---*/
561 /*--- Arguments: Info about filename and wanted section (file type). ---*/
562 /*--- Returns : 0 for success with curf->fp and curf->line filled or ---*/
563 /*--- or < 0 for failure. ---*/
564 /*---------------------------------------------------------------------------*/
565 static int open_file(
566  CURF* curf,
567  unsigned char main_file
568 )
569 {
570  const char* err_cantopen_s = "%s.";
571  const char* err_noheader_v = "Wrong file header.";
572  const char* err_nomagic_d = "Wrong Magic-Number %d.";
573  const char* err_wrongtype_ss = "Wrong file type. Found %s, expected %s.";
574  const char* msg_version_dd = "Format Version %d.%d.";
575 
576  char type[4];
577  unsigned int magic;
578  int version_major;
579  int version_minor;
580  int result = FAILURE;
581 
582  assert(curf != NULL);
583  assert(curf->filename != NULL);
584  assert(curf->section != NULL);
585 
586  /* Prepare the result.
587  */
588  curf->line = 1;
589  curf->fp = NULL;
590 
591  /* reading in the main file? */
592  if( main_file )
593  {
594  char fillname_gr[MAX_PATH_LEN + 3];
595 
596  (void)sprintf(fillname_gr, "%s.%s",
597  curf->filename, "gr");
598 
599  /* try to open .gr */
600  if ((curf->fp = fopen(fillname_gr, "r")) != NULL)
601  {
602  (void)sprintf(curf->filename, "%s", fillname_gr);
603  return(SUCCESS);
604  }
605  else
606  {
607  /* try to open .stp */
608  char fillname_stp[MAX_PATH_LEN + 4];
609  (void) sprintf(fillname_stp, "%s.%s", curf->filename, "stp");
610 
611  if ((curf->fp = fopen(fillname_stp, "r")) == NULL)
612  {
613  message(MSG_FATAL, curf, err_cantopen_s, strerror(errno));
614  return result;
615  }
616  (void)sprintf(curf->filename, "%s", fillname_stp);
617  }
618  }
619 
620 
621  /* Try to open the file...
622  */
623  if (!main_file && (curf->fp = fopen(curf->filename, "r")) == NULL)
624  message(MSG_FATAL, curf, err_cantopen_s, strerror(errno));
625 
626  /* Read Header...
627  */
628  else if (fscanf(curf->fp, "%8x %3s File, STP Format Version %2d.%2d \n",
629  &magic, type, &version_major, &version_minor) != 4)
630  message(MSG_FATAL, curf, err_noheader_v);
631 
632  /* Test Magic...
633  */
634  else if (magic != STP_FILE_MAGIC)
635  message(MSG_FATAL, curf, err_nomagic_d, magic);
636 
637  /* Did we get the right type of file ?
638  */
639  else if (strcmp(strlower(type), curf->section->extension))
640  message(MSG_FATAL, curf, err_wrongtype_ss, type, curf->section->extension);
641  else
642  {
643  /* Succeeded. Just give a warning if the file has a different
644  * version number than the reader and hope it will be ok.
645  */
646  if ((version_major != STP_FILE_VERSION_MAJOR) || (version_minor != STP_FILE_VERSION_MINOR))
647  message(MSG_WARN, curf, msg_version_dd, version_minor, version_major);
648 
649  result = SUCCESS;
650  }
651  return(result);
652 }
653 
654 /*---------------------------------------------------------------------------*/
655 /*--- Name : Start a new Section ---*/
656 /*--- Function : Starts a new section, maybe in another file. ---*/
657 /*--- Parameter: Path for files, Basename, pointer to actual file info, ---*/
658 /*--- Pointer to where to save actual file info, inputline. ---*/
659 /*--- Returns : 0 for success and < 0 for failure. ---*/
660 /*---------------------------------------------------------------------------*/
661 static int start_section(
662  const char* pathname,
663  const char* basename,
664  CURF* curf,
665  CURF* save,
666  const char* s)
667 {
668  const char* err_missing_v = "Section name missing";
669  const char* err_badsect_s = "Unknown section name [%s]";
670  const char* err_required_s = "Can't access required file [%s]";
671 
672  CURF temp;
673  char inclname[MAX_PATH_LEN];
674  char sectname[MAX_KEYWORD_LEN];
675  char dummy [MAX_KEYWORD_LEN];
676  int tokens;
677  int ret = FAILURE;
678 
679  assert(pathname != NULL);
680  assert(basename != NULL);
681  assert(curf != NULL);
682  assert(save != NULL);
683  assert(s != NULL);
684 
685  sectname[0] = '\0';
686  inclname[0] = '\0';
687 
688  /* Extract names
689  */
690  if( (tokens = sscanf(s, "%63s %63s %s", sectname, dummy, inclname)) < 1 )
691  message(MSG_FATAL, curf, err_missing_v);
692  else
693  {
694  /* Known section ?
695  */
696  if( strcmp(strlower(sectname),"comments") == 0 )
697  sectname[7] = '\0';
698 
699  temp.section = (struct section*)bsearch(strlower(sectname),
700  &section_table[1],
701  (sizeof(section_table) / sizeof(struct section)) - 1,
702  sizeof(struct section), sec_cmp);
703 
704  if( temp.section == NULL )
705  message(MSG_FATAL, curf, err_badsect_s, sectname);
706  else
707  {
708  /* Is this section in a separate file ?
709  */
710  if( tokens == 1 || (tokens == 2 && strcmp(strlower(sectname),"tree") == 0) )
711  {
712  curf->section = temp.section;
713  curf->section->mark |= SECTION_EXISTEND;
714  ret = SUCCESS;
715  }
716  else
717  {
718  (void)sprintf(temp.filename, "%s%s%c%s",
719  pathname,
720  (*inclname == '\0') ? basename : inclname,
721  EXTSEP,
722  temp.section->extension);
723 #if defined(_MSC_VER)
724  if (_access(temp.filename, R_OK))
725 #else
726  if (access(temp.filename, R_OK))
727 #endif
728  {
729  /* We can't access the include file.
730  * If the section is optional, we just ignore
731  * the whole thing, otherwise we have a problem.
732  */
733  if (temp.section->flag & FLAG_REQUIRED)
734  message(MSG_FATAL, curf, err_required_s, temp.filename);
735  else
736  {
737  temp.section = &section_table[0];
738  ret = SUCCESS;
739  }
740  }
741  else
742  {
743  if (!open_file(&temp, FALSE) )
744  {
745  *save = *curf;
746  *curf = temp;
747  curf->section->mark |= SECTION_EXISTEND;
748 
749  ret = SUCCESS;
750  }
751  }
752  }
753  }
754  }
755  return(ret);
756 }
757 
758 static
760  SCIP* scip,
761  GRAPH* g,
762  PARA* para,
763  double*** coordinates,
764  int* grid_dim,
765  int* termcount,
766  int dim,
767  int nodes
768  )
769 {
770  int i;
771 
772  if( *coordinates == NULL )
773  {
774  assert(g == NULL);
775  assert(termcount != NULL);
776  assert(grid_dim != NULL);
777  assert(*termcount == 0);
778  assert(nodes > 0);
779 
780  *grid_dim = dim;
781 
782  /* allocate memory for the coordinate arrays */
783  SCIP_CALL( SCIPallocMemoryArray(scip, coordinates, dim) );
784 
785  for( i = 0; i < dim; i++ )
786  SCIP_CALL( SCIPallocMemoryArray(scip, &((*coordinates)[i]), nodes) ); /*lint !e866*/
787  }
788 
789  for( i = 0; i < dim; i++ )
790  (*coordinates)[i][*termcount] = (double)para[i + 1].n;
791 
792  (*termcount)++;
793  return SCIP_OKAY;
794 }
795 
796 static
799  )
800 {
801  int ints;
802  int order;
803  int trail_zeroes;
804  int i;
805  int length;
806  char s;
807  char str_number[SCIP_MAXSTRLEN];
808  (void)SCIPsnprintf(str_number, SCIP_MAXSTRLEN, "%f", number);
809  length = (int) strlen(str_number);
810  if( SCIP_MAXSTRLEN < length )
811  length = (int) SCIP_MAXSTRLEN;
812 
813  for( i = 0; i < length; i++ )
814  {
815  if( str_number[length - i - 1] != '0' )
816  break;
817  }
818  trail_zeroes = i;
819 
820  for( i = 0; i < length; i++ )
821  {
822  s = str_number[i];
823  if( s == '.' )
824  break;
825  }
826  ints = i;
827  order = length - ints - trail_zeroes - 1;
828 
829  return order;
830 }
831 
832 
833 /* scales coordinates in such a way, that they become integer */
834 static
836  double** coordinates,
837  int*** scaled_coords,
838  int* scale_order,
839  int nnodes,
840  int grid_dim
841  )
842 {
843  int i;
844  int j;
845  int tmp;
846  int scale_factor;
847  int max_order = 0;
848 
849  assert(coordinates != NULL);
850  assert(nnodes > 0);
851  assert(grid_dim > 1);
852 
853  SCIP_CALL( SCIPallocMemoryArray(scip, scaled_coords, grid_dim) );
854 
855  for( i = 0; i < grid_dim; i++ )
856  for( j = 0; j < nnodes; j++ )
857  {
858  tmp = get_scale_order(coordinates[i][j]);
859 
860  if( max_order < tmp )
861  {
862  max_order = tmp;
863  }
864  }
865 
866  *scale_order = max_order;
867  scale_factor = (int) pow(10.0, (double) max_order);
868 
869  for( i = 0; i < grid_dim; i++ )
870  {
871  SCIP_CALL( SCIPallocMemoryArray(scip, &((*scaled_coords)[i]), nnodes) ); /*lint !e866*/
872  for( j = 0; j < nnodes; j++ )
873  {
874  (*scaled_coords)[i][j] = (int) (coordinates[i][j] * scale_factor);
875  }
876  }
877  return SCIP_OKAY;
878 }
879 
880 /*---------------------------------------------------------------------------*/
881 /*--- Name : Steiner Tree Problem Load ---*/
882 /*--- Function : Reads a file in STP format and parses it. ---*/
883 /*--- Parameter: Pointer to filename, Pointer to presolve struct ---*/
884 /*---------------------------------------------------------------------------*/
886  SCIP* scip, /**< SCIP data structure */
887  GRAPH** graph, /**< pointer to store the graph */
888  const char* file, /**< file to load */
889  PRESOL* presol /**< presolving struct */
890  )
891 {
892  const char* err_unknown_s = "Unknown keyword [%s]";
893  const char* err_include_v = "Include in included file";
894  const char* err_missing_s = "Required section %s missing";
895  const char* msg_newsect_s = "Processing Section %s";
896  const char* msg_keyword_sd = "Found Keyword \"%s\", code = %d";
897  const char* err_badedge_ddd = "Bad edge %d-%d (%d nodes)";
898  const char* err_badroot_dd = "Bad root %d (%d nodes)";
899  const char* err_baddeg_dd = "More degree constraints (%d) than nodes (%d)";
900 #ifndef WITH_UG
901  const char* msg_finish_dddd = "Nodes: %d Edges: %d Terminals: %d Source=%d\n";
902 #endif
903 
904  const char* endofline = "#;\n\r";
905  const char* separator = " \t:=";
906 
907  static CURF curf_null = { "", 0, NULL, NULL };
908 
909  GRAPH* g = NULL;
910  CURF curf;
911  CURF save;
912  PARA para [MAX_ARGUMENTS];
913  double nodeweight;
914  char buffer [MAX_LINE_LEN];
915  char pathname[MAX_PATH_LEN];
916  char basename[MAX_PATH_LEN];
917  char keyword [MAX_KEYWORD_LEN];
918  int stop_input = FALSE;
919  int ret = SUCCESS;
920  char* s;
921  char* t;
922  struct key* p;
923  double** coordinates = NULL;
924  int i;
925  int head;
926  int tail;
927  int tgroups = 0;
928  int grid_dim = -1;
929  int terms = 0;
930  int nodes = 0;
931  int edges = 0;
932  int nwcount = 0;
933  int degcount = 0;
934  int hoplimit = UNKNOWN;
935  int stp_type = -1;
936  int edgecount = 0;
937  int termcount = 0;
938  int nobstacles = -1;
939  int scale_order = 1;
940  int obstacle_counter = 0;
941  int** scaled_coordinates = NULL;
942  int** obstacle_coords = NULL;
943  int transformed = 0;
944  SCIP_Bool checkInput = FALSE;
945 
946  SCIP_CALL( SCIPgetBoolParam(scip, "stp/checkinput", &checkInput) );
947 
948  if( checkInput )
949  printf("input checker is active \n\n");
950 
951 
952  assert(file != NULL);
953 
954  /* No section loaded so far.
955  */
956  for( i = 1; i < (int)(sizeof(section_table) / sizeof(section_table[0])); i++ )
957  section_table[i].mark = SECTION_MISSING;
958 
959  /* Get the names...
960  */
961  (void)strcpy(pathname, file);
962 
963  /* Did we get a path ?
964  */
965  if( (s = strrchr(pathname, DIRSEP[0])) == NULL )
966  {
967  /* No, no path.
968  */
969  (void)strcpy(basename, pathname);
970  pathname[0] = '\0';
971  }
972  else
973  {
974  /* Yes, there is a path in front.
975  */
976  s++;
977  (void)strcpy(basename, s);
978  *s = '\0';
979  }
980 
981  /* Strip of the extension
982  */
983  if ((s = strrchr(basename, EXTSEP)) != NULL)
984  *s = '\0';
985 
986  /* Build filename
987  */
988  curf.section = &section_table[0];
989  save = curf_null;
990 
991  (void) SCIPsnprintf(curf.filename, MAX_PATH_LEN, "%s%s", pathname, basename);
992 
993  /* Open the file...
994  */
995  if (!open_file(&curf, TRUE))
996  {
997  /* We read while a file is open...
998  */
999  while((curf.fp != NULL) && !stop_input)
1000  {
1001  /* Read a line.
1002  */
1003  if ((s = fgets(buffer, (int) sizeof(buffer), curf.fp)) == NULL)
1004  {
1005  /* No more lines available, so we can close the file.
1006  */
1007  (void)fclose(curf.fp);
1008 
1009  /* If we are in an included file, we come back to our
1010  * main file. Otherwise fp_save is NULL and than fp will
1011  * get NULL so we're finished.
1012  */
1013  curf = save;
1014  save = curf_null;
1015 
1016  continue;
1017  }
1018  /* Count line number
1019  */
1020  curf.line++;
1021 
1022  /* Find the start of the interesting part of an inputline.
1023  */
1024  while(isspace(*s))
1025  s++;
1026 
1027  /* Find the end of the interesting portion of an input line.
1028  * Either the start of a comment or the final NL or CR.
1029  * Since all lines but the last must have at least a NL
1030  * t is nearly never NULL.
1031  */
1032  if ((t = strpbrk(s, endofline)) != NULL)
1033  *t = '\0';
1034 
1035  /* Is there an interesting part left ?
1036  */
1037  if (*s == '\0')
1038  continue;
1039 
1040  /* Build a keyword of form "sectionname.keyword"
1041  */
1042  (void)strcpy(keyword, curf.section->name);
1043 
1044  i = (int)strlen(keyword);
1045  keyword[i] = '.';
1046 
1047  for(i++;
1048  (i < MAX_KEYWORD_LEN - 1) && (isalpha(*s) || (*s == '_'));
1049  i++, s++)
1050  keyword[i] = (char)tolower(*s);
1051 
1052  keyword[i] = '\0';
1053 
1054  /* Skip junk following the keyword.
1055  */
1056  while((*s != '\0') && (strchr(separator, *s) != NULL))
1057  s++;
1058 
1059  if( strcmp(keyword,"comments") == 0 )
1060  keyword[i - 1] = '\0';
1061 
1062  /* Did we know the keyword ?
1063  */
1064  p = (struct key*)bsearch(keyword, keyword_table,
1065  sizeof(keyword_table) / sizeof(struct key),
1066  sizeof(struct key), key_cmp);
1067 
1068  if (p == NULL)
1069  message(MSG_ERROR, &curf, err_unknown_s, keyword);
1070  else
1071  {
1072  char newformat[5] = "";
1073  assert(p != NULL);
1074 
1075  message(MSG_DEBUG, &curf, msg_keyword_sd, p->keyword, p->sw_code);
1076 
1077  /* Yes, so lets get the rest of the line if possible
1078  */
1079  if( (stp_type == STP_MWCSP || stp_type == STP_RMWCSP) && p->format != NULL && (p->sw_code == KEY_TERMINALS_T || p->sw_code == KEY_GRAPH_E) )
1080  strcpy(newformat, "nn");
1081  else if( stp_type == STP_SAP && p->sw_code == KEY_GRAPH_A )
1082  strcpy(newformat, "nnnn");
1083 
1084  if( p->format == NULL || !get_arguments(&curf, (const char*)( newformat[0] != '\0' ? newformat : p->format ), s, para) )
1085  {
1086  int vertex;
1087 
1088  /* Now, what should we do ?
1089  */
1090  switch(p->sw_code)
1091  {
1092  case KEY_SECTION : /* a new Section starts. */
1093  if (save.fp == NULL)
1094  stop_input = start_section(pathname, basename,
1095  &curf, &save, s);
1096  else
1097  {
1098  message(MSG_FATAL, &curf, err_include_v);
1099  stop_input = TRUE;
1100  }
1101  if (!stop_input)
1102  message(MSG_INFO, &curf, msg_newsect_s, curf.section->name);
1103  break;
1104  case KEY_END : /* END found. */
1105  curf.section = &section_table[0];
1106  break;
1107  case KEY_TREE_S : /* fall through */
1108  case KEY_EOF : /* EOF found */
1109  if( !checkInput )
1110  {
1111  ret = SUCCESS;
1112  }
1113  stop_input = TRUE;
1114 
1115  /* Test if all required section were found.
1116  */
1117  for(i = 0; (unsigned)i < sizeof(section_table) / sizeof(struct section); i++)
1118  {
1119  if ((section_table[i].flag & FLAG_REQUIRED)
1120  && !(section_table[i].mark & SECTION_EXISTEND))
1121  {
1122  message(MSG_FATAL, &curf, err_missing_s, section_table[i].name);
1123  ret = FAILURE;
1124  }
1125  }
1126  break;
1127  case KEY_COMMENT_NAME :
1128  case KEY_COMMENT_DATE :
1129  case KEY_COMMENT_CREATOR :
1130  case KEY_COMMENT_PROBLEM :
1131 #ifndef WITH_UG
1132  (void)printf("Problem: [%s]\n", para[0].s);
1133 #endif
1134  if( strcmp(para[0].s, "SPG") == 0 )
1135  stp_type = STP_SPG;
1136  else if( strcmp(para[0].s, "PCSPG") == 0
1137  || strcmp(para[0].s, "Prize-Collecting Steiner Problem in Graphs") == 0 )
1138  stp_type = STP_PCSPG;
1139  else if( strcmp(para[0].s, "RPCST") == 0
1140  || strcmp(para[0].s, "Rooted Prize-Collecting Steiner Problem in Graphs") == 0 )
1141  stp_type = STP_RPCSPG;
1142  else if( strcmp(para[0].s, "NWSPG") == 0 )
1143  stp_type = STP_NWSPG;
1144  else if( strcmp(para[0].s, "DCST") == 0 )
1145  stp_type = STP_DCSTP;
1146  else if( strcmp(para[0].s, "RSMT") == 0 )
1147  stp_type = STP_RSMT;
1148  else if( strcmp(para[0].s, "OARSMT") == 0 )
1149  stp_type = STP_OARSMT;
1150  else if( strcmp(para[0].s, "Maximum Node Weight Connected Subgraph") == 0
1151  || strcmp(para[0].s, "MWCS") == 0 )
1152  stp_type = STP_MWCSP;
1153  else if( strcmp(para[0].s, "Rooted Maximum Node Weight Connected Subgraph") == 0
1154  || strcmp(para[0].s, "RMWCS") == 0 )
1155  stp_type = STP_RMWCSP;
1156  else if( strcmp(para[0].s, "HCDST") == 0 )
1157  stp_type = STP_DHCSTP;
1158  else if( strcmp(para[0].s, "SAP") == 0 )
1159  stp_type = STP_SAP;
1160  else if( strcmp(para[0].s, "GSTP") == 0 )
1161  stp_type = STP_GSTP;
1162  break;
1163  case KEY_COMMENT_REMARK :
1164 #ifndef WITH_UG
1165  (void)printf("Comment: [%s]\n", para[0].s);
1166 #endif
1167  if( strcmp(para[0].s, "Transformed") == 0 )
1168  transformed = 1;
1169  break;
1170  case KEY_GRAPH_NODES :
1171  assert(para != NULL);
1172  nodes = (int)para[0].n;
1173  break;
1174  case KEY_GRAPH_OBSTACLES :
1175  nobstacles = (int)para[0].n;
1176  if( nobstacles > 0 )
1177  stp_type = STP_OARSMT;
1178  break;
1179  case KEY_GRAPH_HOPLIMIT :
1180  hoplimit = (int)para[0].n;
1181  stp_type = STP_DHCSTP;
1182  break;
1183  case KEY_GRAPH_EDGES :
1184  edges = (int)para[0].n;
1185  break;
1186  case KEY_GRAPH_A :
1187  case KEY_GRAPH_AA :
1188  case KEY_GRAPH_E :
1189  if( (int)para[0].n > nodes || (int)para[1].n > nodes )
1190  {
1191  message(MSG_FATAL, &curf, err_badedge_ddd,
1192  (int)para[0].n, (int)para[1].n, nodes);
1193  ret = FAILURE;
1194  break;
1195  }
1196 
1197  if( g == NULL )
1198  {
1199  if( stp_type == STP_GSTP )
1200  SCIP_CALL( graph_init(scip, graph, nodes * 2, edges * 2 + nodes * nodes, 1) );
1201  else
1202  SCIP_CALL( graph_init(scip, graph, nodes, edges * 2, 1) );
1203 
1204  g = *graph;
1205  assert(g != NULL);
1206  assert(g->source == UNKNOWN);
1207  for( i = 0; i < nodes; i++ )
1208  graph_knot_add(g, -1);
1209 
1210  if( stp_type == STP_DHCSTP )
1211  {
1212  assert(hoplimit != UNKNOWN);
1213  g->hoplimit = hoplimit;
1214  }
1215  }
1216 
1217  if( checkInput )
1218  {
1219  edgecount++;
1220 
1221  if( edgecount > edges )
1222  {
1223  SCIPerrorMessage("too many edges (should be at most %d) \n\n", edges);
1224  return SCIP_READERROR;
1225  }
1226  }
1227 
1228  if( stp_type == STP_DHCSTP )
1229  {
1230  tail = (int)para[0].n - 1;
1231  head = (int)para[1].n - 1;
1232  /* check whether the anti-parallel arc has already been added */
1233  for( i = g->inpbeg[head]; i != EAT_LAST; i = g->ieat[i] )
1234  if( g->tail[i] == tail )
1235  break;
1236  if( i == EAT_LAST )
1237  graph_edge_add(scip, g, tail, head, (double)para[2].n, FARAWAY);
1238  else
1239  g->cost[i] = (double)para[2].n;
1240 
1241  }
1242  else if( stp_type == STP_SAP )
1243  {
1244  graph_edge_add(scip, g, (int)para[0].n - 1, (int)para[1].n - 1, (double)para[2].n, (double)para[3].n);
1245  }
1246  else if( stp_type == STP_MWCSP || stp_type == STP_RMWCSP )
1247  {
1248  graph_edge_add(scip, g, (int)para[0].n - 1, (int)para[1].n - 1, 0.0, 0.0);
1249  }
1250  else
1251  {
1252  graph_edge_add(scip, g, (int)para[0].n - 1, (int)para[1].n - 1,
1253  (double)para[2].n,
1254  (p->sw_code == KEY_GRAPH_E)
1255  ? (double)para[2].n
1256  : (double)para[3].n);
1257  }
1258  break;
1259  case KEY_MAXDEGS_MD :
1260  assert(g != NULL);
1261  assert((int)para[0].n >= 0);
1262 
1263  if( degcount < nodes )
1264  {
1265  if( g->maxdeg == NULL )
1266  {
1267  SCIP_CALL( SCIPallocMemoryArray(scip, &(g->maxdeg), nodes ) );
1268  stp_type = STP_DCSTP;
1269  }
1270  g->maxdeg[degcount++] = (int)para[0].n;
1271  }
1272  else
1273  {
1274  message(MSG_FATAL, &curf, err_baddeg_dd,
1275  degcount, nodes);
1276  ret = FAILURE;
1277  }
1278  break;
1279  case KEY_BUDGET_B :
1280  assert(g != NULL && stp_type == STP_BRMWCSP);
1281  assert(para[0].n >= 0.0);
1282  g->budget = para[0].n;
1283 
1284  break;
1285  case KEY_NODEWEIGHTS_NW :
1286  nodeweight = (double) para[0].n;
1287  assert(g != NULL);
1288  assert(presol != NULL);
1289 
1290  if( stp_type != STP_NWSPG && stp_type != STP_NWPTSPG )
1291  stp_type = STP_NWSPG;
1292 
1293  if( g->prize == NULL )
1294  SCIP_CALL( graph_pc_initPrizes(scip, g, nodes) );
1295 
1296  assert(nwcount < nodes);
1297  g->prize[nwcount++] = nodeweight;
1298 
1299  break;
1300  case KEY_NODEWEIGHTS_END :
1301  curf.section = &section_table[0];
1302 
1303  assert(nwcount == nodes);
1304  if( stp_type == STP_NWPTSPG )
1305  g->stp_type = STP_NWPTSPG;
1306 
1307  SCIP_CALL( graph_transNw(scip, presol, g) );
1308 
1309  break;
1310  case KEY_OBSTACLES_RR :
1311  assert(nobstacles > 0);
1312  if( obstacle_coords == NULL )
1313  {
1314  assert(obstacle_counter == 0);
1315  SCIP_CALL( SCIPallocBufferArray(scip, &obstacle_coords, 4) );
1316  for( i = 0; i < 4; i++ )
1317  SCIP_CALL( SCIPallocBufferArray(scip, &(obstacle_coords[i]), nobstacles) ); /*lint !e866*/
1318  }
1319  for( i = 0; i < 4; i++ )
1320  obstacle_coords[i][obstacle_counter] = (int)para[i].n;
1321  obstacle_counter++;
1322  break;
1323  case KEY_OBSTACLES_END :
1324  curf.section = &section_table[0];
1325 
1326  if( obstacle_counter != nobstacles )
1327  {
1328  message(MSG_FATAL, &curf, "obstacle number does not match coordinates \n");
1329  ret = FAILURE;
1330  break;
1331  }
1332  if( scaled_coordinates == NULL )
1333  {
1334  message(MSG_FATAL, &curf, "coordinates not given \n");
1335  ret = FAILURE;
1336  break;
1337  }
1338  assert(g == NULL);
1339 
1340  // todo fix problem with edges over obstacles
1341  message(MSG_FATAL, &curf, "Obstacle avoiding RSMT problems are currently not supported in this format \n");
1342 
1343  SCIP_CALL( graph_obstgrid_create(scip, graph, scaled_coordinates, obstacle_coords, nodes, grid_dim, nobstacles, scale_order) );
1344  g = *graph;
1345  if( obstacle_coords != NULL )
1346  for( i = 3; i >= 0; i-- )
1347  SCIPfreeBufferArrayNull(scip, &(obstacle_coords[i]));
1348  SCIPfreeBufferArrayNull(scip, &(obstacle_coords));
1349  break;
1350  case KEY_TERMINALS_END :
1351  if( transformed == 0 )
1352  {
1353  if( stp_type == STP_RMWCSP )
1354  {
1355  assert(nodes == termcount);
1356  SCIP_CALL( graph_transRmw(scip, g) );
1357  }
1358  else if( stp_type == STP_MWCSP )
1359  {
1360  assert(nodes == termcount);
1361  SCIP_CALL( graph_transMw(scip, g) );
1362  }
1363  else if( stp_type == STP_BRMWCSP )
1364  {
1365  assert(nodes == termcount);
1366  SCIP_CALL( graph_transRmw(scip, g) );
1367  g->stp_type = STP_BRMWCSP;
1368  }
1369  else if( stp_type == STP_PCSPG )
1370  {
1371 //#define STP_PC_2SPG
1372 #ifdef STP_PC_2SPG
1373  SCIP_CALL( graph_transPc2Spg(scip, presol, g) );
1374 #else
1375  SCIP_CALL( graph_transPc(scip, g) );
1376 
1377 #endif
1378  }
1379  else if( stp_type == STP_RPCSPG )
1380  {
1381 #ifdef STP_RPC_FIXEDPROPER
1382  SCIP_CALL( graph_transRpc2FixedProper(scip, presol, g) );
1383 #else
1384  SCIP_CALL( graph_transRpc(scip, g) );
1385 #endif
1386  }
1387  }
1388  curf.section = &section_table[0];
1389  break;
1391  terms = (int)para[0].n;
1392  assert(terms > 0);
1393 
1394  if( stp_type == STP_MWCSP || stp_type == STP_RMWCSP )
1395  {
1396  assert(terms == nodes);
1397  assert(g != NULL);
1398 
1399  if( g->prize == NULL )
1400  SCIP_CALL( graph_pc_initPrizes(scip, g, terms) );
1401  }
1402  break;
1403  case KEY_TERMINALS_GROUPS :
1404  assert(stp_type == STP_GSTP);
1405  tgroups = (int)para[0].n;
1406  for( i = 0; i < tgroups; i++ )
1407  {
1408  graph_knot_add(g, 0);
1409  }
1410  break;
1411  case KEY_TERMINALS_ROOT :
1412  assert(g != NULL);
1413 
1414  if ((int)para[0].n <= nodes)
1415  {
1416  g->source = (int)para[0].n - 1;
1417  graph_knot_chg(g, (int)para[0].n - 1, 0);
1418  }
1419  else
1420  {
1421  message(MSG_FATAL, &curf, err_badroot_dd,
1422  (int)para[0].n, nodes);
1423  ret = FAILURE;
1424  }
1425  break;
1426  case KEY_TERMINALS_ROOTP :
1427  assert(g != NULL);
1428  assert(terms > 0);
1429 
1430  g->source = (int)para[0].n - 1;
1431  graph_knot_chg(g, (int)para[0].n - 1, 0);
1432  stp_type = STP_RPCSPG;
1433 
1434  if( g->prize == NULL )
1435  SCIP_CALL( graph_pc_initPrizes(scip, g, nodes) );
1436 
1437  g->prize[(int)para[0].n - 1] = FARAWAY;
1438  break;
1439  case KEY_TERMINALS_T :
1440  if( stp_type == STP_MWCSP || stp_type == STP_RMWCSP )
1441  {
1442  assert(g != NULL);
1443  assert(g->prize != NULL);
1444  g->prize[(int)para[0].n - 1] = (double)para[1].n;
1445  if( SCIPisGT(scip, (double)para[1].n, 0.0) )
1446  presol->fixed -= (double)para[1].n;
1447  termcount++;
1448  }
1449  else
1450  graph_knot_chg(g, (int)para[0].n - 1, 0);
1451  break;
1452  case KEY_TERMINALS_TF :
1453  assert(g != NULL);
1454  graph_knot_chg(g, (int)para[0].n - 1, 0);
1455  if( g->prize == NULL )
1456  {
1457  stp_type = STP_RPCSPG;
1458  SCIP_CALL( graph_pc_initPrizes(scip, g, nodes) );
1459  }
1460  else
1461  assert(stp_type == STP_RPCSPG);
1462 
1463  g->prize[(int)para[0].n - 1] = FARAWAY;
1464  graph_knot_chg(g, (int)para[0].n - 1, 0);
1465  termcount++;
1466  break;
1467  case KEY_TERMINALS_TG :
1468  assert(g != NULL);
1469  assert(tgroups > 0);
1470  graph_edge_add(scip, g, (int)para[0].n - 1, g->knots - tgroups + (int)para[1].n - 1, BLOCKED, BLOCKED);
1471  assert(Is_term(g->term[g->knots - tgroups + (int)para[1].n - 1]));
1472  break;
1473  case KEY_TERMINALS_TL :
1474  vertex = (int)para[0].n - 1;
1475  assert(g != NULL);
1476  assert(vertex >= 0);
1477 
1478  stp_type = STP_NWPTSPG;
1479  graph_knot_chg(g, vertex, 0);
1480 
1481  for( i = g->outbeg[vertex]; i != EAT_LAST; i = g->oeat[i] )
1482  g->cost[i] = FARAWAY;
1483 
1484  break;
1485  case KEY_TERMINALS_TP :
1486  assert(g != NULL);
1487  graph_knot_chg(g, (int)para[0].n - 1, 0);
1488  if( g->prize == NULL )
1489  {
1490  assert(stp_type != STP_RPCSPG);
1491  stp_type = STP_PCSPG;
1492  SCIP_CALL( graph_pc_initPrizes(scip, g, nodes) );
1493  }
1494  g->prize[(int)para[0].n - 1] = (double)para[1].n;
1495  termcount++;
1496  break;
1497  case KEY_TERMINALS_TR :
1498  assert(stp_type == STP_RMWCSP);
1499  assert(g != NULL);
1500  assert(g->prize != NULL);
1501  g->prize[(int)para[0].n - 1] = FARAWAY;
1502  presol->fixed -= (double)para[1].n;
1503  graph_knot_chg(g, (int)para[0].n - 1, 0);
1504  termcount++;
1505  break;
1506  case KEY_TERMINALS_TB :
1507  stp_type = STP_BRMWCSP;
1508  assert(g != NULL);
1509  assert(g->prize != NULL);
1510  if( g->costbudget == NULL )
1511  {
1512  assert(terms == nodes );
1513  SCIP_CALL( SCIPallocMemoryArray(scip, &(g->costbudget), terms) );
1514  }
1515 
1516  g->costbudget[(int)para[0].n - 1] = (double)para[2].n;
1517  g->prize[(int)para[0].n - 1] = (double)para[1].n;
1518 
1519  if( SCIPisGT(scip, (double)para[1].n, 0.0) )
1520  presol->fixed -= (double)para[1].n;
1521  termcount++;
1522  break;
1523  case KEY_TERMINALS_RB :
1524  stp_type = STP_BRMWCSP;
1525  assert(g != NULL);
1526  assert(g->prize != NULL);
1527  if( g->costbudget == NULL )
1528  {
1529  assert(terms == nodes );
1530  SCIP_CALL( SCIPallocMemoryArray(scip, &(g->costbudget), terms) );
1531  }
1532  assert((double)para[2].n == 0.0);
1533 
1534  g->costbudget[(int)para[0].n - 1] = 0.0;
1535  g->prize[(int)para[0].n - 1] = FARAWAY;
1536  presol->fixed -= (double)para[1].n;
1537  graph_knot_chg(g, (int)para[0].n - 1, 0);
1538  termcount++;
1539  break;
1540  case KEY_COORDINATES_DD :
1541  /* in this case coordinates are not needed */
1542  if( terms > 0 )
1543  {
1544  ret = SUCCESS;
1545  stop_input = TRUE;
1546  break;
1547  }
1548  SCIP_CALL( init_coordinates(scip, g, para, &coordinates, &grid_dim, &termcount, 2, nodes) );
1549  break;
1550  case KEY_COORDINATES_DDD :
1551  SCIP_CALL( init_coordinates(scip, g, para, &coordinates, &grid_dim, &termcount, 3, nodes) );
1552  break;
1553  case KEY_COORDINATES_DDDD :
1554  SCIP_CALL( init_coordinates(scip, g, para, &coordinates, &grid_dim, &termcount, 4, nodes) );
1555  break;
1556  case KEY_COORDINATES_DDDDD :
1557  SCIP_CALL( init_coordinates(scip, g, para, &coordinates, &grid_dim, &termcount, 5, nodes) );
1558  break;
1559  case KEY_COORDINATES_DDDDDD :
1560  SCIP_CALL( init_coordinates(scip, g, para, &coordinates, &grid_dim, &termcount, 6, nodes) );
1561  break;
1563  SCIP_CALL( init_coordinates(scip, g, para, &coordinates, &grid_dim, &termcount, 7, nodes) );
1564  break;
1566  SCIP_CALL( init_coordinates(scip, g, para, &coordinates, &grid_dim, &termcount, 8, nodes) );
1567  break;
1568  case KEY_COORDINATES_END :
1569  assert(g == NULL);
1570  assert(grid_dim > 1);
1571 
1572  curf.section = &section_table[0];
1573  if( termcount != nodes )
1574  {
1575  message(MSG_FATAL, &curf, "node number does not match coordinates \n");
1576  ret = FAILURE;
1577  break;
1578  }
1579 
1580  /* scale all coordinates such that they are integers */
1581  SCIP_CALL( scale_coords(coordinates, &scaled_coordinates, &scale_order, nodes, grid_dim) );
1582 
1583  if( coordinates != NULL )
1584  for( i = 0; i < grid_dim; i++ )
1585  SCIPfreeMemoryArrayNull(scip, &(coordinates[i]));
1586 
1587  SCIPfreeMemoryArrayNull(scip, &coordinates);
1588 
1589  if( stp_type != STP_OARSMT )
1590  {
1591  SCIP_CALL( graph_grid_create(scip, graph, scaled_coordinates, nodes, grid_dim, scale_order) );
1592  g = *graph;
1593  }
1594 
1595  break;
1596  case KEY_COORDINATES_GRID :
1597  break;
1598  case KEY_PRESOLVE_FIXED :
1599  if (presol != NULL)
1600  presol->fixed += (double)para[0].n;
1601  break;
1602  case KEY_PRESOLVE_DATE :
1603  (void)printf("Found presolve information %s\n",
1604  para[0].s);
1605  break;
1606  case KEY_PRESOLVE_LOWER :
1607  if (presol != NULL)
1608  presol->lower = (double)para[0].n;
1609  break;
1610  case KEY_PRESOLVE_UPPER :
1611  if (presol != NULL)
1612  presol->upper = (double)para[0].n;
1613  break;
1614  case KEY_PRESOLVE_TIME :
1615  if (presol != NULL)
1616  presol->time = (int)para[0].n;
1617  break;
1618  case KEY_PRESOLVE_EA :
1619  break;
1620  case KEY_PRESOLVE_EC :
1621  break;
1622  case KEY_PRESOLVE_ED :
1623  break;
1624  case KEY_PRESOLVE_ES :
1625  break;
1626  default :
1627  /* CONSTCOND */
1628  assert(FALSE);
1629  break;
1630  }
1631  }
1632  }
1633  }
1634  }
1635  /* Was there an error in an included file ?
1636  * If so, close the main file.
1637  */
1638  if( save.fp != NULL )
1639  (void)fclose(save.fp);
1640 
1641  /* Close the actual file anyway. Since we stop at encountering
1642  * a line with "EOF" on it, this will be the normal case.
1643  */
1644  if( curf.fp != NULL )
1645  (void)fclose(curf.fp);
1646 
1647  if( ret == SUCCESS )
1648  {
1649  const int nnodes = graph_get_nNodes(g);
1650 
1651  assert(g != NULL);
1652 
1653  if( g->source == UNKNOWN )
1654  {
1655  const int* const grad = g->grad;
1656  for( i = 0; i < nnodes; i++ )
1657  {
1658  if( (g->term[i] == STP_TERM) && ((g->source < 0) || (grad[i] > grad[g->source])) )
1659  g->source = i;
1660  }
1661  }
1662 
1663  if( g->stp_type == UNKNOWN )
1664  {
1665  if( stp_type != UNKNOWN )
1666  g->stp_type = stp_type;
1667  else
1668  g->stp_type = STP_SPG;
1669  }
1670 
1671  if( stp_type == STP_GSTP )
1672  {
1673  graph_transGstpClean(presol, g);
1674  }
1675 
1676 #ifndef WITH_UG
1677  (void)printf(msg_finish_dddd,
1678  g->knots, g->edges, g->terms, g->source);
1679 #endif
1680 
1681  if( checkInput )
1682  {
1683  SCIP_CALL( check_inputgraph(scip, terms, g) );
1684  }
1685 
1686  assert(graph_valid(scip, g));
1687  assert(!graph_hasMultiEdges(scip, g, FALSE));
1688  return SCIP_OKAY;
1689  }
1690  else
1691  {
1692  if( obstacle_coords != NULL )
1693  {
1694  for( i = 0; i < 4; i++ )
1695  SCIPfreeBufferArrayNull(scip, &(obstacle_coords[i]));
1696  SCIPfreeBufferArrayNull(scip, &(obstacle_coords));
1697  }
1698 
1699  SCIPerrorMessage("errors in input found \n\n");
1700 
1701  return SCIP_READERROR;
1702  }
1703 
1704 }
void graph_knot_chg(GRAPH *, int, int)
Definition: graph_node.c:86
static volatile int nterms
Definition: interrupt.c:38
#define FLAG_OPTIONAL
Definition: graph_load.c:269
#define KEY_COORDINATES_DDDDDDDD
Definition: graph_load.c:138
int source
Definition: graphdefs.h:195
int sw_code
Definition: graph_load.c:96
#define MSG_WARN
Definition: graph_load.c:58
#define SCIPfreeMemoryArrayNull(scip, ptr)
Definition: scip_mem.h:72
#define Is_term(a)
Definition: graphdefs.h:102
#define MAX_ARGUMENTS
Definition: graph_load.c:91
#define KEY_MAXDEGS_MD
Definition: graph_load.c:163
#define KEY_SOLUTION_TIME
Definition: graph_load.c:145
SCIP_Bool graph_valid(SCIP *, const GRAPH *)
Definition: graph_base.c:1480
#define SCIP_MAXSTRLEN
Definition: def.h:293
#define KEY_COORDINATES_DDDD
Definition: graph_load.c:134
int terms
Definition: graphdefs.h:192
SCIP_Real upper
Definition: graphdefs.h:277
int mark
Definition: graph_load.c:266
#define MAX_LINE_LEN
Definition: graph_load.c:88
#define SCIPallocMemoryArray(scip, ptr, num)
Definition: scip_mem.h:55
#define KEY_COORDINATES_END
Definition: graph_load.c:140
#define KEY_PRESOLVE_EC
Definition: graph_load.c:155
#define KEY_COMMENT_DATE
Definition: graph_load.c:105
int *RESTRICT maxdeg
Definition: graphdefs.h:206
const char * format
Definition: graph_load.c:97
#define FALSE
Definition: def.h:87
#define KEY_SOLUTION_STEINER
Definition: graph_load.c:146
static int start_section(const char *pathname, const char *basename, CURF *curf, CURF *save, const char *s)
Definition: graph_load.c:661
int *RESTRICT inpbeg
Definition: graphdefs.h:202
#define KEY_COMMENT_CREATOR
Definition: graph_load.c:106
int SCIPsnprintf(char *t, int len, const char *s,...)
Definition: misc.c:10755
#define TRUE
Definition: def.h:86
#define MSG_DEBUG
Definition: graph_load.c:60
enum SCIP_Retcode SCIP_RETCODE
Definition: type_retcode.h:54
#define DIRSEP
Definition: portab.h:91
includes various files containing graph methods used for Steiner tree problems
#define STP_SAP
Definition: graphdefs.h:43
static int get_scale_order(SCIP_Real number)
Definition: graph_load.c:797
#define STP_DCSTP
Definition: graphdefs.h:47
#define KEY_NODEWEIGHTS_END
Definition: graph_load.c:161
SCIP_Real lower
Definition: graphdefs.h:278
char filename[MAX_PATH_LEN]
Definition: graph_load.c:299
#define EAT_LAST
Definition: graphdefs.h:58
#define STP_SPG
Definition: graphdefs.h:42
#define FARAWAY
Definition: graphdefs.h:89
#define STP_FILE_VERSION_MAJOR
Definition: graphdefs.h:112
#define KEY_PRESOLVE_ES
Definition: graph_load.c:157
SCIP_Real * costbudget
Definition: graphdefs.h:211
const int flag
Definition: graph_load.c:265
SCIP_RETCODE graph_obstgrid_create(SCIP *, GRAPH **, int **, int **, int, int, int, int)
Definition: graph_grid.c:175
SCIP_Bool graph_validInput(SCIP *, const GRAPH *)
Definition: graph_base.c:1619
#define KEY_PRESOLVE_LOWER
Definition: graph_load.c:151
#define KEY_END
Definition: graph_load.c:102
#define STP_FILE_MAGIC
Definition: graphdefs.h:111
SCIP_RETCODE graph_pc_initPrizes(SCIP *, GRAPH *, int)
Definition: graph_pcbase.c:741
#define KEY_COMMENT_REMARK
Definition: graph_load.c:108
#define KEY_PRESOLVE_FIXED
Definition: graph_load.c:150
#define SECTION_MISSING
Definition: graph_load.c:272
static SCIP_RETCODE init_coordinates(SCIP *scip, GRAPH *g, PARA *para, double ***coordinates, int *grid_dim, int *termcount, int dim, int nodes)
Definition: graph_load.c:759
#define STP_RSMT
Definition: graphdefs.h:49
int *RESTRICT oeat
Definition: graphdefs.h:231
#define KEY_TERMINALS_TERMINALS
Definition: graph_load.c:119
#define KEY_TERMINALS_T
Definition: graph_load.c:120
struct current_file CURF
#define KEY_GRAPH_OBSTACLES
Definition: graph_load.c:115
SCIP_RETCODE graph_transMw(SCIP *, GRAPH *)
Definition: graph_trans.c:632
#define FAILURE
Definition: portab.h:48
#define SUCCESS
Definition: portab.h:45
int stp_type
Definition: graphdefs.h:264
#define MSG_FATAL
Definition: graph_load.c:56
#define KEY_GRAPH_A
Definition: graph_load.c:113
#define SCIPerrorMessage
Definition: pub_message.h:55
SCIP_Real budget
Definition: graphdefs.h:212
SCIP_RETCODE graph_transPc(SCIP *, GRAPH *)
Definition: graph_trans.c:154
#define KEY_TERMINALS_TB
Definition: graph_load.c:129
#define KEY_TERMINALS_END
Definition: graph_load.c:118
SCIP_RETCODE graph_transNw(SCIP *, PRESOL *, GRAPH *)
Definition: graph_trans.c:1519
#define SCIPfreeBufferArrayNull(scip, ptr)
Definition: scip_mem.h:128
SCIP_Real * prize
Definition: graphdefs.h:210
#define KEY_COORDINATES_GRID
Definition: graph_load.c:141
#define KEY_NODEWEIGHTS_NW
Definition: graph_load.c:160
void graph_edge_add(SCIP *, GRAPH *, int, int, double, double)
int *RESTRICT grad
Definition: graphdefs.h:201
void graph_knot_add(GRAPH *, int)
Definition: graph_node.c:64
SCIP_RETCODE SCIPgetBoolParam(SCIP *scip, const char *name, SCIP_Bool *value)
Definition: scip_param.c:241
SCIP_RETCODE reduce_unconnectedInfeas(SCIP *, SCIP_Bool, GRAPH *, SCIP_Bool *)
struct section * section
Definition: graph_load.c:302
#define NULL
Definition: lpi_spx1.cpp:155
const char * extension
Definition: graph_load.c:264
#define STP_DHCSTP
Definition: graphdefs.h:52
SCIP_RETCODE graph_transPc2Spg(SCIP *, PRESOL *, GRAPH *)
Definition: graph_trans.c:257
#define STP_RMWCSP
Definition: graphdefs.h:54
int knots
Definition: graphdefs.h:190
#define SCIP_CALL(x)
Definition: def.h:384
#define KEY_TERMINALS_ROOT
Definition: graph_load.c:122
#define KEY_COORDINATES_DDDDDDD
Definition: graph_load.c:137
#define KEY_OBSTACLES_RR
Definition: graph_load.c:165
#define MSG_ERROR
Definition: graph_load.c:57
#define STP_PCSPG
Definition: graphdefs.h:44
Definition: graph_load.c:93
#define STP_OARSMT
Definition: graphdefs.h:50
#define KEY_PRESOLVE_ED
Definition: graph_load.c:156
#define SCIPallocBufferArray(scip, ptr, num)
Definition: scip_mem.h:115
union parameter PARA
#define SCIP_Bool
Definition: def.h:84
int *RESTRICT ieat
Definition: graphdefs.h:230
#define STP_NWPTSPG
Definition: graphdefs.h:48
SCIP_Bool graph_hasMultiEdges(SCIP *, const GRAPH *, SCIP_Bool)
Definition: graph_stats.c:185
#define EXTSEP
Definition: graph_load.c:86
const char * keyword
Definition: graph_load.c:95
double n
Definition: graph_load.c:307
#define KEY_GRAPH_EDGES
Definition: graph_load.c:111
int *RESTRICT tail
Definition: graphdefs.h:223
#define SECTION_EXISTEND
Definition: graph_load.c:273
#define KEY_TERMINALS_TL
Definition: graph_load.c:128
#define KEY_PRESOLVE_EA
Definition: graph_load.c:154
#define VERBOSE
Definition: graph_load.c:65
#define STP_TERM
Definition: graphdefs.h:61
#define KEY_COORDINATES_DDD
Definition: graph_load.c:133
#define KEY_GRAPH_NODES
Definition: graph_load.c:110
static const struct key keyword_table[]
Definition: graph_load.c:176
const char * name
Definition: graph_load.c:263
static int get_arguments(const CURF *curf, const char *format, const char *s, PARA *para)
Definition: graph_load.c:452
#define MAX_KEYWORD_LEN
Definition: graph_load.c:89
static int open_file(CURF *curf, unsigned char main_file)
Definition: graph_load.c:565
static int sec_cmp(const void *key, const void *section)
Definition: graph_load.c:434
#define KEY_TERMINALS_TP
Definition: graph_load.c:121
int *RESTRICT term
Definition: graphdefs.h:196
SCIP_RETCODE graph_grid_create(SCIP *, GRAPH **, int **, int, int, int)
Definition: graph_grid.c:338
static char * strlower(char *s)
Definition: graph_load.c:318
SCIP_RETCODE graph_transRpc(SCIP *, GRAPH *)
Definition: graph_trans.c:373
SCIP_RETCODE graph_load(SCIP *scip, GRAPH **graph, const char *file, PRESOL *presol)
Definition: graph_load.c:885
static long * number
#define KEY_TERMINALS_GROUPS
Definition: graph_load.c:125
#define KEY_PRESOLVE_DATE
Definition: graph_load.c:149
#define MAX_STRING_LEN
Definition: graph_load.c:90
Portable definitions.
#define KEY_TERMINALS_TG
Definition: graph_load.c:124
SCIP_RETCODE graph_transRpc2FixedProper(SCIP *, PRESOL *, GRAPH *)
Definition: graph_trans.c:531
#define KEY_OBSTACLES_END
Definition: graph_load.c:166
#define STP_NWSPG
Definition: graphdefs.h:46
#define KEY_COMMENT_NAME
Definition: graph_load.c:104
#define KEY_TREE_S
Definition: graph_load.c:171
#define KEY_SOLUTION_VALUE
Definition: graph_load.c:143
#define KEY_COORDINATES_DD
Definition: graph_load.c:132
#define KEY_PRESOLVE_UPPER
Definition: graph_load.c:152
#define KEY_PRESOLVE_TIME
Definition: graph_load.c:153
#define KEY_TERMINALS_TF
Definition: graph_load.c:127
SCIP_Bool SCIPisGT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
static int key_cmp(const void *key, const void *elem)
Definition: graph_load.c:417
static SCIP_RETCODE scale_coords(double **coordinates, int ***scaled_coords, int *scale_order, int nnodes, int grid_dim)
Definition: graph_load.c:835
SCIP_Real * cost
Definition: graphdefs.h:221
#define KEY_COMMENT_PROBLEM
Definition: graph_load.c:107
#define KEY_SOLUTION_DATE
Definition: graph_load.c:144
#define MSG_INFO
Definition: graph_load.c:59
char s[MAX_STRING_LEN]
Definition: graph_load.c:308
#define KEY_BUDGET_B
Definition: graph_load.c:173
#define SCIP_Real
Definition: def.h:177
#define BLOCKED
Definition: graphdefs.h:90
static struct section section_table[]
Definition: graph_load.c:277
#define KEY_HOPCONS_FACTOR
Definition: graph_load.c:169
int *RESTRICT outbeg
Definition: graphdefs.h:204
#define STP_BRMWCSP
Definition: graphdefs.h:55
static void message(unsigned int type, const CURF *curf, const char *msg,...)
Definition: graph_load.c:381
int edges
Definition: graphdefs.h:219
int graph_get_nNodes(const GRAPH *)
Definition: graph_stats.c:536
#define STP_GSTP
Definition: graphdefs.h:53
#define KEY_GRAPH_AA
Definition: graph_load.c:114
SCIP_Real fixed
Definition: graphdefs.h:276
#define UNKNOWN
Definition: sepa_mcf.c:4095
#define KEY_TERMINALS_TR
Definition: graph_load.c:126
static SCIP_RETCODE check_inputgraph(SCIP *scip, int nterms, GRAPH *graph)
Definition: graph_load.c:333
#define nnodes
Definition: gastrans.c:65
#define KEY_COORDINATES_DDDDDD
Definition: graph_load.c:136
#define FLAG_REQUIRED
Definition: graph_load.c:270
SCIP_RETCODE graph_init(SCIP *, GRAPH **, int, int, int)
Definition: graph_base.c:607
#define KEY_GRAPH_E
Definition: graph_load.c:112
void graph_transGstpClean(PRESOL *, GRAPH *)
Definition: graph_trans.c:1381
SCIP_Bool graph_typeIsSpgLike(const GRAPH *)
Definition: graph_stats.c:57
#define KEY_HOPCONS_LIM
Definition: graph_load.c:168
int hoplimit
Definition: graphdefs.h:216
SCIP_RETCODE graph_transRmw(SCIP *, GRAPH *)
Definition: graph_trans.c:687
includes various reduction methods for Steiner tree problems
#define STP_RPCSPG
Definition: graphdefs.h:45
#define STP_MWCSP
Definition: graphdefs.h:51
#define MAX_PATH_LEN
Definition: graph_load.c:81
#define KEY_SECTION
Definition: graph_load.c:100
#define KEY_TERMINALS_ROOTP
Definition: graph_load.c:123
#define KEY_COORDINATES_DDDDD
Definition: graph_load.c:135
#define KEY_GRAPH_HOPLIMIT
Definition: graph_load.c:116
#define KEY_SOLUTION_S
Definition: graph_load.c:147
#define KEY_TERMINALS_RB
Definition: graph_load.c:130
#define STP_FILE_VERSION_MINOR
Definition: graphdefs.h:113
#define KEY_EOF
Definition: graph_load.c:101