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-2016 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  SCIPdebugMessage("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  SCIPdebugMessage("the buffer might be corrupted\n");
353  }
354  else
355  {
356  SCIPfseek(opbinput->file, -(long) strlen(last), SEEK_CUR);
357  SCIPdebugMessage("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  SCIPdebugMessage("%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  SCIPdebugMessage("(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  SCIPdebugMessage("(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  SCIPdebugMessage("(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  SCIPdebugMessage("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  SCIPdebugMessage("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  SCIPdebugMessage("(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  SCIPdebugMessage("(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  SCIPdebugMessage("(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  SCIPdebugMessage("(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  SCIPdebugMessage("(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  SCIPdebugMessage("(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  SCIPdebugPrintf(" %s * ", SCIPvarGetName(tmpvars[v]));
1028  }
1029  SCIPdebugPrintf("\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  SCIPdebugMessage("(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  SCIPdebugMessage("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  SCIPdebugMessage("(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  SCIPdebugMessage("%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  SCIPdebugMessage("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  SCIPdebugMessage("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  SCIPdebugMessage("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  for( r = *nresvars - 1; r >= 0; --r )
1978  {
1979  ncontainedands = 0;
1980  shouldnotbeinand[ncontainedands] = r;
1981  ++ncontainedands;
1982  v = 0;
1983 
1984  while( v < (*nandvars)[r] )
1985  {
1986  if( SCIPsortedvecFindPtr((void**)(*resvars), SCIPvarComp, (*andvars)[r][v], *nresvars, &pos) )
1987  {
1988  /* check if the found position "pos" is equal to an already visited and resultant in this constraint,
1989  * than here could exist a directed cycle
1990  */
1991  /* better use tarjan's algorithm
1992  * <http://algowiki.net/wiki/index.php?title=Tarjan%27s_algorithm>,
1993  * <http://en.wikipedia.org/wiki/Tarjan%E2%80%99s_strongly_connected_components_algorithm>
1994  * because it could be that the same resultant is part of this and-constraint and than it would fail
1995  * without no cycle
1996  * Note1: tarjans standard algorithm doesn't find cycle from one node to the same;
1997  * Note2: when tarjan's algorithm find a cycle, it's still possible that this cycle is not "real" e.g.
1998  * y = y ~y z (z can also be a product) where y = 0 follows and therefor only "0 = z" is necessary
1999  */
2000  for( a = ncontainedands - 1; a >= 0; --a )
2001  if( shouldnotbeinand[a] == pos )
2002  {
2003  SCIPwarningMessage(scip, "This should not happen here. The and-constraint with resultant variable: ");
2004  SCIP_CALL( SCIPprintVar(scip, (*resvars)[r], NULL) );
2005  SCIPwarningMessage(scip, "possible contains a loop with and-resultant:");
2006  SCIP_CALL( SCIPprintVar(scip, (*resvars)[pos], NULL) );
2007 
2008  /* free memory iff necessary */
2009  SCIPfreeBufferArray(scip, &shouldnotbeinand);
2010  if( !transformed )
2011  {
2012  SCIPfreeBufferArray(scip, &andconss);
2013  }
2014  return SCIP_INVALIDDATA;
2015  }
2016  SCIPdebugMessage("Another and-constraint contains and-resultant:");
2017  SCIPdebug( SCIP_CALL( SCIPprintVar(scip, (*resvars)[pos], NULL) ) );
2018  SCIPdebugMessage("Trying to resolve.\n");
2019 
2020  shouldnotbeinand[ncontainedands] = pos;
2021  ++ncontainedands;
2022 
2023  /* try to resolve containing ands */
2024 
2025  /* resize array and number of variables */
2026  (*nandvars)[r] = (*nandvars)[r] + (*nandvars)[pos] - 1;
2027  SCIP_CALL( SCIPreallocMemoryArray(scip, &((*andvars)[r]), (*nandvars)[r]) ); /*lint !e866 */
2028 
2029  /* copy all variables */
2030  for( a = (*nandvars)[pos] - 1; a >= 0; --a )
2031  (*andvars)[r][(*nandvars)[r] - a - 1] = (*andvars)[pos][a];
2032 
2033  /* check same position with new variable, so we do not increase v */
2034  }
2035  else
2036  ++v;
2037  }
2038  }
2039  SCIPfreeBufferArray(scip, &shouldnotbeinand);
2040 
2041  /* free memory iff necessary */
2042  if( !transformed )
2043  {
2044  SCIPfreeBufferArray(scip, &andconss);
2045  }
2046  }
2047  else
2048  {
2049  SCIPdebugMessage("found no and-constraint-handler\n");
2050  *existands = FALSE;
2051  *existandconshdlr = FALSE;
2052  }
2053 
2054  return SCIP_OKAY;
2055 }
2056 
2057 /** clears the given line buffer */
2058 static
2060  char* linebuffer, /**< line */
2061  int* linecnt /**< number of characters in line */
2062  )
2063 {
2064  assert( linebuffer != NULL );
2065  assert( linecnt != NULL );
2066 
2067  (*linecnt) = 0;
2068  linebuffer[0] = '\0';
2069 }
2070 
2071 
2072 /** ends the given line with '\\0' and prints it to the given file stream */
2073 static
2075  SCIP* scip, /**< SCIP data structure */
2076  FILE* file, /**< output file (or NULL for standard output) */
2077  char* linebuffer, /**< line */
2078  int* linecnt /**< number of characters in line */
2079  )
2080 {
2081  assert( scip != NULL );
2082  assert( linebuffer != NULL );
2083  assert( linecnt != NULL );
2084 
2085  if( (*linecnt) > 0 )
2086  {
2087  linebuffer[(*linecnt)] = '\0';
2088  SCIPinfoMessage(scip, file, "%s", linebuffer);
2089  clearBuffer(linebuffer, linecnt);
2090  }
2091 }
2092 
2093 
2094 /** appends extension to line and prints it to the give file stream if the line buffer get full */
2095 static
2097  SCIP* scip, /**< SCIP data structure */
2098  FILE* file, /**< output file (or NULL for standard output) */
2099  char* linebuffer, /**< line buffer */
2100  int* linecnt, /**< number of characters in line */
2101  const char* extension /**< string to extent the line */
2102  )
2103 {
2104  assert(scip != NULL);
2105  assert(linebuffer != NULL);
2106  assert(linecnt != NULL);
2107  assert(extension != NULL);
2108 
2109  if( (*linecnt) + strlen(extension) >= OPB_MAX_LINELEN - 1 )
2110  writeBuffer(scip, file, linebuffer, linecnt);
2111 
2112  /* append extension to linebuffer */
2113  strncat(linebuffer, extension, OPB_MAX_LINELEN - (unsigned int)(*linecnt) - 1);
2114  (*linecnt) += (int) strlen(extension);
2115 }
2116 
2117 /** write objective function */
2118 static
2120  SCIP*const scip, /**< SCIP data structure */
2121  FILE*const file, /**< output file, or NULL if standard output should be used */
2122  SCIP_VAR**const vars, /**< array with active (binary) variables */
2123  int const nvars, /**< number of active variables in the problem */
2124  SCIP_VAR** const resvars, /**< array of resultant variables */
2125  int const nresvars, /**< number of resultant variables */
2126  SCIP_VAR**const*const andvars, /**< corresponding array of and-variables */
2127  int const*const nandvars, /**< array of numbers of corresponding and-variables */
2128  SCIP_OBJSENSE const objsense, /**< objective sense */
2129  SCIP_Real const objscale, /**< scalar applied to objective function; external objective value is
2130  * extobj = objsense * objscale * (intobj + objoffset) */
2131  SCIP_Real const objoffset, /**< objective offset from bound shifting and fixing */
2132  char const*const multisymbol, /**< the multiplication symbol to use between coefficient and variable */
2133  SCIP_Bool const existands, /**< does some and-constraints exist? */
2134  SCIP_Bool const transformed /**< TRUE iff problem is the transformed problem */
2135  )
2136 {
2137  SCIP_VAR* var;
2138  char linebuffer[OPB_MAX_LINELEN];
2139  char buffer[OPB_MAX_LINELEN];
2140  SCIP_Longint mult;
2141  SCIP_Bool objective;
2142  int v;
2143  int linecnt;
2144  int pos;
2145 
2146  assert(scip != NULL);
2147  assert(file != NULL);
2148  assert(vars != NULL || nvars == 0);
2149  assert(resvars != NULL || nresvars == 0);
2150  assert(andvars != NULL || nandvars == NULL);
2151  assert(multisymbol != NULL);
2152 
2153  mult = 1;
2154  objective = FALSE;
2155 
2156  clearBuffer(linebuffer, &linecnt);
2157 
2158  /* check if a objective function exits and compute the multiplier to
2159  * shift the coefficients to integers */
2160  for( v = 0; v < nvars; ++v )
2161  {
2162  var = vars[v]; /*lint !e613 */
2163 
2164 #ifndef NDEBUG
2165  {
2166  /* in case the original problem has to be posted the variables have to be either "original" or "negated" */
2167  if( !transformed )
2168  assert( SCIPvarGetStatus(var) == SCIP_VARSTATUS_ORIGINAL ||
2170  }
2171 #endif
2172 
2173  /* we found a indicator variable so we assume this is a wbo file */
2174  if( strstr(SCIPvarGetName(var), INDICATORVARNAME) != NULL )
2175  {
2176  /* find the topcost linear inequality which gives us the maximal cost which could be violated by our
2177  * solution, which is an artificial constraint and print this at first
2178  *
2179  * @note: only linear constraint handler is enough in problem stage, otherwise it could be any upgraded linear
2180  * constraint which handles pure binary variables
2181  */
2182  SCIP_CONSHDLR* conshdlr;
2183  SCIP_CONS* topcostcons;
2184  SCIP_Bool printed;
2185 
2186  printed = FALSE;
2187  topcostcons = SCIPfindCons(scip, TOPCOSTCONSNAME);
2188 
2189  if( topcostcons != NULL )
2190  {
2191  conshdlr = SCIPconsGetHdlr(topcostcons);
2192  assert(conshdlr != NULL);
2193 
2194  if( strcmp(SCIPconshdlrGetName(conshdlr), "linear") == 0 )
2195  (void) SCIPsnprintf(buffer, OPB_MAX_LINELEN, "soft: %g;\n", SCIPgetRhsLinear(scip, topcostcons));
2196  else if( strcmp(SCIPconshdlrGetName(conshdlr), "knapsack") == 0 )
2197  (void) SCIPsnprintf(buffer, OPB_MAX_LINELEN, "soft: %g;\n", SCIPgetCapacityKnapsack(scip, topcostcons));
2198  else if( strcmp(SCIPconshdlrGetName(conshdlr), "setppc") == 0 )
2199  (void) SCIPsnprintf(buffer, OPB_MAX_LINELEN, "soft: 1;\n");
2200  else
2201  {
2202  SCIPABORT();
2203  return SCIP_INVALIDDATA; /*lint !e527 */
2204  }
2205  appendBuffer(scip, file, linebuffer, &linecnt, buffer);
2206  writeBuffer(scip, file, linebuffer, &linecnt);
2207  printed = TRUE;
2208  }
2209  /* following works only in transformed stage */
2210  else
2211  {
2212  /* first try linear constraints */
2213  conshdlr = SCIPfindConshdlr(scip, "linear");
2214 
2215  if( conshdlr != NULL )
2216  {
2217  SCIP_CONS** conss;
2218  int nconss;
2219  int c;
2220 
2221  conss = SCIPconshdlrGetConss(conshdlr);
2222  nconss = SCIPconshdlrGetNConss(conshdlr);
2223 
2224  assert(conss != NULL || nconss == 0);
2225 
2226  for( c = 0; c < nconss; ++c )
2227  {
2228  SCIP_VAR** linvars;
2229  int nlinvars;
2230  int w;
2231  SCIP_Bool topcostfound;
2232  SCIP_CONS* cons;
2233 
2234  cons = conss[c]; /*lint !e613 */
2235  assert(cons != NULL);
2236 
2237  linvars = SCIPgetVarsLinear(scip, cons);
2238  nlinvars = SCIPgetNVarsLinear(scip, cons);
2239 
2240  assert(linvars != NULL || nlinvars == 0);
2241  topcostfound = FALSE;
2242 
2243  for( w = 0; w < nlinvars; ++w )
2244  {
2245  if( strstr(SCIPvarGetName(linvars[w]), INDICATORVARNAME) != NULL ) /*lint !e613 */
2246  topcostfound = TRUE;
2247  else
2248  {
2249  assert(!topcostfound);
2250  topcostfound = FALSE;
2251  }
2252  }
2253 
2254  if( topcostfound )
2255  {
2256  (void) SCIPsnprintf(buffer, OPB_MAX_LINELEN, "soft: %g;\n", SCIPgetRhsLinear(scip, cons));
2257  appendBuffer(scip, file, linebuffer, &linecnt, buffer);
2258  writeBuffer(scip, file, linebuffer, &linecnt);
2259  printed = TRUE;
2260  break;
2261  }
2262  }
2263  }
2264 
2265  if( !printed )
2266  {
2267  /* second try knapsack constraints */
2268  conshdlr = SCIPfindConshdlr(scip, "knapsack");
2269 
2270  if( conshdlr != NULL )
2271  {
2272  SCIP_CONS** conss;
2273  int nconss;
2274  int c;
2275 
2276  conss = SCIPconshdlrGetConss(conshdlr);
2277  nconss = SCIPconshdlrGetNConss(conshdlr);
2278 
2279  assert(conss != NULL || nconss == 0);
2280 
2281  for( c = 0; c < nconss; ++c )
2282  {
2283  SCIP_VAR** topvars;
2284  int ntopvars;
2285  int w;
2286  SCIP_Bool topcostfound;
2287  SCIP_CONS* cons;
2288 
2289  cons = conss[c]; /*lint !e613 */
2290  assert(cons != NULL);
2291 
2292  topvars = SCIPgetVarsKnapsack(scip, cons);
2293  ntopvars = SCIPgetNVarsKnapsack(scip, cons);
2294 
2295  assert(topvars != NULL || ntopvars == 0);
2296  topcostfound = FALSE;
2297 
2298  for( w = 0; w < ntopvars; ++w )
2299  {
2300  if( strstr(SCIPvarGetName(topvars[w]), INDICATORVARNAME) != NULL ) /*lint !e613 */
2301  topcostfound = TRUE;
2302  else
2303  {
2304  assert(!topcostfound);
2305  topcostfound = FALSE;
2306  }
2307  }
2308 
2309  if( topcostfound )
2310  {
2311  (void) SCIPsnprintf(buffer, OPB_MAX_LINELEN, "soft: %g;\n", SCIPgetCapacityKnapsack(scip, cons));
2312  appendBuffer(scip, file, linebuffer, &linecnt, buffer);
2313  writeBuffer(scip, file, linebuffer, &linecnt);
2314  printed = TRUE;
2315  break;
2316  }
2317  }
2318  }
2319  }
2320 
2321  if( !printed )
2322  {
2323  /* third try setppc constraints */
2324  conshdlr = SCIPfindConshdlr(scip, "setppc");
2325 
2326  if( conshdlr != NULL )
2327  {
2328  SCIP_CONS** conss;
2329  int nconss;
2330  int c;
2331 
2332  conss = SCIPconshdlrGetConss(conshdlr);
2333  nconss = SCIPconshdlrGetNConss(conshdlr);
2334 
2335  assert(conss != NULL || nconss == 0);
2336 
2337  for( c = 0; c < nconss; ++c )
2338  {
2339  SCIP_VAR** topvars;
2340  int ntopvars;
2341  int w;
2342  SCIP_Bool topcostfound;
2343  SCIP_CONS* cons;
2344 
2345  cons = conss[c]; /*lint !e613 */
2346  assert(cons != NULL);
2347 
2348  topvars = SCIPgetVarsSetppc(scip, cons);
2349  ntopvars = SCIPgetNVarsSetppc(scip, cons);
2350 
2351  assert(topvars != NULL || ntopvars == 0);
2352  topcostfound = FALSE;
2353 
2354  for( w = 0; w < ntopvars; ++w )
2355  {
2356  if( strstr(SCIPvarGetName(topvars[w]), INDICATORVARNAME) != NULL ) /*lint !e613 */
2357  topcostfound = TRUE;
2358  else
2359  {
2360  assert(!topcostfound);
2361  topcostfound = FALSE;
2362  }
2363  }
2364 
2365  if( topcostfound )
2366  {
2367  (void) SCIPsnprintf(buffer, OPB_MAX_LINELEN, "soft: 1;\n");
2368  appendBuffer(scip, file, linebuffer, &linecnt, buffer);
2369  writeBuffer(scip, file, linebuffer, &linecnt);
2370  printed = TRUE;
2371  break;
2372  }
2373  }
2374  }
2375  }
2376  }
2377 
2378  /* no topcost constraint found, so print empty topcost line, which means there is no upper bound on violated soft constraints */
2379  if( !printed )
2380  {
2381  (void) SCIPsnprintf(buffer, OPB_MAX_LINELEN, "soft: ;\n");
2382  appendBuffer(scip, file, linebuffer, &linecnt, buffer);
2383  writeBuffer(scip, file, linebuffer, &linecnt);
2384  }
2385 
2386  return SCIP_OKAY;
2387  }
2388 
2389  if( !SCIPisZero(scip, SCIPvarGetObj(var)) )
2390  {
2391  objective = TRUE;
2392  while( !SCIPisIntegral(scip, SCIPvarGetObj(var) * mult) )
2393  {
2394  assert(mult * 10 > mult);
2395  mult *= 10;
2396  }
2397  }
2398  }
2399 
2400  if( objective )
2401  {
2402  /* there exist a objective function*/
2403  SCIPinfoMessage(scip, file, "* Obj. scale : %.15g\n", objscale * mult);
2404  SCIPinfoMessage(scip, file, "* Obj. offset : %.15g\n", objoffset);
2405 
2406  clearBuffer(linebuffer, &linecnt);
2407 
2408  /* opb format supports only minimization; therefore, a maximization problem has to be converted */
2409  if( objsense == SCIP_OBJSENSE_MAXIMIZE )
2410  mult *= -1;
2411 
2412  SCIPdebugMessage("print objective function multiplied with %" SCIP_LONGINT_FORMAT "\n", mult);
2413 
2414  appendBuffer(scip, file, linebuffer, &linecnt, "min:");
2415 
2416 #ifndef NDEBUG
2417  if( existands )
2418  {
2419  int c;
2420  /* check that these variables are sorted */
2421  for( c = nresvars - 1; c > 0; --c )
2422  assert(SCIPvarGetIndex(resvars[c]) >= SCIPvarGetIndex(resvars[c - 1])); /*lint !e613 */
2423  }
2424 #endif
2425 
2426  for( v = nvars - 1; v >= 0; --v )
2427  {
2428  SCIP_Bool negated;
2429  var = vars[v]; /*lint !e613 */
2430 
2431  assert(var != NULL);
2432 
2433  if( SCIPisZero(scip, SCIPvarGetObj(var)) )
2434  continue;
2435 
2436  negated = SCIPvarIsNegated(var);
2437 
2438  assert( linecnt != 0 );
2439 
2440  if( SCIPvarGetObj(var) * mult > SCIP_LONGINT_MAX )
2441  {
2442  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));
2443  }
2444 
2445  /* replace and-resultant with corresponding variables */
2446  if( existands && SCIPsortedvecFindPtr((void**)resvars, SCIPvarComp, var, nresvars, &pos) )
2447  {
2448  int a;
2449 
2450  assert(andvars != NULL);
2451  assert(nandvars != NULL);
2452  assert(pos >= 0 && nandvars[pos] > 0 && andvars[pos] != NULL);
2453  assert(andvars[pos][nandvars[pos] - 1] != NULL);
2454 
2455  negated = SCIPvarIsNegated(andvars[pos][nandvars[pos] - 1]);
2456 
2457  /* print and-vars */
2458  (void) SCIPsnprintf(buffer, OPB_MAX_LINELEN, " %+" SCIP_LONGINT_FORMAT "%s%s%s",
2459  (SCIP_Longint) (SCIPvarGetObj(var) * mult), multisymbol, negated ? "~" : "",
2460  strstr(SCIPvarGetName(negated ? SCIPvarGetNegationVar(andvars[pos][nandvars[pos] - 1]) : andvars[pos][nandvars[pos] - 1]), "x"));
2461  appendBuffer(scip, file, linebuffer, &linecnt, buffer);
2462 
2463  for(a = nandvars[pos] - 2; a >= 0; --a )
2464  {
2465  negated = SCIPvarIsNegated(andvars[pos][a]);
2466 
2467  (void) SCIPsnprintf(buffer, OPB_MAX_LINELEN, "%s%s%s", multisymbol, negated ? "~" : "", strstr(SCIPvarGetName(negated ? SCIPvarGetNegationVar(andvars[pos][a]) : andvars[pos][a]), "x"));
2468  appendBuffer(scip, file, linebuffer, &linecnt, buffer);
2469  }
2470  }
2471  else
2472  {
2473  (void) SCIPsnprintf(buffer, OPB_MAX_LINELEN, " %+" SCIP_LONGINT_FORMAT "%s%s%s",
2474  (SCIP_Longint) (SCIPvarGetObj(var) * mult), multisymbol, negated ? "~" : "", strstr(SCIPvarGetName(negated ? SCIPvarGetNegationVar(var) : var), "x"));
2475  appendBuffer(scip, file, linebuffer, &linecnt, buffer);
2476  }
2477  }
2478 
2479  /* and objective function line ends with a ';' */
2480  appendBuffer(scip, file, linebuffer, &linecnt, " ;\n");
2481  writeBuffer(scip, file, linebuffer, &linecnt);
2482  }
2483 
2484  return SCIP_OKAY;
2485 }
2486 
2487 /* print maybe non linear row in OPB format to file stream */
2488 static
2490  SCIP*const scip, /**< SCIP data structure */
2491  FILE*const file, /**< output file (or NULL for standard output) */
2492  char const*const type, /**< row type ("=" or ">=") */
2493  SCIP_VAR**const vars, /**< array of variables */
2494  SCIP_Real const*const vals, /**< array of values */
2495  int const nvars, /**< number of variables */
2496  SCIP_Real lhs, /**< left hand side */
2497  SCIP_VAR** const resvars, /**< array of resultant variables */
2498  int const nresvars, /**< number of resultant variables */
2499  SCIP_VAR**const*const andvars, /**< corresponding array of and-variables */
2500  int const*const nandvars, /**< array of numbers of corresponding and-variables */
2501  SCIP_Longint weight, /**< if we found a soft constraint this is the weight, otherwise 0 */
2502  SCIP_Longint*const mult, /**< multiplier for the coefficients */
2503  char const*const multisymbol /**< the multiplication symbol to use between coefficient and variable */
2504  )
2505 {
2506  SCIP_VAR* var;
2507  char buffer[OPB_MAX_LINELEN];
2508  char linebuffer[OPB_MAX_LINELEN + 1];
2509  int v;
2510  int pos;
2511  int linecnt;
2512 
2513  assert(scip != NULL);
2514  assert(strcmp(type, "=") == 0 || strcmp(type, ">=") == 0);
2515  assert(mult != NULL);
2516  assert(resvars != NULL);
2517  assert(nresvars > 0);
2518  assert(andvars != NULL && nandvars != NULL);
2519 
2520  clearBuffer(linebuffer, &linecnt);
2521 
2522  /* check if all coefficients are internal; if not commentstart multiplier */
2523  for( v = 0; v < nvars; ++v )
2524  {
2525  while( !SCIPisIntegral(scip, vals[v] * (*mult)) )
2526  {
2527  if( ABS(*mult) > ABS(*mult * 10) )
2528  return SCIP_INVALIDDATA;
2529  (*mult) *= 10;
2530  }
2531  }
2532 
2533  while( !SCIPisIntegral(scip, lhs * (*mult)) )
2534  {
2535  if( ABS(*mult) > ABS(*mult * 10) )
2536  return SCIP_INVALIDDATA;
2537  (*mult) *= 10;
2538  }
2539 
2540  /* print comment line if we have to multiply the coefficients to get integrals */
2541  if( ABS(*mult) != 1 )
2542  SCIPinfoMessage(scip, file, "* the following constraint is multiplied by %" SCIP_LONGINT_FORMAT " to get integral coefficients\n", ABS(*mult) );
2543 
2544 #ifndef NDEBUG
2545  /* check that these variables are sorted */
2546  for( v = nresvars - 1; v > 0; --v )
2547  assert(SCIPvarGetIndex(resvars[v]) >= SCIPvarGetIndex(resvars[v - 1]));
2548 #endif
2549 
2550  /* if we have a soft constraint print the weight*/
2551  if( weight != 0 )
2552  {
2553  (void) SCIPsnprintf(buffer, OPB_MAX_LINELEN, "[%+" SCIP_LONGINT_FORMAT "] ", weight);
2554  appendBuffer(scip, file, linebuffer, &linecnt, buffer);
2555  }
2556 
2557  /* print coefficients */
2558  for( v = 0; v < nvars; ++v )
2559  {
2560  SCIP_Bool negated;
2561 
2562  var = vars[v];
2563  assert( var != NULL );
2564 
2565  negated = SCIPvarIsNegated(var);
2566 
2567  /* replace and-resultant with corresponding variables */
2568  if( SCIPsortedvecFindPtr((void**)resvars, SCIPvarComp, var, nresvars, &pos) )
2569  {
2570  int a;
2571 
2572  assert(andvars != NULL);
2573  assert(nandvars != NULL);
2574  assert(pos >= 0 && nandvars[pos] > 0 && andvars[pos] != NULL);
2575  assert(andvars[pos][nandvars[pos] - 1] != NULL);
2576 
2577  negated = SCIPvarIsNegated(andvars[pos][nandvars[pos] - 1]);
2578 
2579  if( vals[v] * (*mult) > SCIP_LONGINT_MAX )
2580  {
2581  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)));
2582  }
2583 
2584  /* print and-vars */
2585  (void) SCIPsnprintf(buffer, OPB_MAX_LINELEN, "%+" SCIP_LONGINT_FORMAT "%s%s%s",
2586  (SCIP_Longint) SCIPround(scip, vals[v] * (*mult)), multisymbol, negated ? "~" : "",
2587  strstr(SCIPvarGetName(negated ? SCIPvarGetNegationVar(andvars[pos][nandvars[pos] - 1]) : andvars[pos][nandvars[pos] - 1]), "x") );
2588  appendBuffer(scip, file, linebuffer, &linecnt, buffer);
2589 
2590  for(a = nandvars[pos] - 2; a >= 0; --a )
2591  {
2592  negated = SCIPvarIsNegated(andvars[pos][a]);
2593 
2594  (void) SCIPsnprintf(buffer, OPB_MAX_LINELEN, "%s%s%s", multisymbol, negated ? "~" : "", strstr(SCIPvarGetName(negated ? SCIPvarGetNegationVar(andvars[pos][a]) : andvars[pos][a]), "x"));
2595  appendBuffer(scip, file, linebuffer, &linecnt, buffer);
2596  }
2597 
2598  appendBuffer(scip, file, linebuffer, &linecnt, " ");
2599  }
2600  else
2601  {
2602  (void) SCIPsnprintf(buffer, OPB_MAX_LINELEN, "%+" SCIP_LONGINT_FORMAT "%s%s%s ",
2603  (SCIP_Longint) SCIPround(scip, vals[v] * (*mult)), multisymbol, negated ? "~" : "", strstr(SCIPvarGetName(negated ? SCIPvarGetNegationVar(var) : var), "x"));
2604  appendBuffer(scip, file, linebuffer, &linecnt, buffer);
2605  }
2606  }
2607 
2608  /* print left hand side */
2609  if( SCIPisZero(scip, lhs) )
2610  lhs = 0.0;
2611 
2612  (void) SCIPsnprintf(buffer, OPB_MAX_LINELEN, "%s %" SCIP_LONGINT_FORMAT " ;\n", type, (SCIP_Longint) (lhs * (*mult)) );
2613  appendBuffer(scip, file, linebuffer, &linecnt, buffer);
2614 
2615  writeBuffer(scip, file, linebuffer, &linecnt);
2616 
2617  return SCIP_OKAY;
2618 }
2619 
2620 
2621 /** prints given maybe non-linear constraint information in OPB format to file stream */
2622 static
2624  SCIP*const scip, /**< SCIP data structure */
2625  FILE*const file, /**< output file (or NULL for standard output) */
2626  SCIP_VAR**const vars, /**< array of variables */
2627  SCIP_Real*const vals, /**< array of coefficients values (or NULL if all coefficient values are 1) */
2628  int const nvars, /**< number of variables */
2629  SCIP_Real const lhs, /**< left hand side */
2630  SCIP_Real const rhs, /**< right hand side */
2631  SCIP_VAR** const resvars, /**< array of resultant variables */
2632  int const nresvars, /**< number of resultant variables */
2633  SCIP_VAR**const*const andvars, /**< corresponding array of and-variables */
2634  int const*const nandvars, /**< array of numbers of corresponding and-variables */
2635  SCIP_Longint weight, /**< if we found a soft constraint this is the weight, otherwise 0 */
2636  SCIP_Bool const transformed, /**< transformed constraint? */
2637  char const*const multisymbol /**< the multiplication symbol to use between coefficient and variable */
2638  )
2639 {
2640  SCIP_VAR** activevars;
2641  SCIP_Real* activevals;
2642  SCIP_Real activeconstant;
2643  SCIP_Longint mult;
2644  SCIP_RETCODE retcode;
2645  int v;
2646  int nactivevars;
2647 
2648  assert(scip != NULL);
2649  assert(vars != NULL);
2650  assert(nvars > 0);
2651  assert(lhs <= rhs);
2652  assert(resvars != NULL);
2653  assert(nresvars > 0);
2654  assert(andvars != NULL && nandvars != NULL);
2655 
2656  if( SCIPisInfinity(scip, -lhs) && SCIPisInfinity(scip, rhs) )
2657  return SCIP_OKAY;
2658 
2659  activeconstant = 0.0;
2660  nactivevars = nvars;
2661 
2662  /* duplicate variable and value array */
2663  SCIP_CALL( SCIPduplicateBufferArray(scip, &activevars, vars, nactivevars ) );
2664  if( vals != NULL )
2665  {
2666  SCIP_CALL( SCIPduplicateBufferArray(scip, &activevals, vals, nactivevars ) );
2667  }
2668  else
2669  {
2670  SCIP_CALL( SCIPallocBufferArray(scip, &activevals, nactivevars) );
2671 
2672  for( v = 0; v < nactivevars; ++v )
2673  activevals[v] = 1.0;
2674  }
2675 
2676  /* retransform given variables to active variables */
2677  SCIP_CALL( getActiveVariables(scip, activevars, activevals, &nactivevars, &activeconstant, transformed) );
2678 
2679  mult = 1;
2680  retcode = SCIP_OKAY;
2681 
2682  /* print row(s) in OPB format */
2683  if( SCIPisEQ(scip, lhs, rhs) )
2684  {
2685  assert( !SCIPisInfinity(scip, rhs) );
2686 
2687  /* equality constraint */
2688  retcode = printNLRow(scip, file, "=", activevars, activevals, nactivevars, rhs - activeconstant, resvars,
2689  nresvars, andvars, nandvars, weight, &mult, multisymbol);
2690  }
2691  else
2692  {
2693  if( !SCIPisInfinity(scip, -lhs) )
2694  {
2695  /* print inequality ">=" */
2696  retcode = printNLRow(scip, file, ">=", activevars, activevals, nactivevars, lhs - activeconstant, resvars,
2697  nresvars, andvars, nandvars, weight, &mult, multisymbol);
2698  }
2699 
2700 
2701  if( !SCIPisInfinity(scip, rhs) )
2702  {
2703  mult *= -1;
2704 
2705  /* print inequality ">=" and multiplying all coefficients by -1 */
2706  retcode = printNLRow(scip, file, ">=", activevars, activevals, nactivevars, rhs - activeconstant, resvars,
2707  nresvars, andvars, nandvars, weight, &mult, multisymbol);
2708  }
2709  }
2710 
2711  /* free buffer arrays */
2712  SCIPfreeBufferArray(scip, &activevars);
2713  SCIPfreeBufferArray(scip, &activevals);
2714 
2715  return retcode;
2716 }
2717 
2718 
2719 /* print row in OPB format to file stream */
2720 static
2722  SCIP* scip, /**< SCIP data structure */
2723  FILE* file, /**< output file (or NULL for standard output) */
2724  const char* type, /**< row type ("=" or ">=") */
2725  SCIP_VAR** vars, /**< array of variables */
2726  SCIP_Real* vals, /**< array of values */
2727  int nvars, /**< number of variables */
2728  SCIP_Real lhs, /**< left hand side */
2729  SCIP_Longint weight, /**< if we found a soft constraint this is the weight, otherwise 0 */
2730  SCIP_Longint* mult, /**< multiplier for the coefficients */
2731  const char* multisymbol /**< the multiplication symbol to use between coefficient and variable */
2732  )
2733 {
2734  SCIP_VAR* var;
2735  char buffer[OPB_MAX_LINELEN];
2736  char linebuffer[OPB_MAX_LINELEN + 1];
2737  int v;
2738  int linecnt;
2739 
2740  assert(scip != NULL);
2741  assert(strcmp(type, "=") == 0 || strcmp(type, ">=") == 0);
2742  assert(mult != NULL);
2743 
2744  clearBuffer(linebuffer, &linecnt);
2745 
2746  /* if we found the topcost linear inequality which gives us the maximal cost which could be violated by our solution,
2747  * we can stop printing because it is an artificial constraint
2748  */
2749  if( nvars > 0 && strstr(SCIPvarGetName(vars[0]), INDICATORVARNAME) != NULL )
2750  return SCIP_OKAY;
2751 
2752  /* check if all coefficients are integral; if not commentstart multiplier */
2753  for( v = 0; v < nvars; ++v )
2754  {
2755  while( !SCIPisIntegral(scip, vals[v] * (*mult)) )
2756  {
2757  if( ABS(*mult) > ABS(*mult * 10) )
2758  return SCIP_INVALIDDATA;
2759  (*mult) *= 10;
2760  }
2761  }
2762 
2763  while( !SCIPisIntegral(scip, lhs * (*mult)) )
2764  {
2765  if( ABS(*mult) > ABS(*mult * 10) )
2766  return SCIP_INVALIDDATA;
2767  (*mult) *= 10;
2768  }
2769 
2770  /* print comment line if we have to multiply the coefficients to get integrals */
2771  if( ABS(*mult) != 1 )
2772  SCIPinfoMessage(scip, file, "* the following constraint is multiplied by %" SCIP_LONGINT_FORMAT " to get integral coefficients\n", ABS(*mult) );
2773 
2774  /* if we have a soft constraint print the weight*/
2775  if( weight != 0 )
2776  {
2777  (void) SCIPsnprintf(buffer, OPB_MAX_LINELEN, "[%+" SCIP_LONGINT_FORMAT "] ", weight);
2778  appendBuffer(scip, file, linebuffer, &linecnt, buffer);
2779  }
2780 
2781  /* print coefficients */
2782  for( v = 0; v < nvars; ++v )
2783  {
2784  SCIP_Bool negated;
2785 
2786  var = vars[v];
2787  assert( var != NULL );
2788 
2789  negated = SCIPvarIsNegated(var);
2790 
2791  if( vals[v] * (*mult) > SCIP_LONGINT_MAX )
2792  {
2793  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)));
2794  }
2795 
2796  (void) SCIPsnprintf(buffer, OPB_MAX_LINELEN, "%+" SCIP_LONGINT_FORMAT "%s%s%s ",
2797  (SCIP_Longint) SCIPround(scip, vals[v] * (*mult)), multisymbol, negated ? "~" : "", strstr(SCIPvarGetName(negated ? SCIPvarGetNegationVar(var) : var), "x"));
2798  appendBuffer(scip, file, linebuffer, &linecnt, buffer);
2799  }
2800 
2801  /* print left hand side */
2802  if( SCIPisZero(scip, lhs) )
2803  lhs = 0.0;
2804 
2805  (void) SCIPsnprintf(buffer, OPB_MAX_LINELEN, "%s %" SCIP_LONGINT_FORMAT " ;\n", type, (SCIP_Longint) (lhs * (*mult)) );
2806  appendBuffer(scip, file, linebuffer, &linecnt, buffer);
2807 
2808  writeBuffer(scip, file, linebuffer, &linecnt);
2809 
2810  return SCIP_OKAY;
2811 }
2812 
2813 
2814 /** prints given linear constraint information in OPB format to file stream */
2815 static
2817  SCIP* scip, /**< SCIP data structure */
2818  FILE* file, /**< output file (or NULL for standard output) */
2819  SCIP_VAR** vars, /**< array of variables */
2820  SCIP_Real* vals, /**< array of coefficients values (or NULL if all coefficient values are 1) */
2821  int nvars, /**< number of variables */
2822  SCIP_Real lhs, /**< left hand side */
2823  SCIP_Real rhs, /**< right hand side */
2824  SCIP_Longint weight, /**< if we found a soft constraint this is the weight, otherwise 0 */
2825  SCIP_Bool transformed, /**< transformed constraint? */
2826  const char* multisymbol /**< the multiplication symbol to use between coefficient and variable */
2827  )
2828 {
2829  SCIP_VAR** activevars;
2830  SCIP_Real* activevals;
2831  int nactivevars;
2832  SCIP_Real activeconstant;
2833  SCIP_Longint mult;
2834  SCIP_RETCODE retcode;
2835  int v;
2836 
2837  assert( scip != NULL );
2838  assert( vars != NULL );
2839  assert( nvars > 0 );
2840  assert( lhs <= rhs );
2841 
2842  if( SCIPisInfinity(scip, -lhs) && SCIPisInfinity(scip, rhs) )
2843  return SCIP_OKAY;
2844 
2845  activeconstant = 0.0;
2846 
2847  /* duplicate variable and value array */
2848  nactivevars = nvars;
2849  SCIP_CALL( SCIPduplicateBufferArray(scip, &activevars, vars, nactivevars ) );
2850  if( vals != NULL )
2851  {
2852  SCIP_CALL( SCIPduplicateBufferArray(scip, &activevals, vals, nactivevars ) );
2853  }
2854  else
2855  {
2856  SCIP_CALL( SCIPallocBufferArray(scip, &activevals, nactivevars) );
2857 
2858  for( v = 0; v < nactivevars; ++v )
2859  activevals[v] = 1.0;
2860  }
2861 
2862  /* retransform given variables to active variables */
2863  SCIP_CALL( getActiveVariables(scip, activevars, activevals, &nactivevars, &activeconstant, transformed) );
2864 
2865  mult = 1;
2866  retcode = SCIP_OKAY;
2867 
2868  /* print row(s) in OPB format */
2869  if( SCIPisEQ(scip, lhs, rhs) )
2870  {
2871  assert( !SCIPisInfinity(scip, rhs) );
2872 
2873  /* equality constraint */
2874  retcode = printRow(scip, file, "=", activevars, activevals, nactivevars, rhs - activeconstant, weight, &mult,
2875  multisymbol);
2876  }
2877  else
2878  {
2879  if( !SCIPisInfinity(scip, -lhs) )
2880  {
2881  /* print inequality ">=" */
2882  retcode = printRow(scip, file, ">=", activevars, activevals, nactivevars, lhs - activeconstant, weight, &mult,
2883  multisymbol);
2884  }
2885 
2886  if( !SCIPisInfinity(scip, rhs) )
2887  {
2888  mult *= -1;
2889 
2890  /* print inequality ">=" and multiplying all coefficients by -1 */
2891  retcode = printRow(scip, file, ">=", activevars, activevals, nactivevars, rhs - activeconstant, weight, &mult,
2892  multisymbol);
2893  }
2894  }
2895 
2896  /* free buffer arrays */
2897  SCIPfreeBufferArray(scip, &activevars);
2898  SCIPfreeBufferArray(scip, &activevals);
2899 
2900  return retcode;
2901 }
2902 
2903 /* print row in OPB format to file stream */
2904 static
2906  SCIP*const scip, /**< SCIP data structure */
2907  FILE*const file, /**< output file (or NULL for standard output) */
2908  const char* type, /**< row type ("=" or ">=") */
2909  SCIP_VAR**const linvars, /**< array of variables */
2910  SCIP_Real*const linvals, /**< array of values */
2911  int const nlinvars, /**< number of variables */
2912  SCIP_VAR***const termvars, /**< term array with array of variables to print */
2913  int*const ntermvars, /**< array with number of variables in each term */
2914  SCIP_Real*const termvals, /**< array of coefficient values for non-linear variables */
2915  int const ntermvals, /**< number non-linear variables in the problem */
2916  SCIP_Bool**const negatedarrays, /**< array of arrays to know which variable in a non-linear part is negated */
2917  SCIP_VAR*const indvar, /**< indicator variable, or NULL */
2918  SCIP_Real lhs, /**< left hand side */
2919  SCIP_Longint* mult, /**< multiplier for the coefficients */
2920  const char* multisymbol /**< the multiplication symbol to use between coefficient and variable */
2921  )
2922 {
2923  SCIP_VAR* var;
2924  char buffer[OPB_MAX_LINELEN];
2925  char linebuffer[OPB_MAX_LINELEN + 1];
2926  int v;
2927  int t;
2928  int linecnt;
2929 
2930  assert(scip != NULL);
2931  assert(strcmp(type, "=") == 0 || strcmp(type, ">=") == 0);
2932  assert(linvars != NULL || nlinvars == 0);
2933  assert(linvals != NULL || nlinvars == 0);
2934  assert(termvars != NULL || ntermvals == 0);
2935  assert(ntermvars != NULL || ntermvals == 0);
2936  assert(termvals != NULL || ntermvals == 0);
2937  assert(negatedarrays != NULL || ntermvals == 0);
2938  assert(mult != NULL);
2939 
2940  clearBuffer(linebuffer, &linecnt);
2941 
2942  /* if we found the topcost linear inequality which gives us the maximal cost which could be violated by our solution,
2943  * we can stop printing because it is an artificial constraint
2944  */
2945  if( ntermvals == 0 && nlinvars > 0 && strstr(SCIPvarGetName(linvars[0]), INDICATORVARNAME) != NULL ) /*lint !e613 */
2946  return SCIP_OKAY;
2947 
2948  /* check if all linear coefficients are internal; if not commentstart multiplier */
2949  for( v = 0; v < nlinvars; ++v )
2950  {
2951  while( !SCIPisIntegral(scip, linvals[v] * (*mult)) ) /*lint !e613 */
2952  {
2953  if( ABS(*mult) > ABS(*mult * 10) )
2954  return SCIP_INVALIDDATA;
2955  (*mult) *= 10;
2956  }
2957  }
2958 
2959  /* check if all non-linear coefficients are internal; if not commentstart multiplier */
2960  for( v = 0; v < ntermvals; ++v )
2961  {
2962  while( !SCIPisIntegral(scip, termvals[v] * (*mult)) ) /*lint !e613 */
2963  {
2964  if( ABS(*mult) > ABS(*mult * 10) )
2965  return SCIP_INVALIDDATA;
2966  (*mult) *= 10;
2967  }
2968  }
2969 
2970  while( !SCIPisIntegral(scip, lhs * (*mult)) )
2971  {
2972  if( ABS(*mult) > ABS(*mult * 10) )
2973  return SCIP_INVALIDDATA;
2974  (*mult) *= 10;
2975  }
2976 
2977  /* print comment line if we have to multiply the coefficients to get integrals */
2978  if( ABS(*mult) != 1 )
2979  SCIPinfoMessage(scip, file, "* the following constraint is multiplied by %" SCIP_LONGINT_FORMAT " to get integral coefficients\n", ABS(*mult) );
2980 
2981  /* if indicator variable exist we have a soft constraint */
2982  if( indvar != NULL )
2983  {
2984  SCIP_Real weight;
2985 
2986  weight = SCIPvarGetObj(indvar);
2987  (void) SCIPsnprintf(buffer, OPB_MAX_LINELEN, "[%+g] ", weight);
2988  appendBuffer(scip, file, linebuffer, &linecnt, buffer);
2989  }
2990 
2991  /* print linear part */
2992  for( v = 0; v < nlinvars; ++v )
2993  {
2994  SCIP_Bool negated;
2995 
2996  var = linvars[v]; /*lint !e613 */
2997  assert(var != NULL);
2998 
2999  negated = SCIPvarIsNegated(var);
3000 
3001  (void) SCIPsnprintf(buffer, OPB_MAX_LINELEN, "%+" SCIP_LONGINT_FORMAT "%s%s%s ",
3002  (SCIP_Longint) SCIPround(scip, linvals[v] * (*mult)), multisymbol, negated ? "~" : "", strstr(SCIPvarGetName(negated ? SCIPvarGetNegationVar(var) : var), "x")); /*lint !e613 */
3003  appendBuffer(scip, file, linebuffer, &linecnt, buffer);
3004  }
3005 
3006  /* print non-linear part */
3007  for( t = 0; t < ntermvals; ++t )
3008  {
3009  (void) SCIPsnprintf(buffer, OPB_MAX_LINELEN, "%+"SCIP_LONGINT_FORMAT, (SCIP_Longint) SCIPround(scip, termvals[t] * (*mult))); /*lint !e613 */
3010  appendBuffer(scip, file, linebuffer, &linecnt, buffer);
3011 
3012  for( v = 0; v < ntermvars[t]; ++v ) /*lint !e613 */
3013  {
3014  SCIP_Bool negated;
3015 
3016  var = termvars[t][v]; /*lint !e613 */
3017  assert(var != NULL);
3018 
3019  negated = negatedarrays[t][v]; /*lint !e613 */
3020 
3021  (void) SCIPsnprintf(buffer, OPB_MAX_LINELEN, "%s%s%s", multisymbol, negated ? "~" : "", strstr(SCIPvarGetName(negated ? SCIPvarGetNegationVar(var) : var), "x"));
3022  appendBuffer(scip, file, linebuffer, &linecnt, buffer);
3023  }
3024  appendBuffer(scip, file, linebuffer, &linecnt, " ");
3025  }
3026 
3027  /* print left hand side */
3028  if( SCIPisZero(scip, lhs) )
3029  lhs = 0.0;
3030 
3031  (void) SCIPsnprintf(buffer, OPB_MAX_LINELEN, "%s %" SCIP_LONGINT_FORMAT " ;\n", type, (SCIP_Longint) (lhs * (*mult)) );
3032  appendBuffer(scip, file, linebuffer, &linecnt, buffer);
3033 
3034  writeBuffer(scip, file, linebuffer, &linecnt);
3035 
3036  return SCIP_OKAY;
3037 }
3038 
3039 
3040 /** prints given pseudo boolean constraint information in OPB format to file stream */
3041 static
3043  SCIP*const scip, /**< SCIP data structure */
3044  FILE*const file, /**< output file, or NULL if standard output should be used */
3045  SCIP_VAR**const linvars, /**< array with variables of linear part */
3046  SCIP_Real*const linvals, /**< array of coefficients values of linear part */
3047  int const nlinvars, /**< number variables in linear part of the problem */
3048  SCIP_VAR***const termvars, /**< term array with array of variables to print */
3049  int*const ntermvars, /**< array with number of variables in each term */
3050  SCIP_Real*const termvals, /**< array of coefficient values for non-linear variables */
3051  int const ntermvals, /**< number non-linear variables in the problem */
3052  SCIP_VAR*const indvar, /**< indicator variable, or NULL */
3053  SCIP_Real const lhs, /**< left hand side of constraint */
3054  SCIP_Real const rhs, /**< right hand side of constraint */
3055  SCIP_Bool transformed, /**< should the transformed problem be printed ? */
3056  const char* multisymbol /**< the multiplication symbol to use between coefficient and variable */
3057  )
3058 {
3059  SCIP_VAR*** activetermvars;
3060  SCIP_Bool** negatedarrays;
3061  SCIP_VAR** activelinvars;
3062  SCIP_Real* activelinvals;
3063  int nactivelinvars;
3064  SCIP_Real activelinconstant;
3065  SCIP_Longint mult;
3066  SCIP_RETCODE retcode;
3067  int v;
3068 
3069  assert(scip != NULL);
3070  assert(linvars != NULL || nlinvars == 0);
3071  assert(linvals != NULL || nlinvars == 0);
3072  assert(termvars != NULL || 0 == ntermvals);
3073  assert(ntermvars != NULL || 0 == ntermvals);
3074  assert(termvals != NULL || 0 == ntermvals);
3075  assert(lhs <= rhs);
3076 
3077  if( SCIPisInfinity(scip, -lhs) && SCIPisInfinity(scip, rhs) )
3078  return SCIP_OKAY;
3079 
3080  activelinconstant = 0.0;
3081 
3082  /* duplicate variable and value array for linear part */
3083  nactivelinvars = nlinvars;
3084  if( nactivelinvars > 0 )
3085  {
3086  SCIP_CALL( SCIPduplicateBufferArray(scip, &activelinvars, linvars, nactivelinvars ) );
3087  SCIP_CALL( SCIPduplicateBufferArray(scip, &activelinvals, linvals, nactivelinvars ) );
3088 
3089  /* retransform given variables to active variables */
3090  SCIP_CALL( getActiveVariables(scip, activelinvars, activelinvals, &nactivelinvars, &activelinconstant, transformed) );
3091  }
3092  else
3093  {
3094  activelinvars = NULL;
3095  activelinvals = NULL;
3096  }
3097 
3098  /* create non-linear information for printing */
3099  if( ntermvals > 0 )
3100  {
3101  assert(termvars != NULL);
3102  assert(ntermvars != NULL);
3103  assert(termvals != NULL);
3104 
3105  SCIP_CALL( SCIPallocBufferArray(scip, &activetermvars, ntermvals) );
3106  SCIP_CALL( SCIPallocBufferArray(scip, &negatedarrays, ntermvals) );
3107  for( v = ntermvals - 1; v >= 0; --v )
3108  {
3109  assert(ntermvars[v] > 0); /*lint !e613 */
3110 
3111  if( transformed )
3112  {
3113  SCIP_CALL( SCIPallocBufferArray(scip, &(activetermvars[v]), ntermvars[v]) ); /*lint !e866 */
3114  SCIP_CALL( SCIPallocBufferArray(scip, &(negatedarrays[v]), ntermvars[v]) ); /*lint !e866 */
3115 
3116  /* get binary representatives of binary variables in non-linear terms */
3117  SCIP_CALL( SCIPgetBinvarRepresentatives(scip, ntermvars[v], termvars[v], activetermvars[v], negatedarrays[v]) );
3118  }
3119  else
3120  {
3121  SCIP_CALL( SCIPduplicateBufferArray(scip, &(activetermvars[v]), termvars[v], ntermvars[v]) ); /*lint !e866 */
3122  SCIP_CALL( SCIPallocBufferArray(scip, &(negatedarrays[v]), ntermvars[v]) ); /*lint !e866 */
3123  BMSclearMemoryArray(negatedarrays[v], ntermvars[v]); /*lint !e866 */
3124  }
3125  }
3126  }
3127  else
3128  {
3129  activetermvars = NULL;
3130  negatedarrays = NULL;
3131  }
3132 
3133  mult = 1;
3134  retcode = SCIP_OKAY;
3135 
3136  /* print row(s) in OPB format */
3137  if( SCIPisEQ(scip, lhs, rhs) )
3138  {
3139  assert( !SCIPisInfinity(scip, rhs) );
3140 
3141  /* equality constraint */
3142  retcode = printPBRow(scip, file, "=", activelinvars, activelinvals, nactivelinvars, activetermvars,
3143  ntermvars, termvals, ntermvals, negatedarrays, indvar, rhs - activelinconstant, &mult, multisymbol);
3144  }
3145  else
3146  {
3147  if( !SCIPisInfinity(scip, -lhs) )
3148  {
3149  /* print inequality ">=" */
3150  retcode = printPBRow(scip, file, ">=", activelinvars, activelinvals, nactivelinvars, activetermvars,
3151  ntermvars, termvals, ntermvals, negatedarrays, indvar, lhs - activelinconstant, &mult, multisymbol);
3152  }
3153 
3154  if( !SCIPisInfinity(scip, rhs) )
3155  {
3156  mult *= -1;
3157 
3158  /* print inequality ">=" and multiplying all coefficients by -1 */
3159  retcode = printPBRow(scip, file, ">=", activelinvars, activelinvals, nactivelinvars, activetermvars,
3160  ntermvars, termvals, ntermvals, negatedarrays, indvar, rhs - activelinconstant, &mult, multisymbol);
3161  }
3162  }
3163 
3164 
3165  /* free buffers for non-linear arrays */
3166  if( ntermvals > 0 )
3167  {
3168  assert(negatedarrays != NULL);
3169  assert(activetermvars != NULL);
3170 
3171  for( v = 0; v < ntermvals; ++v )
3172  {
3173  assert(negatedarrays[v] != NULL);
3174  assert(activetermvars[v] != NULL);
3175  SCIPfreeBufferArray(scip, &(negatedarrays[v]));
3176  SCIPfreeBufferArray(scip, &(activetermvars[v]));
3177  }
3178  SCIPfreeBufferArray(scip, &negatedarrays);
3179  SCIPfreeBufferArray(scip, &activetermvars);
3180  }
3181 
3182  /* free buffer for linear arrays */
3183  if( nactivelinvars > 0 )
3184  {
3185  SCIPfreeBufferArray(scip, &activelinvars);
3186  SCIPfreeBufferArray(scip, &activelinvals);
3187  }
3188 
3189  return retcode;
3190 }
3191 
3192 #define HASHTABLESIZE_FACTOR 5
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), SCIPcalcHashtableSize(HASHTABLESIZE_FACTOR * 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), SCIPcalcHashtableSize(HASHTABLESIZE_FACTOR * 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), SCIPcalcHashtableSize(HASHTABLESIZE_FACTOR * 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), SCIPcalcHashtableSize(HASHTABLESIZE_FACTOR * 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 and constraints of inactive but relevant and-resultants and and variables which are fixed to one */
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**const resvars, /**< array of resultant variables */
3750  int const nresvars, /**< number of resultant variables */
3751  SCIP_VAR**const*const andvars, /**< corresponding array of and-variables */
3752  int const*const nandvars, /**< array of numbers of corresponding and-variables */
3753  char const*const multisymbol, /**< the multiplication symbol to use between coefficient and variable */
3754  SCIP_Bool const transformed /**< TRUE iff problem is the transformed problem */
3755  )
3756 {
3757  SCIP_VAR* resvar;
3758  SCIP_Longint rhslhs;
3759  char linebuffer[OPB_MAX_LINELEN];
3760  char buffer[OPB_MAX_LINELEN];
3761  int linecnt;
3762  int r, v;
3763 
3764  assert(scip != NULL);
3765  assert(file != NULL);
3766  assert(resvars != NULL || nresvars == 0);
3767  assert(nandvars != NULL || nresvars == 0);
3768  assert(andvars != NULL || nandvars == NULL);
3769  assert(multisymbol != NULL);
3770 
3771  clearBuffer(linebuffer, &linecnt);
3772 
3773  /* print and-variables which are fixed, maybe doesn't appear and should only be asserted */
3774  for( r = nresvars - 1; r >= 0; --r )
3775  {
3776  SCIP_VAR* var;
3777  SCIP_Bool neg;
3778 
3779  resvar = resvars[r]; /*lint !e613 */
3780 
3781  /* print fixed and-resultants */
3782  if( SCIPvarGetLbLocal(resvar) > 0.5 || SCIPvarGetUbLocal(resvar) < 0.5 )
3783  {
3784  SCIP_CALL( SCIPgetBinvarRepresentative(scip, resvar, &var, &neg) );
3785 
3786  assert(SCIPisFeasIntegral(scip, SCIPvarGetLbLocal(var)));
3787  (void) SCIPsnprintf(buffer, OPB_MAX_LINELEN, "%s%s = %g;\n", neg ? "~" : "", strstr(SCIPvarGetName(neg ? SCIPvarGetNegationVar(var) : var), "x"), SCIPvarGetLbLocal(var));
3788  appendBuffer(scip, file, linebuffer, &linecnt, buffer);
3789  }
3790 
3791  assert(andvars[r] != NULL || nandvars[r] == 0); /*lint !e613 */
3792 
3793  /* print fixed and-variables */
3794  for( v = nandvars[r] - 1; v >= 0; --v ) /*lint !e613 */
3795  {
3796  assert(andvars[r][v] != NULL); /*lint !e613 */
3797 
3798  SCIP_CALL( SCIPgetBinvarRepresentative(scip, andvars[r][v], &var, &neg) ); /*lint !e613 */
3799 
3800  if( SCIPvarGetLbLocal(var) > 0.5 || SCIPvarGetUbLocal(var) < 0.5 )
3801  {
3802  assert(SCIPisFeasIntegral(scip, SCIPvarGetLbLocal(var)));
3803  (void) SCIPsnprintf(buffer, OPB_MAX_LINELEN, "%s%s = %g;\n", neg ? "~" : "", strstr(SCIPvarGetName(neg ? SCIPvarGetNegationVar(var) : var), "x"), SCIPvarGetLbLocal(var));
3804  appendBuffer(scip, file, linebuffer, &linecnt, buffer);
3805  }
3806  }
3807  }
3808 
3809  /* print and-constraints with fixed and-resultant to zero and all and-constraints with
3810  * aggregated resultant, otherwise we would loose this information
3811  */
3812  for( r = nresvars - 1; r >= 0; --r )
3813  {
3814  resvar = resvars[r]; /*lint !e613 */
3815  rhslhs = (SCIPvarGetUbLocal(resvar) < 0.5) ? 0 : ((SCIPvarGetLbLocal(resvar) > 0.5) ? 1 : -1);
3816 
3817  /* if and resultant is fixed to 0 and at least one and-variable is fixed to zero, we don't print this redundant constraint */
3818  if( rhslhs == 0 )
3819  {
3820  SCIP_Bool cont;
3821 
3822  cont = FALSE;
3823 
3824  assert(andvars[r] != NULL || nandvars[r] == 0); /*lint !e613 */
3825 
3826  /* if resultant variable and one other and variable is already zero, so we did not need to print this and
3827  * constraint because all other variables are free
3828  */
3829  for( v = nandvars[r] - 1; v >= 0; --v ) /*lint !e613 */
3830  {
3831  assert(andvars[r][v] != NULL); /*lint !e613 */
3832 
3833  if( SCIPvarGetUbLocal(andvars[r][v]) < 0.5 ) /*lint !e613 */
3834  {
3835  cont = TRUE;
3836  break;
3837  }
3838  }
3839 
3840  if( cont )
3841  continue;
3842  }
3843  /* if and resultant is fixed to 1 and all and-variable are fixed to 1 too, we don't print this redundant constraint */
3844  else if( rhslhs == 1 )
3845  {
3846  SCIP_Bool cont;
3847 
3848  cont = TRUE;
3849 
3850  assert(andvars[r] != NULL || nandvars[r] == 0); /*lint !e613 */
3851 
3852  /* if all variables are already fixed to one, we do not need to print this and constraint */
3853  for( v = nandvars[r] - 1; v >= 0; --v ) /*lint !e613 */
3854  {
3855  assert(andvars[r][v] != NULL); /*lint !e613 */
3856 
3857  if( SCIPvarGetLbLocal(andvars[r][v]) < 0.5 ) /*lint !e613 */
3858  {
3859  cont = FALSE;
3860  break;
3861  }
3862  }
3863 
3864  if( cont )
3865  continue;
3866  }
3867 
3868 
3869  /* print and with fixed or aggregated and-resultant */
3870  /* rhslhs equals to 0 means the and constraint is relevant due to it's not clear on which values the and variables are
3871  * rhslhs equals to 1 means the and constraint is irrelevant cause all and variables have to be 1 too
3872  * rhslhs equals to -1 means the and constraint is relevant cause the variable is only aggregated */
3873  if( !SCIPvarIsActive(resvar) )
3874  {
3875  SCIP_VAR* var;
3876  SCIP_Bool neg;
3877  SCIP_Bool firstprinted;
3878 
3879  firstprinted = FALSE;
3880 
3881  assert(andvars[r] != NULL || nandvars[r] == 0); /*lint !e613 */
3882 
3883  for( v = nandvars[r] - 1; v >= 0; --v ) /*lint !e613 */
3884  {
3885  assert(andvars[r][v] != NULL); /*lint !e613 */
3886 
3887  SCIP_CALL( SCIPgetBinvarRepresentative(scip, andvars[r][v], &var, &neg) ); /*lint !e613 */
3888 
3889  (void) SCIPsnprintf(buffer, OPB_MAX_LINELEN, "%s%s%s", (firstprinted) ? multisymbol : "", neg ? "~" : "", strstr(SCIPvarGetName(neg ? SCIPvarGetNegationVar(var) : var), "x"));
3890  appendBuffer(scip, file, linebuffer, &linecnt, buffer);
3891 
3892  firstprinted = TRUE;
3893  }
3894 
3895  /* if the resultant is aggregated we need to print his binary representation */
3896  if( rhslhs == -1 )
3897  {
3898  int pos;
3899 
3900  assert(transformed);
3901 
3902  SCIP_CALL( SCIPgetBinvarRepresentative(scip, resvar, &resvar, &neg) );
3903 
3904 #ifndef NDEBUG
3905  if( neg )
3906  assert(SCIPvarIsActive(SCIPvarGetNegationVar(resvar)));
3907  else
3908  assert(SCIPvarIsActive(resvar));
3909 #endif
3910 
3911  /* replace and-resultant with corresponding variables */
3912  if( SCIPsortedvecFindPtr((void**)resvars, SCIPvarComp, neg ? SCIPvarGetNegationVar(resvar) : resvar, nresvars, &pos) )
3913  {
3914  SCIP_Bool negated;
3915  int a;
3916 
3917  assert(andvars != NULL);
3918  assert(nandvars != NULL);
3919  assert(pos >= 0 && nandvars[pos] > 0 && andvars[pos] != NULL);
3920  assert(andvars[pos][nandvars[pos] - 1] != NULL);
3921 
3922  negated = SCIPvarIsNegated(andvars[pos][nandvars[pos] - 1]);
3923 
3924  /* print and-vars */
3925  (void) SCIPsnprintf(buffer, OPB_MAX_LINELEN, neg ? " +1%s%s%s" : " -1%s%s%s", multisymbol, negated ? "~" : "",
3926  strstr(SCIPvarGetName(negated ? SCIPvarGetNegationVar(andvars[pos][nandvars[pos] - 1]) : andvars[pos][nandvars[pos] - 1]), "x"));
3927  appendBuffer(scip, file, linebuffer, &linecnt, buffer);
3928 
3929  for(a = nandvars[pos] - 2; a >= 0; --a )
3930  {
3931  negated = SCIPvarIsNegated(andvars[pos][a]);
3932 
3933  (void) SCIPsnprintf(buffer, OPB_MAX_LINELEN, "%s%s%s", multisymbol, negated ? "~" : "", strstr(SCIPvarGetName(negated ? SCIPvarGetNegationVar(andvars[pos][a]) : andvars[pos][a]), "x"));
3934  appendBuffer(scip, file, linebuffer, &linecnt, buffer);
3935  }
3936 
3937  appendBuffer(scip, file, linebuffer, &linecnt, " ");
3938 
3939  if( neg )
3940  rhslhs = 1;
3941  else
3942  rhslhs = 0;
3943  }
3944  else
3945  {
3946  (void) SCIPsnprintf(buffer, OPB_MAX_LINELEN, " -1%s%s%s", multisymbol, neg ? "~" : "",
3947  strstr(SCIPvarGetName(neg ? SCIPvarGetNegationVar(resvar) : resvar), "x"));
3948  appendBuffer(scip, file, linebuffer, &linecnt, buffer);
3949 
3950  rhslhs = 0;
3951  }
3952  }
3953 
3954  /* print rhslhs */
3955  (void) SCIPsnprintf(buffer, OPB_MAX_LINELEN, " = %" SCIP_LONGINT_FORMAT " ;\n", rhslhs);
3956  appendBuffer(scip, file, linebuffer, &linecnt, buffer);
3957 
3958  writeBuffer(scip, file, linebuffer, &linecnt);
3959 
3960  }
3961  }
3962 
3963  return SCIP_OKAY;
3964 }
3965 
3966 /* writes problem to file */
3967 static
3969  SCIP* scip, /**< SCIP data structure */
3970  FILE* file, /**< output file, or NULL if standard output should be used */
3971  const char* name, /**< problem name */
3972  SCIP_Bool transformed, /**< TRUE iff problem is the transformed problem */
3973  SCIP_OBJSENSE objsense, /**< objective sense */
3974  SCIP_Real objscale, /**< scalar applied to objective function; external objective value is
3975  * extobj = objsense * objscale * (intobj + objoffset) */
3976  SCIP_Real objoffset, /**< objective offset from bound shifting and fixing */
3977  SCIP_VAR** vars, /**< array with active (binary) variables */
3978  int nvars, /**< number of acitve variables in the problem */
3979  SCIP_CONS** conss, /**< array with constraints of the problem */
3980  int nconss, /**< number of constraints in the problem */
3981  SCIP_VAR** const resvars, /**< array of resultant variables */
3982  int const nresvars, /**< number of resultant variables */
3983  SCIP_VAR**const*const andvars, /**< corresponding array of and-variables */
3984  int const*const nandvars, /**< array of numbers of corresponding and-variables */
3985  SCIP_Bool const existandconshdlr, /**< does and-constrainthandler exist? */
3986  SCIP_Bool const existands, /**< does some and-constraints exist? */
3987  SCIP_RESULT* result /**< pointer to store the result of the file writing call */
3988  )
3989 {
3990  char multisymbol[OPB_MAX_LINELEN];
3991  SCIP_Bool usesymbole;
3992  SCIP_RETCODE retcode;
3993 
3994  assert( scip != NULL );
3995  assert( vars != NULL || nvars == 0 );
3996  assert( conss != NULL || nconss == 0 );
3997  assert( result != NULL );
3998 
3999  /* check if should use a multipliers symbol star '*' between coefficients and variables */
4000  SCIP_CALL( SCIPgetBoolParam(scip, "reading/"READER_NAME"/multisymbol", &usesymbole) );
4001  (void) SCIPsnprintf(multisymbol, OPB_MAX_LINELEN, "%s", usesymbole ? " * " : " ");
4002 
4003  /* print statistics as comment to file */
4004  SCIPinfoMessage(scip, file, "* SCIP STATISTICS\n");
4005  SCIPinfoMessage(scip, file, "* Problem name : %s\n", name);
4006  SCIPinfoMessage(scip, file, "* Variables : %d (all binary)\n", nvars);
4007  SCIPinfoMessage(scip, file, "* Constraints : %d\n", nconss);
4008 
4009  /* write objective function */
4010  SCIP_CALL( writeOpbObjective(scip, file, vars, nvars, resvars, nresvars, andvars, nandvars,
4011  objsense, objscale, objoffset, multisymbol, existands, transformed) );
4012 
4013  /* write constraints */
4014  retcode = writeOpbConstraints(scip, file, conss, nconss, vars, nvars, resvars, nresvars, andvars, nandvars,
4015  multisymbol, existandconshdlr, existands, transformed);
4016 
4017  if( existands && (retcode == SCIP_OKAY) )
4018  {
4019  /* write and constraints of inactive but relevant and-resultants and and-variables which are fixed to one
4020  with no fixed and resultant */
4021  SCIP_CALL( writeOpbRelevantAnds(scip, file, resvars, nresvars, andvars, nandvars, multisymbol, transformed) );
4022  }
4023 
4024  *result = SCIP_SUCCESS;
4025 
4026  return retcode;
4027 }
4028 
4029 
4030 /*
4031  * extern methods
4032  */
4033 
4034 /** reads problem from file */
4036  SCIP* scip, /**< SCIP data structure */
4037  SCIP_READER* reader, /**< the file reader itself */
4038  const char* filename, /**< full path and name of file to read, or NULL if stdin should be used */
4039  SCIP_RESULT* result /**< pointer to store the result of the file reading call */
4040  )
4041 { /*lint --e{715}*/
4042  OPBINPUT opbinput;
4043  SCIP_RETCODE retcode;
4044  int i;
4045 
4046  /* initialize OPB input data */
4047  opbinput.file = NULL;
4048  opbinput.linebuf[0] = '\0';
4049  SCIP_CALL( SCIPallocBufferArray(scip, &opbinput.token, OPB_MAX_LINELEN) );
4050  opbinput.token[0] = '\0';
4051  SCIP_CALL( SCIPallocBufferArray(scip, &opbinput.tokenbuf, OPB_MAX_LINELEN) );
4052  opbinput.tokenbuf[0] = '\0';
4053  for( i = 0; i < OPB_MAX_PUSHEDTOKENS; ++i )
4054  {
4055  SCIP_CALL( SCIPallocBufferArray(scip, &(opbinput.pushedtokens[i]), OPB_MAX_LINELEN) ); /*lint !e866 */
4056  }
4057 
4058  opbinput.npushedtokens = 0;
4059  opbinput.linenumber = 1;
4060  opbinput.bufpos = 0;
4061  opbinput.linepos = 0;
4062  opbinput.objsense = SCIP_OBJSENSE_MINIMIZE;
4063  opbinput.comment = FALSE;
4064  opbinput.endline = FALSE;
4065  opbinput.eof = FALSE;
4066  opbinput.haserror = FALSE;
4067  opbinput.nproblemcoeffs = 0;
4068  opbinput.wbo = FALSE;
4069  opbinput.topcost = -SCIPinfinity(scip);
4070  opbinput.nindvars = 0;
4071 #if GENCONSNAMES == TRUE
4072  opbinput.consnumber = 0;
4073 #endif
4074 
4075  /* read the file */
4076  retcode = readOPBFile(scip, &opbinput, filename);
4077 
4078  /* free dynamically allocated memory */
4079  for( i = OPB_MAX_PUSHEDTOKENS - 1; i >= 0; --i )
4080  {
4081  SCIPfreeBufferArrayNull(scip, &(opbinput.pushedtokens[i]));
4082  }
4083  SCIPfreeBufferArrayNull(scip, &opbinput.tokenbuf);
4084  SCIPfreeBufferArrayNull(scip, &opbinput.token);
4085 
4086  if( retcode == SCIP_PLUGINNOTFOUND )
4087  retcode = SCIP_READERROR;
4088 
4089  SCIP_CALL( retcode );
4090 
4091  if( opbinput.nproblemcoeffs > 0 )
4092  {
4093  SCIPwarningMessage(scip, "there might be <%d> coefficients or weight out of range!\n", opbinput.nproblemcoeffs);
4094  }
4095 
4096  /* evaluate the result */
4097  if( opbinput.haserror )
4098  return SCIP_READERROR;
4099  else
4100  {
4101  /* set objective sense */
4102  SCIP_CALL( SCIPsetObjsense(scip, opbinput.objsense) );
4103  *result = SCIP_SUCCESS;
4104  }
4105 
4106  return SCIP_OKAY;
4107 }
4108 
4109 /** writes problem to file */
4111  SCIP* scip, /**< SCIP data structure */
4112  FILE* file, /**< output file, or NULL if standard output should be used */
4113  const char* name, /**< problem name */
4114  SCIP_Bool transformed, /**< TRUE iff problem is the transformed problem */
4115  SCIP_OBJSENSE objsense, /**< objective sense */
4116  SCIP_Real objscale, /**< scalar applied to objective function; external objective value is
4117  * extobj = objsense * objscale * (intobj + objoffset) */
4118  SCIP_Real objoffset, /**< objective offset from bound shifting and fixing */
4119  SCIP_VAR** vars, /**< array with active variables ordered binary, integer, implicit, continuous */
4120  int nvars, /**< number of active variables in the problem */
4121  int nbinvars, /**< number of binary variables */
4122  int nintvars, /**< number of general integer variables */
4123  int nimplvars, /**< number of implicit integer variables */
4124  int ncontvars, /**< number of continuous variables */
4125  SCIP_VAR** fixedvars, /**< array with fixed variables */
4126  int nfixedvars, /**< number of fixed and aggregated variables in the problem */
4127  SCIP_CONS** conss, /**< array with constraints of the problem */
4128  int nconss, /**< number of constraints in the problem */
4129  SCIP_Bool genericnames, /**< should generic variable and constraint names be used */
4130  SCIP_RESULT* result /**< pointer to store the result of the file writing call */
4131  )
4132 { /*lint --e{715}*/
4133  SCIP_RETCODE retcode = SCIP_OKAY;
4134 
4135  if( nvars != nbinvars && ncontvars + nimplvars + nbinvars != nvars && ncontvars + nimplvars != ( (SCIPfindConshdlr(scip, "indicator") != NULL) ? SCIPconshdlrGetNConss(SCIPfindConshdlr(scip, "indicator")) : 0 ) )
4136  {
4137  SCIPwarningMessage(scip, "OPB format is only capable for binary problems.\n");
4138  *result = SCIP_DIDNOTRUN;
4139  }
4140  else
4141  {
4142  SCIP_VAR*** andvars;
4143  SCIP_VAR** resvars;
4144  int* nandvars;
4145  SCIP_Bool existands;
4146  SCIP_Bool existandconshdlr;
4147  int nresvars;
4148  int v;
4149 
4150  /* computes all and-resultants and their corresponding constraint variables */
4151  SCIP_CALL( computeAndConstraintInfos(scip, transformed, &resvars, &nresvars, &andvars, &nandvars, &existandconshdlr, &existands) );
4152 
4153  if( genericnames )
4154  {
4155 #ifndef NDEBUG
4156  /* check for correct names for opb-format */
4157  int idx;
4158  int pos;
4159 
4160  for( v = nvars - 1; v >= 0; --v )
4161  {
4162  if( existands )
4163  {
4164  /* and variables are artificial */
4165  if( SCIPsortedvecFindPtr((void**)resvars, SCIPvarComp, vars[v], nresvars, &pos) )
4166  continue;
4167  }
4168 
4169  assert(sscanf(SCIPvarGetName(vars[v]), "x%d", &idx) == 1);
4170  }
4171 #endif
4172  retcode = writeOpb(scip, file, name, transformed, objsense, objscale, objoffset, vars,
4173  nvars, conss, nconss, resvars, nresvars, andvars, nandvars, existandconshdlr, existands, result);
4174  }
4175  else
4176  {
4177  SCIP_Bool printed;
4178  int idx;
4179  int pos;
4180 
4181  printed = FALSE;
4182 
4183  /* check if there are already generic names for all (not fixed variables)*/
4184  for( v = nvars - 1; v >= 0; --v )
4185  if( !existands || !SCIPsortedvecFindPtr((void**)resvars, SCIPvarComp, vars[v], nresvars, &pos) )
4186  {
4187  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 )
4188  {
4189  SCIPwarningMessage(scip, "At least following variable name isn't allowed in opb format.\n");
4190  SCIP_CALL( SCIPprintVar(scip, vars[v], NULL) );
4191  SCIPwarningMessage(scip, "OPB format needs generic variable names!\n");
4192 
4193  if( transformed )
4194  {
4195  SCIPwarningMessage(scip, "write transformed problem with generic variable names.\n");
4196  SCIP_CALL( SCIPprintTransProblem(scip, file, "opb", TRUE) );
4197  }
4198  else
4199  {
4200  SCIPwarningMessage(scip, "write original problem with generic variable names.\n");
4201  SCIP_CALL( SCIPprintOrigProblem(scip, file, "opb", TRUE) );
4202  }
4203  printed = TRUE;
4204  break;
4205  }
4206  }
4207 
4208  if( !printed )
4209  {
4210  /* check if there are already generic names for all (fixed variables)*/
4211  for( v = nfixedvars - 1; v >= 0; --v )
4212  if( !existands || !SCIPsortedvecFindPtr((void**)resvars, SCIPvarComp, vars[v], nresvars, &pos) )
4213  {
4214  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 )
4215  {
4216  SCIPwarningMessage(scip, "At least following variable name isn't allowed in opb format.\n");
4217  SCIP_CALL( SCIPprintVar(scip, fixedvars[v], NULL) );
4218  SCIPwarningMessage(scip, "OPB format needs generic variable names!\n");
4219 
4220  if( transformed )
4221  {
4222  SCIPwarningMessage(scip, "write transformed problem with generic variable names.\n");
4223  SCIP_CALL( SCIPprintTransProblem(scip, file, "opb", TRUE) );
4224  }
4225  else
4226  {
4227  SCIPwarningMessage(scip, "write original problem with generic variable names.\n");
4228  SCIP_CALL( SCIPprintOrigProblem(scip, file, "opb", TRUE) );
4229  }
4230  printed = TRUE;
4231  break;
4232  }
4233  }
4234  }
4235 
4236  if( !printed )
4237  {
4238 #ifndef NDEBUG
4239  for( v = nvars - 1; v >= 0; --v )
4240  {
4241  if( existands )
4242  {
4243  if( SCIPsortedvecFindPtr((void**)resvars, SCIPvarComp, vars[v], nresvars, &pos) )
4244  continue;
4245  }
4246 
4247  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 );
4248  }
4249 #endif
4250  retcode = writeOpb(scip, file, name, transformed, objsense, objscale, objoffset, vars,
4251  nvars, conss, nconss, resvars, nresvars, andvars, nandvars, existandconshdlr, existands, result);
4252  }
4253  }
4254 
4255  if( existands )
4256  {
4257  /* free temporary buffers */
4258  assert(resvars != NULL);
4259  assert(andvars != NULL);
4260  assert(nandvars != NULL);
4261 
4262  for( v = nresvars - 1; v >= 0; --v )
4263  {
4264  assert(andvars[v] != NULL);
4265  SCIPfreeMemoryArray(scip, &andvars[v]);
4266  }
4267  SCIPfreeMemoryArray(scip, &nandvars);
4268  SCIPfreeMemoryArray(scip, &andvars);
4269  SCIPfreeMemoryArray(scip, &resvars);
4270  }
4271 
4272  *result = SCIP_SUCCESS;
4273  }
4274 
4275  if( retcode == SCIP_INVALIDDATA )
4276  return SCIP_WRITEERROR;
4277 
4278  return retcode;
4279 }
4280 
4281 /*
4282  * Callback methods of reader
4283  */
4284 
4285 /** copy method for reader plugins (called when SCIP copies plugins) */
4286 static
4287 SCIP_DECL_READERCOPY(readerCopyOpb)
4288 { /*lint --e{715}*/
4289  assert(scip != NULL);
4290  assert(reader != NULL);
4291  assert(strcmp(SCIPreaderGetName(reader), READER_NAME) == 0);
4292 
4293  /* call inclusion method of reader */
4295 
4296  return SCIP_OKAY;
4297 }
4298 
4299 
4300 /** problem reading method of reader */
4301 static
4302 SCIP_DECL_READERREAD(readerReadOpb)
4303 { /*lint --e{715}*/
4304 
4305  SCIP_CALL( SCIPreadOpb(scip, reader, filename, result) );
4306 
4307  return SCIP_OKAY;
4308 }
4309 
4310 
4311 /** problem writing method of reader */
4312 static
4313 SCIP_DECL_READERWRITE(readerWriteOpb)
4314 { /*lint --e{715}*/
4315 
4316  SCIP_CALL( SCIPwriteOpb(scip, file, name, transformed, objsense, objscale, objoffset, vars,
4317  nvars, nbinvars, nintvars, nimplvars, ncontvars, fixedvars, nfixedvars, conss, nconss, genericnames, result) );
4318 
4319  return SCIP_OKAY;
4320 }
4321 
4322 /*
4323  * reader specific interface methods
4324  */
4325 
4326 /** includes the opb file reader in SCIP */
4328  SCIP* scip /**< SCIP data structure */
4329  )
4330 {
4331  SCIP_READERDATA* readerdata;
4332  SCIP_READER* reader;
4333 
4334  /* create reader data */
4335  readerdata = NULL;
4336 
4337  /* include reader */
4338  SCIP_CALL( SCIPincludeReaderBasic(scip, &reader, READER_NAME, READER_DESC, READER_EXTENSION, readerdata) );
4339 
4340  /* set non fundamental callbacks via setter functions */
4341  SCIP_CALL( SCIPsetReaderCopy(scip, reader, readerCopyOpb) );
4342  SCIP_CALL( SCIPsetReaderRead(scip, reader, readerReadOpb) );
4343  SCIP_CALL( SCIPsetReaderWrite(scip, reader, readerWriteOpb) );
4344 
4345  /* add opb reader parameters */
4347  "reading/"READER_NAME"/dynamicconss", "should model constraints be subject to aging?",
4348  NULL, FALSE, FALSE/*TRUE*/, NULL, NULL) ); /* have to be FALSE, otherwise an error might inccur in restart during branch and bound */
4350  "reading/"READER_NAME"/multisymbol", "use '*' between coefficients and variables by writing to problem?",
4351  NULL, TRUE, FALSE, NULL, NULL) );
4352 
4353  return SCIP_OKAY;
4354 }
enum SCIP_Result SCIP_RESULT
Definition: type_result.h:51
SCIP_Bool SCIPisEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:41572
SCIP_VAR * SCIPvarGetNegationVar(SCIP_VAR *var)
Definition: var.c:16883
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, char const *const multisymbol, SCIP_Bool const transformed)
Definition: reader_opb.c:3746
SCIP_Bool SCIPisZero(SCIP *scip, SCIP_Real val)
Definition: scip.c:41685
int SCIPgetNVars(SCIP *scip)
Definition: scip.c:10698
SCIP_CONSHDLR * SCIPfindConshdlr(SCIP *scip, const char *name)
Definition: scip.c:5878
#define ARTIFICIALVARNAMEPREFIX
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:8086
const char * SCIPvarGetName(SCIP_VAR *var)
Definition: var.c:16443
#define READER_DESC
Definition: reader_opb.c:102
#define INDICATORVARNAME
Definition: reader_opb.c:111
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:17373
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:2489
SCIP_CONS ** SCIPgetOrigConss(SCIP *scip)
Definition: scip.c:11855
Constraint handler for variable bound constraints .
#define SCIPreallocBufferArray(scip, ptr, num)
Definition: scip.h:20589
SCIP_Bool SCIPisInfinity(SCIP *scip, SCIP_Real val)
Definition: scip.c:41648
SCIP_RETCODE SCIPvarGetOrigvarSum(SCIP_VAR **var, SCIP_Real *scalar, SCIP_Real *constant)
Definition: var.c:12033
const char * SCIPreaderGetName(SCIP_READER *reader)
Definition: reader.c:510
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:3968
SCIP_VAR * SCIPgetSlackVarIndicator(SCIP_CONS *cons)
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
SCIP_RETCODE SCIPaddVar(SCIP *scip, SCIP_VAR *var)
Definition: scip.c:10378
void SCIPwarningMessage(SCIP *scip, const char *formatstr,...)
Definition: scip.c:1248
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:15737
SCIP_VAR ** SCIPgetVars(SCIP *scip)
Definition: scip.c:10653
#define SCIP_MAXSTRLEN
Definition: def.h:201
static SCIP_Bool isDelimChar(char c)
Definition: reader_opb.c:209
int SCIPconshdlrGetNConss(SCIP_CONSHDLR *conshdlr)
Definition: cons.c:4288
SCIP_RETCODE SCIPgetLinDatasWithoutAndPseudoboolean(SCIP *const scip, SCIP_CONS *const cons, SCIP_VAR **const linvars, SCIP_Real *const lincoefs, int *const nlinvars)
#define NULL
Definition: lpi_spx.cpp:130
SCIP_Real SCIPvarGetLbLocal(SCIP_VAR *var)
Definition: var.c:17113
#define INDICATORSLACKVARNAME
Definition: reader_opb.c:112
SCIP_CONS ** SCIPconshdlrGetConss(SCIP_CONSHDLR *conshdlr)
Definition: cons.c:4258
SCIP_RETCODE SCIPincludeReaderOpb(SCIP *scip)
Definition: reader_opb.c:4327
int SCIPgetNVarsSetppc(SCIP *scip, SCIP_CONS *cons)
Definition: cons_setppc.c:9086
SCIP_Longint SCIPgetCapacityKnapsack(SCIP *scip, SCIP_CONS *cons)
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
constraint handler for indicator constraints
#define SCIPfreeMemoryArray(scip, ptr)
Definition: scip.h:20544
SCIP_VAR * SCIPgetBinaryVarIndicator(SCIP_CONS *cons)
#define SCIPallocMemoryArray(scip, ptr, num)
Definition: scip.h:20528
SCIP_Bool SCIPconsIsTransformed(SCIP_CONS *cons)
Definition: cons.c:7909
#define FALSE
Definition: def.h:56
SCIP_RETCODE SCIPhashmapCreate(SCIP_HASHMAP **hashmap, BMS_BLKMEM *blkmem, int mapsize)
Definition: misc.c:2057
SCIP_Real SCIPgetLhsVarbound(SCIP *scip, SCIP_CONS *cons)
int SCIPgetNVarsLinear(SCIP *scip, SCIP_CONS *cons)
int SCIPsnprintf(char *t, int len, const char *s,...)
Definition: misc.c:8174
#define TRUE
Definition: def.h:55
SCIP_CONSHDLR * SCIPconsGetHdlr(SCIP_CONS *cons)
Definition: cons.c:7640
enum SCIP_Retcode SCIP_RETCODE
Definition: type_retcode.h:53
#define OPB_INIT_COEFSSIZE
Definition: reader_opb.c:120
#define SCIP_CALL(x)
Definition: def.h:266
void SCIPsortPtrPtrInt(void **ptrarray1, void **ptrarray2, int *intarray, SCIP_DECL_SORTPTRCOMP((*ptrcomp)), int len)
SCIP_Longint * SCIPgetWeightsKnapsack(SCIP *scip, SCIP_CONS *cons)
SCIP_RETCODE SCIPgetBinvarRepresentatives(SCIP *scip, int nvars, SCIP_VAR **vars, SCIP_VAR **repvars, SCIP_Bool *negated)
Definition: scip.c:17280
SCIP_Bool SCIPisFeasZero(SCIP *scip, SCIP_Real val)
Definition: scip.c:41972
SCIP_RETCODE SCIPchgVarObj(SCIP *scip, SCIP_VAR *var, SCIP_Real newobj)
Definition: scip.c:19590
SCIP_Bool SCIPisFeasIntegral(SCIP *scip, SCIP_Real val)
Definition: scip.c:42008
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:2905
static void pushBufferToken(OPBINPUT *opbinput)
Definition: reader_opb.c:526
#define TOPCOSTCONSNAME
Definition: reader_opb.c:113
#define SCIPdebugMessage
Definition: pub_message.h:77
static SCIP_DECL_READERCOPY(readerCopyOpb)
Definition: reader_opb.c:4287
enum OpbExpType OPBEXPTYPE
Definition: reader_opb.c:129
#define BMSclearMemoryArray(ptr, num)
Definition: memory.h:85
Constraint handler for "and" constraints, .
SCIP_Real SCIPvarGetObj(SCIP_VAR *var)
Definition: var.c:16905
void * SCIPhashmapGetImage(SCIP_HASHMAP *hashmap, void *origin)
Definition: misc.c:2116
#define SCIP_LONGINT_MAX
Definition: def.h:113
SCIP_RETCODE SCIPprintCons(SCIP *scip, SCIP_CONS *cons, FILE *file)
Definition: scip.c:26237
SCIP_Real SCIPgetRhsPseudoboolean(SCIP *const scip, SCIP_CONS *const cons)
Constraint handler for the set partitioning / packing / covering constraints .
SCIP_RETCODE SCIPreleaseCons(SCIP *scip, SCIP_CONS **cons)
Definition: scip.c:24949
SCIP_VAR ** SCIPgetVarsKnapsack(SCIP *scip, SCIP_CONS *cons)
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
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:4302
SCIP_RETCODE SCIPaddOrigObjoffset(SCIP *scip, SCIP_Real addval)
Definition: scip.c:10062
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:3547
SCIP_VARSTATUS SCIPvarGetStatus(SCIP_VAR *var)
Definition: var.c:16562
SCIP_RETCODE SCIPsetReaderCopy(SCIP *scip, SCIP_READER *reader, SCIP_DECL_READERCOPY((*readercopy)))
Definition: scip.c:4601
SCIP_FILE * SCIPfopen(const char *path, const char *mode)
Definition: fileio.c:140
SCIP_RETCODE SCIPprintVar(SCIP *scip, SCIP_VAR *var, FILE *file)
Definition: scip.c:24289
SCIP_RETCODE SCIPgetBinvarRepresentative(SCIP *scip, SCIP_VAR *var, SCIP_VAR **repvar, SCIP_Bool *negated)
Definition: scip.c:17233
Constraint handler for knapsack constraints of the form , x binary and .
int SCIPgetNConss(SCIP *scip)
Definition: scip.c:11736
static void clearBuffer(char *linebuffer, int *linecnt)
Definition: reader_opb.c:2059
SCIP_VAR ** SCIPgetVarsAnd(SCIP *scip, SCIP_CONS *cons)
Definition: cons_and.c:5075
static SCIP_Bool isEndingSoftConstraintWeight(SCIP *scip, OPBINPUT *opbinput)
Definition: reader_opb.c:672
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:4110
SCIP_RETCODE SCIPgetAndDatasPseudoboolean(SCIP *const scip, SCIP_CONS *const cons, SCIP_CONS **const andconss, SCIP_Real *const andcoefs, int *const nandconss)
#define SCIPerrorMessage
Definition: pub_message.h:45
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
#define SCIPdebugPrintf
Definition: pub_message.h:80
int SCIPgetNVarsLogicor(SCIP *scip, SCIP_CONS *cons)
Constraint handler for logicor constraints (equivalent to set covering, but algorithms are suited fo...
const char * SCIPconshdlrGetName(SCIP_CONSHDLR *conshdlr)
Definition: cons.c:3897
int SCIPcalcHashtableSize(int minsize)
Definition: misc.c:1157
SCIP_VAR ** SCIPgetVarsSetppc(SCIP *scip, SCIP_CONS *cons)
Definition: cons_setppc.c:9107
static const char delimchars[]
Definition: reader_fzn.c:196
SCIP_RETCODE SCIPgetNegatedVar(SCIP *scip, SCIP_VAR *var, SCIP_VAR **negvar)
Definition: scip.c:17163
int SCIPfeof(SCIP_FILE *stream)
Definition: fileio.c:214
BMS_BLKMEM * SCIPblkmem(SCIP *scip)
Definition: scip.c:41353
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:7620
static SCIP_Bool isEndLine(OPBINPUT *opbinput)
Definition: reader_opb.c:550
#define SCIPdebugPrintCons(x, y, z)
Definition: pub_message.h:83
SCIP_Bool SCIPisFeasEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:41907
SCIPInterval sign(const SCIPInterval &x)
SCIP_Bool SCIPvarIsNegated(SCIP_VAR *var)
Definition: var.c:16598
SCIP_Real SCIPfloor(SCIP *scip, SCIP_Real val)
Definition: scip.c:41758
void SCIPhashmapFree(SCIP_HASHMAP **hashmap)
Definition: misc.c:2075
SCIP_Real SCIPgetRhsLinear(SCIP *scip, SCIP_CONS *cons)
SCIP_VAR * SCIPgetResultantAnd(SCIP *scip, SCIP_CONS *cons)
Definition: cons_and.c:5100
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:9019
SCIP_Real SCIPinfinity(SCIP *scip)
Definition: scip.c:41637
#define READER_EXTENSION
Definition: reader_opb.c:103
SCIP_Real SCIPgetRhsVarbound(SCIP *scip, SCIP_CONS *cons)
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
static SCIP_Bool isTokenChar(char c)
Definition: reader_opb.c:230
SCIP_RETCODE SCIPreadOpb(SCIP *scip, SCIP_READER *reader, const char *filename, SCIP_RESULT *result)
Definition: reader_opb.c:4035
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:2721
SCIP_Real SCIPgetVbdcoefVarbound(SCIP *scip, SCIP_CONS *cons)
#define SCIPdebugGetSolVal(scip, var, val)
Definition: debug.h:264
OpbExpType
Definition: reader_opb.c:123
SCIP_RETCODE SCIPsetReaderRead(SCIP *scip, SCIP_READER *reader, SCIP_DECL_READERREAD((*readerread)))
Definition: scip.c:4649
#define SCIPfreeBufferArrayNull(scip, ptr)
Definition: scip.h:20598
SCIP_RETCODE SCIPreleaseVar(SCIP *scip, SCIP_VAR **var)
Definition: scip.c:16884
static SCIP_Bool isSign(OPBINPUT *opbinput, int *sign)
Definition: reader_opb.c:564
SCIP_CONS * SCIPgetLinearConsPseudoboolean(SCIP *const scip, SCIP_CONS *const cons)
static const char commentchars[]
Definition: reader_opb.c:168
SCIP_Bool SCIPisGT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:41611
SCIP_Real SCIPvarGetUbLocal(SCIP_VAR *var)
Definition: var.c:17123
struct SCIP_ReaderData SCIP_READERDATA
Definition: type_reader.h:37
public data structures and miscellaneous methods
int SCIPvarGetIndex(SCIP_VAR *var)
Definition: var.c:16740
#define SCIP_Bool
Definition: def.h:53
#define READER_NAME
Definition: reader_opb.c:101
#define SCIPduplicateMemoryArray(scip, ptr, source, num)
Definition: scip.h:20540
static SCIP_Bool getNextLine(SCIP *scip, OPBINPUT *opbinput)
Definition: reader_opb.c:297
void SCIPprintSysError(const char *message)
Definition: misc.c:8110
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
SCIP_RETCODE SCIPincludeReaderBasic(SCIP *scip, SCIP_READER **readerptr, const char *name, const char *desc, const char *extension, SCIP_READERDATA *readerdata)
Definition: scip.c:4563
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_Real SCIPgetLhsPseudoboolean(SCIP *const scip, SCIP_CONS *const cons)
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:2623
SCIP_CONS * SCIPfindCons(SCIP *scip, const char *name)
Definition: scip.c:11641
int SCIPgetNLinVarsWithoutAndPseudoboolean(SCIP *const scip, SCIP_CONS *const cons)
methods for debugging
static void swapPointers(char **pointer1, char **pointer2)
Definition: reader_opb.c:393
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:2096
static SCIP_Bool isSense(OPBINPUT *opbinput, OPBSENSE *sense)
Definition: reader_opb.c:625
#define SCIPreallocMemoryArray(scip, ptr, newnum)
Definition: scip.h:20534
SCIP_RETCODE SCIPchgVarBranchPriority(SCIP *scip, SCIP_VAR *var, int branchpriority)
Definition: scip.c:22487
static SCIP_Bool getNextToken(SCIP *scip, OPBINPUT *opbinput)
Definition: reader_opb.c:407
SCIP_RETCODE SCIPprintOrigProblem(SCIP *scip, FILE *file, const char *extension, SCIP_Bool genericnames)
Definition: scip.c:39265
SCIP_VAR * SCIPgetVbdvarVarbound(SCIP *scip, SCIP_CONS *cons)
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
SCIP_CONS * SCIPgetLinearConsIndicator(SCIP_CONS *cons)
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:3042
enum OpbSense OPBSENSE
Definition: reader_opb.c:138
SCIP_RETCODE SCIPaddCons(SCIP *scip, SCIP_CONS *cons)
Definition: scip.c:11477
static SCIP_Bool hasError(OPBINPUT *opbinput)
Definition: reader_opb.c:198
SCIP_VARTYPE SCIPvarGetType(SCIP_VAR *var)
Definition: var.c:16608
#define SCIPallocBufferArray(scip, ptr, num)
Definition: scip.h:20585
SCIP_RETCODE SCIPsetObjsense(SCIP *scip, SCIP_OBJSENSE objsense)
Definition: scip.c:10014
SCIP_RETCODE SCIPsetReaderWrite(SCIP *scip, SCIP_READER *reader, SCIP_DECL_READERWRITE((*readerwrite)))
Definition: scip.c:4673
static void writeBuffer(SCIP *scip, FILE *file, char *linebuffer, int *linecnt)
Definition: reader_opb.c:2074
pseudo-Boolean file reader (opb format)
static const SCIP_Real scalars[]
Definition: lp.c:5506
void SCIPinfoMessage(SCIP *scip, FILE *file, const char *formatstr,...)
Definition: scip.c:1281
static SCIP_RETCODE getVariableOrTerm(SCIP *scip, OPBINPUT *opbinput, SCIP_VAR ***vars, int *nvars, int *varssize)
Definition: reader_opb.c:720
SCIP_VAR ** SCIPgetVarsLogicor(SCIP *scip, SCIP_CONS *cons)
int SCIPgetNVarsKnapsack(SCIP *scip, SCIP_CONS *cons)
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:4922
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 SCIPisIntegral(SCIP *scip, SCIP_Real val)
Definition: scip.c:41721
#define SCIPduplicateBufferArray(scip, ptr, source, num)
Definition: scip.h:20593
#define OPB_MAX_PUSHEDTOKENS
Definition: reader_opb.c:119
SCIP_Bool SCIPisFeasLE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:41933
int SCIPgetNAndsPseudoboolean(SCIP *const scip, SCIP_CONS *const cons)
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:127
static void syntaxError(SCIP *scip, OPBINPUT *opbinput, const char *msg)
Definition: reader_opb.c:175
#define OPB_MAX_LINELEN
Definition: reader_opb.c:118
SCIP_VAR * SCIPfindVar(SCIP *scip, const char *name)
Definition: scip.c:11392
SCIP_Bool SCIPisFeasGE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:41959
SCIP_Real SCIPgetLhsLinear(SCIP *scip, SCIP_CONS *cons)
#define SCIP_Longint
Definition: def.h:112
int SCIPgetNOrigConss(SCIP *scip)
Definition: scip.c:11828
#define SCIPdebugAddSolVal(scip, var, val)
Definition: debug.h:263
SCIP_Real SCIPround(SCIP *scip, SCIP_Real val)
Definition: scip.c:41782
constraint handler for pseudoboolean constraints
#define SCIPfreeBufferArray(scip, ptr)
Definition: scip.h:20597
SCIP_SETPPCTYPE SCIPgetTypeSetppc(SCIP *scip, SCIP_CONS *cons)
Definition: cons_setppc.c:9128
SCIP_Bool SCIPvarIsActive(SCIP_VAR *var)
Definition: var.c:16730
#define SCIPdebug(x)
Definition: pub_message.h:74
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:2119
SCIP_VAR ** SCIPgetVarsLinear(SCIP *scip, SCIP_CONS *cons)
int SCIPcalcMemGrowSize(SCIP *scip, int num)
Definition: scip.c:41422
SCIP_RETCODE SCIPhashmapInsert(SCIP_HASHMAP *hashmap, void *origin, void *image)
Definition: misc.c:2094
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_VAR * SCIPgetVarVarbound(SCIP *scip, SCIP_CONS *cons)
#define HASHTABLESIZE_FACTOR
Definition: reader_opb.c:3192
SCIP_Bool SCIPconsIsEnabled(SCIP_CONS *cons)
Definition: cons.c:7707
static SCIP_DECL_READERWRITE(readerWriteOpb)
Definition: reader_opb.c:4313
#define SCIPABORT()
Definition: def.h:238
SCIP_VAR * SCIPgetIndVarPseudoboolean(SCIP *const scip, SCIP_CONS *const cons)
SCIP_RETCODE SCIPgetBoolParam(SCIP *scip, const char *name, SCIP_Bool *value)
Definition: scip.c:3740
SCIP_Real * SCIPgetValsLinear(SCIP *scip, SCIP_CONS *cons)
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:2816
SCIP_RETCODE SCIPprintTransProblem(SCIP *scip, FILE *file, const char *extension, SCIP_Bool genericnames)
Definition: scip.c:39309
int SCIPgetNVarsAnd(SCIP *scip, SCIP_CONS *cons)
Definition: cons_and.c:5051
static SCIP_Bool isStartingSoftConstraintWeight(SCIP *scip, OPBINPUT *opbinput)
Definition: reader_opb.c:656