Scippy

GCG

Branch-and-Price & Column Generation for Everyone

reader_ref.c
Go to the documentation of this file.
1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2 /* */
3 /* This file is part of the program */
4 /* GCG --- Generic Column Generation */
5 /* a Dantzig-Wolfe decomposition based extension */
6 /* of the branch-cut-and-price framework */
7 /* SCIP --- Solving Constraint Integer Programs */
8 /* */
9 /* Copyright (C) 2010-2021 Operations Research, RWTH Aachen University */
10 /* Zuse Institute Berlin (ZIB) */
11 /* */
12 /* This program is free software; you can redistribute it and/or */
13 /* modify it under the terms of the GNU Lesser General Public License */
14 /* as published by the Free Software Foundation; either version 3 */
15 /* of the License, or (at your option) any later version. */
16 /* */
17 /* This program is distributed in the hope that it will be useful, */
18 /* but WITHOUT ANY WARRANTY; without even the implied warranty of */
19 /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
20 /* GNU Lesser General Public License for more details. */
21 /* */
22 /* You should have received a copy of the GNU Lesser General Public License */
23 /* along with this program; if not, write to the Free Software */
24 /* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.*/
25 /* */
26 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
27 
28 /**@file reader_ref.c
29  * @brief REF file reader for structure information
30  * @author Gerald Gamrath
31  * @author Christian Puchert
32  * @author Martin Bergner
33  */
34 
35 /*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
36 
37 #include <stdlib.h>
38 #include <assert.h>
39 #include <string.h>
40 #if defined(_WIN32) || defined(_WIN64)
41 #else
42 #include <strings.h> /*lint --e{766}*/ /* needed for strcasecmp() */
43 #endif
44 #include <ctype.h>
45 
46 #include "reader_ref.h"
47 #include "gcg.h"
48 #include "scip/cons_linear.h"
49 #include "cons_decomp.h"
50 #include "relax_gcg.h"
51 
52 #define READER_NAME "refreader"
53 #define READER_DESC "file reader for blocks corresponding to a mip in lpb format"
54 #define READER_EXTENSION "ref"
55 
56 /*
57  * Data structures
58  */
59 #define REF_MAX_LINELEN 65536
60 #define REF_MAX_PUSHEDTOKENS 2
61 
62 /** section in REF File */
64 {
66 };
67 typedef enum RefSection REFSECTION;
68 
70 {
72 };
73 typedef enum RefExpType REFEXPTYPE;
74 
75 
76 /** REF reading data */
77 struct RefInput
78 {
79  SCIP_FILE* file; /**< file to read */
80  char linebuf[REF_MAX_LINELEN]; /**< line buffer */
81  char* token; /**< current token */
82  char* tokenbuf; /**< token buffer */
83  char* pushedtokens[REF_MAX_PUSHEDTOKENS]; /**< token stack */
84  int npushedtokens; /**< size of token stack */
85  int linenumber; /**< current line number */
86  int linepos; /**< current line position (column) */
87  int nblocks; /**< number of blocks */
88  int blocknr; /**< current block number */
89  int nassignedvars; /**< number of assigned variables */
90  int* blocksizes; /**< array of block sizes */
91  int totalconss; /**< total number of constraints */
92  int totalreadconss; /**< total number of read constraints */
93  SCIP_CONS** masterconss; /**< array of constraints to be in the master */
94  int nmasterconss; /**< number of constraints to be in the master */
95  REFSECTION section; /**< current section */
96  SCIP_Bool haserror; /**< flag to indicate an error occurence */
97  SCIP_HASHMAP* vartoblock; /**< hashmap mapping variables to blocks (1..nblocks) */
98  SCIP_HASHMAP* constoblock; /**< hashmap mapping constraints to blocks (1..nblocks) */
99 };
100 typedef struct RefInput REFINPUT;
101 
102 static const char delimchars[] = " \f\n\r\t\v";
103 static const char tokenchars[] = "-+:<>=";
104 static const char commentchars[] = "\\";
105 
106 
107 /*
108  * Local methods (for reading)
109  */
110 
111 /** issues an error message and marks the REF data to have errors */
112 static
114  SCIP* scip, /**< SCIP data structure */
115  REFINPUT* refinput, /**< REF reading data */
116  const char* msg /**< error message */
117  )
118 {
119  char formatstr[256];
120 
121  assert(refinput != NULL);
122 
123  SCIPverbMessage(scip, SCIP_VERBLEVEL_MINIMAL, NULL, "Syntax error in line %d: %s ('%s')\n",
124  refinput->linenumber, msg, refinput->token);
125  if( refinput->linebuf[strlen(refinput->linebuf)-1] == '\n' )
126  {
127  SCIPverbMessage(scip, SCIP_VERBLEVEL_MINIMAL, NULL, " input: %s", refinput->linebuf);
128  }
129  else
130  {
131  SCIPverbMessage(scip, SCIP_VERBLEVEL_MINIMAL, NULL, " input: %s\n", refinput->linebuf);
132  }
133  (void) SCIPsnprintf(formatstr, 256, " %%%ds\n", refinput->linepos);
134  SCIPverbMessage(scip, SCIP_VERBLEVEL_MINIMAL, NULL, formatstr, "^");
135  refinput->section = REF_END;
136  refinput->haserror = TRUE;
137 }
138 
139 /** returns whether a syntax error was detected */
140 static
141 SCIP_Bool hasError(
142  REFINPUT* refinput /**< REF reading data */
143  )
144 {
145  assert(refinput != NULL);
146 
147  return refinput->haserror;
148 }
149 
150 /** returns whether the given character is a token delimiter */
151 static
152 SCIP_Bool isDelimChar(
153  char c /**< input character */
154  )
155 {
156  return (c == '\0') || (strchr(delimchars, c) != NULL);
157 }
158 
159 /** returns whether the given character is a single token */
160 static
161 SCIP_Bool isTokenChar(
162  char c /**< input character */
163  )
164 {
165  return (strchr(tokenchars, c) != NULL);
166 }
167 
168 /** returns whether the current character is member of a value string */
169 static
170 SCIP_Bool isValueChar(
171  char c, /**< input character */
172  char nextc, /**< next input character */
173  SCIP_Bool firstchar, /**< is the given character the first char of the token? */
174  SCIP_Bool* hasdot, /**< pointer to update the dot flag */
175  REFEXPTYPE* exptype /**< pointer to update the exponent type */
176  )
177 {
178  assert(hasdot != NULL);
179  assert(exptype != NULL);
180 
181  if( isdigit(c) )
182  return TRUE;
183  else if( (*exptype == REF_EXP_NONE) && !(*hasdot) && (c == '.') )
184  {
185  *hasdot = TRUE;
186  return TRUE;
187  }
188  else if( !firstchar && (*exptype == REF_EXP_NONE) && (c == 'e' || c == 'E') )
189  {
190  if( nextc == '+' || nextc == '-' )
191  {
192  *exptype = REF_EXP_SIGNED;
193  return TRUE;
194  }
195  else if( isdigit(nextc) )
196  {
197  *exptype = REF_EXP_UNSIGNED;
198  return TRUE;
199  }
200  }
201  else if( (*exptype == REF_EXP_SIGNED) && (c == '+' || c == '-') )
202  {
203  *exptype = REF_EXP_UNSIGNED;
204  return TRUE;
205  }
206 
207  return FALSE;
208 }
209 
210 /** reads the next line from the input file into the line buffer; skips comments;
211  * returns whether a line could be read
212  */
213 static
214 SCIP_Bool getNextLine(
215  REFINPUT* refinput /**< REF reading data */
216  )
217 {
218  int i;
219 
220  assert(refinput != NULL);
221 
222  /* clear the line */
223  BMSclearMemoryArray(refinput->linebuf, REF_MAX_LINELEN);
224 
225  /* read next line */
226  refinput->linepos = 0;
227  refinput->linebuf[REF_MAX_LINELEN-2] = '\0';
228  if( SCIPfgets(refinput->linebuf, REF_MAX_LINELEN, refinput->file) == NULL )
229  return FALSE;
230  refinput->linenumber++;
231  if( refinput->linebuf[REF_MAX_LINELEN-2] != '\0' )
232  {
233  SCIPerrorMessage("Error: line %d exceeds %d characters\n", refinput->linenumber, REF_MAX_LINELEN-2);
234  refinput->haserror = TRUE;
235  return FALSE;
236  }
237  refinput->linebuf[REF_MAX_LINELEN-1] = '\0';
238  refinput->linebuf[REF_MAX_LINELEN-2] = '\0'; /* we want to use lookahead of one char -> we need two \0 at the end */
239 
240  /* skip characters after comment symbol */
241  for( i = 0; commentchars[i] != '\0'; ++i )
242  {
243  char* commentstart;
244 
245  commentstart = strchr(refinput->linebuf, commentchars[i]);
246  if( commentstart != NULL )
247  {
248  *commentstart = '\0';
249  *(commentstart+1) = '\0'; /* we want to use lookahead of one char -> we need two \0 at the end */
250  }
251  }
252 
253  return TRUE;
254 }
255 
256 /** reads the next token from the input file into the token buffer; returns whether a token was read */
257 static
258 SCIP_Bool getNextToken(
259  REFINPUT* refinput /**< REF reading data */
260  )
261 {
262  SCIP_Bool hasdot;
263  REFEXPTYPE exptype;
264  char* buf;
265  int tokenlen;
266 
267  assert(refinput != NULL);
268  assert(refinput->linepos < REF_MAX_LINELEN);
269 
270  /* check the token stack */
271  if( refinput->npushedtokens > 0 )
272  {
273  SCIPswapPointers((void**)&refinput->token, (void**)&refinput->pushedtokens[refinput->npushedtokens-1]);
274  refinput->npushedtokens--;
275  SCIPdebugMessage("(line %d) read token again: '%s'\n", refinput->linenumber, refinput->token);
276  return TRUE;
277  }
278 
279  /* skip delimiters */
280  buf = refinput->linebuf;
281  while( isDelimChar(buf[refinput->linepos]) )
282  {
283  if( buf[refinput->linepos] == '\0' )
284  {
285  if( !getNextLine(refinput) )
286  {
287  refinput->section = REF_END;
288  refinput->blocknr++;
289  SCIPdebugMessage("(line %d) end of file\n", refinput->linenumber);
290  return FALSE;
291  }
292  else
293  {
294  if( refinput->section == REF_START )
295  refinput->section = REF_NBLOCKS;
296  else if( refinput->section == REF_BLOCKSIZES )
297  {
298  refinput->section = REF_BLOCKS;
299  refinput->blocknr = 0;
300  }
301  return FALSE;
302  }
303  }
304  else
305  refinput->linepos++;
306  }
307  assert(refinput->linepos < REF_MAX_LINELEN);
308  assert(!isDelimChar(buf[refinput->linepos]));
309 
310  /* check if the token is a value */
311  hasdot = FALSE;
312  exptype = REF_EXP_NONE;
313  if( isValueChar(buf[refinput->linepos], buf[refinput->linepos+1], TRUE, &hasdot, &exptype) ) /*lint !e679*/
314  {
315  /* read value token */
316  tokenlen = 0;
317  do
318  {
319  assert(tokenlen < REF_MAX_LINELEN);
320  assert(!isDelimChar(buf[refinput->linepos]));
321  refinput->token[tokenlen] = buf[refinput->linepos];
322  ++tokenlen;
323  ++(refinput->linepos);
324  assert(refinput->linepos < REF_MAX_LINELEN);
325  }
326  while( isValueChar(buf[refinput->linepos], buf[refinput->linepos+1], FALSE, &hasdot, &exptype) ); /*lint !e679*/
327  }
328  else
329  {
330  /* read non-value token */
331  tokenlen = 0;
332  do
333  {
334  assert(tokenlen < REF_MAX_LINELEN);
335  refinput->token[tokenlen] = buf[refinput->linepos];
336  tokenlen++;
337  refinput->linepos++;
338  if( tokenlen == 1 && isTokenChar(refinput->token[0]) )
339  break;
340  }
341  while( !isDelimChar(buf[refinput->linepos]) && !isTokenChar(buf[refinput->linepos]) );
342 
343  /* if the token is an equation sense '<', '>', or '=', skip a following '='
344  * if the token is an equality token '=' and the next character is a '<' or '>', replace the token by the inequality sense
345  */
346  if( tokenlen >= 1
347  && (refinput->token[tokenlen-1] == '<' || refinput->token[tokenlen-1] == '>' || refinput->token[tokenlen-1] == '=')
348  && buf[refinput->linepos] == '=' )
349  {
350  refinput->linepos++;
351  }
352  else if( refinput->token[tokenlen-1] == '=' && (buf[refinput->linepos] == '<' || buf[refinput->linepos] == '>') )
353  {
354  refinput->token[tokenlen-1] = buf[refinput->linepos];
355  refinput->linepos++;
356  }
357  }
358  assert(tokenlen < REF_MAX_LINELEN);
359  refinput->token[tokenlen] = '\0';
360 
361  return TRUE;
362 }
363 
364 /** returns whether the current token is a value */
365 static
366 SCIP_Bool isInt(
367  SCIP* scip, /**< SCIP data structure */
368  REFINPUT* refinput, /**< REF reading data */
369  int* value /**< pointer to store the value (unchanged, if token is no value) */
370  )
371 {
372  long val;
373  char* endptr;
374 
375  assert(refinput != NULL);
376  assert(value != NULL);
377  assert(!(strcasecmp(refinput->token, "INFINITY") == 0) && !(strcasecmp(refinput->token, "INF") == 0));
378 
379  val = strtol(refinput->token, &endptr, 0);
380  if( endptr != refinput->token && *endptr == '\0' )
381  {
382  if( val < INT_MIN || val > INT_MAX ) /*lint !e685*/
383  return FALSE;
384 
385  *value = (int) val;
386  return TRUE;
387  }
388 
389 
390  return FALSE;
391 }
392 
393 /** reads the header of the file */
394 static
395 SCIP_RETCODE readStart(
396  SCIP* scip, /**< SCIP data structure */
397  REFINPUT* refinput /**< REF reading data */
398  )
399 {
400  assert(refinput != NULL);
401 
402  (void) getNextToken(refinput);
403 
404  return SCIP_OKAY;
405 }
406 
407 /** reads the nblocks section */
408 static
409 SCIP_RETCODE readNBlocks(
410  SCIP* scip, /**< SCIP data structure */
411  REFINPUT* refinput /**< REF reading data */
412  )
413 {
414  int nblocks;
415 
416  assert(refinput != NULL);
417 
418  if( getNextToken(refinput) )
419  {
420  /* read number of blocks */
421  if( isInt(scip, refinput, &nblocks) )
422  {
423  if( refinput->nblocks == -1 )
424  {
425  refinput->nblocks = nblocks;
426  SCIP_CALL( SCIPallocBufferArray(scip, &refinput->blocksizes, nblocks) );
427  }
428  SCIPdebugMessage("Number of blocks = %d\n", refinput->nblocks);
429  }
430  else
431  syntaxError(scip, refinput, "NBlocks: Value not an integer.\n");
432  }
433  else
434  syntaxError(scip, refinput, "Could not read number of blocks.\n");
435 
436  refinput->section = REF_BLOCKSIZES;
437 
438  return SCIP_OKAY;
439 }
440 
441 /** reads the blocksizes section */
442 static
443 SCIP_RETCODE readBlockSizes(
444  SCIP* scip, /**< SCIP data structure */
445  REFINPUT* refinput /**< REF reading data */
446  )
447 {
448  int blocknr;
449  int blocksize;
450 
451  assert(refinput != NULL);
452 
453  for( blocknr = 0; getNextToken(refinput) && blocknr < refinput->nblocks; blocknr++ )
454  {
455  if( isInt(scip, refinput, &blocksize) )
456  {
457  refinput->blocksizes[blocknr] = blocksize;
458  refinput->totalconss += blocksize;
459  }
460  else
461  syntaxError(scip, refinput, "Blocksize: Value not integer.\n");
462  }
463  if( blocknr != refinput->nblocks )
464  syntaxError(scip, refinput, "Could not get sizes for all blocks.\n");
465 
466  return SCIP_OKAY;
467 }
468 
469 /** reads the blocks section */
470 static
471 SCIP_RETCODE readBlocks(
472  SCIP* scip, /**< SCIP data structure */
473  REFINPUT* refinput /**< REF reading data */
474  )
475 {
476  int consctr;
477 
478  assert(refinput != NULL);
479 
480  consctr = 0;
481 
482  while( refinput->blocknr < refinput->nblocks )
483  {
484  SCIPdebugMessage("Reading constraints of block %d/%d\n", refinput->blocknr + 1, refinput->nblocks);
485  while( getNextToken(refinput) )
486  {
487  SCIP_VAR** vars;
488  int consnr;
489  SCIP_CONS** conss = SCIPgetConss(scip);
490 
491  if( isInt(scip, refinput, &consnr) )
492  {
493  SCIP_CONSHDLR* conshdlr;
494  int nvars;
495  int v;
496  SCIP_CONS* cons;
497 
498  SCIPdebugMessage(" -> constraint %d\n", consnr);
499 
500  cons = conss[consnr];
501  conshdlr = SCIPconsGetHdlr(cons);
502 
503  if( strcmp(SCIPconshdlrGetName(conshdlr), "linear") == 0 )
504  {
505  vars = SCIPgetVarsLinear(scip, cons);
506  nvars = SCIPgetNVarsLinear(scip, cons);
507  }
508  else
509  {
510  SCIPdebugMessage(" constraint of unknown type.\n");
511  continue;
512  }
513 
514  SCIP_CALL( SCIPhashmapSetImage(refinput->constoblock, cons, (void*) (size_t) (refinput->blocknr+1) ) );
515 
516  for( v = 0; v < nvars; v++ )
517  {
518  SCIP_VAR* var = vars[v];
519 
520  SCIPdebugMessage(" -> variable %s\n", SCIPvarGetName(var));
521 
522  /* set the block number of the variable to the number of the current block */
523  if( SCIPhashmapExists(refinput->vartoblock, var) )
524  {
525  int block;
526  block = (int)(size_t) SCIPhashmapGetImage(refinput->vartoblock, var); /*lint !e507*/
527  if( block != refinput->blocknr+1 && block != refinput->nblocks+1 )
528  {
529  SCIP_CALL( SCIPhashmapRemove(refinput->vartoblock, var) );
530  SCIP_CALL( SCIPhashmapSetImage(refinput->vartoblock, var, (void*) (size_t) (refinput->nblocks+1)) );
531  }
532  }
533  else
534  {
535  SCIP_CALL( SCIPhashmapSetImage(refinput->vartoblock, var, (void*) (size_t) (refinput->blocknr+1)) );
536  }
537  refinput->nassignedvars++;
538  }
539  consctr++;
540  refinput->totalreadconss++;
541  }
542  else
543  syntaxError(scip, refinput, "ConsNr: Value not an integer.\n");
544  }
545 
546  if( consctr == refinput->blocksizes[refinput->blocknr] )
547  {
548  refinput->blocknr++;
549  consctr = 0;
550  }
551  }
552 
553  return SCIP_OKAY;
554 }
555 
556 
557 /** reads an REF file */
558 static
559 SCIP_RETCODE readREFFile(
560  SCIP* scip, /**< SCIP data structure */
561  SCIP_READER* reader, /**< reader data structure */
562  REFINPUT* refinput, /**< REF reading data */
563  DEC_DECOMP* decomp, /**< decomposition structure */
564  const char* filename /**< name of the input file */
565  )
566 {
567 
568  assert(scip != NULL);
569  assert(reader != NULL);
570  assert(refinput != NULL);
571  assert(filename != NULL);
572 
573  if( SCIPgetStage(scip) < SCIP_STAGE_TRANSFORMED )
574  SCIP_CALL( SCIPtransformProb(scip) );
575 
576  /* open file */
577  refinput->file = SCIPfopen(filename, "r");
578  if( refinput->file == NULL )
579  {
580  SCIPerrorMessage("cannot open file <%s> for reading\n", filename);
581  SCIPprintSysError(filename);
582  return SCIP_NOFILE;
583  }
584 
585  if( SCIPgetStage(scip) >= SCIP_STAGE_PRESOLVED )
586  {
587  SCIPverbMessage(scip, SCIP_VERBLEVEL_MINIMAL, NULL, "Reader 'ref' can only read in unpresolved structures.\n Please re-read the problem and read the decomposition again.\n");
588  return SCIP_OKAY;
589  }
590 
591  /* parse the file */
592  refinput->section = REF_START;
593  while( refinput->section != REF_END && !hasError(refinput) )
594  {
595  switch( refinput->section )
596  {
597  case REF_START:
598  SCIP_CALL( readStart(scip, refinput) );
599  break;
600 
601  case REF_NBLOCKS:
602  SCIP_CALL( readNBlocks(scip, refinput) );
603  DECdecompSetNBlocks(decomp, refinput->nblocks);
604  break;
605 
606  case REF_BLOCKSIZES:
607  SCIP_CALL( readBlockSizes(scip, refinput) );
608  break;
609 
610  case REF_BLOCKS:
611  SCIP_CALL( readBlocks(scip, refinput) );
612  break;
613 
614  case REF_END: /* this is already handled in the while() loop */
615  default:
616  SCIPerrorMessage("invalid REF file section <%d>\n", refinput->section);
617  return SCIP_INVALIDDATA;
618  }
619  }
620 
621  /* close file */
622  SCIPfclose(refinput->file);
623 
624  /* copy information to decomp */
625  SCIP_CALL_QUIET( DECfilloutDecompFromHashmaps(scip, decomp, refinput->vartoblock, refinput->constoblock, refinput->nblocks, FALSE) );
626 
627  DECdecompSetPresolved(decomp, FALSE);
628  DECdecompSetDetector(decomp, NULL);
629 
630  return SCIP_OKAY;
631 }
632 
633 /** writes a Ref file */
634 static
635 SCIP_RETCODE writeREFFile(
636  SCIP* scip, /**< SCIP data structure */
637  SCIP_READER* reader, /**< ref reader */
638  FILE* file /**< target file */
639 
640  )
641 {
642  SCIP_HASHMAP *cons2origindex;
643  DEC_DECOMP* decomp;
644 
645  SCIP_CONS** conss;
646  int nconss;
647  SCIP_CONS*** subscipconss;
648  int* nsubscipconss;
649  int i;
650  int j;
651  int nblocks;
652  assert(scip != NULL);
653  assert(reader != NULL);
654  assert(file != NULL);
655 
656  decomp = DECgetBestDecomp(scip, TRUE);
657 
658  if( decomp == NULL )
659  {
660  decomp = GCGgetStructDecomp(scip);
661  }
662 
663  if( decomp == NULL )
664  {
665  SCIPwarningMessage(scip, "No reformulation exists, cannot write reformulation file!\n");
666  return SCIP_OKAY;
667  }
668  nblocks = DECdecompGetNBlocks(decomp);
669  conss = SCIPgetOrigConss(scip);
670  nconss = SCIPgetNOrigConss(scip);
671 
672  SCIP_CALL( SCIPhashmapCreate(&cons2origindex, SCIPblkmem(scip), 2*nconss) );
673  for( i = 0; i < nconss; ++i )
674  {
675  int ind;
676  SCIP_CONS* cons;
677 
678  ind = i+1;
679 
680  assert(ind > 0);
681  assert(ind <= nconss);
682  cons = SCIPfindCons(scip, SCIPconsGetName(conss[i]));
683 
684  SCIPdebugMessage("cons added: %d\t%p\t%s\n", ind, (void*)cons, SCIPconsGetName(cons));
685  SCIP_CALL( SCIPhashmapInsert(cons2origindex, cons, (void*)(size_t)(ind)) ); /* shift by 1 to enable error checking */
686  }
687 
688  subscipconss = DECdecompGetSubscipconss(decomp);
689  nsubscipconss = DECdecompGetNSubscipconss(decomp);
690  SCIPinfoMessage(scip, file, "%d ", nblocks);
691 
692  assert(nsubscipconss != NULL);
693  assert(subscipconss != NULL);
694 
695  for( i = 0; i < nblocks; ++i )
696  {
697  SCIPinfoMessage(scip, file, "%d ", nsubscipconss[i]);
698  }
699  SCIPinfoMessage(scip, file, "\n");
700 
701  for( i = 0; i < nblocks; ++i )
702  {
703  for( j = 0; j < nsubscipconss[i]; ++j )
704  {
705  int ind;
706  SCIP_CONS* cons;
707 
708  cons = SCIPfindCons(scip, SCIPconsGetName(subscipconss[i][j]));
709  ind = (int)(size_t) SCIPhashmapGetImage(cons2origindex, cons); /*lint !e507*/
710  SCIPdebugMessage("cons retrieve (o): %d\t%p\t%s\n", ind, (void*)cons, SCIPconsGetName(cons));
711 
712  assert(ind > 0); /* shift by 1 */
713  assert(ind <= nconss); /* shift by 1 */
714  SCIPinfoMessage(scip, file, "%d ", ind-1);
715  }
716  SCIPinfoMessage(scip, file, "\n");
717  }
718  SCIPhashmapFree(&cons2origindex);
719 
720  DECdecompFree(scip, &decomp);
721 
722  return SCIP_OKAY;
723 }
724 
725 
726 /*
727  * Callback methods of reader
728  */
729 
730 /** destructor of reader to free user data (called when SCIP is exiting) */
731 #define readerFreeRef NULL
732 
733 /** problem reading method of reader */
734 static
735 SCIP_DECL_READERREAD(readerReadRef)
736 {
737  if( SCIPgetStage(scip) == SCIP_STAGE_INIT || SCIPgetNVars(scip) == 0 || SCIPgetNConss(scip) == 0 )
738  {
739  SCIPverbMessage(scip, SCIP_VERBLEVEL_DIALOG, NULL, "No problem exists, will not detect structure!\n");
740  return SCIP_OKAY;
741  }
742 
743  SCIP_CALL( SCIPreadRef(scip, reader, filename, result) );
744 
745  return SCIP_OKAY;
746 }
747 
748 
749 /** problem writing method of reader */
750 static
751 SCIP_DECL_READERWRITE(readerWriteRef)
752 {
753  /*lint --e{715}*/
754  SCIP_CALL( writeREFFile(scip, reader, file) );
755  *result = SCIP_SUCCESS;
756  return SCIP_OKAY;
757 }
758 
759 /*
760  * reader specific interface methods
761  */
762 
763 /** includes the ref file reader in SCIP */
764 SCIP_RETCODE SCIPincludeReaderRef(
765  SCIP* scip /**< SCIP data structure */
766  )
767 {
768  assert(scip != NULL);
769  /* include lp reader */
770  SCIP_CALL( SCIPincludeReader(scip, READER_NAME, READER_DESC, READER_EXTENSION,
771  NULL, readerFreeRef, readerReadRef, readerWriteRef, NULL) );
772 
773  return SCIP_OKAY;
774 }
775 
776 
777 /** reads problem from file */
778 SCIP_RETCODE SCIPreadRef(
779  SCIP* scip, /**< SCIP data structure */
780  SCIP_READER* reader, /**< the file reader itself */
781  const char* filename, /**< full path and name of file to read, or NULL if stdin should be used */
782  SCIP_RESULT* result /**< pointer to store the result of the file reading call */
783  )
784 {
785  SCIP_RETCODE retcode;
786  REFINPUT refinput;
787  DEC_DECOMP* decomp;
788  int i;
789 #ifdef SCIP_DEBUG
790  SCIP_VAR** vars;
791  int nvars;
792 #endif
793 
794  /* initialize REF input data */
795  refinput.file = NULL;
796  refinput.linebuf[0] = '\0';
797  SCIP_CALL( SCIPallocMemoryArray(scip, &refinput.token, REF_MAX_LINELEN) ); /*lint !e506*/
798  refinput.token[0] = '\0';
799  SCIP_CALL( SCIPallocMemoryArray(scip, &refinput.tokenbuf, REF_MAX_LINELEN) ); /*lint !e506*/
800  refinput.tokenbuf[0] = '\0';
801  for( i = 0; i < REF_MAX_PUSHEDTOKENS; ++i )
802  {
803  SCIP_CALL( SCIPallocMemoryArray(scip, &refinput.pushedtokens[i], REF_MAX_LINELEN) ); /*lint !e506 !e866*/
804  }
805  SCIP_CALL( SCIPallocBufferArray(scip, &refinput.masterconss, 1) );
806 
807  refinput.npushedtokens = 0;
808  refinput.linenumber = 0;
809  refinput.linepos = 0;
810  refinput.nblocks = -1;
811  refinput.blocknr = -2;
812  refinput.totalconss = 0;
813  refinput.totalreadconss = 0;
814  refinput.nassignedvars = 0;
815  refinput.nmasterconss = 0;
816  refinput.haserror = FALSE;
817 
818  SCIP_CALL( SCIPhashmapCreate(&refinput.vartoblock, SCIPblkmem(scip), SCIPgetNVars(scip)) );
819  SCIP_CALL( SCIPhashmapCreate(&refinput.constoblock, SCIPblkmem(scip), SCIPgetNConss(scip)) );
820 
821  /* read the file */
822  SCIP_CALL( DECdecompCreate(scip, &decomp) );
823 
824  retcode = readREFFile(scip, reader, &refinput, decomp, filename);
825 
826  if( retcode == SCIP_OKAY )
827  {
828  SCIP_CALL( GCGconshdlrDecompAddPreexistingDecomp(scip, decomp) );
829  SCIPdebugMessage("Read %d/%d conss in ref-file\n", refinput.totalreadconss, refinput.totalconss);
830  SCIPdebugMessage("Assigned %d variables to %d blocks.\n", refinput.nassignedvars, refinput.nblocks);
831 #ifdef SCIP_DEBUG
832  SCIP_CALL( SCIPgetVarsData(scip, &vars, &nvars, NULL, NULL, NULL, NULL) );
833 
834  for( i = 0; i < nvars; i++ )
835  {
836  if( GCGvarGetBlock(vars[i]) == -1 )
837  {
838  SCIPdebugMessage(" -> not assigned: variable %s\n", SCIPvarGetName(vars[i]));
839  }
840  }
841 #endif
842  }
843 
844  SCIP_CALL( DECdecompFree(scip, &decomp) );
845 
846  /* free dynamically allocated memory */
847  SCIPfreeMemoryArray(scip, &refinput.token);
848  SCIPfreeMemoryArray(scip, &refinput.tokenbuf);
849  for( i = 0; i < REF_MAX_PUSHEDTOKENS; ++i )
850  {
851  SCIPfreeMemoryArray(scip, &refinput.pushedtokens[i]);
852  }
853  SCIPfreeBufferArray(scip, &refinput.masterconss);
854  SCIPfreeBufferArray(scip, &refinput.blocksizes);
855 
856  /* evaluate the result */
857  if( refinput.haserror )
858  return SCIP_READERROR;
859  else if( retcode == SCIP_OKAY )
860  {
861  *result = SCIP_SUCCESS;
862  }
863 
864  return retcode;
865 }
void DECdecompSetNBlocks(DEC_DECOMP *decomp, int nblocks)
Definition: decomp.c:733
static SCIP_Bool getNextLine(REFINPUT *refinput)
Definition: reader_ref.c:214
static SCIP_Bool getNextToken(REFINPUT *refinput)
Definition: reader_ref.c:258
int blocknr
Definition: reader_ref.c:88
SCIP_RETCODE SCIPincludeReaderRef(SCIP *scip)
Definition: reader_ref.c:764
int linepos
Definition: reader_ref.c:86
RefExpType
Definition: reader_ref.c:69
GCG interface methods.
RefSection
Definition: reader_ref.c:63
@ REF_EXP_NONE
Definition: reader_ref.c:71
@ REF_EXP_UNSIGNED
Definition: reader_ref.c:71
SCIP_Bool haserror
Definition: reader_ref.c:96
#define READER_EXTENSION
Definition: reader_ref.c:54
int linenumber
Definition: reader_ref.c:85
@ REF_BLOCKSIZES
Definition: reader_ref.c:65
constraint handler for structure detection
SCIP_RETCODE DECfilloutDecompFromHashmaps(SCIP *scip, DEC_DECOMP *decomp, SCIP_HASHMAP *vartoblock, SCIP_HASHMAP *constoblock, int nblocks, SCIP_Bool staircase)
Definition: decomp.c:1271
SCIP_RETCODE GCGconshdlrDecompAddPreexistingDecomp(SCIP *scip, DEC_DECOMP *decomp)
adds a decomp that exists before the detection is called
static SCIP_RETCODE writeREFFile(SCIP *scip, SCIP_READER *reader, FILE *file)
Definition: reader_ref.c:635
int * DECdecompGetNSubscipconss(DEC_DECOMP *decomp)
Definition: decomp.c:917
int GCGvarGetBlock(SCIP_VAR *var)
Definition: gcgvar.c:1033
static void syntaxError(SCIP *scip, REFINPUT *refinput, const char *msg)
Definition: reader_ref.c:113
enum RefExpType REFEXPTYPE
Definition: reader_ref.c:73
static SCIP_Bool hasError(REFINPUT *refinput)
Definition: reader_ref.c:141
int npushedtokens
Definition: reader_ref.c:84
#define READER_DESC
Definition: reader_ref.c:53
enum RefSection REFSECTION
Definition: reader_ref.c:67
static SCIP_RETCODE readBlockSizes(SCIP *scip, REFINPUT *refinput)
Definition: reader_ref.c:443
#define REF_MAX_LINELEN
Definition: reader_ref.c:59
int nblocks
Definition: reader_ref.c:87
#define READER_NAME
Definition: reader_ref.c:52
char * pushedtokens[REF_MAX_PUSHEDTOKENS]
Definition: reader_ref.c:83
static const char delimchars[]
Definition: reader_ref.c:102
static SCIP_Bool isTokenChar(char c)
Definition: reader_ref.c:161
SCIP_HASHMAP * vartoblock
Definition: reader_ref.c:97
int * blocksizes
Definition: reader_ref.c:90
char linebuf[REF_MAX_LINELEN]
Definition: reader_ref.c:80
int nassignedvars
Definition: reader_ref.c:89
SCIP_CONS ** masterconss
Definition: reader_ref.c:93
static SCIP_RETCODE readNBlocks(SCIP *scip, REFINPUT *refinput)
Definition: reader_ref.c:409
SCIP_HASHMAP * constoblock
Definition: reader_ref.c:98
static SCIP_Bool isDelimChar(char c)
Definition: reader_ref.c:152
int totalconss
Definition: reader_ref.c:91
void DECdecompSetPresolved(DEC_DECOMP *decomp, SCIP_Bool presolved)
Definition: decomp.c:712
#define readerFreeRef
Definition: reader_ref.c:731
static SCIP_RETCODE readBlocks(SCIP *scip, REFINPUT *refinput)
Definition: reader_ref.c:471
SCIP_RETCODE DECdecompFree(SCIP *scip, DEC_DECOMP **decdecomp)
Definition: decomp.c:530
int totalreadconss
Definition: reader_ref.c:92
@ REF_NBLOCKS
Definition: reader_ref.c:65
@ REF_BLOCKS
Definition: reader_ref.c:65
@ REF_START
Definition: reader_ref.c:65
SCIP_CONS *** DECdecompGetSubscipconss(DEC_DECOMP *decomp)
Definition: decomp.c:908
static SCIP_RETCODE readStart(SCIP *scip, REFINPUT *refinput)
Definition: reader_ref.c:395
static SCIP_Bool isInt(SCIP *scip, REFINPUT *refinput, int *value)
Definition: reader_ref.c:366
static SCIP_Bool isValueChar(char c, char nextc, SCIP_Bool firstchar, SCIP_Bool *hasdot, REFEXPTYPE *exptype)
Definition: reader_ref.c:170
static SCIP_RETCODE readREFFile(SCIP *scip, SCIP_READER *reader, REFINPUT *refinput, DEC_DECOMP *decomp, const char *filename)
Definition: reader_ref.c:559
GCG relaxator.
#define REF_MAX_PUSHEDTOKENS
Definition: reader_ref.c:60
SCIP_RETCODE SCIPreadRef(SCIP *scip, SCIP_READER *reader, const char *filename, SCIP_RESULT *result)
Definition: reader_ref.c:778
char * tokenbuf
Definition: reader_ref.c:82
char * token
Definition: reader_ref.c:81
SCIP_FILE * file
Definition: reader_ref.c:79
void DECdecompSetDetector(DEC_DECOMP *decomp, DEC_DETECTOR *detector)
Definition: decomp.c:1579
@ REF_END
Definition: reader_ref.c:65
DEC_DECOMP * GCGgetStructDecomp(SCIP *scip)
Definition: relax_gcg.c:2397
int DECdecompGetNBlocks(DEC_DECOMP *decomp)
Definition: decomp.c:745
static const char tokenchars[]
Definition: reader_ref.c:103
int nmasterconss
Definition: reader_ref.c:94
SCIP_RETCODE DECdecompCreate(SCIP *scip, DEC_DECOMP **decdecomp)
Definition: decomp.c:471
static SCIP_DECL_READERREAD(readerReadRef)
Definition: reader_ref.c:735
@ REF_EXP_SIGNED
Definition: reader_ref.c:71
static const char commentchars[]
Definition: reader_ref.c:104
REFSECTION section
Definition: reader_ref.c:95
static SCIP_DECL_READERWRITE(readerWriteRef)
Definition: reader_ref.c:751
REF file reader for structure information.
DEC_DECOMP * DECgetBestDecomp(SCIP *scip, SCIP_Bool printwarnings)
Gets the best known decomposition.