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