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