Scippy

SCIP

Solving Constraint Integer Programs

reader_opb.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-2017 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 reader_opb.c
17  * @brief pseudo-Boolean file reader (opb format)
18  * @author Stefan Heinz
19  * @author Michael Winkler
20  *
21  * This file reader parses the @a opb format and is also used by the @a wbo reader for the @a wbo format. For a
22  * detailed description of this format see
23  *
24  * - http://www.cril.univ-artois.fr/PB07/solver_req.html
25  * - http://www.cril.univ-artois.fr/PB10/format.pdf
26  *
27  * The syntax of the input file format can be described by a simple Backus-Naur
28  * form. <formula> is the start symbol of this grammar.
29  *
30  * <formula>::= <sequence_of_comments>
31  * [<objective>] | [<softheader>]
32  * <sequence_of_comments_or_constraints>
33  *
34  * <sequence_of_comments>::= <comment> [<sequence_of_comments>]
35  * <comment>::= "*" <any_sequence_of_characters_other_than_EOL> <EOL>
36  * <sequence_of_comments_or_constraints>::=<comment_or_constraint> [<sequence_of_comments_or_constraints>]
37  * <comment_or_constraint>::=<comment>|<constraint>
38  *
39  * <objective>::= "min:" <zeroOrMoreSpace> <sum> ";"
40  * <constraint>::= <sum> <relational_operator> <zeroOrMoreSpace> <integer> <zeroOrMoreSpace> ";"
41  *
42  * <sum>::= <weightedterm> | <weightedterm> <sum>
43  * <weightedterm>::= <integer> <oneOrMoreSpace> <term> <oneOrMoreSpace>
44  *
45  * <integer>::= <unsigned_integer> | "+" <unsigned_integer> | "-" <unsigned_integer>
46  * <unsigned_integer>::= <digit> | <digit><unsigned_integer>
47  *
48  * <relational_operator>::= ">=" | "="
49  *
50  * <variablename>::= "x" <unsigned_integer>
51  *
52  * <oneOrMoreSpace>::= " " [<oneOrMoreSpace>]
53  * <zeroOrMoreSpace>::= [" " <zeroOrMoreSpace>]
54  *
55  * For linear pseudo-Boolean instances, <term> is defined as
56  *
57  * <term>::=<variablename>
58  *
59  * For non-linear instances, <term> is defined as
60  *
61  * <term>::= <oneOrMoreLiterals>
62  * <oneOrMoreLiterals>::= <literal> | <literal> <oneOrMoreSpace> <oneOrMoreLiterals>
63  * <literal>::= <variablename> | "~"<variablename>
64  *
65  * For wbo-files are the following additional/changed things possible.
66  *
67  * <softheader>::= "soft:" [<unsigned integer>] ";"
68  *
69  * <comment_or_constraint>::=<comment>|<constraint>|<softconstraint>
70  *
71  * <softconstraint>::= "[" <zeroOrMoreSpace> <unsigned integer> <zeroOrMoreSpace> "]" <constraint>
72  *
73  */
74 
75 /* Our parser should also be lax by handling variable names and it's possible to read doubles instead of integer and
76  * possible some more :). */
77 
78 /*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
79 
80 #include <stdlib.h>
81 #include <assert.h>
82 #include <string.h>
83 #if defined(_WIN32) || defined(_WIN64)
84 #else
85 #include <strings.h> /*lint --e{766}*/ /* needed for strncasecmp() */
86 #endif
87 #include <ctype.h>
88 
89 #include "scip/cons_and.h"
90 #include "scip/cons_indicator.h"
91 #include "scip/cons_knapsack.h"
92 #include "scip/cons_linear.h"
93 #include "scip/cons_logicor.h"
95 #include "scip/cons_setppc.h"
96 #include "scip/cons_varbound.h"
97 #include "scip/pub_misc.h"
98 #include "scip/reader_opb.h"
99 #include "scip/debug.h"
100 
101 #define READER_NAME "opbreader"
102 #define READER_DESC "file reader for pseudo-Boolean problem in opb format"
103 #define READER_EXTENSION "opb"
104 
105 #define GENCONSNAMES TRUE /* remove if no constraint names should be generated */
106 #define LINEAROBJECTIVE TRUE /* will all non-linear parts inside the objective function be linearized or will
107  * an artificial integer variable be created which will represent the objective
108  * function
109  */
110 
111 #define INDICATORVARNAME "indicatorvar" /* standard part of name for all indicator variables */
112 #define INDICATORSLACKVARNAME "indslack" /* standard part of name for all indicator slack variables; should be the same in cons_indicator */
113 #define TOPCOSTCONSNAME "topcostcons" /* standard name for artificial topcost constraint in wbo problems */
114 
115 /*
116  * Data structures
117  */
118 #define OPB_MAX_LINELEN 65536 /**< size of the line buffer for reading or writing */
119 #define OPB_MAX_PUSHEDTOKENS 2
120 #define OPB_INIT_COEFSSIZE 8192
121 
122 /** Section in OPB File */
124 {
128 };
129 typedef enum OpbExpType OPBEXPTYPE;
130 
132 {
137 };
138 typedef enum OpbSense OPBSENSE;
139 
140 /** OPB reading data */
141 struct OpbInput
142 {
143  SCIP_FILE* file;
144  char linebuf[OPB_MAX_LINELEN+1];
145  char* token;
146  char* tokenbuf;
147  char* pushedtokens[OPB_MAX_PUSHEDTOKENS];
148  int npushedtokens;
149  int linenumber;
150  int linepos;
151  int bufpos;
152  SCIP_OBJSENSE objsense;
153  SCIP_Bool comment;
154  SCIP_Bool endline;
155  SCIP_Bool eof;
156  SCIP_Bool haserror;
157  int nproblemcoeffs;
158  SCIP_Bool wbo;
159  SCIP_Real topcost;
160  int nindvars;
161 #if GENCONSNAMES == TRUE
162  int consnumber;
163 #endif
164 };
165 
166 typedef struct OpbInput OPBINPUT;
167 
168 static const char commentchars[] = "*";
169 /*
170  * Local methods (for reading)
171  */
172 
173 /** issues an error message and marks the OPB data to have errors */
174 static
176  SCIP* scip, /**< SCIP data structure */
177  OPBINPUT* opbinput, /**< OPB reading data */
178  const char* msg /**< error message */
179  )
180 {
181  assert(opbinput != NULL);
182 
183  SCIPerrorMessage("Syntax error in line %d: %s found <%s>\n", opbinput->linenumber, msg, opbinput->token);
184  if( opbinput->linebuf[strlen(opbinput->linebuf)-1] == '\n' )
185  {
186  SCIPerrorMessage(" input: %s", opbinput->linebuf);
187  }
188  else
189  {
190  SCIPerrorMessage(" input: %s\n", opbinput->linebuf);
191  }
192 
193  opbinput->haserror = TRUE;
194 }
195 
196 /** returns whether a syntax error was detected */
197 static
199  OPBINPUT* opbinput /**< OPB reading data */
200  )
201 {
202  assert(opbinput != NULL);
203 
204  return opbinput->haserror;
205 }
206 
207 /** returns whether the given character is a token delimiter */
208 static
210  char c /**< input character */
211  )
212 {
213  switch (c)
214  {
215  case ' ':
216  case '\f':
217  case '\n':
218  case '\r':
219  case '\t':
220  case '\v':
221  case '\0':
222  return TRUE;
223  default:
224  return FALSE;
225  }
226 }
227 
228 /** returns whether the given character is a single token */
229 static
231  char c /**< input character */
232  )
233 {
234  switch (c)
235  {
236  case '-':
237  case '+':
238  case ':':
239  case '<':
240  case '>':
241  case '=':
242  case '[':
243  case ']':
244  case ';':
245  return TRUE;
246  default:
247  return FALSE;
248  }
249 }
250 
251 /** returns whether the current character is member of a value string */
252 static
254  char c, /**< input character */
255  char nextc, /**< next input character */
256  SCIP_Bool firstchar, /**< is the given character the first char of the token? */
257  SCIP_Bool* hasdot, /**< pointer to update the dot flag */
258  OPBEXPTYPE* exptype /**< pointer to update the exponent type */
259  )
260 {
261  assert(hasdot != NULL);
262  assert(exptype != NULL);
263 
264  if( isdigit((unsigned char)c) )
265  return TRUE;
266  else if( (*exptype == OPB_EXP_NONE) && !(*hasdot) && (c == '.') )
267  {
268  *hasdot = TRUE;
269  return TRUE;
270  }
271  else if( !firstchar && (*exptype == OPB_EXP_NONE) && (c == 'e' || c == 'E') )
272  {
273  if( nextc == '+' || nextc == '-' )
274  {
275  *exptype = OPB_EXP_SIGNED;
276  return TRUE;
277  }
278  else if( isdigit((unsigned char)nextc) )
279  {
280  *exptype = OPB_EXP_UNSIGNED;
281  return TRUE;
282  }
283  }
284  else if( (*exptype == OPB_EXP_SIGNED) && (c == '+' || c == '-') )
285  {
286  *exptype = OPB_EXP_UNSIGNED;
287  return TRUE;
288  }
289 
290  return FALSE;
291 }
292 
293 /** reads the next line from the input file into the line buffer; skips comments;
294  * returns whether a line could be read
295  */
296 static
298  SCIP* scip, /**< SCIP data structure */
299  OPBINPUT* opbinput /**< OPB reading data */
300  )
301 {
302  int i;
303 
304  assert(opbinput != NULL);
305 
306  /* if we previously detected a comment we have to parse the remaining line away if there is something left */
307  if( !opbinput->endline && opbinput->comment )
308  {
309  SCIPdebugMsg(scip, "Throwing rest of comment away.\n");
310 
311  do
312  {
313  opbinput->linebuf[OPB_MAX_LINELEN-2] = '\0';
314  (void)SCIPfgets(opbinput->linebuf, (int) sizeof(opbinput->linebuf), opbinput->file);
315  }
316  while( opbinput->linebuf[OPB_MAX_LINELEN-2] != '\0' );
317 
318  opbinput->comment = FALSE;
319  opbinput->endline = TRUE;
320  }
321 
322  /* clear the line */
323  opbinput->linebuf[OPB_MAX_LINELEN-2] = '\0';
324 
325  /* set line position */
326  if( opbinput->endline )
327  {
328  opbinput->linepos = 0;
329  opbinput->linenumber++;
330  }
331  else
332  opbinput->linepos += OPB_MAX_LINELEN - 2;
333 
334  if( SCIPfgets(opbinput->linebuf, (int) sizeof(opbinput->linebuf), opbinput->file) == NULL )
335  return FALSE;
336 
337  opbinput->bufpos = 0;
338 
339  if( opbinput->linebuf[OPB_MAX_LINELEN-2] != '\0' )
340  {
341  char* last;
342 
343  /* buffer is full; erase last token since it might be incomplete */
344  opbinput->endline = FALSE;
345  last = strrchr(opbinput->linebuf, ' ');
346 
347  if( last == NULL )
348  {
349  SCIPwarningMessage(scip, "we read %d character from the file; these might indicates a corrupted input file!",
350  OPB_MAX_LINELEN - 2);
351  opbinput->linebuf[OPB_MAX_LINELEN-2] = '\0';
352  SCIPdebugMsg(scip, "the buffer might be corrupted\n");
353  }
354  else
355  {
356  SCIPfseek(opbinput->file, -(long) strlen(last), SEEK_CUR);
357  SCIPdebugMsg(scip, "correct buffer, reread the last %ld characters\n", (long) strlen(last));
358  *last = '\0';
359  }
360  }
361  else
362  {
363  /* found end of line */
364  opbinput->endline = TRUE;
365  }
366 
367  opbinput->linebuf[OPB_MAX_LINELEN-1] = '\0'; /* we want to use lookahead of one char -> we need two \0 at the end */
368 
369  opbinput->comment = FALSE;
370 
371  /* skip characters after comment symbol */
372  for( i = 0; commentchars[i] != '\0'; ++i )
373  {
374  char* commentstart;
375 
376  commentstart = strchr(opbinput->linebuf, commentchars[i]);
377  if( commentstart != NULL )
378  {
379  *commentstart = '\0';
380  *(commentstart+1) = '\0'; /* we want to use lookahead of one char -> we need two \0 at the end */
381  opbinput->comment = TRUE;
382  break;
383  }
384  }
385 
386  SCIPdebugMsg(scip, "%s\n", opbinput->linebuf);
387 
388  return TRUE;
389 }
390 
391 /** swaps the addresses of two pointers */
392 static
394  char** pointer1, /**< first pointer */
395  char** pointer2 /**< second pointer */
396  )
397 {
398  char* tmp;
399 
400  tmp = *pointer1;
401  *pointer1 = *pointer2;
402  *pointer2 = tmp;
403 }
404 
405 /** reads the next token from the input file into the token buffer; returns whether a token was read */
406 static
408  SCIP* scip, /**< SCIP data structure */
409  OPBINPUT* opbinput /**< OPB reading data */
410  )
411 {
412  SCIP_Bool hasdot;
413  OPBEXPTYPE exptype;
414  char* buf;
415  int tokenlen;
416 
417  assert(opbinput != NULL);
418  assert(opbinput->bufpos < OPB_MAX_LINELEN);
419 
420  /* check the token stack */
421  if( opbinput->npushedtokens > 0 )
422  {
423  swapPointers(&opbinput->token, &opbinput->pushedtokens[opbinput->npushedtokens-1]);
424  opbinput->npushedtokens--;
425  SCIPdebugMsg(scip, "(line %d) read token again: '%s'\n", opbinput->linenumber, opbinput->token);
426  return TRUE;
427  }
428 
429  /* skip delimiters */
430  buf = opbinput->linebuf;
431  while( isDelimChar(buf[opbinput->bufpos]) )
432  {
433  if( buf[opbinput->bufpos] == '\0' )
434  {
435  if( !getNextLine(scip, opbinput) )
436  {
437  SCIPdebugMsg(scip, "(line %d) end of file\n", opbinput->linenumber);
438  return FALSE;
439  }
440  assert(opbinput->bufpos == 0);
441  }
442  else
443  {
444  opbinput->bufpos++;
445  opbinput->linepos++;
446  }
447  }
448  assert(opbinput->bufpos < OPB_MAX_LINELEN);
449  assert(!isDelimChar(buf[opbinput->bufpos]));
450 
451  /* check if the token is a value */
452  hasdot = FALSE;
453  exptype = OPB_EXP_NONE;
454  if( isValueChar(buf[opbinput->bufpos], buf[opbinput->bufpos+1], TRUE, &hasdot, &exptype) )
455  {
456  /* read value token */
457  tokenlen = 0;
458  do
459  {
460  assert(tokenlen < OPB_MAX_LINELEN);
461  assert(!isDelimChar(buf[opbinput->bufpos]));
462  opbinput->token[tokenlen] = buf[opbinput->bufpos];
463  tokenlen++;
464  opbinput->bufpos++;
465  opbinput->linepos++;
466  }
467  while( isValueChar(buf[opbinput->bufpos], buf[opbinput->bufpos+1], FALSE, &hasdot, &exptype) );
468  }
469  else
470  {
471  /* read non-value token */
472  tokenlen = 0;
473  do
474  {
475  assert(tokenlen < OPB_MAX_LINELEN);
476  opbinput->token[tokenlen] = buf[opbinput->bufpos];
477  tokenlen++;
478  opbinput->bufpos++;
479  opbinput->linepos++;
480  if( tokenlen == 1 && isTokenChar(opbinput->token[0]) )
481  break;
482  }
483  while( !isDelimChar(buf[opbinput->bufpos]) && !isTokenChar(buf[opbinput->bufpos]) );
484 
485  /* if the token is an equation sense '<', '>', or '=', skip a following '='
486  * if the token is an equality token '=' and the next character is a '<' or '>',
487  * replace the token by the inequality sense
488  */
489  if( tokenlen >= 1
490  && (opbinput->token[tokenlen-1] == '<' || opbinput->token[tokenlen-1] == '>' || opbinput->token[tokenlen-1] == '=')
491  && buf[opbinput->bufpos] == '=' )
492  {
493  opbinput->bufpos++;
494  opbinput->linepos++;
495  }
496  else if( opbinput->token[tokenlen-1] == '=' && (buf[opbinput->bufpos] == '<' || buf[opbinput->bufpos] == '>') )
497  {
498  opbinput->token[tokenlen-1] = buf[opbinput->bufpos];
499  opbinput->bufpos++;
500  opbinput->linepos++;
501  }
502  }
503  assert(tokenlen < OPB_MAX_LINELEN);
504  opbinput->token[tokenlen] = '\0';
505 
506  SCIPdebugMsg(scip, "(line %d) read token: '%s'\n", opbinput->linenumber, opbinput->token);
507 
508  return TRUE;
509 }
510 
511 /** puts the current token on the token stack, such that it is read at the next call to getNextToken() */
512 static
514  OPBINPUT* opbinput /**< OPB reading data */
515  )
516 {
517  assert(opbinput != NULL);
518  assert(opbinput->npushedtokens < OPB_MAX_PUSHEDTOKENS);
519 
520  swapPointers(&opbinput->pushedtokens[opbinput->npushedtokens], &opbinput->token);
521  opbinput->npushedtokens++;
522 }
523 
524 /** puts the buffered token on the token stack, such that it is read at the next call to getNextToken() */
525 static
527  OPBINPUT* opbinput /**< OPB reading data */
528  )
529 {
530  assert(opbinput != NULL);
531  assert(opbinput->npushedtokens < OPB_MAX_PUSHEDTOKENS);
532 
533  swapPointers(&opbinput->pushedtokens[opbinput->npushedtokens], &opbinput->tokenbuf);
534  opbinput->npushedtokens++;
535 }
536 
537 /** swaps the current token with the token buffer */
538 static
540  OPBINPUT* opbinput /**< OPB reading data */
541  )
542 {
543  assert(opbinput != NULL);
544 
545  swapPointers(&opbinput->token, &opbinput->tokenbuf);
546 }
547 
548 /** checks whether the current token is a section identifier, and if yes, switches to the corresponding section */
549 static
551  OPBINPUT* opbinput /**< OPB reading data */
552  )
553 {
554  assert(opbinput != NULL);
555 
556  if( *(opbinput->token) == ';')
557  return TRUE;
558 
559  return FALSE;
560 }
561 
562 /** returns whether the current token is a sign */
563 static
565  OPBINPUT* opbinput, /**< OPB reading data */
566  int* sign /**< pointer to update the sign */
567  )
568 {
569  assert(opbinput != NULL);
570  assert(sign != NULL);
571  assert(*sign == +1 || *sign == -1);
572 
573  if( strlen(opbinput->token) == 1 )
574  {
575  assert(opbinput->token[1] == '\0');
576 
577  if( *opbinput->token == '+' )
578  return TRUE;
579  else if( *opbinput->token == '-' )
580  {
581  *sign *= -1;
582  return TRUE;
583  }
584  }
585 
586  return FALSE;
587 }
588 
589 /** returns whether the current token is a value */
590 static
592  SCIP* scip, /**< SCIP data structure */
593  OPBINPUT* opbinput, /**< OPB reading data */
594  SCIP_Real* value /**< pointer to store the value (unchanged, if token is no value) */
595  )
596 {
597  assert(opbinput != NULL);
598  assert(value != NULL);
599 
600  if( strcasecmp(opbinput->token, "INFINITY") == 0 || strcasecmp(opbinput->token, "INF") == 0 )
601  {
602  *value = SCIPinfinity(scip);
603  return TRUE;
604  }
605  else
606  {
607  double val;
608  char* endptr;
609 
610  val = strtod(opbinput->token, &endptr);
611  if( endptr != opbinput->token && *endptr == '\0' )
612  {
613  *value = val;
614  if( strlen(opbinput->token) > 18 )
615  opbinput->nproblemcoeffs++;
616  return TRUE;
617  }
618  }
619 
620  return FALSE;
621 }
622 
623 /** returns whether the current token is an equation sense */
624 static
626  OPBINPUT* opbinput, /**< OPB reading data */
627  OPBSENSE* sense /**< pointer to store the equation sense, or NULL */
628  )
629 {
630  assert(opbinput != NULL);
631 
632  if( strcmp(opbinput->token, "<") == 0 )
633  {
634  if( sense != NULL )
635  *sense = OPB_SENSE_LE;
636  return TRUE;
637  }
638  else if( strcmp(opbinput->token, ">") == 0 )
639  {
640  if( sense != NULL )
641  *sense = OPB_SENSE_GE;
642  return TRUE;
643  }
644  else if( strcmp(opbinput->token, "=") == 0 )
645  {
646  if( sense != NULL )
647  *sense = OPB_SENSE_EQ;
648  return TRUE;
649  }
650 
651  return FALSE;
652 }
653 
654 /** returns whether the current token is a value */
655 static
657  SCIP* scip, /**< SCIP data structure */
658  OPBINPUT* opbinput /**< OPB reading data */
659  )
660 {
661  assert(scip != NULL);
662  assert(opbinput != NULL);
663 
664  if( strcmp(opbinput->token, "[") == 0 )
665  return TRUE;
666 
667  return FALSE;
668 }
669 
670 /** returns whether the current token is a value */
671 static
673  SCIP* scip, /**< SCIP data structure */
674  OPBINPUT* opbinput /**< OPB reading data */
675  )
676 {
677  assert(scip != NULL);
678  assert(opbinput != NULL);
679 
680  if( strcmp(opbinput->token, "]") == 0 )
681  return TRUE;
682 
683  return FALSE;
684 }
685 
686 /** create binary variable with given name */
687 static
689  SCIP* scip, /**< SCIP data structure */
690  SCIP_VAR** var, /**< pointer to store the variable */
691  char* name /**< name for the variable */
692  )
693 {
694  SCIP_VAR* newvar;
695  SCIP_Bool dynamiccols;
696  SCIP_Bool initial;
697  SCIP_Bool removable;
698 
699  SCIP_CALL( SCIPgetBoolParam(scip, "reading/dynamiccols", &dynamiccols) );
700  initial = !dynamiccols;
701  removable = dynamiccols;
702 
703  /* create new variable of the given name */
704  SCIPdebugMsg(scip, "creating new variable: <%s>\n", name);
705 
706  SCIP_CALL( SCIPcreateVar(scip, &newvar, name, 0.0, 1.0, 0.0, SCIP_VARTYPE_BINARY,
707  initial, removable, NULL, NULL, NULL, NULL, NULL) );
708  SCIP_CALL( SCIPaddVar(scip, newvar) );
709  *var = newvar;
710 
711  /* because the variable was added to the problem, it is captured by SCIP and we
712  * can safely release it right now without making the returned *var invalid */
713  SCIP_CALL( SCIPreleaseVar(scip, &newvar) );
714 
715  return SCIP_OKAY;
716 }
717 
718 /** returns the variable with the given name, or creates a new variable if it does not exist */
719 static
721  SCIP* scip, /**< SCIP data structure */
722  OPBINPUT* opbinput, /**< OPB reading data */
723  SCIP_VAR*** vars, /**< pointer to store the variables */
724  int* nvars, /**< pointer to store the number of variables */
725  int* varssize /**< pointer to store the varsize, if changed (should already be initialized) */
726  )
727 {
728  SCIP_Bool negated;
729  char* name;
730 
731  assert(scip != NULL);
732  assert(opbinput != NULL);
733  assert(vars != NULL);
734  assert(nvars != NULL);
735  assert(varssize != NULL);
736  assert(*varssize >= 0);
737 
738  *nvars = 0;
739 
740  name = opbinput->token;
741  assert(name != NULL);
742 
743  /* parse AND terms */
744  while(!isdigit((unsigned char) *name ) && !isTokenChar(*name) && !opbinput->haserror )
745  {
746  SCIP_VAR* var;
747 
748  negated = FALSE;
749  if( *name == '~' )
750  {
751  negated = TRUE;
752  ++name;
753  }
754 
755  var = SCIPfindVar(scip, name);
756  if( var == NULL )
757  {
758  SCIP_CALL( createVariable(scip, &var, name) );
759  }
760 
761  if( negated )
762  {
763  SCIP_VAR* negvar;
764  SCIP_CALL( SCIPgetNegatedVar(scip, var, &negvar) );
765 
766  var = negvar;
767  }
768 
769  /* reallocated memory */
770  if( *nvars == *varssize )
771  {
772  *varssize = SCIPcalcMemGrowSize(scip, *varssize + 1);
773  SCIP_CALL( SCIPreallocBufferArray(scip, vars, *varssize) );
774  }
775 
776  (*vars)[*nvars] = var;
777  ++(*nvars);
778 
779  if( !getNextToken(scip, opbinput) )
780  opbinput->haserror = TRUE;
781 
782  name = opbinput->token;
783  }
784 
785  /* check if we found at least on variable */
786  if( *nvars == 0 )
787  syntaxError(scip, opbinput, "expected a variable name");
788 
789  pushToken(opbinput);
790 
791  return SCIP_OKAY;
792 }
793 
794 /** reads an objective or constraint with name and coefficients */
795 static
797  SCIP*const scip, /**< SCIP data structure */
798  OPBINPUT*const opbinput, /**< OPB reading data */
799  char*const name, /**< pointer to store the name of the line; must be at least of size
800  * OPB_MAX_LINELEN */
801  SCIP_VAR*** linvars, /**< pointer to store the array with linear variables (must be freed by caller) */
802  SCIP_Real** lincoefs, /**< pointer to store the array with linear coefficients (must be freed by caller) */
803  int*const nlincoefs, /**< pointer to store the number of linear coefficients */
804  SCIP_VAR**** terms, /**< pointer to store the array with nonlinear variables (must be freed by caller) */
805  SCIP_Real** termcoefs, /**< pointer to store the array with nonlinear coefficients (must be freed by caller) */
806  int** ntermvars, /**< pointer to store the number of nonlinear variables in the terms (must be freed by caller) */
807  int*const ntermcoefs, /**< pointer to store the number of nonlinear coefficients */
808  SCIP_Bool*const newsection, /**< pointer to store whether a new section was encountered */
809  SCIP_Bool*const isNonlinear, /**< pointer to store if we have a nonlinear constraint */
810  SCIP_Bool*const issoftcons, /**< pointer to store whether it is a soft constraint (for wbo files) */
811  SCIP_Real*const weight /**< pointer to store the weight of the soft constraint */
812  )
813 {
814  SCIP_VAR** tmpvars;
815  SCIP_Real* tmpcoefs;
816  SCIP_Bool havesign;
817  SCIP_Bool havevalue;
818  SCIP_Bool haveweightstart;
819  SCIP_Bool haveweightend;
820  SCIP_Real coef;
821  int coefsign;
822  int lincoefssize;
823  int termcoefssize;
824  int tmpvarssize;
825  int ntmpcoefs;
826  int ntmpvars;
827 
828  assert(opbinput != NULL);
829  assert(name != NULL);
830  assert(linvars != NULL);
831  assert(lincoefs != NULL);
832  assert(nlincoefs != NULL);
833  assert(terms != NULL);
834  assert(termcoefs != NULL);
835  assert(ntermvars != NULL);
836  assert(ntermcoefs != NULL);
837  assert(newsection != NULL);
838 
839  *linvars = NULL;
840  *lincoefs = NULL;
841  *terms = NULL;
842  *termcoefs = NULL;
843  *ntermvars = NULL;
844  *name = '\0';
845  *nlincoefs = 0;
846  *ntermcoefs = 0;
847  *newsection = FALSE;
848  *isNonlinear = FALSE;
849  *issoftcons = FALSE;
850 
851  SCIPdebugMsg(scip, "read coefficients\n");
852 
853  /* read the first token, which may be the name of the line */
854  if( getNextToken(scip, opbinput) )
855  {
856  /* remember the token in the token buffer */
857  swapTokenBuffer(opbinput);
858 
859  /* get the next token and check, whether it is a colon */
860  if( getNextToken(scip, opbinput) )
861  {
862  if( strcmp(opbinput->token, ":") == 0 )
863  {
864  /* the second token was a colon ':' the first token is a constraint name */
865  (void)SCIPmemccpy(name, opbinput->tokenbuf, '\0', SCIP_MAXSTRLEN);
866 
867  name[SCIP_MAXSTRLEN-1] = '\0';
868  SCIPdebugMsg(scip, "(line %d) read constraint name: '%s'\n", opbinput->linenumber, name);
869 
870  /* all but the first coefficient need a sign */
871  if( strcmp(name, "soft") == 0 && (SCIPgetNVars(scip) > 0 || SCIPgetNConss(scip) > 0) )
872  {
873  syntaxError(scip, opbinput, "Soft top cost line needs to be the first non-comment line, and without any objective function.\n");
874  return SCIP_OKAY;
875  }
876  }
877  else
878  {
879  /* the second token was no colon: push the tokens back onto the token stack and parse them as coefficients */
880  SCIPdebugMsg(scip, "(line %d) constraint has no name\n", opbinput->linenumber);
881  pushToken(opbinput);
882  pushBufferToken(opbinput);
883  }
884  }
885  else
886  {
887  /* there was only one token left: push it back onto the token stack and parse it as coefficient */
888  pushBufferToken(opbinput);
889  }
890  }
891  else
892  {
893  assert(SCIPfeof( opbinput->file ) );
894  opbinput->eof = TRUE;
895  return SCIP_OKAY;
896  }
897 
898  /* initialize buffers for storing the coefficients */
899  lincoefssize = OPB_INIT_COEFSSIZE;
900  termcoefssize = OPB_INIT_COEFSSIZE;
901  tmpvarssize = OPB_INIT_COEFSSIZE;
902  SCIP_CALL( SCIPallocBufferArray(scip, linvars, lincoefssize) );
903  SCIP_CALL( SCIPallocBufferArray(scip, lincoefs, lincoefssize) );
904  SCIP_CALL( SCIPallocBufferArray(scip, terms, termcoefssize) );
905  SCIP_CALL( SCIPallocBufferArray(scip, termcoefs, termcoefssize) );
906  SCIP_CALL( SCIPallocBufferArray(scip, ntermvars, termcoefssize) );
907  SCIP_CALL( SCIPallocBufferArray(scip, &tmpvars, tmpvarssize) );
908  SCIP_CALL( SCIPallocBufferArray(scip, &tmpcoefs, tmpvarssize) );
909 
910  /* read the coefficients */
911  coefsign = +1;
912  coef = 1.0;
913  havesign = FALSE;
914  havevalue = FALSE;
915  haveweightstart = FALSE;
916  haveweightend = FALSE;
917  ntmpcoefs = 0;
918  ntmpvars = 0;
919  while( getNextToken(scip, opbinput) && !hasError(opbinput) )
920  {
921  if( isEndLine(opbinput) )
922  {
923  *newsection = TRUE;
924  goto TERMINATE;
925  }
926 
927  /* check if we reached an equation sense */
928  if( isSense(opbinput, NULL) )
929  {
930  /* put the sense back onto the token stack */
931  pushToken(opbinput);
932  goto TERMINATE;
933  }
934 
935  /* check if we read a sign */
936  if( isSign(opbinput, &coefsign) )
937  {
938  SCIPdebugMsg(scip, "(line %d) read coefficient sign: %+d\n", opbinput->linenumber, coefsign);
939  havesign = TRUE;
940  continue;
941  }
942 
943  /* check if we read a value */
944  if( isValue(scip, opbinput, &coef) )
945  {
946  /* all but the first coefficient need a sign */
947  if( (*nlincoefs > 0 || *ntermcoefs > 0 || ntmpcoefs > 0) && !havesign )
948  {
949  syntaxError(scip, opbinput, "expected sign ('+' or '-') or sense ('<' or '>')");
950  goto TERMINATE;
951  }
952 
953  SCIPdebugMsg(scip, "(line %d) read coefficient value: %g with sign %+d\n", opbinput->linenumber, coef, coefsign);
954  if( havevalue )
955  {
956  syntaxError(scip, opbinput, "two consecutive values");
957  goto TERMINATE;
958  }
959  havevalue = TRUE;
960 
961  /* if we read a wbo file, the first line should be something like "soft: <weight>;", where weight is a value or nothing */
962  if( strcmp(name, "soft") == 0 )
963  {
964  assert(ntmpcoefs == 0);
965 
966  tmpcoefs[ntmpcoefs] = coefsign * coef;
967  ++ntmpcoefs;
968  }
969 
970  continue;
971  }
972 
973  /* check if we are reading a soft constraint line, it start with "[<weight>]", where weight is a value */
974  if( *nlincoefs == 0 && *ntermcoefs == 0 && ntmpcoefs == 0 && !havesign && !havevalue && strcmp(name, "soft") != 0 && isStartingSoftConstraintWeight(scip, opbinput) )
975  {
976  if( !opbinput->wbo )
977  {
978  SCIPwarningMessage(scip, "Found in line %d a soft constraint, without having read a starting top-cost line.\n", opbinput->linenumber);
979  }
980  haveweightstart = TRUE;
981 
982  continue;
983  }
984  if( *nlincoefs == 0 && *ntermcoefs == 0 && ntmpcoefs == 0 && havevalue && haveweightstart && isEndingSoftConstraintWeight(scip, opbinput) )
985  {
986  *weight = coefsign * coef;
987  SCIPdebugMsg(scip, "(line %d) found soft constraint weight: %g\n", opbinput->linenumber, *weight);
988 
989  coefsign = +1;
990  havesign = FALSE;
991  havevalue = FALSE;
992  haveweightend = TRUE;
993  *issoftcons = TRUE;
994 
995  continue;
996  }
997 
998  /* if we read a '[' we should already read a ']', which indicates that we read a soft constraint,
999  * we have a parsing error */
1000  if( haveweightstart != haveweightend )
1001  {
1002  syntaxError(scip, opbinput, "Wrong soft constraint.");
1003  goto TERMINATE;
1004  }
1005 
1006  /* if we read the first non-comment line of a wbo file we should never be here */
1007  if( strcmp(name, "soft") == 0 )
1008  {
1009  syntaxError(scip, opbinput, "Wrong soft top cost line.");
1010  goto TERMINATE;
1011  }
1012 
1013  /* the token is a variable name: get the corresponding variables (or create a new ones) */
1014  SCIP_CALL( getVariableOrTerm(scip, opbinput, &tmpvars, &ntmpvars, &tmpvarssize) );
1015 
1016  if( ntmpvars > 1 )
1017  {
1018  /* insert non-linear term */
1019  *isNonlinear = TRUE;
1020 
1021  SCIPdebugMsg(scip, "(line %d) found linear term: %+g", opbinput->linenumber, coefsign * coef);
1022 #ifndef NDEBUG
1023  {
1024  int v;
1025  for( v = 0; v < ntmpvars; ++v )
1026  {
1027  SCIPdebugMsgPrint(scip, " %s * ", SCIPvarGetName(tmpvars[v]));
1028  }
1029  SCIPdebugMsgPrint(scip, "\n");
1030  }
1031 #endif
1032  if( !SCIPisZero(scip, coef) )
1033  {
1034  assert(*ntermcoefs <= termcoefssize);
1035  /* resize the terms, ntermvars, and termcoefs array if needed */
1036  if( *ntermcoefs == termcoefssize )
1037  {
1038  termcoefssize = SCIPcalcMemGrowSize(scip, termcoefssize + 1);
1039  SCIP_CALL( SCIPreallocBufferArray(scip, terms, termcoefssize) );
1040  SCIP_CALL( SCIPreallocBufferArray(scip, termcoefs, termcoefssize) );
1041  SCIP_CALL( SCIPreallocBufferArray(scip, ntermvars, termcoefssize) );
1042  }
1043  assert(*ntermcoefs < termcoefssize);
1044 
1045  /* get memory for the last term */
1046  SCIP_CALL( SCIPallocBufferArray(scip, &((*terms)[*ntermcoefs]), ntmpvars) ); /*lint !e866 */
1047 
1048  /* set the number of variable in this term */
1049  (*ntermvars)[*ntermcoefs] = ntmpvars;
1050 
1051  /* add all variables */
1052  for( --ntmpvars; ntmpvars >= 0; --ntmpvars )
1053  {
1054  (*terms)[*ntermcoefs][ntmpvars] = tmpvars[ntmpvars];
1055  }
1056  /* add coefficient */
1057  (*termcoefs)[*ntermcoefs] = coefsign * coef;
1058 
1059  /***********************/
1060  if( !SCIPisIntegral(scip, (*termcoefs)[*ntermcoefs]) )
1061  {
1062  SCIPwarningMessage(scip, "coefficient %g in line %d not integral.\n", (*termcoefs)[*ntermcoefs], opbinput->linenumber);
1063  }
1064 
1065  ++(*ntermcoefs);
1066  }
1067 
1068  /* reset the flags and coefficient value for the next coefficient */
1069  coefsign = +1;
1070  coef = 1.0;
1071  havesign = FALSE;
1072  havevalue = FALSE;
1073  ntmpvars = 0;
1074  }
1075  else
1076  {
1077  assert(ntmpvars == 1);
1078  /* insert linear term */
1079  SCIPdebugMsg(scip, "(line %d) found linear term: %+g<%s>\n", opbinput->linenumber, coefsign * coef, SCIPvarGetName(tmpvars[0]));
1080  if( !SCIPisZero(scip, coef) )
1081  {
1082  assert(*nlincoefs <= lincoefssize);
1083  /* resize the vars and coefs array if needed */
1084  if( *nlincoefs >= lincoefssize )
1085  {
1086  lincoefssize = SCIPcalcMemGrowSize(scip, lincoefssize + 1);
1087  SCIP_CALL( SCIPreallocBufferArray(scip, linvars, lincoefssize) );
1088  SCIP_CALL( SCIPreallocBufferArray(scip, lincoefs, lincoefssize) );
1089  }
1090  assert(*nlincoefs < lincoefssize);
1091 
1092  /* add coefficient */
1093  (*linvars)[*nlincoefs] = tmpvars[0];
1094  (*lincoefs)[*nlincoefs] = coefsign * coef;
1095 
1096  /***********************/
1097  if( !SCIPisIntegral(scip, (*lincoefs)[*nlincoefs]) )
1098  {
1099  SCIPwarningMessage(scip, "coefficient %g in line %d not integral.\n", (*lincoefs)[*nlincoefs], opbinput->linenumber);
1100  }
1101 
1102  ++(*nlincoefs);
1103  }
1104 
1105  /* reset the flags and coefficient value for the next coefficient */
1106  coefsign = +1;
1107  coef = 1.0;
1108  havesign = FALSE;
1109  havevalue = FALSE;
1110  ntmpvars = 0;
1111  }
1112  }
1113 
1114  TERMINATE:
1115  if( !opbinput->haserror )
1116  {
1117  /* all variables should be in the right arrays */
1118  assert(ntmpvars == 0);
1119  /* the following is only the case if we read topcost's of a wbo file, we need to move this topcost value to the
1120  * right array */
1121  if( ntmpcoefs > 0 )
1122  {
1123  /* maximal one topcost value is possible */
1124  assert(ntmpcoefs == 1);
1125  /* no other coefficient should be found here */
1126  assert(*nlincoefs == 0 && *ntermcoefs == 0);
1127 
1128  /* copy value */
1129  (*lincoefs)[*nlincoefs] = tmpcoefs[0];
1130 
1131  /***********************/
1132  if( !SCIPisIntegral(scip, (*lincoefs)[*nlincoefs]) )
1133  {
1134  SCIPwarningMessage(scip, "topcost not integral.\n");
1135  }
1136 
1137  *nlincoefs = 1;
1138  }
1139  }
1140  /* clear memory */
1141  SCIPfreeBufferArray(scip, &tmpcoefs);
1142  SCIPfreeBufferArray(scip, &tmpvars);
1143 
1144  return SCIP_OKAY;
1145 }
1146 
1147 /** set the objective section */
1148 static
1150  SCIP*const scip, /**< SCIP data structure */
1151  OPBINPUT*const opbinput, /**< OPB reading data */
1152  const char* sense, /**< objective sense */
1153  SCIP_VAR**const linvars, /**< array of linear variables */
1154  SCIP_Real*const coefs, /**< array of objective values for linear variables */
1155  int const ncoefs, /**< number of coefficients for linear part */
1156  SCIP_VAR***const terms, /**< array with nonlinear variables */
1157  SCIP_Real*const termcoefs, /**< array of objective values for nonlinear variables */
1158  int*const ntermvars, /**< number of nonlinear variables in the terms */
1159  int const ntermcoefs /**< number of nonlinear coefficients */
1160  )
1161 {
1162  assert(scip != NULL);
1163  assert(opbinput != NULL);
1164  assert(isEndLine(opbinput));
1165  assert(ncoefs == 0 || (linvars != NULL && coefs != NULL));
1166  assert(ntermcoefs == 0 || (terms != NULL && ntermvars != NULL && termcoefs != NULL));
1167 
1168  if( !hasError(opbinput) )
1169  {
1170  SCIP_VAR* var;
1171  int v;
1172  char name[SCIP_MAXSTRLEN];
1173 
1174  if( strcmp(sense, "max" ) == 0 )
1175  opbinput->objsense = SCIP_OBJSENSE_MAXIMIZE;
1176 
1177  /* @todo: what todo with non-linear objectives, maybe create the necessary and-constraints and add the arising linear
1178  * objective (with and-resultants) or add a integer variable to this constraint and put only this variable in the
1179  * objective, for this we need to expand the pseudo-boolean constraints to handle integer variables
1180  *
1181  * integer variant is not implemented
1182  */
1183  if( ntermcoefs > 0 )
1184  {
1185 #if (LINEAROBJECTIVE == TRUE)
1186  /* all non-linear parts are created as and-constraints, even if the same non-linear part was already part of the objective function */
1187 
1188  SCIP_VAR** vars;
1189  int nvars;
1190  int t;
1191  SCIP_CONS* andcons;
1192 
1193  for( t = 0; t < ntermcoefs; ++t )
1194  {
1195  vars = terms[t];
1196  nvars = ntermvars[t];
1197  assert(vars != NULL);
1198  assert(nvars > 1);
1199 
1200  /* create auxiliary variable */
1201  (void)SCIPsnprintf(name, SCIP_MAXSTRLEN, ARTIFICIALVARNAMEPREFIX"obj_%d", t);
1202  SCIP_CALL( SCIPcreateVar(scip, &var, name, 0.0, 1.0, termcoefs[t], SCIP_VARTYPE_BINARY,
1203  TRUE, TRUE, NULL, NULL, NULL, NULL, NULL) );
1204 
1205  /* @todo: check if it is better to change the branching priority for the artificial variables */
1206 #if 1
1207  /* change branching priority of artificial variable to -1 */
1208  SCIP_CALL( SCIPchgVarBranchPriority(scip, var, -1) );
1209 #endif
1210 
1211  /* add auxiliary variable to the problem */
1212  SCIP_CALL( SCIPaddVar(scip, var) );
1213 
1214 #ifdef SCIP_DEBUG_SOLUTION
1215  if( SCIPdebugIsMainscip(scip) )
1216  {
1217  SCIP_Real val;
1218 
1219  for( v = nvars - 1; v >= 0; --v )
1220  {
1221  SCIP_CALL( SCIPdebugGetSolVal(scip, vars[v], &val) );
1222  assert(SCIPisFeasZero(scip, val) || SCIPisFeasEQ(scip, val, 1.0));
1223 
1224  if( val < 0.5 )
1225  break;
1226  }
1227  SCIP_CALL( SCIPdebugAddSolVal(scip, var, (val < 0.5) ? 0.0 : 1.0) );
1228  }
1229 #endif
1230 
1231  /* @todo: check whether all constraint creation flags are the best option */
1232  /* create and-constraint */
1233  (void)SCIPsnprintf(name, SCIP_MAXSTRLEN, "obj_andcons_%d", t);
1234  SCIP_CALL( SCIPcreateConsAnd(scip, &andcons, name, var, nvars, vars,
1235  TRUE, TRUE, TRUE, TRUE, TRUE,
1236  FALSE, FALSE, FALSE, FALSE, FALSE) );
1237  SCIP_CALL( SCIPaddCons(scip, andcons) );
1238  SCIPdebugPrintCons(scip, andcons, NULL);
1239  SCIP_CALL( SCIPreleaseCons(scip, &andcons) );
1240 
1241  SCIP_CALL( SCIPreleaseVar(scip, &var) );
1242  }
1243 #else /* now the integer variant */
1244  SCIP_CONS* pseudocons;
1245  SCIP_Real lb;
1246  SCIP_Real ub;
1247 
1248  lb = 0.0;
1249  ub = 0.0;
1250 
1251  /* add all non linear coefficients up */
1252  for( v = 0; v < ntermcoefs; ++v )
1253  {
1254  if( termcoefs[v] < 0 )
1255  lb += termcoefs[v];
1256  else
1257  ub += termcoefs[v];
1258  }
1259  /* add all linear coefficients up */
1260  for( v = 0; v < ncoefs; ++v )
1261  {
1262  if( coefs[v] < 0 )
1263  lb += coefs[v];
1264  else
1265  ub += coefs[v];
1266  }
1267  assert(lb < ub);
1268 
1269  /* create auxiliary variable */
1270  (void)SCIPsnprintf(name, SCIP_MAXSTRLEN, "artificial_int_obj");
1271  SCIP_CALL( SCIPcreateVar(scip, &var, name, lb, ub, 1.0, SCIP_VARTYPE_INTEGER,
1272  TRUE, TRUE, NULL, NULL, NULL, NULL, NULL) );
1273 
1274  /* @todo: check if it is better to change the branching priority for the artificial variables */
1275 #if 1
1276  /* change branching priority of artificial variable to -1 */
1277  SCIP_CALL( SCIPchgVarBranchPriority(scip, var, -1) );
1278 #endif
1279  /* add auxiliary variable to the problem */
1280  SCIP_CALL( SCIPaddVar(scip, var) );
1281 
1282 #ifdef SCIP_DEBUG_SOLUTION
1283  if( SCIPdebugIsMainscip(scip) )
1284  {
1285  SCIP_Real artval = 0.0;
1286  SCIP_Real val;
1287 
1288  for( t = 0; t < ntermcoefs; ++t )
1289  {
1290  vars = terms[t];
1291  nvars = ntermvars[t];
1292  assert(vars != NULL);
1293  assert(nvars > 1);
1294 
1295  for( v = nvars - 1; v >= 0; --v )
1296  {
1297  SCIP_CALL( SCIPdebugGetSolVal(scip, vars[v], &val) );
1298  assert(SCIPisFeasZero(scip, val) || SCIPisFeasEQ(scip, val, 1.0));
1299 
1300  if( val < 0.5 )
1301  break;
1302  }
1303 
1304  artval += (((val < 0.5) ? 0.0 : 1.0) * termcoefs[t]);
1305  }
1306  assert(SCIPisFeasLE(scip, lb, artval) && SCIPisFeasGE(scip, ub, artval));
1307 
1308  SCIP_CALL( SCIPdebugAddSolVal(scip, var, artval) );
1309  }
1310 #endif
1311 
1312 
1313  /* create artificial objection function constraint containing the artificial integer variable */
1314  (void)SCIPsnprintf(name, SCIP_MAXSTRLEN, "artificial_obj_cons");
1315  SCIP_CALL( SCIPcreateConsPseudoboolean(scip, &pseudocons, name, linvars, ncoefs, coefs, terms, ntermcoefs,
1316  ntermvars, termcoefs, NULL, 0.0, FALSE, var, 0.0, 0.0,
1317  TRUE, TRUE, TRUE, TRUE, TRUE,
1318  FALSE, FALSE, FALSE, FALSE, FALSE) );
1319 
1320  SCIP_CALL( SCIPaddCons(scip, pseudocons) );
1321  SCIPdebugPrintCons(scip, pseudocons, NULL);
1322  SCIP_CALL( SCIPreleaseCons(scip, &pseudocons) );
1323 
1324  SCIP_CALL( SCIPreleaseVar(scip, &var) );
1325 
1326  return SCIP_OKAY;
1327 #endif
1328  }
1329  /* set the objective values */
1330  for( v = 0; v < ncoefs; ++v )
1331  {
1332  if( SCIPvarIsNegated(linvars[v]) )
1333  {
1334  SCIP_VAR* negvar = SCIPvarGetNegationVar(linvars[v]);
1335 
1336  SCIP_CALL( SCIPaddOrigObjoffset(scip, coefs[v]) );
1337  SCIP_CALL( SCIPchgVarObj(scip, negvar, SCIPvarGetObj(negvar) - coefs[v]) );
1338  }
1339  else
1340  {
1341  SCIP_CALL( SCIPchgVarObj(scip, linvars[v], SCIPvarGetObj(linvars[v]) + coefs[v]) );
1342  }
1343  }
1344  }
1345 
1346  return SCIP_OKAY;
1347 }
1348 
1349 /** reads the constraints section */
1350 static
1352  SCIP* scip, /**< SCIP data structure */
1353  OPBINPUT* opbinput, /**< OPB reading data */
1354  int* nNonlinearConss /**< pointer to store number of nonlinear constraints */
1355  )
1356 {
1357  char name[OPB_MAX_LINELEN];
1358  SCIP_CONS* cons;
1359  SCIP_VAR** linvars;
1360  SCIP_Real* lincoefs;
1361  int nlincoefs;
1362  SCIP_VAR*** terms;
1363  SCIP_Real* termcoefs;
1364  int* ntermvars;
1365  int ntermcoefs;
1366  OPBSENSE sense;
1367  SCIP_RETCODE retcode;
1368  SCIP_Real sidevalue;
1369  SCIP_Real lhs;
1370  SCIP_Real rhs;
1371  SCIP_Bool newsection;
1372  SCIP_Bool initialconss;
1373  SCIP_Bool dynamicconss;
1374  SCIP_Bool dynamicrows;
1375  SCIP_Bool initial;
1376  SCIP_Bool separate;
1377  SCIP_Bool enforce;
1378  SCIP_Bool check;
1379  SCIP_Bool propagate;
1380  SCIP_Bool local;
1381  SCIP_Bool modifiable;
1382  SCIP_Bool dynamic;
1383  SCIP_Bool removable;
1384  SCIP_Bool isNonlinear;
1385  int sidesign;
1386  SCIP_Bool issoftcons;
1387  SCIP_Real weight;
1388  SCIP_VAR* indvar;
1389  char indname[SCIP_MAXSTRLEN];
1390  int t;
1391 
1392  assert(scip != NULL);
1393  assert(opbinput != NULL);
1394  assert(nNonlinearConss != NULL);
1395 
1396  weight = -SCIPinfinity(scip);
1397  retcode = SCIP_OKAY;
1398 
1399  /* read the objective coefficients */
1400  SCIP_CALL( readCoefficients(scip, opbinput, name, &linvars, &lincoefs, &nlincoefs, &terms, &termcoefs, &ntermvars, &ntermcoefs, &newsection, &isNonlinear, &issoftcons, &weight) );
1401 
1402  if( hasError(opbinput) || opbinput->eof )
1403  goto TERMINATE;
1404  if( newsection )
1405  {
1406  if( strcmp(name, "min") == 0 || strcmp(name, "max") == 0 )
1407  {
1408  if( opbinput->wbo )
1409  {
1410  syntaxError(scip, opbinput, "Cannot have an objective function when having soft constraints.\n");
1411  goto TERMINATE;
1412  }
1413 
1414  /* set objective function */
1415  SCIP_CALL( setObjective(scip, opbinput, name, linvars, lincoefs, nlincoefs, terms, termcoefs, ntermvars, ntermcoefs) );
1416  }
1417  else if( strcmp(name, "soft") == 0 )
1418  {
1419  /* we have a "weighted boolean optimization"-file(wbo) */
1420  opbinput->wbo = TRUE;
1421  if( nlincoefs == 0 )
1422  opbinput->topcost = SCIPinfinity(scip);
1423  else
1424  {
1425  assert(nlincoefs == 1);
1426  opbinput->topcost = lincoefs[0];
1427  }
1428  SCIPdebugMsg(scip, "Weighted Boolean Optimization problem has topcost of %g\n", opbinput->topcost);
1429  }
1430  else if( nlincoefs > 0 )
1431  syntaxError(scip, opbinput, "expected constraint sense '=' or '>='");
1432  goto TERMINATE;
1433  }
1434 
1435  /* read the constraint sense */
1436  if( !getNextToken(scip, opbinput) || !isSense(opbinput, &sense) )
1437  {
1438  syntaxError(scip, opbinput, "expected constraint sense '=' or '>='");
1439  goto TERMINATE;
1440  }
1441 
1442  /* read the right hand side */
1443  sidesign = +1;
1444  if( !getNextToken(scip, opbinput) )
1445  {
1446  syntaxError(scip, opbinput, "missing right hand side");
1447  goto TERMINATE;
1448  }
1449  if( isSign(opbinput, &sidesign) )
1450  {
1451  if( !getNextToken(scip, opbinput) )
1452  {
1453  syntaxError(scip, opbinput, "missing value of right hand side");
1454  goto TERMINATE;
1455  }
1456  }
1457  if( !isValue(scip, opbinput, &sidevalue) )
1458  {
1459  syntaxError(scip, opbinput, "expected value as right hand side");
1460  goto TERMINATE;
1461  }
1462  sidevalue *= sidesign;
1463 
1464  /* check if we reached the line end */
1465  if( !getNextToken(scip, opbinput) || !isEndLine(opbinput) )
1466  {
1467  syntaxError(scip, opbinput, "expected endline character ';'");
1468  goto TERMINATE;
1469  }
1470 
1471  /* assign the left and right hand side, depending on the constraint sense */
1472  switch( sense )
1473  {
1474  case OPB_SENSE_GE:
1475  lhs = sidevalue;
1476  rhs = SCIPinfinity(scip);
1477  break;
1478  case OPB_SENSE_LE:
1479  lhs = -SCIPinfinity(scip);
1480  rhs = sidevalue;
1481  break;
1482  case OPB_SENSE_EQ:
1483  lhs = sidevalue;
1484  rhs = sidevalue;
1485  break;
1486  case OPB_SENSE_NOTHING:
1487  default:
1488  SCIPerrorMessage("invalid constraint sense <%d>\n", sense);
1489  return SCIP_INVALIDDATA;
1490  }
1491 
1492  /* create and add the linear constraint */
1493  SCIP_CALL( SCIPgetBoolParam(scip, "reading/initialconss", &initialconss) );
1494  SCIP_CALL( SCIPgetBoolParam(scip, "reading/dynamicrows", &dynamicrows) );
1495  SCIP_CALL( SCIPgetBoolParam(scip, "reading/" READER_NAME "/dynamicconss", &dynamicconss) );
1496 
1497  initial = initialconss;
1498  separate = TRUE;
1499  enforce = TRUE;
1500  check = TRUE;
1501  propagate = TRUE;
1502  local = FALSE;
1503  modifiable = FALSE;
1504  dynamic = FALSE;/*dynamicconss;*/
1505  removable = dynamicrows;
1506 
1507  /* create corresponding constraint */
1508  if( issoftcons )
1509  {
1510  (void) SCIPsnprintf(indname, SCIP_MAXSTRLEN, INDICATORVARNAME"%d", opbinput->nindvars);
1511  ++(opbinput->nindvars);
1512  SCIP_CALL( createVariable(scip, &indvar, indname) );
1513 
1514  assert(!SCIPisInfinity(scip, -weight));
1515  SCIP_CALL( SCIPchgVarObj(scip, indvar, weight) );
1516  }
1517  else
1518  indvar = NULL;
1519 
1520  if( ntermcoefs > 0 || issoftcons )
1521  {
1522 #if GENCONSNAMES == TRUE
1523  (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "pseudoboolean%d", opbinput->consnumber);
1524  ++(opbinput->consnumber);
1525 #else
1526  (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "pseudoboolean");
1527 #endif
1528  retcode = SCIPcreateConsPseudoboolean(scip, &cons, name, linvars, nlincoefs, lincoefs, terms, ntermcoefs,
1529  ntermvars, termcoefs, indvar, weight, issoftcons, NULL, lhs, rhs,
1530  initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, FALSE);
1531  if( retcode != SCIP_OKAY )
1532  goto TERMINATE;
1533  }
1534  else
1535  {
1536 #if GENCONSNAMES == TRUE
1537  (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "linear%d", opbinput->consnumber);
1538  ++(opbinput->consnumber);
1539 #else
1540  (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "linear");
1541 #endif
1542  retcode = SCIPcreateConsLinear(scip, &cons, name, nlincoefs, linvars, lincoefs, lhs, rhs,
1543  initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, FALSE);
1544  if( retcode != SCIP_OKAY )
1545  goto TERMINATE;
1546  }
1547 
1548  SCIP_CALL( SCIPaddCons(scip, cons) );
1549  SCIPdebugMsg(scip, "(line %d) created constraint: ", opbinput->linenumber);
1550  SCIPdebugPrintCons(scip, cons, NULL);
1551  SCIP_CALL( SCIPreleaseCons(scip, &cons) );
1552 
1553  if( isNonlinear )
1554  ++(*nNonlinearConss);
1555 
1556  TERMINATE:
1557 
1558  /* free memory */
1559  for( t = ntermcoefs - 1; t >= 0; --t )
1560  SCIPfreeBufferArrayNull(scip, &(terms[t]));
1561 
1562  SCIPfreeBufferArrayNull(scip, &ntermvars);
1563  SCIPfreeBufferArrayNull(scip, &termcoefs);
1564  SCIPfreeBufferArrayNull(scip, &terms);
1565  SCIPfreeBufferArrayNull(scip, &lincoefs);
1566  SCIPfreeBufferArrayNull(scip, &linvars);
1567 
1568  SCIP_CALL( retcode );
1569 
1570  return SCIP_OKAY;
1571 }
1572 
1573 /** tries to read the first comment line which usually contains information about the max size of "and" products */
1574 static
1576  SCIP* scip, /**< SCIP data structure */
1577  OPBINPUT* opbinput, /**< OPB reading data */
1578  const char* filename /**< name of the input file */
1579  )
1580 {
1581  SCIP_Bool stop;
1582  char* commentstart;
1583  char* nproducts;
1584  int i;
1585 
1586  assert(scip != NULL);
1587  assert(opbinput != NULL);
1588 
1589  stop = FALSE;
1590  commentstart = NULL;
1591  nproducts = NULL;
1592 
1593  do
1594  {
1595  if( SCIPfgets(opbinput->linebuf, (int) sizeof(opbinput->linebuf), opbinput->file) == NULL )
1596  {
1597  assert(SCIPfeof( opbinput->file ) );
1598  break;
1599  }
1600 
1601  /* read characters after comment symbol */
1602  for( i = 0; commentchars[i] != '\0'; ++i )
1603  {
1604  commentstart = strchr(opbinput->linebuf, commentchars[i]);
1605 
1606  /* found a comment line */
1607  if( commentstart != NULL )
1608  {
1609  /* search for "#product= xyz" in comment line, where xyz represents the number of and constraints */
1610  nproducts = strstr(opbinput->linebuf, "#product= ");
1611  if( nproducts != NULL )
1612  {
1613  const char delimchars[] = " \t";
1614  char* pos;
1615 
1616  nproducts += strlen("#product= ");
1617 
1618  pos = strtok(nproducts, delimchars);
1619 
1620  if( pos != NULL )
1621  {
1622  SCIPdebugMsg(scip, "%d products supposed to be in file.\n", atoi(pos));
1623  }
1624 
1625  pos = strtok (NULL, delimchars);
1626 
1627  if( pos != NULL && strcmp(pos, "sizeproduct=") == 0 )
1628  {
1629  pos = strtok (NULL, delimchars);
1630  if( pos != NULL )
1631  {
1632  SCIPdebugMsg(scip, "sizeproducts = %d\n", atoi(pos));
1633  }
1634  }
1635 
1636  stop = TRUE;
1637  }
1638  break;
1639  }
1640  }
1641  }
1642  while(commentstart != NULL && !stop);
1643 
1644  opbinput->linebuf[0] = '\0';
1645 
1646 #if 0 /* following lines should be correct, but it seems that gzseek does not reset the position if standing at the end of a file */
1647  /* reset filereader pointer to the beginning */
1648  (void) SCIPfseek(opbinput->file, 0, SEEK_SET);
1649 #else
1650  SCIPfclose(opbinput->file);
1651  opbinput->file = SCIPfopen(filename, "r");
1652 #endif
1653 
1654  return SCIP_OKAY;
1655 }
1656 
1657 /** reads an OPB file */
1658 static
1660  SCIP* scip, /**< SCIP data structure */
1661  OPBINPUT* opbinput, /**< OPB reading data */
1662  const char* filename /**< name of the input file */
1663  )
1664 {
1665  int nNonlinearConss;
1666  int i;
1667 
1668  assert(scip != NULL);
1669  assert(opbinput != NULL);
1670 
1671  /* open file */
1672  opbinput->file = SCIPfopen(filename, "r");
1673  if( opbinput->file == NULL )
1674  {
1675  SCIPerrorMessage("cannot open file <%s> for reading\n", filename);
1676  SCIPprintSysError(filename);
1677  return SCIP_NOFILE;
1678  }
1679 
1680  /* tries to read the first comment line which usually contains information about the max size of "and" products */
1681  SCIP_CALL( getMaxAndConsDim(scip, opbinput, filename) );
1682 
1683  /* reading additional information about the number of and constraints in comments to avoid reallocating
1684  * "opbinput.andconss"
1685  */
1686  BMSclearMemoryArray(opbinput->linebuf, OPB_MAX_LINELEN);
1687 
1688  /* create problem */
1689  SCIP_CALL( SCIPcreateProb(scip, filename, NULL, NULL, NULL, NULL, NULL, NULL, NULL) );
1690 
1691  nNonlinearConss = 0;
1692 
1693  while( !SCIPfeof( opbinput->file ) && !hasError(opbinput) )
1694  {
1695  SCIP_CALL( readConstraints(scip, opbinput, &nNonlinearConss) );
1696  }
1697 
1698  /* if we read a wbo file we need to make sure that the top cost won't be exceeded */
1699  if( opbinput->wbo )
1700  {
1701  SCIP_VAR** topcostvars;
1702  SCIP_Real* topcosts;
1703  SCIP_VAR** vars;
1704  int nvars;
1705  int ntopcostvars;
1706  SCIP_Longint topcostrhs;
1707  SCIP_CONS* topcostcons;
1708 
1709  nvars = SCIPgetNVars(scip);
1710  vars = SCIPgetVars(scip);
1711  assert(nvars > 0 || vars != NULL);
1712 
1713  SCIP_CALL( SCIPallocBufferArray(scip, &topcostvars, nvars) );
1714  SCIP_CALL( SCIPallocBufferArray(scip, &topcosts, nvars) );
1715 
1716  ntopcostvars = 0;
1717  for( i = nvars - 1; i >= 0; --i )
1718  if( !SCIPisZero(scip, SCIPvarGetObj(vars[i])) )
1719  {
1720  topcostvars[ntopcostvars] = vars[i];
1721  topcosts[ntopcostvars] = SCIPvarGetObj(vars[i]);
1722  ++ntopcostvars;
1723  }
1724 
1725  if( SCIPisIntegral(scip, opbinput->topcost) )
1726  topcostrhs = (SCIP_Longint) SCIPfloor(scip, opbinput->topcost - 1);
1727  else
1728  topcostrhs = (SCIP_Longint) SCIPfloor(scip, opbinput->topcost);
1729 
1730  SCIP_CALL( SCIPcreateConsLinear(scip, &topcostcons, TOPCOSTCONSNAME, ntopcostvars, topcostvars, topcosts, -SCIPinfinity(scip),
1731  (SCIP_Real) topcostrhs, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE) );
1732  SCIP_CALL( SCIPaddCons(scip, topcostcons) );
1733  SCIPdebugPrintCons(scip, topcostcons, NULL);
1734  SCIP_CALL( SCIPreleaseCons(scip, &topcostcons) );
1735 
1736  SCIPfreeBufferArray(scip, &topcosts);
1737  SCIPfreeBufferArray(scip, &topcostvars);
1738  }
1739 
1740  /* close file */
1741  SCIPfclose(opbinput->file);
1742 
1743  return SCIP_OKAY;
1744 }
1745 
1746 
1747 /*
1748  * Local methods (for writing)
1749  */
1750 
1751 /** transforms given and constraint variables to the corresponding active or negated variables */
1752 static
1754  SCIP*const scip, /**< SCIP data structure */
1755  SCIP_VAR**const vars, /**< vars array to get active variables for */
1756  int const nvars, /**< pointer to number of variables and values in vars and vals array */
1757  SCIP_Bool const transformed /**< transformed constraint? */
1758  )
1759 {
1760  SCIP_Bool negated;
1761  int v;
1762 
1763  assert( scip != NULL );
1764  assert( vars != NULL );
1765  assert( nvars > 0 );
1766 
1767  if( transformed )
1768  {
1769  for( v = nvars - 1; v >= 0; --v )
1770  {
1771  /* gets a binary variable that is equal to the given binary variable, and that is either active, fixed, or
1772  * multi-aggregated, or the negated variable of an active, fixed, or multi-aggregated variable
1773  */
1774  SCIP_CALL( SCIPgetBinvarRepresentative( scip, vars[v], &vars[v], &negated) );
1775  }
1776  }
1777  else
1778  {
1779  SCIP_Real scalar;
1780  SCIP_Real constant;
1781 
1782  for( v = nvars - 1; v >= 0; --v )
1783  {
1784  scalar = 1.0;
1785  constant = 0.0;
1786 
1787  /* retransforms given variable, scalar and constant to the corresponding original variable, scalar and constant,
1788  * if possible; if the retransformation is impossible, NULL is returned as variable
1789  */
1790  SCIP_CALL( SCIPvarGetOrigvarSum(&vars[v], &scalar, &constant) );
1791 
1792  if( vars[v] == NULL )
1793  {
1794  SCIPdebugMsg(scip, "A variable couldn't retransformed to an original variable.\n");
1795  return SCIP_INVALIDDATA;
1796  }
1797  if( SCIPisEQ(scip, scalar, -1.0) && SCIPisEQ(scip, constant, 1.0) )
1798  {
1799  SCIP_CALL( SCIPgetNegatedVar(scip, vars[v], &vars[v]) );
1800  }
1801  else
1802  {
1803  if( !SCIPisEQ(scip, scalar, 1.0) || !SCIPisZero(scip, constant) )
1804  {
1805  SCIPdebugMsg(scip, "A variable couldn't retransformed to an original variable or a negated variable of an original variable (scalar = %g, constant = %g).\n", scalar, constant);
1806  return SCIP_INVALIDDATA;
1807  }
1808  }
1809  }
1810  }
1811 
1812  return SCIP_OKAY;
1813 }
1814 
1815 /** transforms given variables, scalars, and constant to the corresponding active variables, scalars, and constant */
1816 static
1818  SCIP* scip, /**< SCIP data structure */
1819  SCIP_VAR** vars, /**< vars array to get active variables for */
1820  SCIP_Real* scalars, /**< scalars a_1, ..., a_n in linear sum a_1*x_1 + ... + a_n*x_n + c */
1821  int* nvars, /**< pointer to number of variables and values in vars and vals array */
1822  SCIP_Real* constant, /**< pointer to constant c in linear sum a_1*x_1 + ... + a_n*x_n + c */
1823  SCIP_Bool transformed /**< transformed constraint? */
1824  )
1825 {
1826  int requiredsize;
1827  int v;
1828 
1829  assert(scip != NULL);
1830  assert(vars != NULL);
1831  assert(scalars != NULL);
1832  assert(nvars != NULL);
1833  assert(constant != NULL);
1834 
1835  if( transformed )
1836  {
1837  SCIP_CALL( SCIPgetProbvarLinearSum(scip, vars, scalars, nvars, *nvars, constant, &requiredsize, TRUE) );
1838 
1839  if( requiredsize > *nvars )
1840  {
1841  SCIP_CALL( SCIPreallocBufferArray(scip, &vars, requiredsize) );
1842  SCIP_CALL( SCIPreallocBufferArray(scip, &scalars, requiredsize) );
1843 
1844  SCIP_CALL( SCIPgetProbvarLinearSum(scip, vars, scalars, nvars, requiredsize, constant, &requiredsize, TRUE) );
1845  assert( requiredsize <= *nvars );
1846  }
1847  }
1848  else
1849  for( v = 0; v < *nvars; ++v )
1850  {
1851  SCIP_CALL( SCIPvarGetOrigvarSum(&vars[v], &scalars[v], constant) );
1852 
1853  if( vars[v] == NULL )
1854  return SCIP_INVALIDDATA;
1855  }
1856 
1857  return SCIP_OKAY;
1858 }
1859 
1860 /* computes all and-resultants and their corresponding constraint variables */
1861 static
1863  SCIP*const scip, /**< SCIP data structure */
1864  SCIP_Bool const transformed, /**< transformed problem? */
1865  SCIP_VAR*** resvars, /**< pointer to store all resultant variables */
1866  int* nresvars, /**< pointer to store the number of all resultant variables */
1867  SCIP_VAR**** andvars, /**< pointer to store to all resultant variables their corresponding active( or negated) and-constraint variables */
1868  int** nandvars, /**< pointer to store the number of all corresponding and-variables to their corresponding resultant variable */
1869  SCIP_Bool*const existandconshdlr, /**< pointer to store whether the and-constrainthandler exists*/
1870  SCIP_Bool*const existands /**< pointer to store if their exists some and-constraints */
1871  )
1872 {
1873  SCIP_CONSHDLR* conshdlr;
1874 
1875  assert(scip != NULL);
1876  assert(resvars != NULL);
1877  assert(nresvars != NULL);
1878  assert(andvars != NULL);
1879  assert(nandvars != NULL);
1880  assert(existandconshdlr != NULL);
1881  assert(existands != NULL);
1882 
1883  *resvars = NULL;
1884  *nandvars = NULL;
1885  *andvars = NULL;
1886  *nresvars = 0;
1887 
1888  /* detect all and-resultants */
1889  conshdlr = SCIPfindConshdlr(scip, "and");
1890  if( conshdlr != NULL )
1891  {
1892  SCIP_CONS** andconss;
1893  int nandconss;
1894  int* shouldnotbeinand;
1895  int a;
1896  int c;
1897  int r;
1898  int v;
1899  int pos;
1900  int ncontainedands;
1901 
1902  andconss = NULL;
1903  nandconss = 0;
1904  *existandconshdlr = TRUE;
1905 
1906  /* if we write the original problem we need to get the original and constraints */
1907  if( !transformed )
1908  {
1909  SCIP_CONS** origconss;
1910  int norigconss;
1911 
1912  origconss = SCIPgetOrigConss(scip);
1913  norigconss = SCIPgetNOrigConss(scip);
1914 
1915  /* allocate memory for all possible and-constraints */
1916  SCIP_CALL( SCIPallocBufferArray(scip, &andconss, norigconss) );
1917 
1918  /* collect all original and-constraints */
1919  for( c = norigconss - 1; c >= 0; --c )
1920  {
1921  conshdlr = SCIPconsGetHdlr(origconss[c]);
1922  assert( conshdlr != NULL );
1923 
1924  if( strcmp(SCIPconshdlrGetName(conshdlr), "and") == 0 )
1925  {
1926  andconss[nandconss] = origconss[c];
1927  ++nandconss;
1928  }
1929  }
1930  }
1931  else
1932  {
1933  nandconss = SCIPconshdlrGetNConss(conshdlr);
1934  andconss = SCIPconshdlrGetConss(conshdlr);
1935  }
1936 
1937  assert(andconss != NULL || nandconss == 0);
1938 
1939  *nresvars = nandconss;
1940 
1941  if( nandconss > 0 )
1942  {
1943  *existands = TRUE;
1944 
1945  assert(andconss != NULL);
1946 
1947  SCIP_CALL( SCIPallocMemoryArray(scip, resvars, *nresvars) );
1948  SCIP_CALL( SCIPallocMemoryArray(scip, andvars, *nresvars) );
1949  SCIP_CALL( SCIPallocMemoryArray(scip, nandvars, *nresvars) );
1950 
1951  /* collect all and-constraint variables */
1952  for( c = nandconss - 1; c >= 0; --c )
1953  {
1954  assert(andconss[c] != NULL);
1955 
1956  (*nandvars)[c] = SCIPgetNVarsAnd(scip, andconss[c]);
1957  SCIP_CALL( SCIPduplicateMemoryArray(scip, &((*andvars)[c]), SCIPgetVarsAnd(scip, andconss[c]), (*nandvars)[c]) ); /*lint !e866 */
1958  SCIP_CALL( getBinVarsRepresentatives(scip, (*andvars)[c], (*nandvars)[c], transformed) );
1959 
1960  (*resvars)[c] = SCIPgetResultantAnd(scip, andconss[c]);
1961 
1962  assert((*andvars)[c] != NULL && (*nandvars)[c] > 0);
1963  assert((*resvars)[c] != NULL);
1964  }
1965 
1966  /* sorted the array */
1967  SCIPsortPtrPtrInt((void**)(*resvars), (void**)(*andvars), (*nandvars), SCIPvarComp, (*nresvars));
1968  }
1969  else
1970  *existands = FALSE;
1971 
1972  SCIP_CALL( SCIPallocBufferArray(scip, &shouldnotbeinand, *nresvars) );
1973 
1974  /* check that all and-constraints doesn't contain any and-resultants, if they do try to resolve this */
1975  /* attention: if resolving leads to x = x*y*... , we can't do anything here ( this only means (... >=x and) y >= x, so normally the and-constraint needs to be
1976  deleted and the inequality from before needs to be added ) */
1977  assert(*nandvars != NULL || *nresvars == 0);
1978  for( r = *nresvars - 1; r >= 0; --r )
1979  {
1980  ncontainedands = 0;
1981  shouldnotbeinand[ncontainedands] = r;
1982  ++ncontainedands;
1983  v = 0;
1984 
1985  while( v < (*nandvars)[r] )
1986  {
1987  if( SCIPsortedvecFindPtr((void**)(*resvars), SCIPvarComp, (*andvars)[r][v], *nresvars, &pos) )
1988  {
1989  /* check if the found position "pos" is equal to an already visited and resultant in this constraint,
1990  * than here could exist a directed cycle
1991  */
1992  /* better use tarjan's algorithm
1993  * <http://algowiki.net/wiki/index.php?title=Tarjan%27s_algorithm>,
1994  * <http://en.wikipedia.org/wiki/Tarjan%E2%80%99s_strongly_connected_components_algorithm>
1995  * because it could be that the same resultant is part of this and-constraint and than it would fail
1996  * without no cycle
1997  * Note1: tarjans standard algorithm doesn't find cycle from one node to the same;
1998  * Note2: when tarjan's algorithm find a cycle, it's still possible that this cycle is not "real" e.g.
1999  * y = y ~y z (z can also be a product) where y = 0 follows and therefor only "0 = z" is necessary
2000  */
2001  for( a = ncontainedands - 1; a >= 0; --a )
2002  if( shouldnotbeinand[a] == pos )
2003  {
2004  SCIPwarningMessage(scip, "This should not happen here. The and-constraint with resultant variable: ");
2005  SCIP_CALL( SCIPprintVar(scip, (*resvars)[r], NULL) );
2006  SCIPwarningMessage(scip, "possible contains a loop with and-resultant:");
2007  SCIP_CALL( SCIPprintVar(scip, (*resvars)[pos], NULL) );
2008 
2009  /* free memory iff necessary */
2010  SCIPfreeBufferArray(scip, &shouldnotbeinand);
2011  if( !transformed )
2012  {
2013  SCIPfreeBufferArray(scip, &andconss);
2014  }
2015  return SCIP_INVALIDDATA;
2016  }
2017  SCIPdebugMsg(scip, "Another and-constraint contains and-resultant:");
2018  SCIPdebug( SCIP_CALL( SCIPprintVar(scip, (*resvars)[pos], NULL) ) );
2019  SCIPdebugMsg(scip, "Trying to resolve.\n");
2020 
2021  shouldnotbeinand[ncontainedands] = pos;
2022  ++ncontainedands;
2023 
2024  /* try to resolve containing ands */
2025 
2026  /* resize array and number of variables */
2027  (*nandvars)[r] = (*nandvars)[r] + (*nandvars)[pos] - 1;
2028  SCIP_CALL( SCIPreallocMemoryArray(scip, &((*andvars)[r]), (*nandvars)[r]) ); /*lint !e866 */
2029 
2030  /* copy all variables */
2031  for( a = (*nandvars)[pos] - 1; a >= 0; --a )
2032  (*andvars)[r][(*nandvars)[r] - a - 1] = (*andvars)[pos][a];
2033 
2034  /* check same position with new variable, so we do not increase v */
2035  }
2036  else
2037  ++v;
2038  }
2039  }
2040  SCIPfreeBufferArray(scip, &shouldnotbeinand);
2041 
2042  /* free memory iff necessary */
2043  if( !transformed )
2044  {
2045  SCIPfreeBufferArray(scip, &andconss);
2046  }
2047  }
2048  else
2049  {
2050  SCIPdebugMsg(scip, "found no and-constraint-handler\n");
2051  *existands = FALSE;
2052  *existandconshdlr = FALSE;
2053  }
2054 
2055  return SCIP_OKAY;
2056 }
2057 
2058 /** clears the given line buffer */
2059 static
2061  char* linebuffer, /**< line */
2062  int* linecnt /**< number of characters in line */
2063  )
2064 {
2065  assert( linebuffer != NULL );
2066  assert( linecnt != NULL );
2067 
2068  (*linecnt) = 0;
2069  linebuffer[0] = '\0';
2070 }
2071 
2072 
2073 /** ends the given line with '\\0' and prints it to the given file stream */
2074 static
2076  SCIP* scip, /**< SCIP data structure */
2077  FILE* file, /**< output file (or NULL for standard output) */
2078  char* linebuffer, /**< line */
2079  int* linecnt /**< number of characters in line */
2080  )
2081 {
2082  assert( scip != NULL );
2083  assert( linebuffer != NULL );
2084  assert( linecnt != NULL );
2085 
2086  if( (*linecnt) > 0 )
2087  {
2088  linebuffer[(*linecnt)] = '\0';
2089  SCIPinfoMessage(scip, file, "%s", linebuffer);
2090  clearBuffer(linebuffer, linecnt);
2091  }
2092 }
2093 
2094 
2095 /** appends extension to line and prints it to the give file stream if the line buffer get full */
2096 static
2098  SCIP* scip, /**< SCIP data structure */
2099  FILE* file, /**< output file (or NULL for standard output) */
2100  char* linebuffer, /**< line buffer */
2101  int* linecnt, /**< number of characters in line */
2102  const char* extension /**< string to extent the line */
2103  )
2104 {
2105  assert(scip != NULL);
2106  assert(linebuffer != NULL);
2107  assert(linecnt != NULL);
2108  assert(extension != NULL);
2109 
2110  if( (*linecnt) + strlen(extension) >= OPB_MAX_LINELEN - 1 )
2111  writeBuffer(scip, file, linebuffer, linecnt);
2112 
2113  /* append extension to linebuffer */
2114  strncat(linebuffer, extension, OPB_MAX_LINELEN - (unsigned int)(*linecnt) - 1);
2115  (*linecnt) += (int) strlen(extension);
2116 }
2117 
2118 /** write objective function */
2119 static
2121  SCIP*const scip, /**< SCIP data structure */
2122  FILE*const file, /**< output file, or NULL if standard output should be used */
2123  SCIP_VAR**const vars, /**< array with active (binary) variables */
2124  int const nvars, /**< number of active variables in the problem */
2125  SCIP_VAR** const resvars, /**< array of resultant variables */
2126  int const nresvars, /**< number of resultant variables */
2127  SCIP_VAR**const*const andvars, /**< corresponding array of and-variables */
2128  int const*const nandvars, /**< array of numbers of corresponding and-variables */
2129  SCIP_OBJSENSE const objsense, /**< objective sense */
2130  SCIP_Real const objscale, /**< scalar applied to objective function; external objective value is
2131  * extobj = objsense * objscale * (intobj + objoffset) */
2132  SCIP_Real const objoffset, /**< objective offset from bound shifting and fixing */
2133  char const*const multisymbol, /**< the multiplication symbol to use between coefficient and variable */
2134  SCIP_Bool const existands, /**< does some and-constraints exist? */
2135  SCIP_Bool const transformed /**< TRUE iff problem is the transformed problem */
2136  )
2137 {
2138  SCIP_VAR* var;
2139  char linebuffer[OPB_MAX_LINELEN];
2140  char buffer[OPB_MAX_LINELEN];
2141  SCIP_Longint mult;
2142  SCIP_Bool objective;
2143  int v;
2144  int linecnt;
2145  int pos;
2146 
2147  assert(scip != NULL);
2148  assert(file != NULL);
2149  assert(vars != NULL || nvars == 0);
2150  assert(resvars != NULL || nresvars == 0);
2151  assert(andvars != NULL || nandvars == NULL);
2152  assert(multisymbol != NULL);
2153 
2154  mult = 1;
2155  objective = FALSE;
2156 
2157  clearBuffer(linebuffer, &linecnt);
2158 
2159  /* check if a objective function exits and compute the multiplier to
2160  * shift the coefficients to integers */
2161  for( v = 0; v < nvars; ++v )
2162  {
2163  var = vars[v]; /*lint !e613 */
2164 
2165 #ifndef NDEBUG
2166  {
2167  /* in case the original problem has to be posted the variables have to be either "original" or "negated" */
2168  if( !transformed )
2169  assert( SCIPvarGetStatus(var) == SCIP_VARSTATUS_ORIGINAL ||
2171  }
2172 #endif
2173 
2174  /* we found a indicator variable so we assume this is a wbo file */
2175  if( strstr(SCIPvarGetName(var), INDICATORVARNAME) != NULL )
2176  {
2177  /* find the topcost linear inequality which gives us the maximal cost which could be violated by our
2178  * solution, which is an artificial constraint and print this at first
2179  *
2180  * @note: only linear constraint handler is enough in problem stage, otherwise it could be any upgraded linear
2181  * constraint which handles pure binary variables
2182  */
2183  SCIP_CONSHDLR* conshdlr;
2184  SCIP_CONS* topcostcons;
2185  SCIP_Bool printed;
2186 
2187  printed = FALSE;
2188  topcostcons = SCIPfindCons(scip, TOPCOSTCONSNAME);
2189 
2190  if( topcostcons != NULL )
2191  {
2192  conshdlr = SCIPconsGetHdlr(topcostcons);
2193  assert(conshdlr != NULL);
2194 
2195  if( strcmp(SCIPconshdlrGetName(conshdlr), "linear") == 0 )
2196  (void) SCIPsnprintf(buffer, OPB_MAX_LINELEN, "soft: %g;\n", SCIPgetRhsLinear(scip, topcostcons));
2197  else if( strcmp(SCIPconshdlrGetName(conshdlr), "knapsack") == 0 )
2198  (void) SCIPsnprintf(buffer, OPB_MAX_LINELEN, "soft: %g;\n", SCIPgetCapacityKnapsack(scip, topcostcons));
2199  else if( strcmp(SCIPconshdlrGetName(conshdlr), "setppc") == 0 )
2200  (void) SCIPsnprintf(buffer, OPB_MAX_LINELEN, "soft: 1;\n");
2201  else
2202  {
2203  SCIPABORT();
2204  return SCIP_INVALIDDATA; /*lint !e527 */
2205  }
2206  appendBuffer(scip, file, linebuffer, &linecnt, buffer);
2207  writeBuffer(scip, file, linebuffer, &linecnt);
2208  printed = TRUE;
2209  }
2210  /* following works only in transformed stage */
2211  else
2212  {
2213  /* first try linear constraints */
2214  conshdlr = SCIPfindConshdlr(scip, "linear");
2215 
2216  if( conshdlr != NULL )
2217  {
2218  SCIP_CONS** conss;
2219  int nconss;
2220  int c;
2221 
2222  conss = SCIPconshdlrGetConss(conshdlr);
2223  nconss = SCIPconshdlrGetNConss(conshdlr);
2224 
2225  assert(conss != NULL || nconss == 0);
2226 
2227  for( c = 0; c < nconss; ++c )
2228  {
2229  SCIP_VAR** linvars;
2230  int nlinvars;
2231  int w;
2232  SCIP_Bool topcostfound;
2233  SCIP_CONS* cons;
2234 
2235  cons = conss[c]; /*lint !e613 */
2236  assert(cons != NULL);
2237 
2238  linvars = SCIPgetVarsLinear(scip, cons);
2239  nlinvars = SCIPgetNVarsLinear(scip, cons);
2240 
2241  assert(linvars != NULL || nlinvars == 0);
2242  topcostfound = FALSE;
2243 
2244  for( w = 0; w < nlinvars; ++w )
2245  {
2246  if( strstr(SCIPvarGetName(linvars[w]), INDICATORVARNAME) != NULL ) /*lint !e613 */
2247  topcostfound = TRUE;
2248  else
2249  {
2250  assert(!topcostfound);
2251  topcostfound = FALSE;
2252  }
2253  }
2254 
2255  if( topcostfound )
2256  {
2257  (void) SCIPsnprintf(buffer, OPB_MAX_LINELEN, "soft: %g;\n", SCIPgetRhsLinear(scip, cons));
2258  appendBuffer(scip, file, linebuffer, &linecnt, buffer);
2259  writeBuffer(scip, file, linebuffer, &linecnt);
2260  printed = TRUE;
2261  break;
2262  }
2263  }
2264  }
2265 
2266  if( !printed )
2267  {
2268  /* second try knapsack constraints */
2269  conshdlr = SCIPfindConshdlr(scip, "knapsack");
2270 
2271  if( conshdlr != NULL )
2272  {
2273  SCIP_CONS** conss;
2274  int nconss;
2275  int c;
2276 
2277  conss = SCIPconshdlrGetConss(conshdlr);
2278  nconss = SCIPconshdlrGetNConss(conshdlr);
2279 
2280  assert(conss != NULL || nconss == 0);
2281 
2282  for( c = 0; c < nconss; ++c )
2283  {
2284  SCIP_VAR** topvars;
2285  int ntopvars;
2286  int w;
2287  SCIP_Bool topcostfound;
2288  SCIP_CONS* cons;
2289 
2290  cons = conss[c]; /*lint !e613 */
2291  assert(cons != NULL);
2292 
2293  topvars = SCIPgetVarsKnapsack(scip, cons);
2294  ntopvars = SCIPgetNVarsKnapsack(scip, cons);
2295 
2296  assert(topvars != NULL || ntopvars == 0);
2297  topcostfound = FALSE;
2298 
2299  for( w = 0; w < ntopvars; ++w )
2300  {
2301  if( strstr(SCIPvarGetName(topvars[w]), INDICATORVARNAME) != NULL ) /*lint !e613 */
2302  topcostfound = TRUE;
2303  else
2304  {
2305  assert(!topcostfound);
2306  topcostfound = FALSE;
2307  }
2308  }
2309 
2310  if( topcostfound )
2311  {
2312  (void) SCIPsnprintf(buffer, OPB_MAX_LINELEN, "soft: %g;\n", SCIPgetCapacityKnapsack(scip, cons));
2313  appendBuffer(scip, file, linebuffer, &linecnt, buffer);
2314  writeBuffer(scip, file, linebuffer, &linecnt);
2315  printed = TRUE;
2316  break;
2317  }
2318  }
2319  }
2320  }
2321 
2322  if( !printed )
2323  {
2324  /* third try setppc constraints */
2325  conshdlr = SCIPfindConshdlr(scip, "setppc");
2326 
2327  if( conshdlr != NULL )
2328  {
2329  SCIP_CONS** conss;
2330  int nconss;
2331  int c;
2332 
2333  conss = SCIPconshdlrGetConss(conshdlr);
2334  nconss = SCIPconshdlrGetNConss(conshdlr);
2335 
2336  assert(conss != NULL || nconss == 0);
2337 
2338  for( c = 0; c < nconss; ++c )
2339  {
2340  SCIP_VAR** topvars;
2341  int ntopvars;
2342  int w;
2343  SCIP_Bool topcostfound;
2344  SCIP_CONS* cons;
2345 
2346  cons = conss[c]; /*lint !e613 */
2347  assert(cons != NULL);
2348 
2349  topvars = SCIPgetVarsSetppc(scip, cons);
2350  ntopvars = SCIPgetNVarsSetppc(scip, cons);
2351 
2352  assert(topvars != NULL || ntopvars == 0);
2353  topcostfound = FALSE;
2354 
2355  for( w = 0; w < ntopvars; ++w )
2356  {
2357  if( strstr(SCIPvarGetName(topvars[w]), INDICATORVARNAME) != NULL ) /*lint !e613 */
2358  topcostfound = TRUE;
2359  else
2360  {
2361  assert(!topcostfound);
2362  topcostfound = FALSE;
2363  }
2364  }
2365 
2366  if( topcostfound )
2367  {
2368  (void) SCIPsnprintf(buffer, OPB_MAX_LINELEN, "soft: 1;\n");
2369  appendBuffer(scip, file, linebuffer, &linecnt, buffer);
2370  writeBuffer(scip, file, linebuffer, &linecnt);
2371  printed = TRUE;
2372  break;
2373  }
2374  }
2375  }
2376  }
2377  }
2378 
2379  /* no topcost constraint found, so print empty topcost line, which means there is no upper bound on violated soft constraints */
2380  if( !printed )
2381  {
2382  (void) SCIPsnprintf(buffer, OPB_MAX_LINELEN, "soft: ;\n");
2383  appendBuffer(scip, file, linebuffer, &linecnt, buffer);
2384  writeBuffer(scip, file, linebuffer, &linecnt);
2385  }
2386 
2387  return SCIP_OKAY;
2388  }
2389 
2390  if( !SCIPisZero(scip, SCIPvarGetObj(var)) )
2391  {
2392  objective = TRUE;
2393  while( !SCIPisIntegral(scip, SCIPvarGetObj(var) * mult) )
2394  {
2395  assert(mult * 10 > mult);
2396  mult *= 10;
2397  }
2398  }
2399  }
2400 
2401  if( objective )
2402  {
2403  /* there exist a objective function*/
2404  SCIPinfoMessage(scip, file, "* Obj. scale : %.15g\n", objscale * mult);
2405  SCIPinfoMessage(scip, file, "* Obj. offset : %.15g\n", objoffset);
2406 
2407  clearBuffer(linebuffer, &linecnt);
2408 
2409  /* opb format supports only minimization; therefore, a maximization problem has to be converted */
2410  if( objsense == SCIP_OBJSENSE_MAXIMIZE )
2411  mult *= -1;
2412 
2413  SCIPdebugMsg(scip, "print objective function multiplied with %" SCIP_LONGINT_FORMAT "\n", mult);
2414 
2415  appendBuffer(scip, file, linebuffer, &linecnt, "min:");
2416 
2417 #ifndef NDEBUG
2418  if( existands )
2419  {
2420  int c;
2421  /* check that these variables are sorted */
2422  for( c = nresvars - 1; c > 0; --c )
2423  assert(SCIPvarGetIndex(resvars[c]) >= SCIPvarGetIndex(resvars[c - 1])); /*lint !e613 */
2424  }
2425 #endif
2426 
2427  for( v = nvars - 1; v >= 0; --v )
2428  {
2429  SCIP_Bool negated;
2430  var = vars[v]; /*lint !e613 */
2431 
2432  assert(var != NULL);
2433 
2434  if( SCIPisZero(scip, SCIPvarGetObj(var)) )
2435  continue;
2436 
2437  negated = SCIPvarIsNegated(var);
2438 
2439  assert( linecnt != 0 );
2440 
2441  if( SCIPvarGetObj(var) * mult > SCIP_LONGINT_MAX )
2442  {
2443  SCIPerrorMessage("Integral objective value to big (mult = %" SCIP_LONGINT_FORMAT ", value = %g, mult*value = %g, printingvalue = %" SCIP_LONGINT_FORMAT ")for printing in opb format.\n", mult, SCIPvarGetObj(var), SCIPvarGetObj(var) * mult, (SCIP_Longint) SCIPround(scip, SCIPvarGetObj(var) * mult));
2444  }
2445 
2446  /* replace and-resultant with corresponding variables */
2447  if( existands && SCIPsortedvecFindPtr((void**)resvars, SCIPvarComp, var, nresvars, &pos) )
2448  {
2449  int a;
2450 
2451  assert(andvars != NULL);
2452  assert(nandvars != NULL);
2453  assert(pos >= 0 && nandvars[pos] > 0 && andvars[pos] != NULL);
2454  assert(andvars[pos][nandvars[pos] - 1] != NULL);
2455 
2456  negated = SCIPvarIsNegated(andvars[pos][nandvars[pos] - 1]);
2457 
2458  /* print and-vars */
2459  (void) SCIPsnprintf(buffer, OPB_MAX_LINELEN, " %+" SCIP_LONGINT_FORMAT "%s%s%s",
2460  (SCIP_Longint) (SCIPvarGetObj(var) * mult), multisymbol, negated ? "~" : "",
2461  strstr(SCIPvarGetName(negated ? SCIPvarGetNegationVar(andvars[pos][nandvars[pos] - 1]) : andvars[pos][nandvars[pos] - 1]), "x"));
2462  appendBuffer(scip, file, linebuffer, &linecnt, buffer);
2463 
2464  for(a = nandvars[pos] - 2; a >= 0; --a )
2465  {
2466  negated = SCIPvarIsNegated(andvars[pos][a]);
2467 
2468  (void) SCIPsnprintf(buffer, OPB_MAX_LINELEN, "%s%s%s", multisymbol, negated ? "~" : "", strstr(SCIPvarGetName(negated ? SCIPvarGetNegationVar(andvars[pos][a]) : andvars[pos][a]), "x"));
2469  appendBuffer(scip, file, linebuffer, &linecnt, buffer);
2470  }
2471  }
2472  else
2473  {
2474  (void) SCIPsnprintf(buffer, OPB_MAX_LINELEN, " %+" SCIP_LONGINT_FORMAT "%s%s%s",
2475  (SCIP_Longint) (SCIPvarGetObj(var) * mult), multisymbol, negated ? "~" : "", strstr(SCIPvarGetName(negated ? SCIPvarGetNegationVar(var) : var), "x"));
2476  appendBuffer(scip, file, linebuffer, &linecnt, buffer);
2477  }
2478  }
2479 
2480  /* and objective function line ends with a ';' */
2481  appendBuffer(scip, file, linebuffer, &linecnt, " ;\n");
2482  writeBuffer(scip, file, linebuffer, &linecnt);
2483  }
2484 
2485  return SCIP_OKAY;
2486 }
2487 
2488 /* print maybe non linear row in OPB format to file stream */
2489 static
2491  SCIP*const scip, /**< SCIP data structure */
2492  FILE*const file, /**< output file (or NULL for standard output) */
2493  char const*const type, /**< row type ("=" or ">=") */
2494  SCIP_VAR**const vars, /**< array of variables */
2495  SCIP_Real const*const vals, /**< array of values */
2496  int const nvars, /**< number of variables */
2497  SCIP_Real lhs, /**< left hand side */
2498  SCIP_VAR** const resvars, /**< array of resultant variables */
2499  int const nresvars, /**< number of resultant variables */
2500  SCIP_VAR**const*const andvars, /**< corresponding array of and-variables */
2501  int const*const nandvars, /**< array of numbers of corresponding and-variables */
2502  SCIP_Longint weight, /**< if we found a soft constraint this is the weight, otherwise 0 */
2503  SCIP_Longint*const mult, /**< multiplier for the coefficients */
2504  char const*const multisymbol /**< the multiplication symbol to use between coefficient and variable */
2505  )
2506 {
2507  SCIP_VAR* var;
2508  char buffer[OPB_MAX_LINELEN];
2509  char linebuffer[OPB_MAX_LINELEN + 1];
2510  int v;
2511  int pos;
2512  int linecnt;
2513 
2514  assert(scip != NULL);
2515  assert(strcmp(type, "=") == 0 || strcmp(type, ">=") == 0);
2516  assert(mult != NULL);
2517  assert(resvars != NULL);
2518  assert(nresvars > 0);
2519  assert(andvars != NULL && nandvars != NULL);
2520 
2521  clearBuffer(linebuffer, &linecnt);
2522 
2523  /* check if all coefficients are internal; if not commentstart multiplier */
2524  for( v = 0; v < nvars; ++v )
2525  {
2526  while( !SCIPisIntegral(scip, vals[v] * (*mult)) )
2527  {
2528  if( ABS(*mult) > ABS(*mult * 10) )
2529  return SCIP_INVALIDDATA;
2530  (*mult) *= 10;
2531  }
2532  }
2533 
2534  while( !SCIPisIntegral(scip, lhs * (*mult)) )
2535  {
2536  if( ABS(*mult) > ABS(*mult * 10) )
2537  return SCIP_INVALIDDATA;
2538  (*mult) *= 10;
2539  }
2540 
2541  /* print comment line if we have to multiply the coefficients to get integrals */
2542  if( ABS(*mult) != 1 )
2543  SCIPinfoMessage(scip, file, "* the following constraint is multiplied by %" SCIP_LONGINT_FORMAT " to get integral coefficients\n", ABS(*mult) );
2544 
2545 #ifndef NDEBUG
2546  /* check that these variables are sorted */
2547  for( v = nresvars - 1; v > 0; --v )
2548  assert(SCIPvarGetIndex(resvars[v]) >= SCIPvarGetIndex(resvars[v - 1]));
2549 #endif
2550 
2551  /* if we have a soft constraint print the weight*/
2552  if( weight != 0 )
2553  {
2554  (void) SCIPsnprintf(buffer, OPB_MAX_LINELEN, "[%+" SCIP_LONGINT_FORMAT "] ", weight);
2555  appendBuffer(scip, file, linebuffer, &linecnt, buffer);
2556  }
2557 
2558  /* print coefficients */
2559  for( v = 0; v < nvars; ++v )
2560  {
2561  SCIP_Bool negated;
2562 
2563  var = vars[v];
2564  assert( var != NULL );
2565 
2566  negated = SCIPvarIsNegated(var);
2567 
2568  /* replace and-resultant with corresponding variables */
2569  if( SCIPsortedvecFindPtr((void**)resvars, SCIPvarComp, var, nresvars, &pos) )
2570  {
2571  int a;
2572 
2573  assert(andvars != NULL);
2574  assert(nandvars != NULL);
2575  assert(pos >= 0 && nandvars[pos] > 0 && andvars[pos] != NULL);
2576  assert(andvars[pos][nandvars[pos] - 1] != NULL);
2577 
2578  negated = SCIPvarIsNegated(andvars[pos][nandvars[pos] - 1]);
2579 
2580  if( vals[v] * (*mult) > SCIP_LONGINT_MAX )
2581  {
2582  SCIPerrorMessage("Integral coefficient to big (mult = %" SCIP_LONGINT_FORMAT ", value = %g, mult*value = %g, printingvalue = %" SCIP_LONGINT_FORMAT ")for printing in opb format.\n", *mult, vals[v], vals[v] * (*mult), (SCIP_Longint) SCIPround(scip, vals[v] * (*mult)));
2583  }
2584 
2585  /* print and-vars */
2586  (void) SCIPsnprintf(buffer, OPB_MAX_LINELEN, "%+" SCIP_LONGINT_FORMAT "%s%s%s",
2587  (SCIP_Longint) SCIPround(scip, vals[v] * (*mult)), multisymbol, negated ? "~" : "",
2588  strstr(SCIPvarGetName(negated ? SCIPvarGetNegationVar(andvars[pos][nandvars[pos] - 1]) : andvars[pos][nandvars[pos] - 1]), "x") );
2589  appendBuffer(scip, file, linebuffer, &linecnt, buffer);
2590 
2591  for(a = nandvars[pos] - 2; a >= 0; --a )
2592  {
2593  negated = SCIPvarIsNegated(andvars[pos][a]);
2594 
2595  (void) SCIPsnprintf(buffer, OPB_MAX_LINELEN, "%s%s%s", multisymbol, negated ? "~" : "", strstr(SCIPvarGetName(negated ? SCIPvarGetNegationVar(andvars[pos][a]) : andvars[pos][a]), "x"));
2596  appendBuffer(scip, file, linebuffer, &linecnt, buffer);
2597  }
2598 
2599  appendBuffer(scip, file, linebuffer, &linecnt, " ");
2600  }
2601  else
2602  {
2603  (void) SCIPsnprintf(buffer, OPB_MAX_LINELEN, "%+" SCIP_LONGINT_FORMAT "%s%s%s ",
2604  (SCIP_Longint) SCIPround(scip, vals[v] * (*mult)), multisymbol, negated ? "~" : "", strstr(SCIPvarGetName(negated ? SCIPvarGetNegationVar(var) : var), "x"));
2605  appendBuffer(scip, file, linebuffer, &linecnt, buffer);
2606  }
2607  }
2608 
2609  /* print left hand side */
2610  if( SCIPisZero(scip, lhs) )
2611  lhs = 0.0;
2612 
2613  (void) SCIPsnprintf(buffer, OPB_MAX_LINELEN, "%s %" SCIP_LONGINT_FORMAT " ;\n", type, (SCIP_Longint) (lhs * (*mult)) );
2614  appendBuffer(scip, file, linebuffer, &linecnt, buffer);
2615 
2616  writeBuffer(scip, file, linebuffer, &linecnt);
2617 
2618  return SCIP_OKAY;
2619 }
2620 
2621 
2622 /** prints given maybe non-linear constraint information in OPB format to file stream */
2623 static
2625  SCIP*const scip, /**< SCIP data structure */
2626  FILE*const file, /**< output file (or NULL for standard output) */
2627  SCIP_VAR**const vars, /**< array of variables */
2628  SCIP_Real*const vals, /**< array of coefficients values (or NULL if all coefficient values are 1) */
2629  int const nvars, /**< number of variables */
2630  SCIP_Real const lhs, /**< left hand side */
2631  SCIP_Real const rhs, /**< right hand side */
2632  SCIP_VAR** const resvars, /**< array of resultant variables */
2633  int const nresvars, /**< number of resultant variables */
2634  SCIP_VAR**const*const andvars, /**< corresponding array of and-variables */
2635  int const*const nandvars, /**< array of numbers of corresponding and-variables */
2636  SCIP_Longint weight, /**< if we found a soft constraint this is the weight, otherwise 0 */
2637  SCIP_Bool const transformed, /**< transformed constraint? */
2638  char const*const multisymbol /**< the multiplication symbol to use between coefficient and variable */
2639  )
2640 {
2641  SCIP_VAR** activevars;
2642  SCIP_Real* activevals;
2643  SCIP_Real activeconstant;
2644  SCIP_Longint mult;
2645  SCIP_RETCODE retcode;
2646  int v;
2647  int nactivevars;
2648 
2649  assert(scip != NULL);
2650  assert(vars != NULL);
2651  assert(nvars > 0);
2652  assert(lhs <= rhs);
2653  assert(resvars != NULL);
2654  assert(nresvars > 0);
2655  assert(andvars != NULL && nandvars != NULL);
2656 
2657  if( SCIPisInfinity(scip, -lhs) && SCIPisInfinity(scip, rhs) )
2658  return SCIP_OKAY;
2659 
2660  activeconstant = 0.0;
2661  nactivevars = nvars;
2662 
2663  /* duplicate variable and value array */
2664  SCIP_CALL( SCIPduplicateBufferArray(scip, &activevars, vars, nactivevars ) );
2665  if( vals != NULL )
2666  {
2667  SCIP_CALL( SCIPduplicateBufferArray(scip, &activevals, vals, nactivevars ) );
2668  }
2669  else
2670  {
2671  SCIP_CALL( SCIPallocBufferArray(scip, &activevals, nactivevars) );
2672 
2673  for( v = 0; v < nactivevars; ++v )
2674  activevals[v] = 1.0;
2675  }
2676 
2677  /* retransform given variables to active variables */
2678  SCIP_CALL( getActiveVariables(scip, activevars, activevals, &nactivevars, &activeconstant, transformed) );
2679 
2680  mult = 1;
2681  retcode = SCIP_OKAY;
2682 
2683  /* print row(s) in OPB format */
2684  if( SCIPisEQ(scip, lhs, rhs) )
2685  {
2686  assert( !SCIPisInfinity(scip, rhs) );
2687 
2688  /* equality constraint */
2689  retcode = printNLRow(scip, file, "=", activevars, activevals, nactivevars, rhs - activeconstant, resvars,
2690  nresvars, andvars, nandvars, weight, &mult, multisymbol);
2691  }
2692  else
2693  {
2694  if( !SCIPisInfinity(scip, -lhs) )
2695  {
2696  /* print inequality ">=" */
2697  retcode = printNLRow(scip, file, ">=", activevars, activevals, nactivevars, lhs - activeconstant, resvars,
2698  nresvars, andvars, nandvars, weight, &mult, multisymbol);
2699  }
2700 
2701 
2702  if( !SCIPisInfinity(scip, rhs) )
2703  {
2704  mult *= -1;
2705 
2706  /* print inequality ">=" and multiplying all coefficients by -1 */
2707  retcode = printNLRow(scip, file, ">=", activevars, activevals, nactivevars, rhs - activeconstant, resvars,
2708  nresvars, andvars, nandvars, weight, &mult, multisymbol);
2709  }
2710  }
2711 
2712  /* free buffer arrays */
2713  SCIPfreeBufferArray(scip, &activevars);
2714  SCIPfreeBufferArray(scip, &activevals);
2715 
2716  return retcode;
2717 }
2718 
2719 
2720 /* print row in OPB format to file stream */
2721 static
2723  SCIP* scip, /**< SCIP data structure */
2724  FILE* file, /**< output file (or NULL for standard output) */
2725  const char* type, /**< row type ("=" or ">=") */
2726  SCIP_VAR** vars, /**< array of variables */
2727  SCIP_Real* vals, /**< array of values */
2728  int nvars, /**< number of variables */
2729  SCIP_Real lhs, /**< left hand side */
2730  SCIP_Longint weight, /**< if we found a soft constraint this is the weight, otherwise 0 */
2731  SCIP_Longint* mult, /**< multiplier for the coefficients */
2732  const char* multisymbol /**< the multiplication symbol to use between coefficient and variable */
2733  )
2734 {
2735  SCIP_VAR* var;
2736  char buffer[OPB_MAX_LINELEN];
2737  char linebuffer[OPB_MAX_LINELEN + 1];
2738  int v;
2739  int linecnt;
2740 
2741  assert(scip != NULL);
2742  assert(strcmp(type, "=") == 0 || strcmp(type, ">=") == 0);
2743  assert(mult != NULL);
2744 
2745  clearBuffer(linebuffer, &linecnt);
2746 
2747  /* if we found the topcost linear inequality which gives us the maximal cost which could be violated by our solution,
2748  * we can stop printing because it is an artificial constraint
2749  */
2750  if( nvars > 0 && strstr(SCIPvarGetName(vars[0]), INDICATORVARNAME) != NULL )
2751  return SCIP_OKAY;
2752 
2753  /* check if all coefficients are integral; if not commentstart multiplier */
2754  for( v = 0; v < nvars; ++v )
2755  {
2756  while( !SCIPisIntegral(scip, vals[v] * (*mult)) )
2757  {
2758  if( ABS(*mult) > ABS(*mult * 10) )
2759  return SCIP_INVALIDDATA;
2760  (*mult) *= 10;
2761  }
2762  }
2763 
2764  while( !SCIPisIntegral(scip, lhs * (*mult)) )
2765  {
2766  if( ABS(*mult) > ABS(*mult * 10) )
2767  return SCIP_INVALIDDATA;
2768  (*mult) *= 10;
2769  }
2770 
2771  /* print comment line if we have to multiply the coefficients to get integrals */
2772  if( ABS(*mult) != 1 )
2773  SCIPinfoMessage(scip, file, "* the following constraint is multiplied by %" SCIP_LONGINT_FORMAT " to get integral coefficients\n", ABS(*mult) );
2774 
2775  /* if we have a soft constraint print the weight*/
2776  if( weight != 0 )
2777  {
2778  (void) SCIPsnprintf(buffer, OPB_MAX_LINELEN, "[%+" SCIP_LONGINT_FORMAT "] ", weight);
2779  appendBuffer(scip, file, linebuffer, &linecnt, buffer);
2780  }
2781 
2782  /* print coefficients */
2783  for( v = 0; v < nvars; ++v )
2784  {
2785  SCIP_Bool negated;
2786 
2787  var = vars[v];
2788  assert( var != NULL );
2789 
2790  negated = SCIPvarIsNegated(var);
2791 
2792  if( vals[v] * (*mult) > SCIP_LONGINT_MAX )
2793  {
2794  SCIPerrorMessage("Integral coefficient to big (mult = %" SCIP_LONGINT_FORMAT ", value = %g, mult*value = %g, printingvalue = %" SCIP_LONGINT_FORMAT ")for printing in opb format.\n", *mult, vals[v], vals[v] * (*mult), (SCIP_Longint) SCIPround(scip, vals[v] * (*mult)));
2795  }
2796 
2797  (void) SCIPsnprintf(buffer, OPB_MAX_LINELEN, "%+" SCIP_LONGINT_FORMAT "%s%s%s ",
2798  (SCIP_Longint) SCIPround(scip, vals[v] * (*mult)), multisymbol, negated ? "~" : "", strstr(SCIPvarGetName(negated ? SCIPvarGetNegationVar(var) : var), "x"));
2799  appendBuffer(scip, file, linebuffer, &linecnt, buffer);
2800  }
2801 
2802  /* print left hand side */
2803  if( SCIPisZero(scip, lhs) )
2804  lhs = 0.0;
2805 
2806  (void) SCIPsnprintf(buffer, OPB_MAX_LINELEN, "%s %" SCIP_LONGINT_FORMAT " ;\n", type, (SCIP_Longint) (lhs * (*mult)) );
2807  appendBuffer(scip, file, linebuffer, &linecnt, buffer);
2808 
2809  writeBuffer(scip, file, linebuffer, &linecnt);
2810 
2811  return SCIP_OKAY;
2812 }
2813 
2814 
2815 /** prints given linear constraint information in OPB format to file stream */
2816 static
2818  SCIP* scip, /**< SCIP data structure */
2819  FILE* file, /**< output file (or NULL for standard output) */
2820  SCIP_VAR** vars, /**< array of variables */
2821  SCIP_Real* vals, /**< array of coefficients values (or NULL if all coefficient values are 1) */
2822  int nvars, /**< number of variables */
2823  SCIP_Real lhs, /**< left hand side */
2824  SCIP_Real rhs, /**< right hand side */
2825  SCIP_Longint weight, /**< if we found a soft constraint this is the weight, otherwise 0 */
2826  SCIP_Bool transformed, /**< transformed constraint? */
2827  const char* multisymbol /**< the multiplication symbol to use between coefficient and variable */
2828  )
2829 {
2830  SCIP_VAR** activevars;
2831  SCIP_Real* activevals;
2832  int nactivevars;
2833  SCIP_Real activeconstant;
2834  SCIP_Longint mult;
2835  SCIP_RETCODE retcode;
2836  int v;
2837 
2838  assert( scip != NULL );
2839  assert( vars != NULL );
2840  assert( nvars > 0 );
2841  assert( lhs <= rhs );
2842 
2843  if( SCIPisInfinity(scip, -lhs) && SCIPisInfinity(scip, rhs) )
2844  return SCIP_OKAY;
2845 
2846  activeconstant = 0.0;
2847 
2848  /* duplicate variable and value array */
2849  nactivevars = nvars;
2850  SCIP_CALL( SCIPduplicateBufferArray(scip, &activevars, vars, nactivevars ) );
2851  if( vals != NULL )
2852  {
2853  SCIP_CALL( SCIPduplicateBufferArray(scip, &activevals, vals, nactivevars ) );
2854  }
2855  else
2856  {
2857  SCIP_CALL( SCIPallocBufferArray(scip, &activevals, nactivevars) );
2858 
2859  for( v = 0; v < nactivevars; ++v )
2860  activevals[v] = 1.0;
2861  }
2862 
2863  /* retransform given variables to active variables */
2864  SCIP_CALL( getActiveVariables(scip, activevars, activevals, &nactivevars, &activeconstant, transformed) );
2865 
2866  mult = 1;
2867  retcode = SCIP_OKAY;
2868 
2869  /* print row(s) in OPB format */
2870  if( SCIPisEQ(scip, lhs, rhs) )
2871  {
2872  assert( !SCIPisInfinity(scip, rhs) );
2873 
2874  /* equality constraint */
2875  retcode = printRow(scip, file, "=", activevars, activevals, nactivevars, rhs - activeconstant, weight, &mult,
2876  multisymbol);
2877  }
2878  else
2879  {
2880  if( !SCIPisInfinity(scip, -lhs) )
2881  {
2882  /* print inequality ">=" */
2883  retcode = printRow(scip, file, ">=", activevars, activevals, nactivevars, lhs - activeconstant, weight, &mult,
2884  multisymbol);
2885  }
2886 
2887  if( !SCIPisInfinity(scip, rhs) )
2888  {
2889  mult *= -1;
2890 
2891  /* print inequality ">=" and multiplying all coefficients by -1 */
2892  retcode = printRow(scip, file, ">=", activevars, activevals, nactivevars, rhs - activeconstant, weight, &mult,
2893  multisymbol);
2894  }
2895  }
2896 
2897  /* free buffer arrays */
2898  SCIPfreeBufferArray(scip, &activevars);
2899  SCIPfreeBufferArray(scip, &activevals);
2900 
2901  return retcode;
2902 }
2903 
2904 /* print row in OPB format to file stream */
2905 static
2907  SCIP*const scip, /**< SCIP data structure */
2908  FILE*const file, /**< output file (or NULL for standard output) */
2909  const char* type, /**< row type ("=" or ">=") */
2910  SCIP_VAR**const linvars, /**< array of variables */
2911  SCIP_Real*const linvals, /**< array of values */
2912  int const nlinvars, /**< number of variables */
2913  SCIP_VAR***const termvars, /**< term array with array of variables to print */
2914  int*const ntermvars, /**< array with number of variables in each term */
2915  SCIP_Real*const termvals, /**< array of coefficient values for non-linear variables */
2916  int const ntermvals, /**< number non-linear variables in the problem */
2917  SCIP_Bool**const negatedarrays, /**< array of arrays to know which variable in a non-linear part is negated */
2918  SCIP_VAR*const indvar, /**< indicator variable, or NULL */
2919  SCIP_Real lhs, /**< left hand side */
2920  SCIP_Longint* mult, /**< multiplier for the coefficients */
2921  const char* multisymbol /**< the multiplication symbol to use between coefficient and variable */
2922  )
2923 {
2924  SCIP_VAR* var;
2925  char buffer[OPB_MAX_LINELEN];
2926  char linebuffer[OPB_MAX_LINELEN + 1];
2927  int v;
2928  int t;
2929  int linecnt;
2930 
2931  assert(scip != NULL);
2932  assert(strcmp(type, "=") == 0 || strcmp(type, ">=") == 0);
2933  assert(linvars != NULL || nlinvars == 0);
2934  assert(linvals != NULL || nlinvars == 0);
2935  assert(termvars != NULL || ntermvals == 0);
2936  assert(ntermvars != NULL || ntermvals == 0);
2937  assert(termvals != NULL || ntermvals == 0);
2938  assert(negatedarrays != NULL || ntermvals == 0);
2939  assert(mult != NULL);
2940 
2941  clearBuffer(linebuffer, &linecnt);
2942 
2943  /* if we found the topcost linear inequality which gives us the maximal cost which could be violated by our solution,
2944  * we can stop printing because it is an artificial constraint
2945  */
2946  if( ntermvals == 0 && nlinvars > 0 && strstr(SCIPvarGetName(linvars[0]), INDICATORVARNAME) != NULL ) /*lint !e613 */
2947  return SCIP_OKAY;
2948 
2949  /* check if all linear coefficients are internal; if not commentstart multiplier */
2950  for( v = 0; v < nlinvars; ++v )
2951  {
2952  while( !SCIPisIntegral(scip, linvals[v] * (*mult)) ) /*lint !e613 */
2953  {
2954  if( ABS(*mult) > ABS(*mult * 10) )
2955  return SCIP_INVALIDDATA;
2956  (*mult) *= 10;
2957  }
2958  }
2959 
2960  /* check if all non-linear coefficients are internal; if not commentstart multiplier */
2961  for( v = 0; v < ntermvals; ++v )
2962  {
2963  while( !SCIPisIntegral(scip, termvals[v] * (*mult)) ) /*lint !e613 */
2964  {
2965  if( ABS(*mult) > ABS(*mult * 10) )
2966  return SCIP_INVALIDDATA;
2967  (*mult) *= 10;
2968  }
2969  }
2970 
2971  while( !SCIPisIntegral(scip, lhs * (*mult)) )
2972  {
2973  if( ABS(*mult) > ABS(*mult * 10) )
2974  return SCIP_INVALIDDATA;
2975  (*mult) *= 10;
2976  }
2977 
2978  /* print comment line if we have to multiply the coefficients to get integrals */
2979  if( ABS(*mult) != 1 )
2980  SCIPinfoMessage(scip, file, "* the following constraint is multiplied by %" SCIP_LONGINT_FORMAT " to get integral coefficients\n", ABS(*mult) );
2981 
2982  /* if indicator variable exist we have a soft constraint */
2983  if( indvar != NULL )
2984  {
2985  SCIP_Real weight;
2986 
2987  weight = SCIPvarGetObj(indvar);
2988  (void) SCIPsnprintf(buffer, OPB_MAX_LINELEN, "[%+g] ", weight);
2989  appendBuffer(scip, file, linebuffer, &linecnt, buffer);
2990  }
2991 
2992  /* print linear part */
2993  for( v = 0; v < nlinvars; ++v )
2994  {
2995  SCIP_Bool negated;
2996 
2997  var = linvars[v]; /*lint !e613 */
2998  assert(var != NULL);
2999 
3000  negated = SCIPvarIsNegated(var);
3001 
3002  (void) SCIPsnprintf(buffer, OPB_MAX_LINELEN, "%+" SCIP_LONGINT_FORMAT "%s%s%s ",
3003  (SCIP_Longint) SCIPround(scip, linvals[v] * (*mult)), multisymbol, negated ? "~" : "", strstr(SCIPvarGetName(negated ? SCIPvarGetNegationVar(var) : var), "x")); /*lint !e613 */
3004  appendBuffer(scip, file, linebuffer, &linecnt, buffer);
3005  }
3006 
3007  /* print non-linear part */
3008  for( t = 0; t < ntermvals; ++t )
3009  {
3010  (void) SCIPsnprintf(buffer, OPB_MAX_LINELEN, "%+" SCIP_LONGINT_FORMAT, (SCIP_Longint) SCIPround(scip, termvals[t] * (*mult))); /*lint !e613 */
3011  appendBuffer(scip, file, linebuffer, &linecnt, buffer);
3012 
3013  for( v = 0; v < ntermvars[t]; ++v ) /*lint !e613 */
3014  {
3015  SCIP_Bool negated;
3016 
3017  var = termvars[t][v]; /*lint !e613 */
3018  assert(var != NULL);
3019 
3020  negated = negatedarrays[t][v]; /*lint !e613 */
3021 
3022  (void) SCIPsnprintf(buffer, OPB_MAX_LINELEN, "%s%s%s", multisymbol, negated ? "~" : "", strstr(SCIPvarGetName(negated ? SCIPvarGetNegationVar(var) : var), "x"));
3023  appendBuffer(scip, file, linebuffer, &linecnt, buffer);
3024  }
3025  appendBuffer(scip, file, linebuffer, &linecnt, " ");
3026  }
3027 
3028  /* print left hand side */
3029  if( SCIPisZero(scip, lhs) )
3030  lhs = 0.0;
3031 
3032  (void) SCIPsnprintf(buffer, OPB_MAX_LINELEN, "%s %" SCIP_LONGINT_FORMAT " ;\n", type, (SCIP_Longint) (lhs * (*mult)) );
3033  appendBuffer(scip, file, linebuffer, &linecnt, buffer);
3034 
3035  writeBuffer(scip, file, linebuffer, &linecnt);
3036 
3037  return SCIP_OKAY;
3038 }
3039 
3040 
3041 /** prints given pseudo boolean constraint information in OPB format to file stream */
3042 static
3044  SCIP*const scip, /**< SCIP data structure */
3045  FILE*const file, /**< output file, or NULL if standard output should be used */
3046  SCIP_VAR**const linvars, /**< array with variables of linear part */
3047  SCIP_Real*const linvals, /**< array of coefficients values of linear part */
3048  int const nlinvars, /**< number variables in linear part of the problem */
3049  SCIP_VAR***const termvars, /**< term array with array of variables to print */
3050  int*const ntermvars, /**< array with number of variables in each term */
3051  SCIP_Real*const termvals, /**< array of coefficient values for non-linear variables */
3052  int const ntermvals, /**< number non-linear variables in the problem */
3053  SCIP_VAR*const indvar, /**< indicator variable, or NULL */
3054  SCIP_Real const lhs, /**< left hand side of constraint */
3055  SCIP_Real const rhs, /**< right hand side of constraint */
3056  SCIP_Bool transformed, /**< should the transformed problem be printed ? */
3057  const char* multisymbol /**< the multiplication symbol to use between coefficient and variable */
3058  )
3059 {
3060  SCIP_VAR*** activetermvars;
3061  SCIP_Bool** negatedarrays;
3062  SCIP_VAR** activelinvars;
3063  SCIP_Real* activelinvals;
3064  int nactivelinvars;
3065  SCIP_Real activelinconstant;
3066  SCIP_Longint mult;
3067  SCIP_RETCODE retcode;
3068  int v;
3069 
3070  assert(scip != NULL);
3071  assert(linvars != NULL || nlinvars == 0);
3072  assert(linvals != NULL || nlinvars == 0);
3073  assert(termvars != NULL || 0 == ntermvals);
3074  assert(ntermvars != NULL || 0 == ntermvals);
3075  assert(termvals != NULL || 0 == ntermvals);
3076  assert(lhs <= rhs);
3077 
3078  if( SCIPisInfinity(scip, -lhs) && SCIPisInfinity(scip, rhs) )
3079  return SCIP_OKAY;
3080 
3081  activelinconstant = 0.0;
3082 
3083  /* duplicate variable and value array for linear part */
3084  nactivelinvars = nlinvars;
3085  if( nactivelinvars > 0 )
3086  {
3087  SCIP_CALL( SCIPduplicateBufferArray(scip, &activelinvars, linvars, nactivelinvars ) );
3088  SCIP_CALL( SCIPduplicateBufferArray(scip, &activelinvals, linvals, nactivelinvars ) );
3089 
3090  /* retransform given variables to active variables */
3091  SCIP_CALL( getActiveVariables(scip, activelinvars, activelinvals, &nactivelinvars, &activelinconstant, transformed) );
3092  }
3093  else
3094  {
3095  activelinvars = NULL;
3096  activelinvals = NULL;
3097  }
3098 
3099  /* create non-linear information for printing */
3100  if( ntermvals > 0 )
3101  {
3102  assert(termvars != NULL);
3103  assert(ntermvars != NULL);
3104  assert(termvals != NULL);
3105 
3106  SCIP_CALL( SCIPallocBufferArray(scip, &activetermvars, ntermvals) );
3107  SCIP_CALL( SCIPallocBufferArray(scip, &negatedarrays, ntermvals) );
3108  for( v = ntermvals - 1; v >= 0; --v )
3109  {
3110  assert(ntermvars[v] > 0); /*lint !e613 */
3111 
3112  if( transformed )
3113  {
3114  SCIP_CALL( SCIPallocBufferArray(scip, &(activetermvars[v]), ntermvars[v]) ); /*lint !e866 */
3115  SCIP_CALL( SCIPallocBufferArray(scip, &(negatedarrays[v]), ntermvars[v]) ); /*lint !e866 */
3116 
3117  /* get binary representatives of binary variables in non-linear terms */
3118  SCIP_CALL( SCIPgetBinvarRepresentatives(scip, ntermvars[v], termvars[v], activetermvars[v], negatedarrays[v]) );
3119  }
3120  else
3121  {
3122  SCIP_CALL( SCIPduplicateBufferArray(scip, &(activetermvars[v]), termvars[v], ntermvars[v]) ); /*lint !e866 */
3123  SCIP_CALL( SCIPallocBufferArray(scip, &(negatedarrays[v]), ntermvars[v]) ); /*lint !e866 */
3124  BMSclearMemoryArray(negatedarrays[v], ntermvars[v]); /*lint !e866 */
3125  }
3126  }
3127  }
3128  else
3129  {
3130  activetermvars = NULL;
3131  negatedarrays = NULL;
3132  }
3133 
3134  mult = 1;
3135  retcode = SCIP_OKAY;
3136 
3137  /* print row(s) in OPB format */
3138  if( SCIPisEQ(scip, lhs, rhs) )
3139  {
3140  assert( !SCIPisInfinity(scip, rhs) );
3141 
3142  /* equality constraint */
3143  retcode = printPBRow(scip, file, "=", activelinvars, activelinvals, nactivelinvars, activetermvars,
3144  ntermvars, termvals, ntermvals, negatedarrays, indvar, rhs - activelinconstant, &mult, multisymbol);
3145  }
3146  else
3147  {
3148  if( !SCIPisInfinity(scip, -lhs) )
3149  {
3150  /* print inequality ">=" */
3151  retcode = printPBRow(scip, file, ">=", activelinvars, activelinvals, nactivelinvars, activetermvars,
3152  ntermvars, termvals, ntermvals, negatedarrays, indvar, lhs - activelinconstant, &mult, multisymbol);
3153  }
3154 
3155  if( !SCIPisInfinity(scip, rhs) )
3156  {
3157  mult *= -1;
3158 
3159  /* print inequality ">=" and multiplying all coefficients by -1 */
3160  retcode = printPBRow(scip, file, ">=", activelinvars, activelinvals, nactivelinvars, activetermvars,
3161  ntermvars, termvals, ntermvals, negatedarrays, indvar, rhs - activelinconstant, &mult, multisymbol);
3162  }
3163  }
3164 
3165 
3166  /* free buffers for non-linear arrays */
3167  if( ntermvals > 0 )
3168  {
3169  assert(negatedarrays != NULL);
3170  assert(activetermvars != NULL);
3171 
3172  for( v = 0; v < ntermvals; ++v )
3173  {
3174  assert(negatedarrays[v] != NULL);
3175  assert(activetermvars[v] != NULL);
3176  SCIPfreeBufferArray(scip, &(negatedarrays[v]));
3177  SCIPfreeBufferArray(scip, &(activetermvars[v]));
3178  }
3179  SCIPfreeBufferArray(scip, &negatedarrays);
3180  SCIPfreeBufferArray(scip, &activetermvars);
3181  }
3182 
3183  /* free buffer for linear arrays */
3184  if( nactivelinvars > 0 )
3185  {
3186  SCIPfreeBufferArray(scip, &activelinvars);
3187  SCIPfreeBufferArray(scip, &activelinvals);
3188  }
3189 
3190  return retcode;
3191 }
3192 
3193 
3194 static
3196  SCIP*const scip, /**< SCIP data structure */
3197  FILE*const file, /**< output file, or NULL if standard output should be used */
3198  SCIP_CONS**const conss, /**< array with constraints of the problem */
3199  int const nconss, /**< number of constraints in the problem */
3200  SCIP_VAR**const vars, /**< array with active (binary) variables */
3201  int const nvars, /**< number of active variables in the problem */
3202  SCIP_VAR** const resvars, /**< array of resultant variables */
3203  int const nresvars, /**< number of resultant variables */
3204  SCIP_VAR**const*const andvars, /**< corresponding array of and-variables */
3205  int const*const nandvars, /**< array of numbers of corresponding and-variables */
3206  char const*const multisymbol, /**< the multiplication symbol to use between coefficient and variable */
3207  SCIP_Bool const existandconshdlr, /**< does and-constrainthandler exist? */
3208  SCIP_Bool const existands, /**< does some and-constraints exist? */
3209  SCIP_Bool const transformed /**< TRUE iff problem is the transformed problem */
3210  )
3211 {
3212  SCIP_CONSHDLR* conshdlr;
3213  const char* conshdlrname;
3214  SCIP_CONS* cons;
3215  SCIP_VAR** consvars;
3216  SCIP_Real* consvals;
3217  SCIP_RETCODE retcode;
3218  int nconsvars;
3219  int v, c;
3220  SCIP_HASHMAP* linconssofindicatorsmap = NULL;
3221  SCIP_HASHMAP* linconssofpbsmap = NULL;
3222 
3223  assert(scip != NULL);
3224  assert(file != NULL);
3225  assert(conss != NULL || nconss == 0);
3226  assert(vars != NULL || nvars == 0);
3227  assert(resvars != NULL || nresvars == 0);
3228  assert(andvars != NULL || nandvars == 0);
3229  assert(multisymbol != NULL);
3230 
3231  if( transformed )
3232  {
3233  conshdlr = SCIPfindConshdlr(scip, "indicator");
3234 
3235  /* find artificial linear constraints which correspond to indicator constraints to avoid double printing */
3236  if( conshdlr != NULL )
3237  {
3238  SCIP_CONS** indconss;
3239  int nindconss;
3240 
3241  indconss = SCIPconshdlrGetConss(conshdlr);
3242  nindconss = SCIPconshdlrGetNConss(conshdlr);
3243  assert(indconss != NULL || nindconss == 0);
3244 
3245  if( nindconss > 0 )
3246  {
3247  SCIP_CONS* lincons;
3248 
3249  /* create the linear constraint of indicator constraints hash map */
3250  SCIP_CALL( SCIPhashmapCreate(&linconssofindicatorsmap, SCIPblkmem(scip), nindconss) );
3251  assert(indconss != NULL);
3252 
3253  for( c = 0; c < nindconss; ++c )
3254  {
3255  assert(indconss[c] != NULL);
3256  lincons = SCIPgetLinearConsIndicator(indconss[c]);
3257  assert(lincons != NULL);
3258 
3259  /* insert constraint into mapping between */
3260  SCIP_CALL( SCIPhashmapInsert(linconssofindicatorsmap, (void*)lincons, (void*)lincons) );
3261  }
3262  }
3263  }
3264 
3265  conshdlr = SCIPfindConshdlr(scip, "pseudoboolean");
3266 
3267  /* find artifical linear constraints which correspond to indicator constraints to avoid double printing */
3268  if( conshdlr != NULL )
3269  {
3270  SCIP_CONS** pbconss;
3271  int npbconss;
3272 
3273  pbconss = SCIPconshdlrGetConss(conshdlr);
3274  npbconss = SCIPconshdlrGetNConss(conshdlr);
3275  assert(pbconss != NULL || npbconss == 0);
3276 
3277  if( npbconss > 0 )
3278  {
3279  SCIP_CONS* lincons;
3280 
3281  /* create the linear constraint of indicator constraints hash map */
3282  SCIP_CALL( SCIPhashmapCreate(&linconssofpbsmap, SCIPblkmem(scip), npbconss) );
3283 
3284  for( c = 0; c < npbconss; ++c )
3285  {
3286  assert(pbconss[c] != NULL); /*lint !e613*/
3287  lincons = SCIPgetLinearConsPseudoboolean(scip, pbconss[c]); /*lint !e613*/
3288  assert(lincons != NULL);
3289 
3290  /* insert constraint into mapping between */
3291  SCIP_CALL( SCIPhashmapInsert(linconssofpbsmap, (void*)lincons, (void*)lincons) );
3292  }
3293  }
3294  }
3295  }
3296  /* in original space we cannot ask the constraint handler for its constraints, therefore we have to loop over all
3297  * original to check for artificial linear once
3298  */
3299  else
3300  {
3301  SCIP_CONS* lincons;
3302  SCIP_Bool pbhashmapcreated = FALSE;
3303  SCIP_Bool indhashmapcreated = FALSE;
3304 
3305  /* loop over all constraint for printing */
3306  for( c = 0; c < nconss; ++c )
3307  {
3308  conshdlr = SCIPconsGetHdlr(conss[c]); /*lint !e613*/
3309  assert(conshdlr != NULL);
3310 
3311  conshdlrname = SCIPconshdlrGetName(conshdlr);
3312 
3313  if( strcmp(conshdlrname, "pseudoboolean") == 0 )
3314  {
3315  if( !pbhashmapcreated )
3316  {
3317  /* create the linear constraint of indicator constraints hash map */
3318  SCIP_CALL( SCIPhashmapCreate(&linconssofpbsmap, SCIPblkmem(scip), nconss) );
3319  pbhashmapcreated = TRUE;
3320  }
3321 
3322  lincons = SCIPgetLinearConsPseudoboolean(scip, conss[c]); /*lint !e613*/
3323  assert(lincons != NULL);
3324 
3325  /* insert constraint into mapping between */
3326  SCIP_CALL( SCIPhashmapInsert(linconssofpbsmap, (void*)lincons, (void*)lincons) );
3327  }
3328  else if( strcmp(conshdlrname, "indicator") == 0 )
3329  {
3330  if( !indhashmapcreated )
3331  {
3332  /* create the linear constraint of indicator constraints hash map */
3333  SCIP_CALL( SCIPhashmapCreate(&linconssofindicatorsmap, SCIPblkmem(scip), nconss) );
3334  indhashmapcreated = TRUE;
3335  }
3336 
3337  lincons = SCIPgetLinearConsIndicator(conss[c]); /*lint !e613*/
3338  assert(lincons != NULL);
3339 
3340  /* insert constraint into mapping between */
3341  SCIP_CALL( SCIPhashmapInsert(linconssofindicatorsmap, (void*)lincons, (void*)lincons) );
3342  }
3343  }
3344  }
3345 
3346  retcode = SCIP_OKAY;
3347  cons = NULL;
3348 
3349  /* loop over all constraint for printing */
3350  for( c = 0; c < nconss && retcode == SCIP_OKAY; ++c )
3351  {
3352  SCIP_CONS* artcons;
3353 
3354  artcons = NULL;
3355 
3356  cons = conss[c]; /*lint !e613 */
3357  assert(cons != NULL);
3358 
3359  conshdlr = SCIPconsGetHdlr(cons);
3360  assert(conshdlr != NULL);
3361 
3362  conshdlrname = SCIPconshdlrGetName(conshdlr);
3363  assert(transformed == SCIPconsIsTransformed(cons));
3364 
3365  /* in case the transformed is written only constraint are posted which are enabled in the current node */
3366  assert(!transformed || SCIPconsIsEnabled(cons));
3367 
3368  if( linconssofpbsmap != NULL )
3369  artcons = (SCIP_CONS*) SCIPhashmapGetImage(linconssofpbsmap, (void*)cons);
3370  if( artcons == NULL && linconssofindicatorsmap != NULL )
3371  artcons = (SCIP_CONS*) SCIPhashmapGetImage(linconssofindicatorsmap, (void*)cons);
3372 
3373  if( artcons == NULL )
3374  {
3375  if( strcmp(conshdlrname, "linear") == 0 )
3376  {
3377  if( SCIPgetNVarsLinear(scip, cons) == 0 )
3378  {
3379  if( SCIPisGT(scip, SCIPgetLhsLinear(scip, cons), SCIPgetRhsLinear(scip, cons)) )
3380  {
3381  SCIPerrorMessage("Cannot print empty violated constraint %s, %g <= %g is not fulfilled\n",
3382  SCIPconsGetName(cons), SCIPgetLhsLinear(scip, cons), SCIPgetRhsLinear(scip, cons));
3383  }
3384  continue;
3385  }
3386 
3387  if( existands )
3388  {
3389  retcode = printNonLinearCons(scip, file,
3390  SCIPgetVarsLinear(scip, cons), SCIPgetValsLinear(scip, cons), SCIPgetNVarsLinear(scip, cons),
3391  SCIPgetLhsLinear(scip, cons), SCIPgetRhsLinear(scip, cons), resvars, nresvars, andvars, nandvars,
3392  0LL, transformed, multisymbol);
3393  }
3394  else
3395  {
3396  retcode = printLinearCons(scip, file,
3397  SCIPgetVarsLinear(scip, cons), SCIPgetValsLinear(scip, cons), SCIPgetNVarsLinear(scip, cons),
3398  SCIPgetLhsLinear(scip, cons), SCIPgetRhsLinear(scip, cons), 0LL, transformed, multisymbol);
3399  }
3400  }
3401  else if( strcmp(conshdlrname, "setppc") == 0 )
3402  {
3403  consvars = SCIPgetVarsSetppc(scip, cons);
3404  nconsvars = SCIPgetNVarsSetppc(scip, cons);
3405 
3406  if( nconsvars == 0 )
3407  continue;
3408 
3409  switch( SCIPgetTypeSetppc(scip, cons) )
3410  {
3412  if( existands )
3413  {
3414  retcode = printNonLinearCons(scip, file, consvars, NULL, nconsvars, 1.0, 1.0, resvars, nresvars,
3415  andvars, nandvars, 0LL, transformed, multisymbol);
3416  }
3417  else
3418  {
3419  retcode = printLinearCons(scip, file,
3420  consvars, NULL, nconsvars, 1.0, 1.0, 0LL, transformed, multisymbol);
3421  }
3422  break;
3424  if( existands )
3425  {
3426  retcode = printNonLinearCons(scip, file,
3427  consvars, NULL, nconsvars, -SCIPinfinity(scip), 1.0, resvars, nresvars, andvars, nandvars,
3428  0LL, transformed, multisymbol);
3429  }
3430  else
3431  {
3432  retcode = printLinearCons(scip, file,
3433  consvars, NULL, nconsvars, -SCIPinfinity(scip), 1.0, 0LL, transformed, multisymbol);
3434  }
3435  break;
3437  if( existands )
3438  {
3439  retcode = printNonLinearCons(scip, file,
3440  consvars, NULL, nconsvars, 1.0, SCIPinfinity(scip), resvars, nresvars, andvars, nandvars,
3441  0LL, transformed, multisymbol);
3442  }
3443  else
3444  {
3445  retcode = printLinearCons(scip, file,
3446  consvars, NULL, nconsvars, 1.0, SCIPinfinity(scip), 0LL, transformed, multisymbol);
3447  }
3448  break;
3449  }
3450  }
3451  else if( strcmp(conshdlrname, "logicor") == 0 )
3452  {
3453  if( SCIPgetNVarsLogicor(scip, cons) == 0 )
3454  continue;
3455 
3456  if( existands )
3457  {
3458  retcode = printNonLinearCons(scip, file,
3459  SCIPgetVarsLogicor(scip, cons), NULL, SCIPgetNVarsLogicor(scip, cons), 1.0, SCIPinfinity(scip),
3460  resvars, nresvars, andvars, nandvars, 0LL, transformed, multisymbol);
3461  }
3462  else
3463  {
3464  retcode = printLinearCons(scip, file,
3465  SCIPgetVarsLogicor(scip, cons), NULL, SCIPgetNVarsLogicor(scip, cons),
3466  1.0, SCIPinfinity(scip), 0LL, transformed, multisymbol);
3467  }
3468  }
3469  else if( strcmp(conshdlrname, "knapsack") == 0 )
3470  {
3471  SCIP_Longint* weights;
3472 
3473  consvars = SCIPgetVarsKnapsack(scip, cons);
3474  nconsvars = SCIPgetNVarsKnapsack(scip, cons);
3475 
3476  if( nconsvars == 0 )
3477  continue;
3478 
3479  /* copy Longint array to SCIP_Real array */
3480  weights = SCIPgetWeightsKnapsack(scip, cons);
3481  SCIP_CALL( SCIPallocBufferArray(scip, &consvals, nconsvars) );
3482  for( v = 0; v < nconsvars; ++v )
3483  consvals[v] = (SCIP_Real)weights[v];
3484 
3485  if( existands )
3486  {
3487  retcode = printNonLinearCons(scip, file, consvars, consvals, nconsvars, -SCIPinfinity(scip),
3488  (SCIP_Real) SCIPgetCapacityKnapsack(scip, cons), resvars, nresvars, andvars, nandvars,
3489  0LL, transformed, multisymbol);
3490  }
3491  else
3492  {
3493  retcode = printLinearCons(scip, file, consvars, consvals, nconsvars, -SCIPinfinity(scip),
3494  (SCIP_Real) SCIPgetCapacityKnapsack(scip, cons), 0LL, transformed, multisymbol);
3495  }
3496 
3497  SCIPfreeBufferArray(scip, &consvals);
3498  }
3499  else if( strcmp(conshdlrname, "varbound") == 0 )
3500  {
3501  SCIP_CALL( SCIPallocBufferArray(scip, &consvars, 2) );
3502  SCIP_CALL( SCIPallocBufferArray(scip, &consvals, 2) );
3503 
3504  consvars[0] = SCIPgetVarVarbound(scip, cons);
3505  consvars[1] = SCIPgetVbdvarVarbound(scip, cons);
3506 
3507  consvals[0] = 1.0;
3508  consvals[1] = SCIPgetVbdcoefVarbound(scip, cons);
3509 
3510  if( existands )
3511  {
3512  retcode = printNonLinearCons(scip, file, consvars, consvals, 2, SCIPgetLhsVarbound(scip, cons),
3513  SCIPgetRhsVarbound(scip, cons), resvars, nresvars, andvars, nandvars, 0LL, transformed, multisymbol);
3514  }
3515  else
3516  {
3517  retcode = printLinearCons(scip, file, consvars, consvals, 2, SCIPgetLhsVarbound(scip, cons),
3518  SCIPgetRhsVarbound(scip, cons), 0LL, transformed, multisymbol);
3519  }
3520 
3521  SCIPfreeBufferArray(scip, &consvars);
3522  SCIPfreeBufferArray(scip, &consvals);
3523  }
3524  else if( strcmp(conshdlrname, "pseudoboolean") == 0 )
3525  {
3526  SCIP_VAR*** termvars;
3527  int* ntermvars;
3528  int termvarssize;
3529  SCIP_CONS** andconss;
3530  SCIP_Real* andcoefs ;
3531  SCIP_VAR** linvars;
3532  SCIP_Real* lincoefs ;
3533  int nlinvars;
3534  int t;
3535 
3536  /* get the required array size for the variables array and for the number of variables in each variable array */
3537  termvarssize = SCIPgetNAndsPseudoboolean(scip, cons);
3538  assert(termvarssize >= 0);
3539 
3540  /* allocate temporary memory */
3541  SCIP_CALL( SCIPallocBufferArray(scip, &andconss, termvarssize) );
3542  SCIP_CALL( SCIPallocBufferArray(scip, &termvars, termvarssize) );
3543  SCIP_CALL( SCIPallocBufferArray(scip, &andcoefs, termvarssize) );
3544  SCIP_CALL( SCIPallocBufferArray(scip, &ntermvars, termvarssize) );
3545 
3546  /* get all corresponding and-constraints and therefor all variables */
3547  SCIP_CALL( SCIPgetAndDatasPseudoboolean(scip, cons, andconss, andcoefs, &termvarssize) );
3548  for( t = termvarssize - 1; t >= 0; --t )
3549  {
3550  termvars[t] = SCIPgetVarsAnd(scip, andconss[t]);
3551  ntermvars[t] = SCIPgetNVarsAnd(scip, andconss[t]);
3552  }
3553 
3554  /* gets number of linear variables without artificial terms variables of pseudoboolean constraint */
3555  nlinvars = SCIPgetNLinVarsWithoutAndPseudoboolean(scip, cons);
3556 
3557  /* allocate temporary memory */
3558  SCIP_CALL( SCIPallocBufferArray(scip, &linvars, nlinvars) );
3559  SCIP_CALL( SCIPallocBufferArray(scip, &lincoefs, nlinvars) );
3560 
3561  /* gets linear constraint of pseudoboolean constraint */
3562  SCIP_CALL( SCIPgetLinDatasWithoutAndPseudoboolean(scip, cons, linvars, lincoefs, &nlinvars) );
3563 
3564  retcode = printPseudobooleanCons(scip, file, linvars, lincoefs, nlinvars,
3565  termvars, ntermvars, andcoefs, termvarssize, SCIPgetIndVarPseudoboolean(scip, cons),
3566  SCIPgetLhsPseudoboolean(scip, cons), SCIPgetRhsPseudoboolean(scip, cons), transformed, multisymbol);
3567 
3568  /* free temporary memory */
3569  SCIPfreeBufferArray(scip, &lincoefs);
3570  SCIPfreeBufferArray(scip, &linvars);
3571  SCIPfreeBufferArray(scip, &ntermvars);
3572  SCIPfreeBufferArray(scip, &andcoefs);
3573  SCIPfreeBufferArray(scip, &termvars);
3574  SCIPfreeBufferArray(scip, &andconss);
3575  }
3576  else if( strcmp(conshdlrname, "indicator") == 0 )
3577  {
3578  SCIP_CONS* lincons;
3579  SCIP_VAR* indvar;
3580  SCIP_VAR* slackvar;
3581  SCIP_Longint weight;
3582 
3583  /* get artificial binary indicator variables */
3584  indvar = SCIPgetBinaryVarIndicator(cons);
3585  assert(indvar != NULL);
3586 
3587  if( SCIPvarGetStatus(indvar) == SCIP_VARSTATUS_NEGATED )
3588  {
3589  indvar = SCIPvarGetNegationVar(indvar);
3590  assert(indvar != NULL);
3592 
3593  /* get the soft cost of this constraint */
3594  weight = (SCIP_Longint) SCIPvarGetObj(indvar);
3595  }
3596  else
3597  {
3599 
3600  /* get the soft cost of this constraint */
3601  weight = -(SCIP_Longint) SCIPvarGetObj(indvar);
3602  }
3603 
3604  /* get artificial slack variable */
3605  slackvar = SCIPgetSlackVarIndicator(cons);
3606  assert(slackvar != NULL);
3607 
3608  /* only need to print indicator constraints with weights on their indicator variable */
3609  if( weight != 0 )
3610  {
3611  SCIP_Bool cont;
3612  int nonbinarypos;
3613 
3614  lincons = SCIPgetLinearConsIndicator(cons);
3615  assert(lincons != NULL);
3616 
3617  nconsvars = SCIPgetNVarsLinear(scip, lincons);
3618 
3619  /* allocate temporary memory */
3620  SCIP_CALL( SCIPduplicateBufferArray(scip, &consvars, SCIPgetVarsLinear(scip, lincons), nconsvars) );
3621  SCIP_CALL( SCIPduplicateBufferArray(scip, &consvals, SCIPgetValsLinear(scip, lincons), nconsvars) );
3622 
3623  nonbinarypos = -1;
3624  cont = FALSE;
3625 
3626  /* find non-binary variable */
3627  for( v = 0; v < nconsvars; ++v )
3628  {
3629  if( SCIPvarGetType(consvars[v]) != SCIP_VARTYPE_BINARY )
3630  {
3631  if( consvars[v] == slackvar )
3632  {
3633  assert(nonbinarypos == -1);
3634  nonbinarypos = v;
3635  }
3636  else
3637  {
3638  SCIPwarningMessage(scip, "cannot print linear constraint <%s> of indicator constraint <%s> because it has more than one non-binary variable\n", SCIPconsGetName(lincons), SCIPconsGetName(cons) );
3639  SCIPinfoMessage(scip, file, "* ");
3640  SCIP_CALL( SCIPprintCons(scip, cons, file) );
3641  SCIPinfoMessage(scip, file, ";\n");
3642  cont = TRUE;
3643  break;
3644  }
3645  }
3646  }
3647 
3648  /* if we have not found any non-binary variable we do not print the constraint, maybe we should ??? */
3649  if( nonbinarypos == -1 )
3650  {
3651  SCIPwarningMessage(scip, "cannot print linear constraint <%s> of indicator constraint <%s> because it has no slack variable\n", SCIPconsGetName(lincons), SCIPconsGetName(cons) );
3652  SCIPinfoMessage(scip, file, "* ");
3653  SCIP_CALL( SCIPprintCons(scip, cons, file) );
3654  SCIPinfoMessage(scip, file, ";\n");
3655 
3656  /* free temporary memory */
3657  SCIPfreeBufferArray(scip, &consvals);
3658  SCIPfreeBufferArray(scip, &consvars);
3659  continue;
3660  }
3661 
3662  /* if the constraint has more than two non-binary variables is not printable and we go to the next */
3663  if( cont )
3664  {
3665  /* free temporary memory */
3666  SCIPfreeBufferArray(scip, &consvals);
3667  SCIPfreeBufferArray(scip, &consvars);
3668  continue;
3669  }
3670 
3671  assert(0 <= nonbinarypos && nonbinarypos < nconsvars);
3672 
3673  /* remove slackvariable in linear constraint for printing */
3674  --nconsvars;
3675  consvars[nonbinarypos] = consvars[nconsvars];
3676  consvals[nonbinarypos] = consvals[nconsvars];
3677 
3678  if( existands )
3679  {
3680  retcode = printNonLinearCons(scip, file,
3681  consvars, consvals, nconsvars, SCIPgetLhsLinear(scip, lincons), SCIPgetRhsLinear(scip, lincons),
3682  resvars, nresvars, andvars, nandvars,
3683  weight, transformed, multisymbol);
3684  }
3685  else
3686  {
3687  retcode = printLinearCons(scip, file,
3688  consvars, consvals, nconsvars, SCIPgetLhsLinear(scip, lincons), SCIPgetRhsLinear(scip, lincons),
3689  weight, transformed, multisymbol);
3690  }
3691 
3692  /* free temporary memory */
3693  SCIPfreeBufferArray(scip, &consvals);
3694  SCIPfreeBufferArray(scip, &consvars);
3695  }
3696  else
3697  {
3698  SCIPwarningMessage(scip, "indicator constraint <%s> will not be printed because the indicator variable has no objective value(= weight of this soft constraint)\n", SCIPconsGetName(cons) );
3699  SCIPinfoMessage(scip, file, "* ");
3700  SCIP_CALL( SCIPprintCons(scip, cons, file) );
3701  SCIPinfoMessage(scip, file, ";\n");
3702  }
3703  }
3704  else if( strcmp(conshdlrname, "and") == 0 )
3705  {
3706  /* all resultants of the and constraint will be replaced by all corresponding variables of this constraint,
3707  * so no and-constraint will be printed directly */
3708  assert(existandconshdlr);
3709  }
3710  else
3711  {
3712  SCIPwarningMessage(scip, "constraint handler <%s> cannot print requested format\n", conshdlrname );
3713  SCIPinfoMessage(scip, file, "* ");
3714  SCIP_CALL( SCIPprintCons(scip, cons, file) );
3715  SCIPinfoMessage(scip, file, ";\n");
3716  }
3717  }
3718  }
3719 
3720  if( retcode == SCIP_INVALIDDATA )
3721  {
3722  assert(cons != NULL);
3723 
3724  SCIPerrorMessage("Cannot print constraint %s with non-integral coefficient or sides in opb-format\n",
3725  SCIPconsGetName(cons));
3726  SCIP_CALL( SCIPprintCons(scip, cons, stderr) );
3727  SCIPinfoMessage(scip, file, ";\n");
3728  }
3729 
3730  if( linconssofpbsmap != NULL )
3731  {
3732  /* free hash map */
3733  SCIPhashmapFree(&linconssofpbsmap);
3734  }
3735  if( linconssofindicatorsmap != NULL )
3736  {
3737  /* free hash map */
3738  SCIPhashmapFree(&linconssofindicatorsmap);
3739  }
3740 
3741  return retcode;
3742 }
3743 
3744 /* write fixed variables (unless already done because they are an and resultant or and variable) */
3745 static
3747  SCIP*const scip, /**< SCIP data structure */
3748  FILE*const file, /**< output file, or NULL if standard output should be used */
3749  SCIP_VAR** vars, /**< array with active (binary) variables */
3750  int nvars, /**< number of active variables in the problem */
3751  SCIP_HASHTABLE*const printedfixing, /**< hashmap to store if a fixed variable was already printed */
3752  char const*const multisymbol, /**< the multiplication symbol to use between coefficient and variable */
3753  SCIP_Bool const transformed /**< TRUE iff problem is the transformed problem */
3754  )
3755 {
3756  char linebuffer[OPB_MAX_LINELEN];
3757  char buffer[OPB_MAX_LINELEN];
3758  int linecnt;
3759  int v;
3760 
3761  assert(scip != NULL);
3762  assert(file != NULL);
3763  assert(vars != NULL || nvars == 0);
3764  assert(printedfixing != NULL);
3765  assert(multisymbol != NULL);
3766 
3767  clearBuffer(linebuffer, &linecnt);
3768 
3769  /* print variables which are fixed */
3770  for( v = 0; v < nvars; ++v )
3771  {
3772  SCIP_VAR* var;
3773  SCIP_Real lb;
3774  SCIP_Real ub;
3775  SCIP_Bool neg = FALSE;
3776 
3777  assert( vars != NULL );
3778  var = vars[v];
3779 
3780  if( transformed )
3781  {
3782  /* in case the transformed is written only local bounds are posted which are valid in the current node */
3783  lb = SCIPvarGetLbLocal(var);
3784  ub = SCIPvarGetUbLocal(var);
3785  }
3786  else
3787  {
3788  lb = SCIPvarGetLbOriginal(var);
3789  ub = SCIPvarGetUbOriginal(var);
3790  }
3791  assert(lb > -0.5 && ub < 1.5);
3792  assert(SCIPisFeasIntegral(scip, lb));
3793  assert(SCIPisFeasIntegral(scip, ub));
3794 
3795  /* print fixed and-resultants */
3796  if( lb > 0.5 || ub < 0.5 )
3797  {
3798  if( transformed ) {
3799  SCIP_CALL( SCIPgetBinvarRepresentative(scip, var, &var, &neg) );
3800  }
3801 
3802  if( SCIPhashtableExists(printedfixing, (void*)var) )
3803  continue;
3804 
3805  (void) SCIPsnprintf(buffer, OPB_MAX_LINELEN, "+1%s%s%s = %g ;\n", multisymbol, neg ? "~" : "", strstr(SCIPvarGetName(neg ? SCIPvarGetNegationVar(var) : var), "x"), lb);
3806  appendBuffer(scip, file, linebuffer, &linecnt, buffer);
3807 
3808  /* add variable to the hashmap */
3809  SCIP_CALL( SCIPhashtableInsert(printedfixing, (void*)var) );
3810  }
3811  }
3812 
3813  writeBuffer(scip, file, linebuffer, &linecnt);
3814 
3815  return SCIP_OKAY;
3816 }
3817 
3818 /* write and constraints of inactive but relevant and-resultants and and variables which are fixed to one */
3819 static
3821  SCIP*const scip, /**< SCIP data structure */
3822  FILE*const file, /**< output file, or NULL if standard output should be used */
3823  SCIP_VAR**const resvars, /**< array of resultant variables */
3824  int const nresvars, /**< number of resultant variables */
3825  SCIP_VAR**const*const andvars, /**< corresponding array of and-variables */
3826  int const*const nandvars, /**< array of numbers of corresponding and-variables */
3827  SCIP_HASHTABLE*const printedfixing, /**< hashmap to store if a fixed variable was already printed */
3828  char const*const multisymbol, /**< the multiplication symbol to use between coefficient and variable */
3829  SCIP_Bool const transformed /**< TRUE iff problem is the transformed problem */
3830  )
3831 {
3832  SCIP_VAR* resvar;
3833  SCIP_Longint rhslhs;
3834  char linebuffer[OPB_MAX_LINELEN];
3835  char buffer[OPB_MAX_LINELEN];
3836  int linecnt;
3837  int r, v;
3838 
3839  assert(scip != NULL);
3840  assert(file != NULL);
3841  assert(resvars != NULL || nresvars == 0);
3842  assert(nandvars != NULL || nresvars == 0);
3843  assert(andvars != NULL || nandvars == NULL);
3844  assert(multisymbol != NULL);
3845 
3846  clearBuffer(linebuffer, &linecnt);
3847 
3848  /* print and-variables which are fixed */
3849  /* @todo remove this block here and the hashtable and let writeOpbFixedVars() do the job? */
3850  for( r = nresvars - 1; r >= 0; --r )
3851  {
3852  SCIP_VAR* var;
3853  SCIP_Bool neg;
3854  SCIP_Real lb;
3855  SCIP_Real ub;
3856 
3857  assert( resvars != NULL );
3858  resvar = resvars[r];
3859 
3860  if( transformed )
3861  {
3862  /* in case the transformed is written only local bounds are posted which are valid in the current node */
3863  lb = SCIPvarGetLbLocal(resvar);
3864  ub = SCIPvarGetUbLocal(resvar);
3865  }
3866  else
3867  {
3868  lb = SCIPvarGetLbOriginal(resvar);
3869  ub = SCIPvarGetUbOriginal(resvar);
3870  }
3871 
3872  /* print fixed and-resultants */
3873  if( lb > 0.5 || ub < 0.5 )
3874  {
3875  SCIP_CALL( SCIPgetBinvarRepresentative(scip, resvar, &var, &neg) );
3876 
3877  assert(SCIPisFeasIntegral(scip, lb));
3878  (void) SCIPsnprintf(buffer, OPB_MAX_LINELEN, "+1%s%s%s = %g ;\n", multisymbol, neg ? "~" : "", strstr(SCIPvarGetName(neg ? SCIPvarGetNegationVar(var) : var), "x"), lb);
3879  appendBuffer(scip, file, linebuffer, &linecnt, buffer);
3880 
3881  /* add variable to the hashmap */
3882  SCIP_CALL( SCIPhashtableInsert(printedfixing, (void*)var) );
3883  }
3884 
3885  assert( andvars != NULL && nandvars != NULL );
3886  assert( andvars[r] != NULL || nandvars[r] == 0 );
3887 
3888  /* print fixed and-variables */
3889  for( v = nandvars[r] - 1; v >= 0; --v ) /*lint !e613 */
3890  {
3891  assert( andvars[r] != NULL );
3892  assert( andvars[r][v] != NULL );
3893 
3894  if( transformed )
3895  {
3896  /* in case the transformed is written only local bounds are posted which are valid in the current node */
3897  lb = SCIPvarGetLbLocal(andvars[r][v]);
3898  ub = SCIPvarGetUbLocal(andvars[r][v]);
3899  }
3900  else
3901  {
3902  lb = SCIPvarGetLbOriginal(andvars[r][v]);
3903  ub = SCIPvarGetUbOriginal(andvars[r][v]);
3904  }
3905 
3906  if( lb > 0.5 || ub < 0.5 )
3907  {
3908  SCIP_CALL( SCIPgetBinvarRepresentative(scip, andvars[r][v], &var, &neg) ); /*lint !e613 */
3909 
3910  assert(SCIPisFeasIntegral(scip, lb));
3911  (void) SCIPsnprintf(buffer, OPB_MAX_LINELEN, "+1%s%s%s = %g ;\n", multisymbol, neg ? "~" : "", strstr(SCIPvarGetName(neg ? SCIPvarGetNegationVar(var) : var), "x"), lb);
3912  appendBuffer(scip, file, linebuffer, &linecnt, buffer);
3913 
3914  /* add variable to the hashmap */
3915  SCIP_CALL( SCIPhashtableInsert(printedfixing, (void*)var) );
3916 
3917  }
3918  }
3919  }
3920 
3921  /* print and-constraints with fixed and-resultant to zero and all and-constraints with
3922  * aggregated resultant, otherwise we would loose this information
3923  */
3924  for( r = nresvars - 1; r >= 0; --r )
3925  {
3926  assert( resvars != NULL );
3927  resvar = resvars[r];
3928  rhslhs = (SCIPvarGetUbLocal(resvar) < 0.5) ? 0 : ((SCIPvarGetLbLocal(resvar) > 0.5) ? 1 : -1);
3929 
3930  /* if and resultant is fixed to 0 and at least one and-variable is fixed to zero, we don't print this redundant constraint */
3931  if( rhslhs == 0 )
3932  {
3933  SCIP_Bool cont;
3934 
3935  cont = FALSE;
3936 
3937  assert( andvars != NULL && nandvars != NULL );
3938  assert( andvars[r] != NULL || nandvars[r] == 0 );
3939 
3940  /* if resultant variable and one other and variable is already zero, so we did not need to print this and
3941  * constraint because all other variables are free
3942  */
3943  for( v = nandvars[r] - 1; v >= 0; --v ) /*lint !e613 */
3944  {
3945  assert( andvars[r] != NULL );
3946  assert( andvars[r][v] != NULL );
3947 
3948  if( SCIPvarGetUbLocal(andvars[r][v]) < 0.5 ) /*lint !e613 */
3949  {
3950  cont = TRUE;
3951  break;
3952  }
3953  }
3954 
3955  if( cont )
3956  continue;
3957  }
3958  /* if and resultant is fixed to 1 and all and-variable are fixed to 1 too, we don't print this redundant constraint */
3959  else if( rhslhs == 1 )
3960  {
3961  SCIP_Bool cont;
3962 
3963  cont = TRUE;
3964 
3965  assert( andvars != NULL && nandvars != NULL );
3966  assert( andvars[r] != NULL || nandvars[r] == 0 );
3967 
3968  /* if all variables are already fixed to one, we do not need to print this and constraint */
3969  for( v = nandvars[r] - 1; v >= 0; --v )
3970  {
3971  assert( andvars[r] != NULL );
3972  assert( andvars[r][v] != NULL );
3973 
3974  if( SCIPvarGetLbLocal(andvars[r][v]) < 0.5 ) /*lint !e613 */
3975  {
3976  cont = FALSE;
3977  break;
3978  }
3979  }
3980 
3981  if( cont )
3982  continue;
3983  }
3984 
3985 
3986  /* print and with fixed or aggregated and-resultant */
3987  /* rhslhs equals to 0 means the and constraint is relevant due to it's not clear on which values the and variables are
3988  * rhslhs equals to 1 means the and constraint is irrelevant cause all and variables have to be 1 too
3989  * rhslhs equals to -1 means the and constraint is relevant cause the variable is only aggregated */
3990  if( !SCIPvarIsActive(resvar) )
3991  {
3992  SCIP_VAR* var;
3993  SCIP_Bool neg;
3994  SCIP_Bool firstprinted;
3995 
3996  firstprinted = FALSE;
3997 
3998  assert( andvars != NULL && nandvars != NULL );
3999  assert( andvars[r] != NULL || nandvars[r] == 0 );
4000 
4001  for( v = nandvars[r] - 1; v >= 0; --v )
4002  {
4003  assert( andvars[r] != NULL );
4004  assert( andvars[r][v] != NULL );
4005 
4006  SCIP_CALL( SCIPgetBinvarRepresentative(scip, andvars[r][v], &var, &neg) ); /*lint !e613 */
4007 
4008  (void) SCIPsnprintf(buffer, OPB_MAX_LINELEN, "%s%s%s", (firstprinted) ? multisymbol : "", neg ? "~" : "", strstr(SCIPvarGetName(neg ? SCIPvarGetNegationVar(var) : var), "x"));
4009  appendBuffer(scip, file, linebuffer, &linecnt, buffer);
4010 
4011  firstprinted = TRUE;
4012  }
4013 
4014  /* if the resultant is aggregated we need to print his binary representation */
4015  if( rhslhs == -1 )
4016  {
4017  int pos;
4018 
4019  assert(transformed);
4020 
4021  SCIP_CALL( SCIPgetBinvarRepresentative(scip, resvar, &resvar, &neg) );
4022 
4023 #ifndef NDEBUG
4024  if( neg )
4025  assert(SCIPvarIsActive(SCIPvarGetNegationVar(resvar)));
4026  else
4027  assert(SCIPvarIsActive(resvar));
4028 #endif
4029 
4030  /* replace and-resultant with corresponding variables */
4031  if( SCIPsortedvecFindPtr((void**)resvars, SCIPvarComp, neg ? SCIPvarGetNegationVar(resvar) : resvar, nresvars, &pos) )
4032  {
4033  SCIP_Bool negated;
4034  int a;
4035 
4036  assert(andvars != NULL);
4037  assert(nandvars != NULL);
4038  assert(pos >= 0 && nandvars[pos] > 0 && andvars[pos] != NULL);
4039  assert(andvars[pos][nandvars[pos] - 1] != NULL);
4040 
4041  negated = SCIPvarIsNegated(andvars[pos][nandvars[pos] - 1]);
4042 
4043  /* print and-vars */
4044  (void) SCIPsnprintf(buffer, OPB_MAX_LINELEN, neg ? " +1%s%s%s" : " -1%s%s%s", multisymbol, negated ? "~" : "",
4045  strstr(SCIPvarGetName(negated ? SCIPvarGetNegationVar(andvars[pos][nandvars[pos] - 1]) : andvars[pos][nandvars[pos] - 1]), "x"));
4046  appendBuffer(scip, file, linebuffer, &linecnt, buffer);
4047 
4048  for(a = nandvars[pos] - 2; a >= 0; --a )
4049  {
4050  negated = SCIPvarIsNegated(andvars[pos][a]);
4051 
4052  (void) SCIPsnprintf(buffer, OPB_MAX_LINELEN, "%s%s%s", multisymbol, negated ? "~" : "", strstr(SCIPvarGetName(negated ? SCIPvarGetNegationVar(andvars[pos][a]) : andvars[pos][a]), "x"));
4053  appendBuffer(scip, file, linebuffer, &linecnt, buffer);
4054  }
4055 
4056  appendBuffer(scip, file, linebuffer, &linecnt, " ");
4057 
4058  if( neg )
4059  rhslhs = 1;
4060  else
4061  rhslhs = 0;
4062  }
4063  else
4064  {
4065  (void) SCIPsnprintf(buffer, OPB_MAX_LINELEN, " -1%s%s%s", multisymbol, neg ? "~" : "",
4066  strstr(SCIPvarGetName(neg ? SCIPvarGetNegationVar(resvar) : resvar), "x"));
4067  appendBuffer(scip, file, linebuffer, &linecnt, buffer);
4068 
4069  rhslhs = 0;
4070  }
4071  }
4072 
4073  /* print rhslhs */
4074  (void) SCIPsnprintf(buffer, OPB_MAX_LINELEN, " = %" SCIP_LONGINT_FORMAT " ;\n", rhslhs);
4075  appendBuffer(scip, file, linebuffer, &linecnt, buffer);
4076 
4077  writeBuffer(scip, file, linebuffer, &linecnt);
4078 
4079  }
4080  }
4081 
4082  return SCIP_OKAY;
4083 }
4084 
4085 /* writes problem to file */
4086 static
4088  SCIP* scip, /**< SCIP data structure */
4089  FILE* file, /**< output file, or NULL if standard output should be used */
4090  const char* name, /**< problem name */
4091  SCIP_Bool transformed, /**< TRUE iff problem is the transformed problem */
4092  SCIP_OBJSENSE objsense, /**< objective sense */
4093  SCIP_Real objscale, /**< scalar applied to objective function; external objective value is
4094  * extobj = objsense * objscale * (intobj + objoffset) */
4095  SCIP_Real objoffset, /**< objective offset from bound shifting and fixing */
4096  SCIP_VAR** vars, /**< array with active (binary) variables */
4097  int nvars, /**< number of active variables in the problem */
4098  SCIP_CONS** conss, /**< array with constraints of the problem */
4099  int nconss, /**< number of constraints in the problem */
4100  SCIP_VAR** const resvars, /**< array of resultant variables */
4101  int const nresvars, /**< number of resultant variables */
4102  SCIP_VAR**const*const andvars, /**< corresponding array of and-variables */
4103  int const*const nandvars, /**< array of numbers of corresponding and-variables */
4104  SCIP_Bool const existandconshdlr, /**< does and-constrainthandler exist? */
4105  SCIP_Bool const existands, /**< does some and-constraints exist? */
4106  SCIP_RESULT* result /**< pointer to store the result of the file writing call */
4107  )
4108 {
4109  char multisymbol[OPB_MAX_LINELEN];
4110  SCIP_HASHTABLE* printedfixing;
4111  SCIP_Bool usesymbol;
4112  SCIP_RETCODE retcode;
4113 
4114  assert( scip != NULL );
4115  assert( vars != NULL || nvars == 0 );
4116  assert( conss != NULL || nconss == 0 );
4117  assert( result != NULL );
4118 
4119  /* check if should use a multipliers symbol star '*' between coefficients and variables */
4120  SCIP_CALL( SCIPgetBoolParam(scip, "reading/" READER_NAME "/multisymbol", &usesymbol) );
4121  (void) SCIPsnprintf(multisymbol, OPB_MAX_LINELEN, "%s", usesymbol ? " * " : " ");
4122 
4123  /* print statistics as comment to file */
4124  SCIPinfoMessage(scip, file, "* SCIP STATISTICS\n");
4125  SCIPinfoMessage(scip, file, "* Problem name : %s\n", name);
4126  SCIPinfoMessage(scip, file, "* Variables : %d (all binary)\n", nvars);
4127  SCIPinfoMessage(scip, file, "* Constraints : %d\n", nconss);
4128 
4129  /* create a hash table */
4130  SCIP_CALL( SCIPhashtableCreate(&printedfixing, SCIPblkmem(scip), nvars,
4131  SCIPvarGetHashkey, SCIPvarIsHashkeyEq, SCIPvarGetHashkeyVal, NULL) );
4132 
4133  /* write objective function */
4134  SCIP_CALL( writeOpbObjective(scip, file, vars, nvars, resvars, nresvars, andvars, nandvars,
4135  objsense, objscale, objoffset, multisymbol, existands, transformed) );
4136 
4137  /* write constraints */
4138  retcode = writeOpbConstraints(scip, file, conss, nconss, vars, nvars, resvars, nresvars, andvars, nandvars,
4139  multisymbol, existandconshdlr, existands, transformed);
4140 
4141  if( existands && (retcode == SCIP_OKAY) )
4142  {
4143  /* write and constraints of inactive but relevant and-resultants and and-variables which are fixed to one
4144  with no fixed and resultant */
4145  SCIP_CALL( writeOpbRelevantAnds(scip, file, resvars, nresvars, andvars, nandvars, printedfixing, multisymbol, transformed) );
4146  }
4147 
4148  /* write fixed variables */
4149  SCIP_CALL( writeOpbFixedVars(scip, file, vars, nvars, printedfixing, multisymbol, transformed) );
4150 
4151  SCIPhashtableFree(&printedfixing);
4152 
4153  *result = SCIP_SUCCESS;
4154 
4155  return retcode;
4156 }
4157 
4158 
4159 /*
4160  * extern methods
4161  */
4162 
4163 /** reads problem from file */
4165  SCIP* scip, /**< SCIP data structure */
4166  SCIP_READER* reader, /**< the file reader itself */
4167  const char* filename, /**< full path and name of file to read, or NULL if stdin should be used */
4168  SCIP_RESULT* result /**< pointer to store the result of the file reading call */
4169  )
4170 { /*lint --e{715}*/
4171  OPBINPUT opbinput;
4172  SCIP_RETCODE retcode;
4173  int i;
4174 
4175  /* initialize OPB input data */
4176  opbinput.file = NULL;
4177  opbinput.linebuf[0] = '\0';
4178  SCIP_CALL( SCIPallocBufferArray(scip, &opbinput.token, OPB_MAX_LINELEN) );
4179  opbinput.token[0] = '\0';
4180  SCIP_CALL( SCIPallocBufferArray(scip, &opbinput.tokenbuf, OPB_MAX_LINELEN) );
4181  opbinput.tokenbuf[0] = '\0';
4182  for( i = 0; i < OPB_MAX_PUSHEDTOKENS; ++i )
4183  {
4184  SCIP_CALL( SCIPallocBufferArray(scip, &(opbinput.pushedtokens[i]), OPB_MAX_LINELEN) ); /*lint !e866 */
4185  }
4186 
4187  opbinput.npushedtokens = 0;
4188  opbinput.linenumber = 1;
4189  opbinput.bufpos = 0;
4190  opbinput.linepos = 0;
4191  opbinput.objsense = SCIP_OBJSENSE_MINIMIZE;
4192  opbinput.comment = FALSE;
4193  opbinput.endline = FALSE;
4194  opbinput.eof = FALSE;
4195  opbinput.haserror = FALSE;
4196  opbinput.nproblemcoeffs = 0;
4197  opbinput.wbo = FALSE;
4198  opbinput.topcost = -SCIPinfinity(scip);
4199  opbinput.nindvars = 0;
4200 #if GENCONSNAMES == TRUE
4201  opbinput.consnumber = 0;
4202 #endif
4203 
4204  /* read the file */
4205  retcode = readOPBFile(scip, &opbinput, filename);
4206 
4207  /* free dynamically allocated memory */
4208  for( i = OPB_MAX_PUSHEDTOKENS - 1; i >= 0; --i )
4209  {
4210  SCIPfreeBufferArrayNull(scip, &(opbinput.pushedtokens[i]));
4211  }
4212  SCIPfreeBufferArrayNull(scip, &opbinput.tokenbuf);
4213  SCIPfreeBufferArrayNull(scip, &opbinput.token);
4214 
4215  if( retcode == SCIP_PLUGINNOTFOUND )
4216  retcode = SCIP_READERROR;
4217 
4218  SCIP_CALL( retcode );
4219 
4220  if( opbinput.nproblemcoeffs > 0 )
4221  {
4222  SCIPwarningMessage(scip, "there might be <%d> coefficients or weight out of range!\n", opbinput.nproblemcoeffs);
4223  }
4224 
4225  /* evaluate the result */
4226  if( opbinput.haserror )
4227  return SCIP_READERROR;
4228  else
4229  {
4230  /* set objective sense */
4231  SCIP_CALL( SCIPsetObjsense(scip, opbinput.objsense) );
4232  *result = SCIP_SUCCESS;
4233  }
4234 
4235  return SCIP_OKAY;
4236 }
4237 
4238 /** writes problem to file */
4240  SCIP* scip, /**< SCIP data structure */
4241  FILE* file, /**< output file, or NULL if standard output should be used */
4242  const char* name, /**< problem name */
4243  SCIP_Bool transformed, /**< TRUE iff problem is the transformed problem */
4244  SCIP_OBJSENSE objsense, /**< objective sense */
4245  SCIP_Real objscale, /**< scalar applied to objective function; external objective value is
4246  * extobj = objsense * objscale * (intobj + objoffset) */
4247  SCIP_Real objoffset, /**< objective offset from bound shifting and fixing */
4248  SCIP_VAR** vars, /**< array with active variables ordered binary, integer, implicit, continuous */
4249  int nvars, /**< number of active variables in the problem */
4250  int nbinvars, /**< number of binary variables */
4251  int nintvars, /**< number of general integer variables */
4252  int nimplvars, /**< number of implicit integer variables */
4253  int ncontvars, /**< number of continuous variables */
4254  SCIP_VAR** fixedvars, /**< array with fixed variables */
4255  int nfixedvars, /**< number of fixed and aggregated variables in the problem */
4256  SCIP_CONS** conss, /**< array with constraints of the problem */
4257  int nconss, /**< number of constraints in the problem */
4258  SCIP_Bool genericnames, /**< should generic variable and constraint names be used */
4259  SCIP_RESULT* result /**< pointer to store the result of the file writing call */
4260  )
4261 { /*lint --e{715}*/
4262  SCIP_RETCODE retcode = SCIP_OKAY;
4263 
4264  if( nvars != nbinvars && ncontvars + nimplvars + nbinvars != nvars && ncontvars + nimplvars != ( (SCIPfindConshdlr(scip, "indicator") != NULL) ? SCIPconshdlrGetNConss(SCIPfindConshdlr(scip, "indicator")) : 0 ) )
4265  {
4266  SCIPwarningMessage(scip, "OPB format is only capable for binary problems.\n");
4267  *result = SCIP_DIDNOTRUN;
4268  }
4269  else
4270  {
4271  SCIP_VAR*** andvars;
4272  SCIP_VAR** resvars;
4273  int* nandvars;
4274  SCIP_Bool existands;
4275  SCIP_Bool existandconshdlr;
4276  int nresvars;
4277  int v;
4278 
4279  /* computes all and-resultants and their corresponding constraint variables */
4280  SCIP_CALL( computeAndConstraintInfos(scip, transformed, &resvars, &nresvars, &andvars, &nandvars, &existandconshdlr, &existands) );
4281 
4282  if( genericnames )
4283  {
4284 #ifndef NDEBUG
4285  /* check for correct names for opb-format */
4286  int idx;
4287  int pos;
4288 
4289  for( v = nvars - 1; v >= 0; --v )
4290  {
4291  if( existands )
4292  {
4293  /* and variables are artificial */
4294  if( SCIPsortedvecFindPtr((void**)resvars, SCIPvarComp, vars[v], nresvars, &pos) )
4295  continue;
4296  }
4297 
4298  assert(sscanf(SCIPvarGetName(vars[v]), "x%d", &idx) == 1);
4299  }
4300 #endif
4301  retcode = writeOpb(scip, file, name, transformed, objsense, objscale, objoffset, vars,
4302  nvars, conss, nconss, resvars, nresvars, andvars, nandvars, existandconshdlr, existands, result);
4303  }
4304  else
4305  {
4306  SCIP_Bool printed;
4307  int idx;
4308  int pos;
4309 
4310  printed = FALSE;
4311 
4312  /* check if there are already generic names for all (not fixed variables)*/
4313  for( v = nvars - 1; v >= 0; --v )
4314  if( !existands || !SCIPsortedvecFindPtr((void**)resvars, SCIPvarComp, vars[v], nresvars, &pos) )
4315  {
4316  if( sscanf(SCIPvarGetName(vars[v]), transformed ? "t_x%d" : "x%d", &idx) != 1 && strstr(SCIPvarGetName(vars[v]), INDICATORVARNAME) == NULL && strstr(SCIPvarGetName(vars[v]), INDICATORSLACKVARNAME) == NULL )
4317  {
4318  SCIPwarningMessage(scip, "At least following variable name isn't allowed in opb format.\n");
4319  SCIP_CALL( SCIPprintVar(scip, vars[v], NULL) );
4320  SCIPwarningMessage(scip, "OPB format needs generic variable names!\n");
4321 
4322  if( transformed )
4323  {
4324  SCIPwarningMessage(scip, "write transformed problem with generic variable names.\n");
4325  SCIP_CALL( SCIPprintTransProblem(scip, file, "opb", TRUE) );
4326  }
4327  else
4328  {
4329  SCIPwarningMessage(scip, "write original problem with generic variable names.\n");
4330  SCIP_CALL( SCIPprintOrigProblem(scip, file, "opb", TRUE) );
4331  }
4332  printed = TRUE;
4333  break;
4334  }
4335  }
4336 
4337  if( !printed )
4338  {
4339  /* check if there are already generic names for all (fixed variables)*/
4340  for( v = nfixedvars - 1; v >= 0; --v )
4341  if( !existands || !SCIPsortedvecFindPtr((void**)resvars, SCIPvarComp, vars[v], nresvars, &pos) )
4342  {
4343  if( sscanf(SCIPvarGetName(fixedvars[v]), transformed ? "t_x%d" : "x%d", &idx) != 1 && strstr(SCIPvarGetName(fixedvars[v]), INDICATORVARNAME) == NULL && strstr(SCIPvarGetName(fixedvars[v]), INDICATORSLACKVARNAME) == NULL )
4344  {
4345  SCIPwarningMessage(scip, "At least following variable name isn't allowed in opb format.\n");
4346  SCIP_CALL( SCIPprintVar(scip, fixedvars[v], NULL) );
4347  SCIPwarningMessage(scip, "OPB format needs generic variable names!\n");
4348 
4349  if( transformed )
4350  {
4351  SCIPwarningMessage(scip, "write transformed problem with generic variable names.\n");
4352  SCIP_CALL( SCIPprintTransProblem(scip, file, "opb", TRUE) );
4353  }
4354  else
4355  {
4356  SCIPwarningMessage(scip, "write original problem with generic variable names.\n");
4357  SCIP_CALL( SCIPprintOrigProblem(scip, file, "opb", TRUE) );
4358  }
4359  printed = TRUE;
4360  break;
4361  }
4362  }
4363  }
4364 
4365  if( !printed )
4366  {
4367 #ifndef NDEBUG
4368  for( v = nvars - 1; v >= 0; --v )
4369  {
4370  if( existands )
4371  {
4372  if( SCIPsortedvecFindPtr((void**)resvars, SCIPvarComp, vars[v], nresvars, &pos) )
4373  continue;
4374  }
4375 
4376  assert(sscanf(SCIPvarGetName(vars[v]), transformed ? "t_x%d" : "x%d", &idx) == 1 || strstr(SCIPvarGetName(vars[v]), INDICATORVARNAME) != NULL || strstr(SCIPvarGetName(vars[v]), INDICATORSLACKVARNAME) != NULL );
4377  }
4378 #endif
4379  retcode = writeOpb(scip, file, name, transformed, objsense, objscale, objoffset, vars,
4380  nvars, conss, nconss, resvars, nresvars, andvars, nandvars, existandconshdlr, existands, result);
4381  }
4382  }
4383 
4384  if( existands )
4385  {
4386  /* free temporary buffers */
4387  assert(resvars != NULL);
4388  assert(andvars != NULL);
4389  assert(nandvars != NULL);
4390 
4391  for( v = nresvars - 1; v >= 0; --v )
4392  {
4393  assert(andvars[v] != NULL);
4394  SCIPfreeMemoryArray(scip, &andvars[v]);
4395  }
4396  SCIPfreeMemoryArray(scip, &nandvars);
4397  SCIPfreeMemoryArray(scip, &andvars);
4398  SCIPfreeMemoryArray(scip, &resvars);
4399  }
4400 
4401  *result = SCIP_SUCCESS;
4402  }
4403 
4404  if( retcode == SCIP_INVALIDDATA )
4405  return SCIP_WRITEERROR;
4406 
4407  return retcode;
4408 }
4409 
4410 /*
4411  * Callback methods of reader
4412  */
4413 
4414 /** copy method for reader plugins (called when SCIP copies plugins) */
4415 static
4416 SCIP_DECL_READERCOPY(readerCopyOpb)
4417 { /*lint --e{715}*/
4418  assert(scip != NULL);
4419  assert(reader != NULL);
4420  assert(strcmp(SCIPreaderGetName(reader), READER_NAME) == 0);
4421 
4422  /* call inclusion method of reader */
4424 
4425  return SCIP_OKAY;
4426 }
4427 
4428 
4429 /** problem reading method of reader */
4430 static
4431 SCIP_DECL_READERREAD(readerReadOpb)
4432 { /*lint --e{715}*/
4433 
4434  SCIP_CALL( SCIPreadOpb(scip, reader, filename, result) );
4435 
4436  return SCIP_OKAY;
4437 }
4438 
4439 
4440 /** problem writing method of reader */
4441 static
4442 SCIP_DECL_READERWRITE(readerWriteOpb)
4443 { /*lint --e{715}*/
4444 
4445  SCIP_CALL( SCIPwriteOpb(scip, file, name, transformed, objsense, objscale, objoffset, vars,
4446  nvars, nbinvars, nintvars, nimplvars, ncontvars, fixedvars, nfixedvars, conss, nconss, genericnames, result) );
4447 
4448  return SCIP_OKAY;
4449 }
4450 
4451 /*
4452  * reader specific interface methods
4453  */
4454 
4455 /** includes the opb file reader in SCIP */
4457  SCIP* scip /**< SCIP data structure */
4458  )
4459 {
4460  SCIP_READER* reader;
4461 
4462  /* include reader */
4464 
4465  /* set non fundamental callbacks via setter functions */
4466  SCIP_CALL( SCIPsetReaderCopy(scip, reader, readerCopyOpb) );
4467  SCIP_CALL( SCIPsetReaderRead(scip, reader, readerReadOpb) );
4468  SCIP_CALL( SCIPsetReaderWrite(scip, reader, readerWriteOpb) );
4469 
4470  /* add opb reader parameters */
4472  "reading/" READER_NAME "/dynamicconss", "should model constraints be subject to aging?",
4473  NULL, FALSE, FALSE/*TRUE*/, NULL, NULL) ); /* have to be FALSE, otherwise an error might inccur in restart during branch and bound */
4475  "reading/" READER_NAME "/multisymbol", "use '*' between coefficients and variables by writing to problem?",
4476  NULL, TRUE, FALSE, NULL, NULL) );
4477 
4478  return SCIP_OKAY;
4479 }
enum SCIP_Result SCIP_RESULT
Definition: type_result.h:52
SCIP_Bool SCIPisFeasZero(SCIP *scip, SCIP_Real val)
Definition: scip.c:46385
SCIP_RETCODE SCIPincludeReaderOpb(SCIP *scip)
Definition: reader_opb.c:4456
#define ARTIFICIALVARNAMEPREFIX
SCIP_Bool SCIPconsIsEnabled(SCIP_CONS *cons)
Definition: cons.c:7978
static void swapTokenBuffer(OPBINPUT *opbinput)
Definition: reader_opb.c:539
int SCIPmemccpy(char *dest, const char *src, char stop, unsigned int cnt)
Definition: misc.c:9252
SCIP_Bool SCIPisFeasEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:46320
#define READER_DESC
Definition: reader_opb.c:102
#define INDICATORVARNAME
Definition: reader_opb.c:111
SCIP_RETCODE SCIPgetBinvarRepresentative(SCIP *scip, SCIP_VAR *var, SCIP_VAR **repvar, SCIP_Bool *negated)
Definition: scip.c:18810
static SCIP_RETCODE printNLRow(SCIP *const scip, FILE *const file, char const *const type, SCIP_VAR **const vars, SCIP_Real const *const vals, int const nvars, SCIP_Real lhs, SCIP_VAR **const resvars, int const nresvars, SCIP_VAR **const *const andvars, int const *const nandvars, SCIP_Longint weight, SCIP_Longint *const mult, char const *const multisymbol)
Definition: reader_opb.c:2490
Constraint handler for variable bound constraints .
static SCIP_RETCODE writeOpb(SCIP *scip, FILE *file, const char *name, SCIP_Bool transformed, SCIP_OBJSENSE objsense, SCIP_Real objscale, SCIP_Real objoffset, SCIP_VAR **vars, int nvars, SCIP_CONS **conss, int nconss, SCIP_VAR **const resvars, int const nresvars, SCIP_VAR **const *const andvars, int const *const nandvars, SCIP_Bool const existandconshdlr, SCIP_Bool const existands, SCIP_RESULT *result)
Definition: reader_opb.c:4087
SCIP_RETCODE SCIPhashtableInsert(SCIP_HASHTABLE *hashtable, void *element)
Definition: misc.c:2253
SCIP_RETCODE SCIPaddOrigObjoffset(SCIP *scip, SCIP_Real addval)
Definition: scip.c:10982
SCIP_CONSHDLR * SCIPfindConshdlr(SCIP *scip, const char *name)
Definition: scip.c:6576
SCIP_RETCODE SCIPgetAndDatasPseudoboolean(SCIP *const scip, SCIP_CONS *const cons, SCIP_CONS **const andconss, SCIP_Real *const andcoefs, int *const nandconss)
static SCIP_RETCODE readCoefficients(SCIP *const scip, OPBINPUT *const opbinput, char *const name, SCIP_VAR ***linvars, SCIP_Real **lincoefs, int *const nlincoefs, SCIP_VAR ****terms, SCIP_Real **termcoefs, int **ntermvars, int *const ntermcoefs, SCIP_Bool *const newsection, SCIP_Bool *const isNonlinear, SCIP_Bool *const issoftcons, SCIP_Real *const weight)
Definition: reader_opb.c:796
int SCIPgetNVarsSetppc(SCIP *scip, SCIP_CONS *cons)
Definition: cons_setppc.c:9172
int SCIPgetNVarsLogicor(SCIP *scip, SCIP_CONS *cons)
#define SCIP_MAXSTRLEN
Definition: def.h:225
static SCIP_Bool isDelimChar(char c)
Definition: reader_opb.c:209
SCIP_RETCODE SCIPcreateProb(SCIP *scip, const char *name, SCIP_DECL_PROBDELORIG((*probdelorig)), SCIP_DECL_PROBTRANS((*probtrans)), SCIP_DECL_PROBDELTRANS((*probdeltrans)), SCIP_DECL_PROBINITSOL((*probinitsol)), SCIP_DECL_PROBEXITSOL((*probexitsol)), SCIP_DECL_PROBCOPY((*probcopy)), SCIP_PROBDATA *probdata)
Definition: scip.c:9813
int SCIPcalcMemGrowSize(SCIP *scip, int num)
Definition: scip.c:45835
#define INDICATORSLACKVARNAME
Definition: reader_opb.c:112
SCIP_Real SCIPvarGetLbLocal(SCIP_VAR *var)
Definition: var.c:17225
SCIP_RETCODE SCIPprintTransProblem(SCIP *scip, FILE *file, const char *extension, SCIP_Bool genericnames)
Definition: scip.c:43536
static SCIP_RETCODE getMaxAndConsDim(SCIP *scip, OPBINPUT *opbinput, const char *filename)
Definition: reader_opb.c:1575
static SCIP_RETCODE getBinVarsRepresentatives(SCIP *const scip, SCIP_VAR **const vars, int const nvars, SCIP_Bool const transformed)
Definition: reader_opb.c:1753
const char * SCIPreaderGetName(SCIP_READER *reader)
Definition: reader.c:515
SCIP_RETCODE SCIPreleaseVar(SCIP *scip, SCIP_VAR **var)
Definition: scip.c:18461
constraint handler for indicator constraints
SCIP_Bool SCIPisFeasGE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:46372
SCIP_CONS ** SCIPconshdlrGetConss(SCIP_CONSHDLR *conshdlr)
Definition: cons.c:4485
#define FALSE
Definition: def.h:64
SCIP_RETCODE SCIPhashmapCreate(SCIP_HASHMAP **hashmap, BMS_BLKMEM *blkmem, int mapsize)
Definition: misc.c:2764
SCIP_Real SCIPinfinity(SCIP *scip)
Definition: scip.c:46050
int SCIPsnprintf(char *t, int len, const char *s,...)
Definition: misc.c:9340
#define TRUE
Definition: def.h:63
#define SCIPdebug(x)
Definition: pub_message.h:74
enum SCIP_Retcode SCIP_RETCODE
Definition: type_retcode.h:53
#define OPB_INIT_COEFSSIZE
Definition: reader_opb.c:120
void SCIPsortPtrPtrInt(void **ptrarray1, void **ptrarray2, int *intarray, SCIP_DECL_SORTPTRCOMP((*ptrcomp)), int len)
SCIP_RETCODE SCIPcreateConsPseudoboolean(SCIP *scip, SCIP_CONS **cons, const char *name, SCIP_VAR **linvars, int nlinvars, SCIP_Real *linvals, SCIP_VAR ***terms, int nterms, int *ntermvars, SCIP_Real *termvals, SCIP_VAR *indvar, SCIP_Real weight, SCIP_Bool issoftcons, SCIP_VAR *intvar, SCIP_Real lhs, SCIP_Real rhs, SCIP_Bool initial, SCIP_Bool separate, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool propagate, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool dynamic, SCIP_Bool removable, SCIP_Bool stickingatnode)
SCIP_Bool SCIPconsIsTransformed(SCIP_CONS *cons)
Definition: cons.c:8190
SCIP_VAR ** SCIPgetVarsKnapsack(SCIP *scip, SCIP_CONS *cons)
static SCIP_RETCODE printPBRow(SCIP *const scip, FILE *const file, const char *type, SCIP_VAR **const linvars, SCIP_Real *const linvals, int const nlinvars, SCIP_VAR ***const termvars, int *const ntermvars, SCIP_Real *const termvals, int const ntermvals, SCIP_Bool **const negatedarrays, SCIP_VAR *const indvar, SCIP_Real lhs, SCIP_Longint *mult, const char *multisymbol)
Definition: reader_opb.c:2906
static void pushBufferToken(OPBINPUT *opbinput)
Definition: reader_opb.c:526
#define TOPCOSTCONSNAME
Definition: reader_opb.c:113
static SCIP_DECL_READERCOPY(readerCopyOpb)
Definition: reader_opb.c:4416
enum OpbExpType OPBEXPTYPE
Definition: reader_opb.c:129
Constraint handler for AND constraints, .
#define SCIPduplicateBufferArray(scip, ptr, source, num)
Definition: scip.h:21999
void * SCIPhashmapGetImage(SCIP_HASHMAP *hashmap, void *origin)
Definition: misc.c:2902
SCIP_Bool SCIPisEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:45985
SCIP_VAR * SCIPgetIndVarPseudoboolean(SCIP *const scip, SCIP_CONS *const cons)
#define SCIP_LONGINT_MAX
Definition: def.h:131
#define SCIPfreeBufferArray(scip, ptr)
Definition: scip.h:22003
SCIP_RETCODE SCIPreadOpb(SCIP *scip, SCIP_READER *reader, const char *filename, SCIP_RESULT *result)
Definition: reader_opb.c:4164
Constraint handler for the set partitioning / packing / covering constraints .
#define SCIPdebugPrintCons(x, y, z)
Definition: pub_message.h:83
SCIP_VAR * SCIPvarGetNegationVar(SCIP_VAR *var)
Definition: var.c:16995
void SCIPwarningMessage(SCIP *scip, const char *formatstr,...)
Definition: scip.c:1260
static SCIP_RETCODE writeOpbConstraints(SCIP *const scip, FILE *const file, SCIP_CONS **const conss, int const nconss, SCIP_VAR **const vars, int const nvars, SCIP_VAR **const resvars, int const nresvars, SCIP_VAR **const *const andvars, int const *const nandvars, char const *const multisymbol, SCIP_Bool const existandconshdlr, SCIP_Bool const existands, SCIP_Bool const transformed)
Definition: reader_opb.c:3195
int SCIPfseek(SCIP_FILE *stream, long offset, int whence)
Definition: fileio.c:199
#define SCIPdebugMsgPrint
Definition: scip.h:452
#define SCIPdebugMsg
Definition: scip.h:451
SCIP_Real SCIPgetRhsLinear(SCIP *scip, SCIP_CONS *cons)
void SCIPinfoMessage(SCIP *scip, FILE *file, const char *formatstr,...)
Definition: scip.c:1336
static SCIP_RETCODE createVariable(SCIP *scip, SCIP_VAR **var, char *name)
Definition: reader_opb.c:688
static SCIP_DECL_READERREAD(readerReadOpb)
Definition: reader_opb.c:4431
SCIP_RETCODE SCIPhashtableCreate(SCIP_HASHTABLE **hashtable, BMS_BLKMEM *blkmem, int tablesize, SCIP_DECL_HASHGETKEY((*hashgetkey)), SCIP_DECL_HASHKEYEQ((*hashkeyeq)), SCIP_DECL_HASHKEYVAL((*hashkeyval)), void *userptr)
Definition: misc.c:2014
SCIP_VAR * SCIPgetSlackVarIndicator(SCIP_CONS *cons)
SCIP_VAR * SCIPfindVar(SCIP *scip, const char *name)
Definition: scip.c:12374
SCIP_FILE * SCIPfopen(const char *path, const char *mode)
Definition: fileio.c:140
SCIP_RETCODE SCIPsetObjsense(SCIP *scip, SCIP_OBJSENSE objsense)
Definition: scip.c:10934
Constraint handler for knapsack constraints of the form , x binary and .
static void clearBuffer(char *linebuffer, int *linecnt)
Definition: reader_opb.c:2060
SCIP_VAR ** SCIPgetVarsAnd(SCIP *scip, SCIP_CONS *cons)
Definition: cons_and.c:5101
SCIP_VAR * SCIPgetVarVarbound(SCIP *scip, SCIP_CONS *cons)
static SCIP_Bool isEndingSoftConstraintWeight(SCIP *scip, OPBINPUT *opbinput)
Definition: reader_opb.c:672
SCIP_RETCODE SCIPgetBinvarRepresentatives(SCIP *scip, int nvars, SCIP_VAR **vars, SCIP_VAR **repvars, SCIP_Bool *negated)
Definition: scip.c:18857
SCIP_RETCODE SCIPcreateConsAnd(SCIP *scip, SCIP_CONS **cons, const char *name, SCIP_VAR *resvar, int nvars, SCIP_VAR **vars, SCIP_Bool initial, SCIP_Bool separate, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool propagate, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool dynamic, SCIP_Bool removable, SCIP_Bool stickingatnode)
Definition: cons_and.c:4948
#define SCIPerrorMessage
Definition: pub_message.h:45
const char * SCIPconshdlrGetName(SCIP_CONSHDLR *conshdlr)
Definition: cons.c:4113
static SCIP_RETCODE getActiveVariables(SCIP *scip, SCIP_VAR **vars, SCIP_Real *scalars, int *nvars, SCIP_Real *constant, SCIP_Bool transformed)
Definition: reader_opb.c:1817
SCIP_RETCODE SCIPaddCons(SCIP *scip, SCIP_CONS *cons)
Definition: scip.c:12459
SCIP_Real SCIPvarGetLbOriginal(SCIP_VAR *var)
Definition: var.c:17115
SCIP_VAR * SCIPgetResultantAnd(SCIP *scip, SCIP_CONS *cons)
Definition: cons_and.c:5126
SCIP_Real SCIPgetRhsVarbound(SCIP *scip, SCIP_CONS *cons)
Constraint handler for logicor constraints (equivalent to set covering, but algorithms are suited fo...
SCIP_Real SCIPvarGetUbOriginal(SCIP_VAR *var)
Definition: var.c:17135
SCIP_Real SCIPgetVbdcoefVarbound(SCIP *scip, SCIP_CONS *cons)
static const char delimchars[]
Definition: reader_fzn.c:197
#define SCIPfreeBufferArrayNull(scip, ptr)
Definition: scip.h:22004
SCIP_RETCODE SCIPwriteOpb(SCIP *scip, FILE *file, const char *name, SCIP_Bool transformed, SCIP_OBJSENSE objsense, SCIP_Real objscale, SCIP_Real objoffset, SCIP_VAR **vars, int nvars, int nbinvars, int nintvars, int nimplvars, int ncontvars, SCIP_VAR **fixedvars, int nfixedvars, SCIP_CONS **conss, int nconss, SCIP_Bool genericnames, SCIP_RESULT *result)
Definition: reader_opb.c:4239
int SCIPfeof(SCIP_FILE *stream)
Definition: fileio.c:214
BMS_BLKMEM * SCIPblkmem(SCIP *scip)
Definition: scip.c:45753
struct SCIP_File SCIP_FILE
Definition: pub_fileio.h:34
char * SCIPfgets(char *s, int size, SCIP_FILE *stream)
Definition: fileio.c:187
SCIP_Bool SCIPsortedvecFindPtr(void **ptrarray, SCIP_DECL_SORTPTRCOMP((*ptrcomp)), void *val, int len, int *pos)
OpbSense
Definition: reader_opb.c:131
const char * SCIPconsGetName(SCIP_CONS *cons)
Definition: cons.c:7881
static SCIP_Bool isEndLine(OPBINPUT *opbinput)
Definition: reader_opb.c:550
SCIPInterval sign(const SCIPInterval &x)
SCIP_VAR ** SCIPgetVarsLogicor(SCIP *scip, SCIP_CONS *cons)
SCIP_CONS ** SCIPgetOrigConss(SCIP *scip)
Definition: scip.c:12847
const char * SCIPvarGetName(SCIP_VAR *var)
Definition: var.c:16555
void SCIPhashmapFree(SCIP_HASHMAP **hashmap)
Definition: misc.c:2797
SCIP_RETCODE SCIPgetLinDatasWithoutAndPseudoboolean(SCIP *const scip, SCIP_CONS *const cons, SCIP_VAR **const linvars, SCIP_Real *const lincoefs, int *const nlinvars)
SCIP_RETCODE SCIPgetBoolParam(SCIP *scip, const char *name, SCIP_Bool *value)
Definition: scip.c:4404
int SCIPgetNLinVarsWithoutAndPseudoboolean(SCIP *const scip, SCIP_CONS *const cons)
SCIP_CONS * SCIPfindCons(SCIP *scip, const char *name)
Definition: scip.c:12633
SCIP_RETCODE SCIPprintOrigProblem(SCIP *scip, FILE *file, const char *extension, SCIP_Bool genericnames)
Definition: scip.c:43492
#define NULL
Definition: lpi_spx1.cpp:137
SCIP_VAR * SCIPgetVbdvarVarbound(SCIP *scip, SCIP_CONS *cons)
#define READER_EXTENSION
Definition: reader_opb.c:103
#define SCIP_CALL(x)
Definition: def.h:316
static void pushToken(OPBINPUT *opbinput)
Definition: reader_opb.c:513
static SCIP_Bool isValue(SCIP *scip, OPBINPUT *opbinput, SCIP_Real *value)
Definition: reader_opb.c:591
int SCIPgetNOrigConss(SCIP *scip)
Definition: scip.c:12820
SCIP_RETCODE SCIPgetProbvarLinearSum(SCIP *scip, SCIP_VAR **vars, SCIP_Real *scalars, int *nvars, int varssize, SCIP_Real *constant, int *requiredsize, SCIP_Bool mergemultiples)
Definition: scip.c:18950
SCIP_Bool SCIPisFeasLE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:46346
static SCIP_RETCODE writeOpbFixedVars(SCIP *const scip, FILE *const file, SCIP_VAR **vars, int nvars, SCIP_HASHTABLE *const printedfixing, char const *const multisymbol, SCIP_Bool const transformed)
Definition: reader_opb.c:3746
static SCIP_Bool isTokenChar(char c)
Definition: reader_opb.c:230
SCIP_Real SCIPgetLhsPseudoboolean(SCIP *const scip, SCIP_CONS *const cons)
static SCIP_RETCODE printRow(SCIP *scip, FILE *file, const char *type, SCIP_VAR **vars, SCIP_Real *vals, int nvars, SCIP_Real lhs, SCIP_Longint weight, SCIP_Longint *mult, const char *multisymbol)
Definition: reader_opb.c:2722
#define SCIPdebugGetSolVal(scip, var, val)
Definition: debug.h:265
OpbExpType
Definition: reader_opb.c:123
static SCIP_Bool isSign(OPBINPUT *opbinput, int *sign)
Definition: reader_opb.c:564
int SCIPconshdlrGetNConss(SCIP_CONSHDLR *conshdlr)
Definition: cons.c:4515
static const char commentchars[]
Definition: reader_opb.c:168
SCIP_Longint SCIPgetCapacityKnapsack(SCIP *scip, SCIP_CONS *cons)
SCIP_RETCODE SCIPchgVarObj(SCIP *scip, SCIP_VAR *var, SCIP_Real newobj)
Definition: scip.c:21542
#define SCIPallocBufferArray(scip, ptr, num)
Definition: scip.h:21991
public data structures and miscellaneous methods
#define SCIP_Bool
Definition: def.h:61
#define READER_NAME
Definition: reader_opb.c:101
SCIP_RETCODE SCIPincludeReaderBasic(SCIP *scip, SCIP_READER **readerptr, const char *name, const char *desc, const char *extension, SCIP_READERDATA *readerdata)
Definition: scip.c:5236
#define SCIPduplicateMemoryArray(scip, ptr, source, num)
Definition: scip.h:21936
static SCIP_Bool getNextLine(SCIP *scip, OPBINPUT *opbinput)
Definition: reader_opb.c:297
void SCIPprintSysError(const char *message)
Definition: misc.c:9276
enum SCIP_Objsense SCIP_OBJSENSE
Definition: type_prob.h:41
static SCIP_Bool isValueChar(char c, char nextc, SCIP_Bool firstchar, SCIP_Bool *hasdot, OPBEXPTYPE *exptype)
Definition: reader_opb.c:253
static SCIP_RETCODE writeOpbRelevantAnds(SCIP *const scip, FILE *const file, SCIP_VAR **const resvars, int const nresvars, SCIP_VAR **const *const andvars, int const *const nandvars, SCIP_HASHTABLE *const printedfixing, char const *const multisymbol, SCIP_Bool const transformed)
Definition: reader_opb.c:3820
SCIP_SETPPCTYPE SCIPgetTypeSetppc(SCIP *scip, SCIP_CONS *cons)
Definition: cons_setppc.c:9214
int SCIPgetNAndsPseudoboolean(SCIP *const scip, SCIP_CONS *const cons)
SCIP_RETCODE SCIPprintCons(SCIP *scip, SCIP_CONS *cons, FILE *file)
Definition: scip.c:28746
static SCIP_RETCODE printNonLinearCons(SCIP *const scip, FILE *const file, SCIP_VAR **const vars, SCIP_Real *const vals, int const nvars, SCIP_Real const lhs, SCIP_Real const rhs, SCIP_VAR **const resvars, int const nresvars, SCIP_VAR **const *const andvars, int const *const nandvars, SCIP_Longint weight, SCIP_Bool const transformed, char const *const multisymbol)
Definition: reader_opb.c:2624
SCIP_CONSHDLR * SCIPconsGetHdlr(SCIP_CONS *cons)
Definition: cons.c:7901
methods for debugging
static void swapPointers(char **pointer1, char **pointer2)
Definition: reader_opb.c:393
SCIP_CONS * SCIPgetLinearConsPseudoboolean(SCIP *const scip, SCIP_CONS *const cons)
static SCIP_RETCODE readConstraints(SCIP *scip, OPBINPUT *opbinput, int *nNonlinearConss)
Definition: reader_opb.c:1351
static void appendBuffer(SCIP *scip, FILE *file, char *linebuffer, int *linecnt, const char *extension)
Definition: reader_opb.c:2097
SCIP_Real SCIPvarGetObj(SCIP_VAR *var)
Definition: var.c:17017
SCIP_RETCODE SCIPcreateVar(SCIP *scip, SCIP_VAR **var, const char *name, SCIP_Real lb, SCIP_Real ub, SCIP_Real obj, SCIP_VARTYPE vartype, SCIP_Bool initial, SCIP_Bool removable, SCIP_DECL_VARDELORIG((*vardelorig)), SCIP_DECL_VARTRANS((*vartrans)), SCIP_DECL_VARDELTRANS((*vardeltrans)), SCIP_DECL_VARCOPY((*varcopy)), SCIP_VARDATA *vardata)
Definition: scip.c:17314
static SCIP_Bool isSense(OPBINPUT *opbinput, OPBSENSE *sense)
Definition: reader_opb.c:625
SCIP_RETCODE SCIPsetReaderWrite(SCIP *scip, SCIP_READER *reader, SCIP_DECL_READERWRITE((*readerwrite)))
Definition: scip.c:5346
#define SCIPfreeMemoryArray(scip, ptr)
Definition: scip.h:21940
#define SCIPreallocMemoryArray(scip, ptr, newnum)
Definition: scip.h:21930
static SCIP_Bool getNextToken(SCIP *scip, OPBINPUT *opbinput)
Definition: reader_opb.c:407
SCIP_RETCODE SCIPchgVarBranchPriority(SCIP *scip, SCIP_VAR *var, int branchpriority)
Definition: scip.c:24945
#define SCIPallocMemoryArray(scip, ptr, num)
Definition: scip.h:21924
Constraint handler for linear constraints in their most general form, .
static SCIP_RETCODE computeAndConstraintInfos(SCIP *const scip, SCIP_Bool const transformed, SCIP_VAR ***resvars, int *nresvars, SCIP_VAR ****andvars, int **nandvars, SCIP_Bool *const existandconshdlr, SCIP_Bool *const existands)
Definition: reader_opb.c:1862
static SCIP_RETCODE printPseudobooleanCons(SCIP *const scip, FILE *const file, SCIP_VAR **const linvars, SCIP_Real *const linvals, int const nlinvars, SCIP_VAR ***const termvars, int *const ntermvars, SCIP_Real *const termvals, int const ntermvals, SCIP_VAR *const indvar, SCIP_Real const lhs, SCIP_Real const rhs, SCIP_Bool transformed, const char *multisymbol)
Definition: reader_opb.c:3043
SCIP_Bool SCIPisInfinity(SCIP *scip, SCIP_Real val)
Definition: scip.c:46061
SCIP_RETCODE SCIPvarGetOrigvarSum(SCIP_VAR **var, SCIP_Real *scalar, SCIP_Real *constant)
Definition: var.c:12080
SCIP_VAR * SCIPgetBinaryVarIndicator(SCIP_CONS *cons)
SCIP_RETCODE SCIPsetReaderCopy(SCIP *scip, SCIP_READER *reader, SCIP_DECL_READERCOPY((*readercopy)))
Definition: scip.c:5274
SCIP_VAR ** SCIPgetVarsSetppc(SCIP *scip, SCIP_CONS *cons)
Definition: cons_setppc.c:9193
void SCIPhashtableFree(SCIP_HASHTABLE **hashtable)
Definition: misc.c:2064
int SCIPgetNVars(SCIP *scip)
Definition: scip.c:11680
enum OpbSense OPBSENSE
Definition: reader_opb.c:138
static SCIP_Bool hasError(OPBINPUT *opbinput)
Definition: reader_opb.c:198
SCIP_RETCODE SCIPcreateConsLinear(SCIP *scip, SCIP_CONS **cons, const char *name, int nvars, SCIP_VAR **vars, SCIP_Real *vals, SCIP_Real lhs, SCIP_Real rhs, SCIP_Bool initial, SCIP_Bool separate, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool propagate, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool dynamic, SCIP_Bool removable, SCIP_Bool stickingatnode)
SCIP_Bool SCIPisGT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:46024
SCIP_Bool SCIPisIntegral(SCIP *scip, SCIP_Real val)
Definition: scip.c:46134
static void writeBuffer(SCIP *scip, FILE *file, char *linebuffer, int *linecnt)
Definition: reader_opb.c:2075
pseudo-Boolean file reader (opb format)
static const SCIP_Real scalars[]
Definition: lp.c:5573
SCIP_RETCODE SCIPaddVar(SCIP *scip, SCIP_VAR *var)
Definition: scip.c:11360
SCIP_VAR ** SCIPgetVarsLinear(SCIP *scip, SCIP_CONS *cons)
static SCIP_RETCODE getVariableOrTerm(SCIP *scip, OPBINPUT *opbinput, SCIP_VAR ***vars, int *nvars, int *varssize)
Definition: reader_opb.c:720
int SCIPgetNConss(SCIP *scip)
Definition: scip.c:12728
SCIP_RETCODE SCIPreleaseCons(SCIP *scip, SCIP_CONS **cons)
Definition: scip.c:27417
#define OPB_MAX_PUSHEDTOKENS
Definition: reader_opb.c:119
SCIP_VAR ** SCIPgetVars(SCIP *scip)
Definition: scip.c:11635
SCIP_VARSTATUS SCIPvarGetStatus(SCIP_VAR *var)
Definition: var.c:16674
static SCIP_RETCODE setObjective(SCIP *const scip, OPBINPUT *const opbinput, const char *sense, SCIP_VAR **const linvars, SCIP_Real *const coefs, int const ncoefs, SCIP_VAR ***const terms, SCIP_Real *const termcoefs, int *const ntermvars, int const ntermcoefs)
Definition: reader_opb.c:1149
#define SCIP_Real
Definition: def.h:145
static void syntaxError(SCIP *scip, OPBINPUT *opbinput, const char *msg)
Definition: reader_opb.c:175
int SCIPgetNVarsAnd(SCIP *scip, SCIP_CONS *cons)
Definition: cons_and.c:5077
#define OPB_MAX_LINELEN
Definition: reader_opb.c:118
int SCIPgetNVarsKnapsack(SCIP *scip, SCIP_CONS *cons)
SCIP_RETCODE SCIPsetReaderRead(SCIP *scip, SCIP_READER *reader, SCIP_DECL_READERREAD((*readerread)))
Definition: scip.c:5322
#define SCIP_Longint
Definition: def.h:130
int SCIPvarGetIndex(SCIP_VAR *var)
Definition: var.c:16852
#define SCIPdebugAddSolVal(scip, var, val)
Definition: debug.h:264
SCIP_VARTYPE SCIPvarGetType(SCIP_VAR *var)
Definition: var.c:16720
SCIP_Bool SCIPhashtableExists(SCIP_HASHTABLE *hashtable, void *element)
Definition: misc.c:2365
SCIP_Bool SCIPisZero(SCIP *scip, SCIP_Real val)
Definition: scip.c:46098
SCIP_Real * SCIPgetValsLinear(SCIP *scip, SCIP_CONS *cons)
constraint handler for pseudoboolean constraints
SCIP_Real SCIPvarGetUbLocal(SCIP_VAR *var)
Definition: var.c:17235
SCIP_Bool SCIPisFeasIntegral(SCIP *scip, SCIP_Real val)
Definition: scip.c:46421
static SCIP_RETCODE writeOpbObjective(SCIP *const scip, FILE *const file, SCIP_VAR **const vars, int const nvars, SCIP_VAR **const resvars, int const nresvars, SCIP_VAR **const *const andvars, int const *const nandvars, SCIP_OBJSENSE const objsense, SCIP_Real const objscale, SCIP_Real const objoffset, char const *const multisymbol, SCIP_Bool const existands, SCIP_Bool const transformed)
Definition: reader_opb.c:2120
SCIP_RETCODE SCIPhashmapInsert(SCIP_HASHMAP *hashmap, void *origin, void *image)
Definition: misc.c:2845
#define BMSclearMemoryArray(ptr, num)
Definition: memory.h:89
int SCIPfclose(SCIP_FILE *fp)
Definition: fileio.c:219
struct OpbInput OPBINPUT
Definition: reader_opb.c:166
static SCIP_RETCODE readOPBFile(SCIP *scip, OPBINPUT *opbinput, const char *filename)
Definition: reader_opb.c:1659
SCIP_CONS * SCIPgetLinearConsIndicator(SCIP_CONS *cons)
SCIP_Longint * SCIPgetWeightsKnapsack(SCIP *scip, SCIP_CONS *cons)
static SCIP_DECL_READERWRITE(readerWriteOpb)
Definition: reader_opb.c:4442
SCIP_Real SCIPgetLhsVarbound(SCIP *scip, SCIP_CONS *cons)
#define SCIPABORT()
Definition: def.h:288
SCIP_Real SCIPround(SCIP *scip, SCIP_Real val)
Definition: scip.c:46195
int SCIPgetNVarsLinear(SCIP *scip, SCIP_CONS *cons)
SCIP_Real SCIPgetLhsLinear(SCIP *scip, SCIP_CONS *cons)
SCIP_Real SCIPfloor(SCIP *scip, SCIP_Real val)
Definition: scip.c:46171
static SCIP_RETCODE printLinearCons(SCIP *scip, FILE *file, SCIP_VAR **vars, SCIP_Real *vals, int nvars, SCIP_Real lhs, SCIP_Real rhs, SCIP_Longint weight, SCIP_Bool transformed, const char *multisymbol)
Definition: reader_opb.c:2817
SCIP_RETCODE SCIPprintVar(SCIP *scip, SCIP_VAR *var, FILE *file)
Definition: scip.c:26758
SCIP_RETCODE SCIPgetNegatedVar(SCIP *scip, SCIP_VAR *var, SCIP_VAR **negvar)
Definition: scip.c:18740
SCIP_RETCODE SCIPaddBoolParam(SCIP *scip, const char *name, const char *desc, SCIP_Bool *valueptr, SCIP_Bool isadvanced, SCIP_Bool defaultvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
Definition: scip.c:4211
SCIP_Bool SCIPvarIsActive(SCIP_VAR *var)
Definition: var.c:16842
SCIP_Bool SCIPvarIsNegated(SCIP_VAR *var)
Definition: var.c:16710
#define SCIPreallocBufferArray(scip, ptr, num)
Definition: scip.h:21995
SCIP_Real SCIPgetRhsPseudoboolean(SCIP *const scip, SCIP_CONS *const cons)
static SCIP_Bool isStartingSoftConstraintWeight(SCIP *scip, OPBINPUT *opbinput)
Definition: reader_opb.c:656