Scippy

GCG

Branch-and-Price & Column Generation for Everyone

reader_blk.cpp
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_blk.cpp
29  * @brief BLK file reader for structure information
30  * @author Gerald Gamrath
31  * @author Martin Bergner
32  * @author Christian Puchert
33  *
34  * This reader reads in a blk-file that defines the structur to be used for the decomposition.
35  * The structure is defined variable-wise, i.e., the number of blocks and the variables belonging to each block are
36  * defined. Afterwards, each constraint that has only variables of one block is added to that block,
37  * constraints having variables of more than one block go into the master. If needed, constraints can also be
38  * forced into the master, even if they could be transferred to one block.
39  *
40  * The keywords are:
41  * - Presolved: to be followed by either 0 or 1 indicating that the decomposition is for the presolved or unpresolved problem
42  * - NBlocks: to be followed by a line giving the number of blocks
43  * - Block i with 1 <= i <= nblocks: to be followed by the names of the variables belonging to block i, one per line.
44  * - Masterconss: to be followed by names of constraints, one per line, that should go into the master,
45  * even if they only contain variables of one block and could thus be added to this block.
46  */
47 
48 /*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
49 
50 #include <stdlib.h>
51 #include <assert.h>
52 #include <string.h>
53 #if defined(_WIN32) || defined(_WIN64)
54 #else
55 #include <strings.h> /*lint --e{766}*/ /* needed for strcasecmp() */
56 #endif
57 #include <ctype.h>
58 
59 #include "reader_blk.h"
60 #include "relax_gcg.h"
61 #include "pub_gcgvar.h"
62 #include "pub_decomp.h"
63 #include "cons_decomp.h"
64 #include "cons_decomp.hpp"
65 #include "scip_misc.h"
66 #include "class_partialdecomp.h"
67 
68 #define READER_NAME "blkreader"
69 #define READER_DESC "file reader for structures in blk format"
70 #define READER_EXTENSION "blk"
71 
72 /*
73  * Data structures
74  */
75 #define BLK_MAX_LINELEN 65536
76 #define BLK_MAX_PUSHEDTOKENS 2
77 
78 /** section in BLK File */
80 {
82 };
83 typedef enum BlkSection BLKSECTION;
84 
85 /** exponent indicator of the a value */
87 {
89 };
90 typedef enum BlkExpType BLKEXPTYPE;
91 
92 
93 /** BLK reading data */
94 struct BlkInput
95 {
96  SCIP_FILE* file; /**< file to read */
97  char linebuf[BLK_MAX_LINELEN]; /**< line buffer */
98  char* token; /**< current token */
99  char* tokenbuf; /**< token buffer */
100  char* pushedtokens[BLK_MAX_PUSHEDTOKENS]; /**< token stack */
101  int npushedtokens; /**< size of token buffer */
102  int linenumber; /**< current line number */
103  int linepos; /**< current line position (column) */
104  SCIP_Bool presolved; /**< does the decomposition refer to the presolved problem? */
105  SCIP_Bool haspresolvesection; /**< does the decomposition have a presolved section */
106  int nblocks; /**< number of blocks */
107  int blocknr; /**< number of the currentblock between 0 and Nblocks-1*/
108  BLKSECTION section; /**< current section */
109  SCIP_Bool haserror; /**< flag to indicate an error occurence */
110 };
111 typedef struct BlkInput BLKINPUT;
112 
113 /** data for blk reader */
115 {
116  int* varstoblock; /**< index=varid; value= -1 or blockID or -2 for multipleblocks */
117  int* nblockvars; /**< number of variable per block that are not linkingvars */
118  int** linkingvarsblocks; /**< array with blocks assigned to one linking var */
119  int* nlinkingvarsblocks; /**< array with number of blocks assigned to each linking var */
120  SCIP_HASHMAP* constoblock; /**< hashmap key=constaint value=block*/
121  SCIP_CONS*** blockcons; /**< array of assignments from constraints to their blocks [blocknr][consid] */
122  int* nblockcons; /**< number of block-constraints for blockID*/
123  int nlinkingcons; /**< number of linking constraints*/
124  int nlinkingvars; /**< number of linking vars*/
125 };
126 
127 static const int NOVALUE = -1;
128 static const int LINKINGVALUE = -2;
129 static const char delimchars[] = " \f\n\r\t\v";
130 static const char tokenchars[] = "-+:<>=";
131 static const char commentchars[] = "\\";
132 
133 
134 
135 
136 /*
137  * Local methods (for reading)
138  */
139 
140 /** issues an error message and marks the BLK data to have errors */
141 static
143  SCIP* scip, /**< SCIP data structure */
144  BLKINPUT* blkinput, /**< BLK reading data */
145  const char* msg /**< error message */
146  )
147 {
148  char formatstr[256];
149 
150  assert(blkinput != NULL);
151 
152  SCIPverbMessage(scip, SCIP_VERBLEVEL_MINIMAL, NULL, "Syntax error in line %d: %s ('%s')\n",
153  blkinput->linenumber, msg, blkinput->token);
154  if( blkinput->linebuf[strlen(blkinput->linebuf)-1] == '\n' )
155  {
156  SCIPverbMessage(scip, SCIP_VERBLEVEL_MINIMAL, NULL, " input: %s", blkinput->linebuf);
157  }
158  else
159  {
160  SCIPverbMessage(scip, SCIP_VERBLEVEL_MINIMAL, NULL, " input: %s\n", blkinput->linebuf);
161  }
162  (void) SCIPsnprintf(formatstr, 256, " %%%ds\n", blkinput->linepos);
163  SCIPverbMessage(scip, SCIP_VERBLEVEL_MINIMAL, NULL, formatstr, "^");
164  blkinput->section = BLK_END;
165  blkinput->haserror = TRUE;
166 }
167 
168 /** returns whether a syntax error was detected */
169 static
170 SCIP_Bool hasError(
171  BLKINPUT* blkinput /**< BLK reading data */
172  )
173 {
174  assert(blkinput != NULL);
175 
176  return blkinput->haserror;
177 }
178 
179 /** returns whether the given character is a token delimiter */
180 static
181 SCIP_Bool isDelimChar(
182  char c /**< input character */
183  )
184 {
185  return (c == '\0') || (strchr(delimchars, c) != NULL);
186 }
187 
188 /** returns whether the given character is a single token */
189 static
190 SCIP_Bool isTokenChar(
191  char c /**< input character */
192  )
193 {
194  return (strchr(tokenchars, c) != NULL);
195 }
196 
197 /** returns whether the current character is member of a value string */
198 static
199 SCIP_Bool isValueChar(
200  char c, /**< input character */
201  char nextc, /**< next input character */
202  SCIP_Bool firstchar, /**< is the given character the first char of the token? */
203  SCIP_Bool* hasdot, /**< pointer to update the dot flag */
204  BLKEXPTYPE* exptype /**< pointer to update the exponent type */
205  )
206 {
207  assert(hasdot != NULL);
208  assert(exptype != NULL);
209 
210  if( isdigit(c) )
211  return TRUE;
212  else if( (*exptype == BLK_EXP_NONE) && !(*hasdot) && (c == '.') )
213  {
214  *hasdot = TRUE;
215  return TRUE;
216  }
217  else if( !firstchar && (*exptype == BLK_EXP_NONE) && (c == 'e' || c == 'E') )
218  {
219  if( nextc == '+' || nextc == '-' )
220  {
221  *exptype = BLK_EXP_SIGNED;
222  return TRUE;
223  }
224  else if( isdigit(nextc) )
225  {
226  *exptype = BLK_EXP_UNSIGNED;
227  return TRUE;
228  }
229  }
230  else if( (*exptype == BLK_EXP_SIGNED) && (c == '+' || c == '-') )
231  {
232  *exptype = BLK_EXP_UNSIGNED;
233  return TRUE;
234  }
235 
236  return FALSE;
237 }
238 
239 /** reads the next line from the input file into the line buffer; skips comments;
240  * returns whether a line could be read
241  */
242 static
243 SCIP_Bool getNextLine(
244  BLKINPUT* blkinput /**< BLK reading data */
245  )
246 {
247  int i;
248 
249  assert(blkinput != NULL);
250 
251  /* clear the line */
252  BMSclearMemoryArray(blkinput->linebuf, BLK_MAX_LINELEN);
253 
254  /* read next line */
255  blkinput->linepos = 0;
256  blkinput->linebuf[BLK_MAX_LINELEN-2] = '\0';
257  if( SCIPfgets(blkinput->linebuf, BLK_MAX_LINELEN, blkinput->file) == NULL )
258  return FALSE;
259  blkinput->linenumber++;
260  if( blkinput->linebuf[BLK_MAX_LINELEN-2] != '\0' )
261  {
262  SCIPerrorMessage("Error: line %d exceeds %d characters\n", blkinput->linenumber, BLK_MAX_LINELEN-2);
263  blkinput->haserror = TRUE;
264  return FALSE;
265  }
266  blkinput->linebuf[BLK_MAX_LINELEN-1] = '\0';
267  blkinput->linebuf[BLK_MAX_LINELEN-2] = '\0'; /* we want to use lookahead of one char -> we need two \0 at the end */
268 
269  /* skip characters after comment symbol */
270  for( i = 0; commentchars[i] != '\0'; ++i )
271  {
272  char* commentstart;
273 
274  commentstart = strchr(blkinput->linebuf, commentchars[i]);
275  if( commentstart != NULL )
276  {
277  *commentstart = '\0';
278  *(commentstart+1) = '\0'; /* we want to use lookahead of one char -> we need two \0 at the end */
279  }
280  }
281 
282  return TRUE;
283 }
284 
285 /** swaps the addresses of two pointers */
286 static
288  char** pointer1, /**< first pointer */
289  char** pointer2 /**< second pointer */
290  )
291 {
292  char* tmp;
293 
294  tmp = *pointer1;
295  *pointer1 = *pointer2;
296  *pointer2 = tmp;
297 }
298 
299 /** reads the next token from the input file into the token buffer; returns whether a token was read */
300 static
301 SCIP_Bool getNextToken(
302  BLKINPUT* blkinput /**< BLK reading data */
303  )
304 {
305  SCIP_Bool hasdot;
306  BLKEXPTYPE exptype;
307  char* buf;
308  int tokenlen;
309 
310  assert(blkinput != NULL);
311  assert(blkinput->linepos < BLK_MAX_LINELEN);
312 
313  /* check the token stack */
314  if( blkinput->npushedtokens > 0 )
315  {
316  swapPointers(&blkinput->token, &blkinput->pushedtokens[blkinput->npushedtokens-1]);
317  blkinput->npushedtokens--;
318  SCIPdebugMessage("(line %d) read token again: '%s'\n", blkinput->linenumber, blkinput->token);
319  return TRUE;
320  }
321 
322  /* skip delimiters */
323  buf = blkinput->linebuf;
324  while( isDelimChar(buf[blkinput->linepos]) )
325  {
326  if( buf[blkinput->linepos] == '\0' )
327  {
328  if( !getNextLine(blkinput) )
329  {
330  blkinput->section = BLK_END;
331  SCIPdebugMessage("(line %d) end of file\n", blkinput->linenumber);
332  return FALSE;
333  }
334  assert(blkinput->linepos == 0);
335  }
336  else
337  blkinput->linepos++;
338  }
339  assert(blkinput->linepos < BLK_MAX_LINELEN);
340  assert(!isDelimChar(buf[blkinput->linepos]));
341 
342  /* check if the token is a value */
343  hasdot = FALSE;
344  exptype = BLK_EXP_NONE;
345  if( isValueChar(buf[blkinput->linepos], buf[blkinput->linepos+1], TRUE, &hasdot, &exptype) ) /*lint !e679*/
346  {
347  /* read value token */
348  tokenlen = 0;
349  do
350  {
351  assert(tokenlen < BLK_MAX_LINELEN);
352  assert(!isDelimChar(buf[blkinput->linepos]));
353  blkinput->token[tokenlen] = buf[blkinput->linepos];
354  ++tokenlen;
355  ++(blkinput->linepos);
356  assert(blkinput->linepos < BLK_MAX_LINELEN);
357  }
358  while( isValueChar(buf[blkinput->linepos], buf[blkinput->linepos+1], FALSE, &hasdot, &exptype) ); /*lint !e679*/
359  }
360  else
361  {
362  /* read non-value token */
363  tokenlen = 0;
364  do
365  {
366  assert(tokenlen < BLK_MAX_LINELEN);
367  blkinput->token[tokenlen] = buf[blkinput->linepos];
368  tokenlen++;
369  blkinput->linepos++;
370  if( tokenlen == 1 && isTokenChar(blkinput->token[0]) )
371  break;
372  }
373  while( !isDelimChar(buf[blkinput->linepos]) && !isTokenChar(buf[blkinput->linepos]) );
374 
375  /* if the token is an equation sense '<', '>', or '=', skip a following '='
376  * if the token is an equality token '=' and the next character is a '<' or '>', replace the token by the inequality sense
377  */
378  if( tokenlen >= 1
379  && (blkinput->token[tokenlen-1] == '<' || blkinput->token[tokenlen-1] == '>' || blkinput->token[tokenlen-1] == '=')
380  && buf[blkinput->linepos] == '=' )
381  {
382  blkinput->linepos++;
383  }
384  else if( blkinput->token[tokenlen-1] == '=' && (buf[blkinput->linepos] == '<' || buf[blkinput->linepos] == '>') )
385  {
386  blkinput->token[tokenlen-1] = buf[blkinput->linepos];
387  blkinput->linepos++;
388  }
389  }
390  assert(tokenlen < BLK_MAX_LINELEN);
391  blkinput->token[tokenlen] = '\0';
392 
393  SCIPdebugMessage("(line %d) read token: '%s'\n", blkinput->linenumber, blkinput->token);
394 
395  return TRUE;
396 }
397 
398 /** puts the current token on the token stack, such that it is read at the next call to getNextToken() */
399 static
401  BLKINPUT* blkinput /**< BLK reading data */
402  )
403 {
404  assert(blkinput != NULL);
405  assert(blkinput->npushedtokens < BLK_MAX_PUSHEDTOKENS);
406 
407  swapPointers(&blkinput->pushedtokens[blkinput->npushedtokens], &blkinput->token);
408  blkinput->npushedtokens++;
409 }
410 
411 /** swaps the current token with the token buffer */
412 static
414  BLKINPUT* blkinput /**< BLK reading data */
415  )
416 {
417  assert(blkinput != NULL);
418 
419  swapPointers(&blkinput->token, &blkinput->tokenbuf);
420 }
421 
422 /** returns whether the current token is a value */
423 static
424 SCIP_Bool isInt(
425  SCIP* scip, /**< SCIP data structure */
426  BLKINPUT* blkinput, /**< BLK reading data */
427  int* value /**< pointer to store the value (unchanged, if token is no value) */
428  )
429 {
430  long val;
431  char* endptr;
432 
433  assert(blkinput != NULL);
434  assert(value != NULL);
435  assert(!(strcasecmp(blkinput->token, "INFINITY") == 0) && !(strcasecmp(blkinput->token, "INF") == 0));
436 
437  val = strtol(blkinput->token, &endptr, 0);
438  if( endptr != blkinput->token && *endptr == '\0' )
439  {
440  if(val < INT_MIN || val > INT_MAX ) /*lint !e685*/
441  return FALSE;
442 
443  *value = (int) val;
444  return TRUE;
445  }
446 
447  return FALSE;
448 }
449 
450 /** checks whether the current token is a section identifier, and if yes, switches to the corresponding section */
451 static
452 SCIP_Bool isNewSection(
453  SCIP* scip, /**< SCIP data structure */
454  BLKINPUT* blkinput /**< BLK reading data */
455  )
456 {
457  SCIP_Bool iscolon;
458 
459  assert(blkinput != NULL);
460 
461  /* remember first token by swapping the token buffer */
462  swapTokenBuffer(blkinput);
463 
464  /* look at next token: if this is a ':', the first token is a name and no section keyword */
465  iscolon = FALSE;
466  if( getNextToken(blkinput) )
467  {
468  iscolon = (strcmp(blkinput->token, ":") == 0);
469  pushToken(blkinput);
470  }
471 
472  /* reinstall the previous token by swapping back the token buffer */
473  swapTokenBuffer(blkinput);
474 
475  /* check for ':' */
476  if( iscolon )
477  return FALSE;
478 
479  if( strcasecmp(blkinput->token, "PRESOLVED") == 0 )
480  {
481  SCIPdebugMessage("(line %d) new section: PRESOLVED\n", blkinput->linenumber);
482  blkinput->section = BLK_PRESOLVED;
483  return TRUE;
484  }
485 
486  if( strcasecmp(blkinput->token, "NBLOCKS") == 0 )
487  {
488  SCIPdebugMessage("(line %d) new section: NBLOCKS\n", blkinput->linenumber);
489  blkinput->section = BLK_NBLOCKS;
490  return TRUE;
491  }
492 
493  if( strcasecmp(blkinput->token, "BLOCK") == 0 )
494  {
495  int blocknr;
496 
497  blkinput->section = BLK_BLOCK;
498 
499  if( getNextToken(blkinput) )
500  {
501  /* read block number */
502  if( isInt(scip, blkinput, &blocknr) )
503  {
504  assert(blocknr >= 0);
505  assert(blocknr <= blkinput->nblocks);
506 
507  blkinput->blocknr = blocknr-1;
508  }
509  else
510  syntaxError(scip, blkinput, "no block number after block keyword!\n");
511  }
512  else
513  syntaxError(scip, blkinput, "no block number after block keyword!\n");
514 
515  SCIPdebugMessage("new section: BLOCK %d\n", blkinput->blocknr);
516 
517  return TRUE;
518 
519  }
520 
521  if( strcasecmp(blkinput->token, "MASTERCONSS") == 0 )
522  {
523  blkinput->section = BLK_MASTERCONSS;
524 
525  SCIPdebugMessage("new section: MASTERCONSS\n");
526 
527  return TRUE;
528  }
529 
530  if( strcasecmp(blkinput->token, "END") == 0 )
531  {
532  SCIPdebugMessage("(line %d) new section: END\n", blkinput->linenumber);
533  blkinput->section = BLK_END;
534  return TRUE;
535  }
536 
537  return FALSE;
538 }
539 
540 /** reads the header of the file */
541 static
542 SCIP_RETCODE readStart(
543  SCIP* scip, /**< SCIP data structure */
544  BLKINPUT* blkinput /**< BLK reading data */
545  )
546 {
547  assert(blkinput != NULL);
548 
549  /* everything before first section is treated as comment */
550  do
551  {
552  /* get token */
553  if( !getNextToken(blkinput) )
554  return SCIP_OKAY;
555  }
556  while( !isNewSection(scip, blkinput) );
557 
558  return SCIP_OKAY;
559 }
560 
561 /** reads the presolved section */
562 static
563 SCIP_RETCODE readPresolved(
564  SCIP* scip, /**< SCIP data structure */
565  BLKINPUT* blkinput /**< DEC reading data */
566  )
567 {
568  int presolved;
569 
570  assert(scip != NULL);
571  assert(blkinput != NULL);
572 
573  while( getNextToken(blkinput) )
574  {
575  /* check if we reached a new section */
576  if( isNewSection(scip, blkinput) )
577  return SCIP_OKAY;
578 
579  /* read number of blocks */
580  if( isInt(scip, blkinput, &presolved) )
581  {
582  blkinput->haspresolvesection = TRUE;
583  if( presolved == 1 )
584  blkinput->presolved = TRUE;
585  else if ( presolved == 0 )
586  blkinput->presolved = FALSE;
587  else
588  syntaxError(scip, blkinput, "presolved parameter must be 0 or 1");
589  SCIPdebugMessage("Decomposition is%s from presolved problem\n",
590  blkinput->presolved ? "" : " not");
591  }
592  }
593 
594  return SCIP_OKAY;
595 }
596 
597 /** reads the nblocks section */
598 static
599 SCIP_RETCODE readNBlocks(
600  SCIP* scip, /**< SCIP data structure */
601  gcg::PARTIALDECOMP* partialdec, /**< partialdec to edit */
602  BLKINPUT* blkinput /**< BLK reading data */
603  )
604 {
605  int nblocks;
606 
607  assert(scip != NULL);
608  assert(blkinput != NULL);
609  assert(partialdec != NULL);
610 
611  while( getNextToken(blkinput) )
612  {
613  /* check if we reached a new section */
614  if( isNewSection(scip, blkinput) )
615  {
616  if( blkinput->nblocks == NOVALUE )
617  syntaxError(scip, blkinput, "no integer value in nblocks section");
618  else
619  return SCIP_OKAY;
620  }
621 
622  /* read number of blocks */
623  if( isInt(scip, blkinput, &nblocks) )
624  {
625  if( blkinput->nblocks == NOVALUE )
626  {
627  blkinput->nblocks = nblocks;
628  partialdec->setNBlocks(nblocks);
629  }
630  else
631  syntaxError(scip, blkinput, "2 integer values in nblocks section");
632  SCIPdebugMessage("Number of blocks = %d\n", blkinput->nblocks);
633  }
634  }
635 
636  return SCIP_OKAY;
637 }
638 
639 /** reads a block section */
640 static
641 SCIP_RETCODE readBlock(
642  SCIP* scip, /**< SCIP data structure */
643  BLKINPUT* blkinput, /**< BLK reading data */
644  gcg::PARTIALDECOMP* partialdec, /**< partialdec to edit */
645  SCIP_READERDATA* readerdata /**< reader data */
646  )
647 {
648  int blockid;
649 
650  assert(blkinput != NULL);
651  assert(partialdec != NULL);
652 
653  blockid = blkinput->blocknr;
654 
655  while( getNextToken(blkinput) )
656  {
657  SCIP_VAR* var;
658  int varidx;
659  int oldblock;
660 
661  /* check if we reached a new section */
662  if( isNewSection(scip, blkinput) )
663  return SCIP_OKAY;
664 
665  /* the token must be the name of an existing variable */
666  var = SCIPfindVar(scip, blkinput->token);
667  if( var == NULL )
668  {
669  syntaxError(scip, blkinput, "unknown variable in block section");
670  return SCIP_OKAY;
671  }
672 
673  varidx = SCIPvarGetProbindex(var);
674  oldblock = readerdata->varstoblock[varidx];
675 
676  /* set the block number of the variable to the number of the current block */
677  if( oldblock == NOVALUE )
678  {
679  SCIPdebugMessage("\tVar %s temporary in block %d.\n", SCIPvarGetName(var), blockid);
680  readerdata->varstoblock[varidx] = blockid;
681  ++(readerdata->nblockvars[blockid]);
682  partialdec->fixVarToBlockByName(blkinput->token, blockid);
683  }
684  /* variable was assigned to another (non-linking) block before, so it becomes a linking variable, now */
685  else if( (oldblock != LINKINGVALUE) )
686  {
687  assert(oldblock != blockid);
688  SCIPdebugMessage("\tVar %s is linking (old %d != %d new).\n", SCIPvarGetName(var), oldblock, blockid);
689 
690  readerdata->varstoblock[varidx] = LINKINGVALUE;
691 
692  /* decrease the number of variables in the old block and increase the number of linking variables */
693  --(readerdata->nblockvars[oldblock]);
694  ++(readerdata->nlinkingvars);
695 
696  assert(readerdata->nlinkingvarsblocks[varidx] == 0);
697  assert(readerdata->linkingvarsblocks[varidx] == NULL);
698  SCIP_CALL( SCIPallocMemoryArray(scip, &readerdata->linkingvarsblocks[varidx], 2) ); /*lint !e506 !e866*/
699  readerdata->linkingvarsblocks[varidx][0] = oldblock;
700  readerdata->linkingvarsblocks[varidx][1] = blockid;
701  readerdata->nlinkingvarsblocks[varidx] = 2;
702 
703  partialdec->fixVarToLinkingByName(blkinput->token);
704  }
705  /* variable is a linking variable already, store the new block to which it belongs */
706  else
707  {
708  assert(oldblock == LINKINGVALUE);
709  assert(readerdata->nlinkingvarsblocks[varidx] >= 2);
710  assert(readerdata->linkingvarsblocks[varidx] != NULL);
711  SCIP_CALL( SCIPreallocMemoryArray(scip, &readerdata->linkingvarsblocks[varidx], (size_t) readerdata->nlinkingvarsblocks[varidx] + 1) ); /*lint !e866*/
712  readerdata->linkingvarsblocks[varidx][readerdata->nlinkingvarsblocks[varidx]] = blockid;
713  ++(readerdata->nlinkingvarsblocks[varidx]);
714  }
715  }
716 
717  return SCIP_OKAY;
718 }
719 
720 /** reads the masterconss section */
721 static
722 SCIP_RETCODE readMasterconss(
723  SCIP* scip, /**< SCIP data structure */
724  BLKINPUT* blkinput, /**< BLK reading data */
725  gcg::PARTIALDECOMP* partialdec, /**< PARTIALDECOMP to edit */
726  SCIP_READERDATA* readerdata /**< reader data */
727  )
728 {
729  assert(blkinput != NULL);
730  assert(partialdec != NULL);
731 
732  while( getNextToken(blkinput) )
733  {
734  SCIP_CONS* cons;
735 
736  /* check if we reached a new section */
737  if( isNewSection(scip, blkinput) )
738  return SCIP_OKAY;
739 
740  /* the token must be the name of an existing constraint */
741  cons = SCIPfindCons(scip, blkinput->token);
742  if( cons == NULL )
743  {
744  syntaxError(scip, blkinput, "unknown constraint in masterconss section");
745  return SCIP_OKAY;
746  }
747  else
748  {
749  assert(SCIPhashmapGetImage(readerdata->constoblock, cons) == (void*) (size_t) NOVALUE);
750  SCIP_CALL( SCIPhashmapSetImage(readerdata->constoblock, cons, (void*) (size_t) (blkinput->nblocks +1)) );
751  partialdec->fixConsToMasterByName(blkinput->token);
752  }
753  }
754 
755  return SCIP_OKAY;
756 }
757 
758 /** fills the whole Decomp struct after the blk file has been read */
759 static
760 SCIP_RETCODE fillDecompStruct(
761  SCIP* scip, /**< SCIP data structure */
762  BLKINPUT* blkinput, /**< blk reading data */
763  DEC_DECOMP* decomp, /**< DEC_DECOMP structure to fill */
764  gcg::PARTIALDECOMP* partialdec, /**< partialdec to fill for internal handling */
765  SCIP_READERDATA* readerdata /**< reader data*/
766  )
767 {
768  SCIP_HASHMAP* constoblock;
769  SCIP_CONS** allcons;
770  SCIP_VAR** allvars;
771 
772  SCIP_VAR** consvars;
773  SCIP_RETCODE retcode;
774  int i;
775  int j;
776  int nvars;
777  int blocknr;
778  int nconss;
779  int nblocks;
780 
781  assert(scip != NULL);
782  assert(blkinput != NULL);
783  assert(readerdata != NULL);
784  assert(partialdec != NULL);
785 
786  allcons = SCIPgetConss(scip);
787  allvars = SCIPgetVars(scip);
788  nvars = SCIPgetNVars(scip);
789  nconss = SCIPgetNConss(scip);
790  nblocks = blkinput->nblocks;
791 
792  DECdecompSetPresolved(decomp, blkinput->presolved);
793  DECdecompSetNBlocks(decomp, nblocks);
794  DECdecompSetDetector(decomp, NULL);
795 
796  SCIP_CALL( DECdecompSetType(decomp, DEC_DECTYPE_ARROWHEAD) );
797 
798  /* hashmaps */
799  SCIP_CALL( SCIPhashmapCreate(&constoblock, SCIPblkmem(scip), nconss) );
800  SCIP_CALL( SCIPallocMemoryArray(scip, &consvars, nvars) );
801 
802  /* assign unassigned variables as master variables */
803  for( i = 0; i < nvars; ++i)
804  {
805  SCIP_VAR* var;
806  var = allvars[i];
807  if( readerdata->varstoblock[i] == NOVALUE )
808  {
809  partialdec->fixVarToMasterByName(SCIPvarGetName(var));
810  }
811  }
812 
813  /* assign constraints to blocks or declare them linking */
814  for( i = 0; i < nconss; ++i )
815  {
816  SCIP_CONS* cons;
817 
818  cons = allcons[i];
819 
820  if( SCIPhashmapGetImage(readerdata->constoblock, cons) == (void*) (size_t) LINKINGVALUE )
821  {
822  SCIP_CALL( SCIPhashmapInsert(constoblock, cons, (void*) (size_t) (nblocks+1)) );
823 
824  SCIPdebugMessage("cons %s is linking\n", SCIPconsGetName(cons));
825  }
826  /* check whether all variables in the constraint belong to one block */
827  else
828  {
829  int nconsvars;
830 
831  nconsvars = GCGconsGetNVars(scip, cons);
832  assert(nconsvars < nvars);
833 
834  SCIP_CALL( GCGconsGetVars(scip, cons, consvars, nvars) );
835 
836  blocknr = -1;
837 
838  /* find the first unique assignment of a contained variable to a block */
839  for( j = 0; j < nconsvars; ++j )
840  {
841  /* if a contained variable is directly transferred to the master, the constraint is a linking constraint */
842  if( readerdata->varstoblock[SCIPvarGetProbindex(consvars[j])] == NOVALUE )
843  {
844  blocknr = -1;
845  break;
846  }
847  /* assign the constraint temporarily to the block of the variable, if it is unique */
848  if( blocknr == -1 && readerdata->varstoblock[SCIPvarGetProbindex(consvars[j])] != LINKINGVALUE )
849  {
850  blocknr = readerdata->varstoblock[SCIPvarGetProbindex(consvars[j])];
851  }
852  }
853  if( blocknr != -1 )
854  {
855  /* check whether all contained variables are copied into the assigned block;
856  * if not, the constraint is treated as a linking constraint
857  */
858  for( j = 0; j < nconsvars; ++j )
859  {
860  int varidx = SCIPvarGetProbindex(consvars[j]);
861  int varblock = readerdata->varstoblock[varidx];
862  assert(varblock != NOVALUE);
863 
864  if( varblock != LINKINGVALUE && varblock != blocknr )
865  {
866  blocknr = -1;
867  break;
868  }
869  else if( varblock == LINKINGVALUE )
870  {
871  int k;
872 
873  for( k = 0; k < readerdata->nlinkingvarsblocks[varidx]; ++k )
874  {
875  if( readerdata->linkingvarsblocks[varidx][k] == blocknr )
876  break;
877  }
878  /* we did not break, so the variable is not assigned to the block */
879  if( k == readerdata->nlinkingvarsblocks[varidx] )
880  {
881  blocknr = -1;
882  break;
883  }
884  }
885  }
886  }
887 
888  if( blocknr == -1 )
889  {
890  SCIP_CALL( SCIPhashmapInsert(constoblock, cons, (void*) (size_t) (nblocks+1)) );
891  partialdec->fixConsToMasterByName(SCIPconsGetName(cons));
892 
893  SCIPdebugMessage("constraint <%s> is a linking constraint\n",
894  SCIPconsGetName(cons));
895  }
896  else
897  {
898  SCIP_CALL( SCIPhashmapInsert(constoblock, cons, (void*) (size_t) (blocknr+1)) );
899  partialdec->fixConsToBlockByName(SCIPconsGetName(cons), blocknr);
900  SCIPdebugMessage("constraint <%s> is assigned to block %d\n", SCIPconsGetName(cons), blocknr);
901  }
902  }
903  }
904 
905  SCIPinfoMessage(scip, NULL, "just read blk file:\n");
906 
907  retcode = DECfilloutDecompFromConstoblock(scip, decomp, constoblock, nblocks, FALSE);
908  SCIPfreeMemoryArray(scip, &consvars);
909 
910  return retcode;
911 }
912 
913 /** reads an BLK file */
914 static
915 SCIP_RETCODE readBLKFile(
916  SCIP* scip, /**< SCIP data structure */
917  SCIP_READER* reader, /**< reader data structure */
918  BLKINPUT* blkinput, /**< BLK reading data */
919  const char* filename /**< name of the input file */
920  )
921 {
922  SCIP_RETCODE retcode = SCIP_ERROR;
923  DEC_DECOMP *decdecomp;
924  int i;
925  int nconss;
926  int nblocksread;
927  int nvars;
928  SCIP_READERDATA* readerdata;
929  SCIP_CONS** conss;
930  nblocksread = FALSE;
931 
932  assert(scip != NULL);
933  assert(reader != NULL);
934  assert(blkinput != NULL);
935 
936  if( SCIPgetStage(scip) < SCIP_STAGE_TRANSFORMED )
937  SCIP_CALL( SCIPtransformProb(scip) );
938 
939  readerdata = SCIPreaderGetData(reader);
940  assert(readerdata != NULL);
941 
942  readerdata->nlinkingcons = SCIPgetNConss(scip);
943  readerdata->nlinkingvars = 0;
944  nvars = SCIPgetNVars(scip);
945  conss = SCIPgetConss(scip);
946  nconss = SCIPgetNConss(scip);
947 
948  /* alloc: var -> block mapping */
949  SCIP_CALL( SCIPallocMemoryArray(scip, &readerdata->varstoblock, nvars) );
950  for( i = 0; i < nvars; i ++ )
951  {
952  readerdata->varstoblock[i] = NOVALUE;
953  }
954 
955  /* alloc: linkingvar -> blocks mapping */
956  SCIP_CALL( SCIPallocMemoryArray(scip, &readerdata->linkingvarsblocks, nvars) );
957  SCIP_CALL( SCIPallocMemoryArray(scip, &readerdata->nlinkingvarsblocks, nvars) );
958  BMSclearMemoryArray(readerdata->linkingvarsblocks, nvars);
959  BMSclearMemoryArray(readerdata->nlinkingvarsblocks, nvars);
960 
961  /* cons -> block mapping */
962  SCIP_CALL( SCIPhashmapCreate(&readerdata->constoblock, SCIPblkmem(scip), nconss) );
963  for( i = 0; i < SCIPgetNConss(scip); i ++ )
964  {
965  SCIP_CALL( SCIPhashmapInsert(readerdata->constoblock, conss[i], (void*)(size_t) NOVALUE) );
966  }
967 
968  /* open file */
969  blkinput->file = SCIPfopen(filename, "r");
970  if( blkinput->file == NULL )
971  {
972  SCIPerrorMessage("cannot open file <%s> for reading\n", filename);
973  SCIPprintSysError(filename);
974  return SCIP_NOFILE;
975  }
976 
977  /* parse the file */
978  blkinput->section = BLK_START;
979  gcg::PARTIALDECOMP* newpartialdec = NULL;
980  while( blkinput->section != BLK_END && !hasError(blkinput) )
981  {
982  switch( blkinput->section )
983  {
984  case BLK_START:
985  SCIP_CALL( readStart(scip, blkinput) );
986  break;
987 
988  case BLK_PRESOLVED:
989  SCIP_CALL( readPresolved(scip, blkinput) );
990  if( blkinput->presolved && SCIPgetStage(scip) < SCIP_STAGE_PRESOLVED )
991  {
992  SCIPpresolve(scip);
993  assert(blkinput->haspresolvesection);
994 
995  /** @bug GCG should be able to presolve the problem first */
996 
997  // SCIPverbMessage(scip, SCIP_VERBLEVEL_MINIMAL, NULL, "decomposition belongs to the presolved problem, please presolve the problem first.\n");
998  }
999  break;
1000 
1001  case BLK_NBLOCKS:
1002  if( blkinput->haspresolvesection )
1003  {
1004  newpartialdec = new gcg::PARTIALDECOMP(scip, !blkinput->presolved);
1006  }
1007  SCIP_CALL( readNBlocks(scip, newpartialdec, blkinput) );
1008  if( blkinput->haspresolvesection && !blkinput->presolved && SCIPgetStage(scip) >= SCIP_STAGE_PRESOLVED )
1009  {
1010  SCIPverbMessage(scip, SCIP_VERBLEVEL_MINIMAL, NULL, "decomposition belongs to the original problem, please re-read the problem and read the decomposition without presolving.\n");
1011  goto TERMINATE;
1012  }
1013  if( !blkinput->haspresolvesection )
1014  {
1015  SCIPwarningMessage(scip, "decomposition has no presolve section at beginning. It is assumed to belong to the unpresolved problem but the behaviour is undefined. See the FAQ for further information.\n");
1016  blkinput->presolved = FALSE;
1017  newpartialdec = new gcg::PARTIALDECOMP(scip, !blkinput->presolved);
1019  }
1020 
1021  break;
1022 
1023  case BLK_BLOCK:
1024  if( nblocksread == FALSE )
1025  {
1026  /* alloc n vars per block */
1027  SCIP_CALL( SCIPallocMemoryArray(scip, &readerdata->nblockvars, blkinput->nblocks) );
1028  SCIP_CALL( SCIPallocMemoryArray(scip, &readerdata->nblockcons, blkinput->nblocks) );
1029  SCIP_CALL( SCIPallocMemoryArray(scip, &readerdata->blockcons, blkinput->nblocks) );
1030  for( i = 0; i < blkinput->nblocks; ++i )
1031  {
1032  readerdata->nblockvars[i] = 0;
1033  readerdata->nblockcons[i] = 0;
1034  SCIP_CALL( SCIPallocMemoryArray(scip, &(readerdata->blockcons[i]), nconss) ); /*lint !e866*/
1035  }
1036  nblocksread = TRUE;
1037  }
1038  SCIP_CALL( readBlock(scip, blkinput, newpartialdec, readerdata) );
1039  break;
1040 
1041  case BLK_MASTERCONSS:
1042  SCIP_CALL( readMasterconss(scip, blkinput, newpartialdec, readerdata) );
1043  break;
1044 
1045  case BLK_END: /* this is already handled in the while() loop */
1046  default:
1047  SCIPerrorMessage("invalid BLK file section <%d>\n", blkinput->section);
1048  return SCIP_INVALIDDATA;
1049  }
1050  }
1051 
1052  SCIP_CALL( DECdecompCreate(scip, &decdecomp) );
1053 
1054  /* fill decomp */
1055  retcode = fillDecompStruct(scip, blkinput, decdecomp, newpartialdec, readerdata);
1056 
1057  GCGconshdlrDecompAddPreexisitingPartialDec(scip, newpartialdec);
1058 
1059  SCIP_CALL( DECdecompFree(scip, &decdecomp) );
1060 
1061  for( i = 0; i < nvars; ++i )
1062  {
1063  assert(readerdata->linkingvarsblocks[i] != NULL || readerdata->nlinkingvarsblocks[i] == 0);
1064  if( readerdata->nlinkingvarsblocks[i] > 0 )
1065  {
1066  SCIPfreeMemoryArray(scip, &readerdata->linkingvarsblocks[i]);
1067  }
1068  }
1069 
1070  TERMINATE:
1071  if( nblocksread )
1072  {
1073  for( i = blkinput->nblocks - 1; i >= 0; --i )
1074  {
1075  SCIPfreeMemoryArray(scip, &(readerdata->blockcons[i]));
1076  }
1077  SCIPfreeMemoryArray(scip, &readerdata->blockcons);
1078  SCIPfreeMemoryArray(scip, &readerdata->nblockcons);
1079  SCIPfreeMemoryArray(scip, &readerdata->nblockvars);
1080  }
1081 
1082  SCIPhashmapFree(&readerdata->constoblock);
1083 
1084  SCIPfreeMemoryArray(scip, &readerdata->nlinkingvarsblocks);
1085  SCIPfreeMemoryArray(scip, &readerdata->linkingvarsblocks);
1086  SCIPfreeMemoryArray(scip, &readerdata->varstoblock);
1087 
1088  /* close file */
1089  SCIPfclose(blkinput->file);
1090 
1091  return retcode;
1092 }
1093 
1094 
1095 /*
1096  * Callback methods of reader
1097  */
1098 
1099 /** destructor of reader to free user data (called when SCIP is exiting) */
1100 static
1101 SCIP_DECL_READERFREE(readerFreeBlk)
1102 {
1103  SCIP_READERDATA* readerdata;
1104 
1105  readerdata = SCIPreaderGetData(reader);
1106  assert(readerdata != NULL);
1107 
1108  SCIPfreeMemory(scip, &readerdata);
1109 
1110  return SCIP_OKAY;
1111 }
1112 
1113 
1114 /** problem reading method of reader */
1115 static
1116 SCIP_DECL_READERREAD(readerReadBlk)
1117 { /*lint --e{715} */
1118 
1119  if( SCIPgetStage(scip) == SCIP_STAGE_INIT || SCIPgetNVars(scip) == 0 || SCIPgetNConss(scip) == 0 )
1120  {
1121  SCIPverbMessage(scip, SCIP_VERBLEVEL_DIALOG, NULL, "Please read in a problem before reading in the corresponding structure file!\n");
1122  return SCIP_OKAY;
1123  }
1124  SCIP_CALL( SCIPreadBlk(scip, filename, result) );
1125 
1126  return SCIP_OKAY;
1127 }
1128 
1129 
1130 /** problem writing method of reader */
1131 static
1132 SCIP_DECL_READERWRITE(readerWriteBlk)
1133 { /*lint --e{715}*/
1134  return SCIP_OKAY;
1135 }
1136 
1137 /*
1138  * reader specific interface methods
1139  */
1140 
1141 /** includes the blk file reader in SCIP */
1143  SCIP* scip /**< SCIP data structure */
1144  )
1145 {
1146  SCIP_READERDATA* readerdata;
1147 
1148  /* create blk reader data */
1149  SCIP_CALL( SCIPallocMemory(scip, &readerdata) );
1150 
1151  /* include blk reader */
1152  SCIP_CALL( SCIPincludeReader(scip, READER_NAME, READER_DESC, READER_EXTENSION, NULL,
1153  readerFreeBlk, readerReadBlk, readerWriteBlk, readerdata) );
1154 
1155  return SCIP_OKAY;
1156 }
1157 
1158 
1159 /* reads problem from file */
1160 SCIP_RETCODE SCIPreadBlk(
1161  SCIP* scip, /**< SCIP data structure */
1162  const char* filename, /**< full path and name of file to read, or NULL if stdin should be used */
1163  SCIP_RESULT* result /**< pointer to store the result of the file reading call */
1164  )
1165 {
1166  SCIP_RETCODE retcode;
1167  SCIP_READER* reader;
1168  BLKINPUT blkinput;
1169  int i;
1170  char* ext;
1171  char copyfilename[SCIP_MAXSTRLEN];
1172 
1173  reader = SCIPfindReader(scip, READER_NAME);
1174  assert(reader != NULL);
1175 
1176  (void) SCIPsnprintf(copyfilename, SCIP_MAXSTRLEN, "%s", filename);
1177  SCIPsplitFilename(copyfilename, NULL, NULL, &ext, NULL);
1178 
1179  if ( strcmp(ext, "blk") != 0 )
1180  {
1181  return SCIP_READERROR;
1182  }
1183 
1184  /* initialize BLK input data */
1185  blkinput.file = NULL;
1186  blkinput.linebuf[0] = '\0';
1187  SCIP_CALL( SCIPallocMemoryArray(scip, &blkinput.token, BLK_MAX_LINELEN) ); /*lint !e506*/
1188  blkinput.token[0] = '\0';
1189  SCIP_CALL( SCIPallocMemoryArray(scip, &blkinput.tokenbuf, BLK_MAX_LINELEN) ); /*lint !e506*/
1190  blkinput.tokenbuf[0] = '\0';
1191  for( i = 0; i < BLK_MAX_PUSHEDTOKENS; ++i )
1192  {
1193  SCIP_CALL( SCIPallocMemoryArray(scip, &blkinput.pushedtokens[i], BLK_MAX_LINELEN) ); /*lint !e506 !e866*/
1194  }
1195 
1196  blkinput.npushedtokens = 0;
1197  blkinput.linenumber = 0;
1198  blkinput.linepos = 0;
1199  blkinput.section = BLK_START;
1200  blkinput.presolved = FALSE;
1201  blkinput.haspresolvesection = FALSE;
1202  blkinput.nblocks = -1;
1203  blkinput.blocknr = -2;
1204  blkinput.haserror = FALSE;
1205 
1206  /* read the file */
1207  retcode = readBLKFile(scip, reader, &blkinput, filename);
1208 
1209  /* free dynamically allocated memory */
1210  SCIPfreeMemoryArray(scip, &blkinput.token);
1211  SCIPfreeMemoryArray(scip, &blkinput.tokenbuf);
1212  for( i = 0; i < BLK_MAX_PUSHEDTOKENS; ++i )
1213  {
1214  SCIPfreeMemoryArray(scip, &blkinput.pushedtokens[i]);
1215  }
1216 
1217  /* evaluate the result */
1218  if( blkinput.haserror )
1219  return SCIP_READERROR;
1220  else if( retcode == SCIP_OKAY )
1221  {
1222  *result = SCIP_SUCCESS;
1223  }
1224 
1225  return SCIP_OKAY;
1226 }
void DECdecompSetNBlocks(DEC_DECOMP *decomp, int nblocks)
Definition: decomp.c:733
static void pushToken(BLKINPUT *blkinput)
Definition: reader_blk.cpp:400
#define BLK_MAX_PUSHEDTOKENS
Definition: reader_blk.cpp:76
static SCIP_RETCODE readMasterconss(SCIP *scip, BLKINPUT *blkinput, gcg::PARTIALDECOMP *partialdec, SCIP_READERDATA *readerdata)
Definition: reader_blk.cpp:722
static SCIP_Bool isInt(SCIP *scip, BLKINPUT *blkinput, int *value)
Definition: reader_blk.cpp:424
@ BLK_END
Definition: reader_blk.cpp:81
#define READER_DESC
Definition: reader_blk.cpp:69
static SCIP_Bool getNextLine(BLKINPUT *blkinput)
Definition: reader_blk.cpp:243
enum BlkSection BLKSECTION
Definition: reader_blk.cpp:83
void setNBlocks(int nblocks)
sets number of blocks, only increasing number allowed
static SCIP_DECL_READERWRITE(readerWriteBlk)
@ DEC_DECTYPE_ARROWHEAD
Definition: type_decomp.h:50
char * pushedtokens[BLK_MAX_PUSHEDTOKENS]
Definition: reader_blk.cpp:100
constraint handler for structure detection
static SCIP_Bool isNewSection(SCIP *scip, BLKINPUT *blkinput)
Definition: reader_blk.cpp:452
static void swapTokenBuffer(BLKINPUT *blkinput)
Definition: reader_blk.cpp:413
SCIP_RETCODE GCGconsGetVars(SCIP *scip, SCIP_CONS *cons, SCIP_VAR **vars, int nvars)
Definition: scip_misc.c:490
static SCIP_Bool hasError(BLKINPUT *blkinput)
Definition: reader_blk.cpp:170
SCIP_CONS *** blockcons
Definition: reader_blk.cpp:121
int npushedtokens
Definition: reader_blk.cpp:101
char * tokenbuf
Definition: reader_blk.cpp:99
static SCIP_RETCODE readStart(SCIP *scip, BLKINPUT *blkinput)
Definition: reader_blk.cpp:542
bool fixVarToMasterByName(const char *varname)
assigns a variable with given name as master
static const int LINKINGVALUE
Definition: reader_blk.cpp:128
BLKSECTION section
Definition: reader_blk.cpp:108
various SCIP helper methods
bool fixVarToLinkingByName(const char *varname)
assigns a variable by name to the linking variables
SCIP_Bool haserror
Definition: reader_blk.cpp:109
static SCIP_RETCODE readNBlocks(SCIP *scip, gcg::PARTIALDECOMP *partialdec, BLKINPUT *blkinput)
Definition: reader_blk.cpp:599
void setUsergiven(USERGIVEN usergiven)
sets whether this partialdec is user given
static const int NOVALUE
Definition: reader_blk.cpp:127
int ** linkingvarsblocks
Definition: reader_blk.cpp:118
static SCIP_DECL_READERFREE(readerFreeBlk)
SCIP_Bool presolved
Definition: reader_blk.cpp:104
BLK file reader for structure information.
char * token
Definition: reader_blk.cpp:98
static void syntaxError(SCIP *scip, BLKINPUT *blkinput, const char *msg)
Definition: reader_blk.cpp:142
static const char delimchars[]
Definition: reader_blk.cpp:129
SCIP_FILE * file
Definition: reader_blk.cpp:96
static const char tokenchars[]
Definition: reader_blk.cpp:130
SCIP_HASHMAP * constoblock
Definition: reader_blk.cpp:120
@ BLK_PRESOLVED
Definition: reader_blk.cpp:81
static SCIP_RETCODE fillDecompStruct(SCIP *scip, BLKINPUT *blkinput, DEC_DECOMP *decomp, gcg::PARTIALDECOMP *partialdec, SCIP_READERDATA *readerdata)
Definition: reader_blk.cpp:760
SCIP_RETCODE DECfilloutDecompFromConstoblock(SCIP *scip, DEC_DECOMP *decomp, SCIP_HASHMAP *constoblock, int nblocks, SCIP_Bool staircase)
Definition: decomp.c:1455
@ BLK_BLOCK
Definition: reader_blk.cpp:81
void DECdecompSetPresolved(DEC_DECOMP *decomp, SCIP_Bool presolved)
Definition: decomp.c:712
C++ interface of cons_decomp.
char linebuf[BLK_MAX_LINELEN]
Definition: reader_blk.cpp:97
SCIP_RETCODE DECdecompFree(SCIP *scip, DEC_DECOMP **decdecomp)
Definition: decomp.c:530
@ BLK_EXP_SIGNED
Definition: reader_blk.cpp:88
BlkExpType
Definition: reader_blk.cpp:86
SCIP_RETCODE SCIPreadBlk(SCIP *scip, const char *filename, SCIP_RESULT *result)
static SCIP_Bool isValueChar(char c, char nextc, SCIP_Bool firstchar, SCIP_Bool *hasdot, BLKEXPTYPE *exptype)
Definition: reader_blk.cpp:199
BlkSection
Definition: reader_blk.cpp:79
int GCGconsGetNVars(SCIP *scip, SCIP_CONS *cons)
Definition: scip_misc.c:434
int linenumber
Definition: reader_blk.cpp:102
#define READER_NAME
Definition: reader_blk.cpp:68
GCG relaxator.
bool fixConsToMasterByName(const char *consname)
assgins a constraint by name as master
class to manage partial decompositions
SCIP_Bool haspresolvesection
Definition: reader_blk.cpp:105
static SCIP_DECL_READERREAD(readerReadBlk)
@ BLK_START
Definition: reader_blk.cpp:81
SCIP_RETCODE GCGconshdlrDecompAddPreexisitingPartialDec(SCIP *scip, PARTIALDECOMP *partialdec)
adds a preexisting partial dec to be considered at the beginning of the detection
static SCIP_RETCODE readBlock(SCIP *scip, BLKINPUT *blkinput, gcg::PARTIALDECOMP *partialdec, SCIP_READERDATA *readerdata)
Definition: reader_blk.cpp:641
static void swapPointers(char **pointer1, char **pointer2)
Definition: reader_blk.cpp:287
void DECdecompSetDetector(DEC_DECOMP *decomp, DEC_DETECTOR *detector)
Definition: decomp.c:1579
bool fixVarToBlockByName(const char *varname, int blockid)
assigns a variable by name to a block
static SCIP_RETCODE readPresolved(SCIP *scip, BLKINPUT *blkinput)
Definition: reader_blk.cpp:563
@ BLK_NBLOCKS
Definition: reader_blk.cpp:81
SCIP_RETCODE DECdecompCreate(SCIP *scip, DEC_DECOMP **decdecomp)
Definition: decomp.c:471
bool fixConsToBlockByName(const char *consname, int blockid)
assigns a constraint by name to a block
class storing (potentially incomplete) decompositions
public methods for GCG variables
#define READER_EXTENSION
Definition: reader_blk.cpp:70
static SCIP_RETCODE readBLKFile(SCIP *scip, SCIP_READER *reader, BLKINPUT *blkinput, const char *filename)
Definition: reader_blk.cpp:915
static const char commentchars[]
Definition: reader_blk.cpp:131
@ BLK_EXP_UNSIGNED
Definition: reader_blk.cpp:88
static SCIP_Bool isTokenChar(char c)
Definition: reader_blk.cpp:190
static SCIP_Bool getNextToken(BLKINPUT *blkinput)
Definition: reader_blk.cpp:301
@ BLK_MASTERCONSS
Definition: reader_blk.cpp:81
SCIP_RETCODE SCIPincludeReaderBlk(SCIP *scip)
SCIP_RETCODE DECdecompSetType(DEC_DECOMP *decomp, DEC_DECTYPE type)
Definition: decomp.c:647
static SCIP_Bool isDelimChar(char c)
Definition: reader_blk.cpp:181
int * nlinkingvarsblocks
Definition: reader_blk.cpp:119
@ BLK_EXP_NONE
Definition: reader_blk.cpp:88
@ COMPLETED_CONSTOMASTER
public methods for working with decomposition structures
enum BlkExpType BLKEXPTYPE
Definition: reader_blk.cpp:90
#define BLK_MAX_LINELEN
Definition: reader_blk.cpp:75