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