Scippy

SCIP

Solving Constraint Integer Programs

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