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 
2118  if( (*linecnt) > 0 )
2119  {
2120  linebuffer[(*linecnt)] = '\0';
2121  SCIPinfoMessage(scip, file, "%s", linebuffer);
2122  clearBuffer(linebuffer, linecnt);
2123  }
2124 }
2125 
2126 
2127 /** appends extension to line and prints it to the give file stream if the line buffer get full */
2128 static
2130  SCIP* scip, /**< SCIP data structure */
2131  FILE* file, /**< output file (or NULL for standard output) */
2132  char* linebuffer, /**< line buffer */
2133  int* linecnt, /**< number of characters in line */
2134  const char* extension /**< string to extent the line */
2135  )
2136 {
2137  assert(scip != NULL);
2138  assert(linebuffer != NULL);
2139  assert(linecnt != NULL);
2140  assert(extension != NULL);
2141 
2142  if( (*linecnt) + (int) strlen(extension) >= OPB_MAX_LINELEN - 1 )
2143  writeBuffer(scip, file, linebuffer, linecnt);
2144 
2145  /* append extension to linebuffer */
2146  (void) strncat(linebuffer, extension, OPB_MAX_LINELEN - (unsigned int)(*linecnt));
2147  (*linecnt) += (int) strlen(extension);
2148 }
2149 
2150 /** write objective function */
2151 static
2153  SCIP*const scip, /**< SCIP data structure */
2154  FILE*const file, /**< output file, or NULL if standard output should be used */
2155  SCIP_VAR**const vars, /**< array with active (binary) variables */
2156  int const nvars, /**< number of active variables in the problem */
2157  SCIP_VAR** const resvars, /**< array of resultant variables */
2158  int const nresvars, /**< number of resultant variables */
2159  SCIP_VAR**const*const andvars, /**< corresponding array of and-variables */
2160  int const*const nandvars, /**< array of numbers of corresponding and-variables */
2161  SCIP_OBJSENSE const objsense, /**< objective sense */
2162  SCIP_Real const objscale, /**< scalar applied to objective function; external objective value is
2163  * extobj = objsense * objscale * (intobj + objoffset) */
2164  SCIP_Real const objoffset, /**< objective offset from bound shifting and fixing */
2165  char const*const multisymbol, /**< the multiplication symbol to use between coefficient and variable */
2166  SCIP_Bool const existands, /**< does some and-constraints exist? */
2167  SCIP_Bool const transformed /**< TRUE iff problem is the transformed problem */
2168  )
2169 {
2170  SCIP_VAR* var;
2171  char linebuffer[OPB_MAX_LINELEN+1];
2172  char buffer[OPB_MAX_LINELEN];
2173  SCIP_Longint mult;
2174  SCIP_Bool objective;
2175  int v;
2176  int linecnt;
2177  int pos;
2178 
2179  assert(scip != NULL);
2180  assert(file != NULL);
2181  assert(vars != NULL || nvars == 0);
2182  assert(resvars != NULL || nresvars == 0);
2183  assert(andvars != NULL || nandvars == NULL);
2184  assert(multisymbol != NULL);
2185 
2186  mult = 1;
2187  objective = FALSE;
2188 
2189  clearBuffer(linebuffer, &linecnt);
2190 
2191  /* check if a objective function exits and compute the multiplier to
2192  * shift the coefficients to integers */
2193  for( v = 0; v < nvars; ++v )
2194  {
2195  var = vars[v]; /*lint !e613 */
2196 
2197 #ifndef NDEBUG
2198  {
2199  /* in case the original problem has to be posted the variables have to be either "original" or "negated" */
2200  if( !transformed )
2201  assert( SCIPvarGetStatus(var) == SCIP_VARSTATUS_ORIGINAL ||
2203  }
2204 #endif
2205 
2206  /* we found a indicator variable so we assume this is a wbo file */
2207  if( strstr(SCIPvarGetName(var), INDICATORVARNAME) != NULL )
2208  {
2209  /* find the topcost linear inequality which gives us the maximal cost which could be violated by our
2210  * solution, which is an artificial constraint and print this at first
2211  *
2212  * @note: only linear constraint handler is enough in problem stage, otherwise it could be any upgraded linear
2213  * constraint which handles pure binary variables
2214  */
2215  SCIP_CONSHDLR* conshdlr;
2216  SCIP_CONS* topcostcons;
2217  SCIP_Bool printed;
2218 
2219  printed = FALSE;
2220  topcostcons = SCIPfindCons(scip, TOPCOSTCONSNAME);
2221 
2222  if( topcostcons != NULL )
2223  {
2224  conshdlr = SCIPconsGetHdlr(topcostcons);
2225  assert(conshdlr != NULL);
2226 
2227  if( strcmp(SCIPconshdlrGetName(conshdlr), "linear") == 0 )
2228  (void) SCIPsnprintf(buffer, OPB_MAX_LINELEN, "soft: %g;\n", SCIPgetRhsLinear(scip, topcostcons));
2229  else if( strcmp(SCIPconshdlrGetName(conshdlr), "knapsack") == 0 )
2230  (void) SCIPsnprintf(buffer, OPB_MAX_LINELEN, "soft: %g;\n", SCIPgetCapacityKnapsack(scip, topcostcons));
2231  else if( strcmp(SCIPconshdlrGetName(conshdlr), "setppc") == 0 )
2232  (void) SCIPsnprintf(buffer, OPB_MAX_LINELEN, "soft: 1;\n");
2233  else
2234  {
2235  SCIPABORT();
2236  return SCIP_INVALIDDATA; /*lint !e527 */
2237  }
2238  appendBuffer(scip, file, linebuffer, &linecnt, buffer);
2239  writeBuffer(scip, file, linebuffer, &linecnt);
2240  printed = TRUE;
2241  }
2242  /* following works only in transformed stage */
2243  else
2244  {
2245  /* first try linear constraints */
2246  conshdlr = SCIPfindConshdlr(scip, "linear");
2247 
2248  if( conshdlr != NULL )
2249  {
2250  SCIP_CONS** conss;
2251  int nconss;
2252  int c;
2253 
2254  conss = SCIPconshdlrGetConss(conshdlr);
2255  nconss = SCIPconshdlrGetNConss(conshdlr);
2256 
2257  assert(conss != NULL || nconss == 0);
2258 
2259  for( c = 0; c < nconss; ++c )
2260  {
2261  SCIP_VAR** linvars;
2262  int nlinvars;
2263  int w;
2264  SCIP_Bool topcostfound;
2265  SCIP_CONS* cons;
2266 
2267  cons = conss[c]; /*lint !e613 */
2268  assert(cons != NULL);
2269 
2270  linvars = SCIPgetVarsLinear(scip, cons);
2271  nlinvars = SCIPgetNVarsLinear(scip, cons);
2272 
2273  assert(linvars != NULL || nlinvars == 0);
2274  topcostfound = FALSE;
2275 
2276  for( w = 0; w < nlinvars; ++w )
2277  {
2278  if( strstr(SCIPvarGetName(linvars[w]), INDICATORVARNAME) != NULL ) /*lint !e613 */
2279  topcostfound = TRUE;
2280  else
2281  {
2282  assert(!topcostfound);
2283  topcostfound = FALSE;
2284  }
2285  }
2286 
2287  if( topcostfound )
2288  {
2289  (void) SCIPsnprintf(buffer, OPB_MAX_LINELEN, "soft: %g;\n", SCIPgetRhsLinear(scip, cons));
2290  appendBuffer(scip, file, linebuffer, &linecnt, buffer);
2291  writeBuffer(scip, file, linebuffer, &linecnt);
2292  printed = TRUE;
2293  break;
2294  }
2295  }
2296  }
2297 
2298  if( !printed )
2299  {
2300  /* second try knapsack constraints */
2301  conshdlr = SCIPfindConshdlr(scip, "knapsack");
2302 
2303  if( conshdlr != NULL )
2304  {
2305  SCIP_CONS** conss;
2306  int nconss;
2307  int c;
2308 
2309  conss = SCIPconshdlrGetConss(conshdlr);
2310  nconss = SCIPconshdlrGetNConss(conshdlr);
2311 
2312  assert(conss != NULL || nconss == 0);
2313 
2314  for( c = 0; c < nconss; ++c )
2315  {
2316  SCIP_VAR** topvars;
2317  int ntopvars;
2318  int w;
2319  SCIP_Bool topcostfound;
2320  SCIP_CONS* cons;
2321 
2322  cons = conss[c]; /*lint !e613 */
2323  assert(cons != NULL);
2324 
2325  topvars = SCIPgetVarsKnapsack(scip, cons);
2326  ntopvars = SCIPgetNVarsKnapsack(scip, cons);
2327 
2328  assert(topvars != NULL || ntopvars == 0);
2329  topcostfound = FALSE;
2330 
2331  for( w = 0; w < ntopvars; ++w )
2332  {
2333  if( strstr(SCIPvarGetName(topvars[w]), INDICATORVARNAME) != NULL ) /*lint !e613 */
2334  topcostfound = TRUE;
2335  else
2336  {
2337  assert(!topcostfound);
2338  topcostfound = FALSE;
2339  }
2340  }
2341 
2342  if( topcostfound )
2343  {
2344  (void) SCIPsnprintf(buffer, OPB_MAX_LINELEN, "soft: %g;\n", SCIPgetCapacityKnapsack(scip, cons));
2345  appendBuffer(scip, file, linebuffer, &linecnt, buffer);
2346  writeBuffer(scip, file, linebuffer, &linecnt);
2347  printed = TRUE;
2348  break;
2349  }
2350  }
2351  }
2352  }
2353 
2354  if( !printed )
2355  {
2356  /* third try setppc constraints */
2357  conshdlr = SCIPfindConshdlr(scip, "setppc");
2358 
2359  if( conshdlr != NULL )
2360  {
2361  SCIP_CONS** conss;
2362  int nconss;
2363  int c;
2364 
2365  conss = SCIPconshdlrGetConss(conshdlr);
2366  nconss = SCIPconshdlrGetNConss(conshdlr);
2367 
2368  assert(conss != NULL || nconss == 0);
2369 
2370  for( c = 0; c < nconss; ++c )
2371  {
2372  SCIP_VAR** topvars;
2373  int ntopvars;
2374  int w;
2375  SCIP_Bool topcostfound;
2376  SCIP_CONS* cons;
2377 
2378  cons = conss[c]; /*lint !e613 */
2379  assert(cons != NULL);
2380 
2381  topvars = SCIPgetVarsSetppc(scip, cons);
2382  ntopvars = SCIPgetNVarsSetppc(scip, cons);
2383 
2384  assert(topvars != NULL || ntopvars == 0);
2385  topcostfound = FALSE;
2386 
2387  for( w = 0; w < ntopvars; ++w )
2388  {
2389  if( strstr(SCIPvarGetName(topvars[w]), INDICATORVARNAME) != NULL ) /*lint !e613 */
2390  topcostfound = TRUE;
2391  else
2392  {
2393  assert(!topcostfound);
2394  topcostfound = FALSE;
2395  }
2396  }
2397 
2398  if( topcostfound )
2399  {
2400  (void) SCIPsnprintf(buffer, OPB_MAX_LINELEN, "soft: 1;\n");
2401  appendBuffer(scip, file, linebuffer, &linecnt, buffer);
2402  writeBuffer(scip, file, linebuffer, &linecnt);
2403  printed = TRUE;
2404  break;
2405  }
2406  }
2407  }
2408  }
2409  }
2410 
2411  /* no topcost constraint found, so print empty topcost line, which means there is no upper bound on violated soft constraints */
2412  if( !printed )
2413  {
2414  (void) SCIPsnprintf(buffer, OPB_MAX_LINELEN, "soft: ;\n");
2415  appendBuffer(scip, file, linebuffer, &linecnt, buffer);
2416  writeBuffer(scip, file, linebuffer, &linecnt);
2417  }
2418 
2419  return SCIP_OKAY;
2420  }
2421 
2422  if( !SCIPisZero(scip, SCIPvarGetObj(var)) )
2423  {
2424  objective = TRUE;
2425  while( !SCIPisIntegral(scip, SCIPvarGetObj(var) * mult) )
2426  {
2427  assert(mult * 10 > mult);
2428  mult *= 10;
2429  }
2430  }
2431  }
2432 
2433  if( objective )
2434  {
2435  /* there exist a objective function*/
2436  SCIPinfoMessage(scip, file, "* Obj. scale : %.15g\n", objscale * mult);
2437  SCIPinfoMessage(scip, file, "* Obj. offset : %.15g\n", objoffset);
2438 
2439  clearBuffer(linebuffer, &linecnt);
2440 
2441  /* opb format supports only minimization; therefore, a maximization problem has to be converted */
2442  if( objsense == SCIP_OBJSENSE_MAXIMIZE )
2443  mult *= -1;
2444 
2445  SCIPdebugMsg(scip, "print objective function multiplied with %" SCIP_LONGINT_FORMAT "\n", mult);
2446 
2447  appendBuffer(scip, file, linebuffer, &linecnt, "min:");
2448 
2449 #ifndef NDEBUG
2450  if( existands )
2451  {
2452  int c;
2453  /* check that these variables are sorted */
2454  for( c = nresvars - 1; c > 0; --c )
2455  assert(SCIPvarGetIndex(resvars[c]) >= SCIPvarGetIndex(resvars[c - 1])); /*lint !e613 */
2456  }
2457 #endif
2458 
2459  for( v = nvars - 1; v >= 0; --v )
2460  {
2461  SCIP_Bool negated;
2462  var = vars[v]; /*lint !e613 */
2463 
2464  assert(var != NULL);
2465 
2466  if( SCIPisZero(scip, SCIPvarGetObj(var)) )
2467  continue;
2468 
2469  negated = SCIPvarIsNegated(var);
2470 
2471  assert( linecnt != 0 );
2472 
2473  if( SCIPvarGetObj(var) * mult > SCIP_LONGINT_MAX )
2474  {
2475  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));
2476  }
2477 
2478  /* replace and-resultant with corresponding variables */
2479  if( existands && SCIPsortedvecFindPtr((void**)resvars, SCIPvarComp, var, nresvars, &pos) )
2480  {
2481  int a;
2482 
2483  assert(andvars != NULL);
2484  assert(nandvars != NULL);
2485  assert(pos >= 0 && nandvars[pos] > 0 && andvars[pos] != NULL);
2486  assert(andvars[pos][nandvars[pos] - 1] != NULL);
2487 
2488  negated = SCIPvarIsNegated(andvars[pos][nandvars[pos] - 1]);
2489 
2490  /* print and-vars */
2491  (void) SCIPsnprintf(buffer, OPB_MAX_LINELEN, " %+" SCIP_LONGINT_FORMAT "%s%s%s",
2492  (SCIP_Longint) (SCIPvarGetObj(var) * mult), multisymbol, negated ? "~" : "",
2493  strstr(SCIPvarGetName(negated ? SCIPvarGetNegationVar(andvars[pos][nandvars[pos] - 1]) : andvars[pos][nandvars[pos] - 1]), "x"));
2494  appendBuffer(scip, file, linebuffer, &linecnt, buffer);
2495 
2496  for(a = nandvars[pos] - 2; a >= 0; --a )
2497  {
2498  negated = SCIPvarIsNegated(andvars[pos][a]);
2499 
2500  (void) SCIPsnprintf(buffer, OPB_MAX_LINELEN, "%s%s%s", multisymbol, negated ? "~" : "", strstr(SCIPvarGetName(negated ? SCIPvarGetNegationVar(andvars[pos][a]) : andvars[pos][a]), "x"));
2501  appendBuffer(scip, file, linebuffer, &linecnt, buffer);
2502  }
2503  }
2504  else
2505  {
2506  (void) SCIPsnprintf(buffer, OPB_MAX_LINELEN, " %+" SCIP_LONGINT_FORMAT "%s%s%s",
2507  (SCIP_Longint) (SCIPvarGetObj(var) * mult), multisymbol, negated ? "~" : "", strstr(SCIPvarGetName(negated ? SCIPvarGetNegationVar(var) : var), "x"));
2508  appendBuffer(scip, file, linebuffer, &linecnt, buffer);
2509  }
2510  }
2511 
2512  /* and objective function line ends with a ';' */
2513  appendBuffer(scip, file, linebuffer, &linecnt, " ;\n");
2514  writeBuffer(scip, file, linebuffer, &linecnt);
2515  }
2516 
2517  return SCIP_OKAY;
2518 }
2519 
2520 /* print maybe non linear row in OPB format to file stream */
2521 static
2523  SCIP*const scip, /**< SCIP data structure */
2524  FILE*const file, /**< output file (or NULL for standard output) */
2525  char const*const type, /**< row type ("=" or ">=") */
2526  SCIP_VAR**const vars, /**< array of variables */
2527  SCIP_Real const*const vals, /**< array of values */
2528  int const nvars, /**< number of variables */
2529  SCIP_Real lhs, /**< left hand side */
2530  SCIP_VAR** const resvars, /**< array of resultant variables */
2531  int const nresvars, /**< number of resultant variables */
2532  SCIP_VAR**const*const andvars, /**< corresponding array of and-variables */
2533  int const*const nandvars, /**< array of numbers of corresponding and-variables */
2534  SCIP_Longint weight, /**< if we found a soft constraint this is the weight, otherwise 0 */
2535  SCIP_Longint*const mult, /**< multiplier for the coefficients */
2536  char const*const multisymbol /**< the multiplication symbol to use between coefficient and variable */
2537  )
2538 {
2539  SCIP_VAR* var;
2540  char buffer[OPB_MAX_LINELEN];
2541  char linebuffer[OPB_MAX_LINELEN + 1];
2542  int v;
2543  int pos;
2544  int linecnt;
2545 
2546  assert(scip != NULL);
2547  assert(strcmp(type, "=") == 0 || strcmp(type, ">=") == 0);
2548  assert(mult != NULL);
2549  assert(resvars != NULL);
2550  assert(nresvars > 0);
2551  assert(andvars != NULL && nandvars != NULL);
2552 
2553  clearBuffer(linebuffer, &linecnt);
2554 
2555  /* check if all coefficients are internal; if not commentstart multiplier */
2556  for( v = 0; v < nvars; ++v )
2557  {
2558  while( !SCIPisIntegral(scip, vals[v] * (*mult)) )
2559  {
2560  if( ABS(*mult) > ABS(*mult * 10) )
2561  return SCIP_INVALIDDATA;
2562  (*mult) *= 10;
2563  }
2564  }
2565 
2566  while( !SCIPisIntegral(scip, lhs * (*mult)) )
2567  {
2568  if( ABS(*mult) > ABS(*mult * 10) )
2569  return SCIP_INVALIDDATA;
2570  (*mult) *= 10;
2571  }
2572 
2573  /* print comment line if we have to multiply the coefficients to get integrals */
2574  if( ABS(*mult) != 1 )
2575  SCIPinfoMessage(scip, file, "* the following constraint is multiplied by %" SCIP_LONGINT_FORMAT " to get integral coefficients\n", ABS(*mult) );
2576 
2577 #ifndef NDEBUG
2578  /* check that these variables are sorted */
2579  for( v = nresvars - 1; v > 0; --v )
2580  assert(SCIPvarGetIndex(resvars[v]) >= SCIPvarGetIndex(resvars[v - 1]));
2581 #endif
2582 
2583  /* if we have a soft constraint print the weight*/
2584  if( weight != 0 )
2585  {
2586  (void) SCIPsnprintf(buffer, OPB_MAX_LINELEN, "[%+" SCIP_LONGINT_FORMAT "] ", weight);
2587  appendBuffer(scip, file, linebuffer, &linecnt, buffer);
2588  }
2589 
2590  /* print coefficients */
2591  for( v = 0; v < nvars; ++v )
2592  {
2593  SCIP_Bool negated;
2594 
2595  var = vars[v];
2596  assert( var != NULL );
2597 
2598  negated = SCIPvarIsNegated(var);
2599 
2600  /* replace and-resultant with corresponding variables */
2601  if( SCIPsortedvecFindPtr((void**)resvars, SCIPvarComp, var, nresvars, &pos) )
2602  {
2603  int a;
2604 
2605  assert(andvars != NULL);
2606  assert(nandvars != NULL);
2607  assert(pos >= 0 && nandvars[pos] > 0 && andvars[pos] != NULL);
2608  assert(andvars[pos][nandvars[pos] - 1] != NULL);
2609 
2610  negated = SCIPvarIsNegated(andvars[pos][nandvars[pos] - 1]);
2611 
2612  if( vals[v] * (*mult) > SCIP_LONGINT_MAX )
2613  {
2614  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)));
2615  }
2616 
2617  /* print and-vars */
2618  (void) SCIPsnprintf(buffer, OPB_MAX_LINELEN, "%+" SCIP_LONGINT_FORMAT "%s%s%s",
2619  (SCIP_Longint) SCIPround(scip, vals[v] * (*mult)), multisymbol, negated ? "~" : "",
2620  strstr(SCIPvarGetName(negated ? SCIPvarGetNegationVar(andvars[pos][nandvars[pos] - 1]) : andvars[pos][nandvars[pos] - 1]), "x") );
2621  appendBuffer(scip, file, linebuffer, &linecnt, buffer);
2622 
2623  for(a = nandvars[pos] - 2; a >= 0; --a )
2624  {
2625  negated = SCIPvarIsNegated(andvars[pos][a]);
2626 
2627  (void) SCIPsnprintf(buffer, OPB_MAX_LINELEN, "%s%s%s", multisymbol, negated ? "~" : "", strstr(SCIPvarGetName(negated ? SCIPvarGetNegationVar(andvars[pos][a]) : andvars[pos][a]), "x"));
2628  appendBuffer(scip, file, linebuffer, &linecnt, buffer);
2629  }
2630 
2631  appendBuffer(scip, file, linebuffer, &linecnt, " ");
2632  }
2633  else
2634  {
2635  (void) SCIPsnprintf(buffer, OPB_MAX_LINELEN, "%+" SCIP_LONGINT_FORMAT "%s%s%s ",
2636  (SCIP_Longint) SCIPround(scip, vals[v] * (*mult)), multisymbol, negated ? "~" : "", strstr(SCIPvarGetName(negated ? SCIPvarGetNegationVar(var) : var), "x"));
2637  appendBuffer(scip, file, linebuffer, &linecnt, buffer);
2638  }
2639  }
2640 
2641  /* print left hand side */
2642  if( SCIPisZero(scip, lhs) )
2643  lhs = 0.0;
2644 
2645  (void) SCIPsnprintf(buffer, OPB_MAX_LINELEN, "%s %" SCIP_LONGINT_FORMAT " ;\n", type, (SCIP_Longint) (lhs * (*mult)) );
2646  appendBuffer(scip, file, linebuffer, &linecnt, buffer);
2647 
2648  writeBuffer(scip, file, linebuffer, &linecnt);
2649 
2650  return SCIP_OKAY;
2651 }
2652 
2653 
2654 /** prints given maybe non-linear constraint information in OPB format to file stream */
2655 static
2657  SCIP*const scip, /**< SCIP data structure */
2658  FILE*const file, /**< output file (or NULL for standard output) */
2659  SCIP_VAR**const vars, /**< array of variables */
2660  SCIP_Real*const vals, /**< array of coefficients values (or NULL if all coefficient values are 1) */
2661  int const nvars, /**< number of variables */
2662  SCIP_Real const lhs, /**< left hand side */
2663  SCIP_Real const rhs, /**< right hand side */
2664  SCIP_VAR** const resvars, /**< array of resultant variables */
2665  int const nresvars, /**< number of resultant variables */
2666  SCIP_VAR**const*const andvars, /**< corresponding array of and-variables */
2667  int const*const nandvars, /**< array of numbers of corresponding and-variables */
2668  SCIP_Longint weight, /**< if we found a soft constraint this is the weight, otherwise 0 */
2669  SCIP_Bool const transformed, /**< transformed constraint? */
2670  char const*const multisymbol /**< the multiplication symbol to use between coefficient and variable */
2671  )
2672 {
2673  SCIP_VAR** activevars;
2674  SCIP_Real* activevals;
2675  SCIP_Real activeconstant;
2676  SCIP_Longint mult;
2677  SCIP_RETCODE retcode;
2678  int v;
2679  int nactivevars;
2680 
2681  assert(scip != NULL);
2682  assert(vars != NULL);
2683  assert(nvars > 0);
2684  assert(lhs <= rhs);
2685  assert(resvars != NULL);
2686  assert(nresvars > 0);
2687  assert(andvars != NULL && nandvars != NULL);
2688 
2689  if( SCIPisInfinity(scip, -lhs) && SCIPisInfinity(scip, rhs) )
2690  return SCIP_OKAY;
2691 
2692  activeconstant = 0.0;
2693  nactivevars = nvars;
2694 
2695  /* duplicate variable and value array */
2696  SCIP_CALL( SCIPduplicateBufferArray(scip, &activevars, vars, nactivevars ) );
2697  if( vals != NULL )
2698  {
2699  SCIP_CALL( SCIPduplicateBufferArray(scip, &activevals, vals, nactivevars ) );
2700  }
2701  else
2702  {
2703  SCIP_CALL( SCIPallocBufferArray(scip, &activevals, nactivevars) );
2704 
2705  for( v = 0; v < nactivevars; ++v )
2706  activevals[v] = 1.0;
2707  }
2708 
2709  /* retransform given variables to active variables */
2710  SCIP_CALL( getActiveVariables(scip, activevars, activevals, &nactivevars, &activeconstant, transformed) );
2711 
2712  mult = 1;
2713  retcode = SCIP_OKAY;
2714 
2715  /* print row(s) in OPB format */
2716  if( SCIPisEQ(scip, lhs, rhs) )
2717  {
2718  assert( !SCIPisInfinity(scip, rhs) );
2719 
2720  /* equality constraint */
2721  retcode = printNLRow(scip, file, "=", activevars, activevals, nactivevars, rhs - activeconstant, resvars,
2722  nresvars, andvars, nandvars, weight, &mult, multisymbol);
2723  }
2724  else
2725  {
2726  if( !SCIPisInfinity(scip, -lhs) )
2727  {
2728  /* print inequality ">=" */
2729  retcode = printNLRow(scip, file, ">=", activevars, activevals, nactivevars, lhs - activeconstant, resvars,
2730  nresvars, andvars, nandvars, weight, &mult, multisymbol);
2731  }
2732 
2733  if( !SCIPisInfinity(scip, rhs) )
2734  {
2735  mult *= -1;
2736 
2737  /* print inequality ">=" and multiplying all coefficients by -1 */
2738  retcode = printNLRow(scip, file, ">=", activevars, activevals, nactivevars, rhs - activeconstant, resvars,
2739  nresvars, andvars, nandvars, weight, &mult, multisymbol);
2740  }
2741  }
2742 
2743  /* free buffer arrays */
2744  SCIPfreeBufferArray(scip, &activevars);
2745  SCIPfreeBufferArray(scip, &activevals);
2746 
2747  return retcode;
2748 }
2749 
2750 
2751 /* print row in OPB format to file stream */
2752 static
2754  SCIP* scip, /**< SCIP data structure */
2755  FILE* file, /**< output file (or NULL for standard output) */
2756  const char* type, /**< row type ("=" or ">=") */
2757  SCIP_VAR** vars, /**< array of variables */
2758  SCIP_Real* vals, /**< array of values */
2759  int nvars, /**< number of variables */
2760  SCIP_Real lhs, /**< left hand side */
2761  SCIP_Longint weight, /**< if we found a soft constraint this is the weight, otherwise 0 */
2762  SCIP_Longint* mult, /**< multiplier for the coefficients */
2763  const char* multisymbol /**< the multiplication symbol to use between coefficient and variable */
2764  )
2765 {
2766  SCIP_VAR* var;
2767  char buffer[OPB_MAX_LINELEN];
2768  char linebuffer[OPB_MAX_LINELEN + 1];
2769  int v;
2770  int linecnt;
2771 
2772  assert(scip != NULL);
2773  assert(strcmp(type, "=") == 0 || strcmp(type, ">=") == 0);
2774  assert(mult != NULL);
2775 
2776  clearBuffer(linebuffer, &linecnt);
2777 
2778  /* if we found the topcost linear inequality which gives us the maximal cost which could be violated by our solution,
2779  * we can stop printing because it is an artificial constraint
2780  */
2781  if( nvars > 0 && strstr(SCIPvarGetName(vars[0]), INDICATORVARNAME) != NULL )
2782  return SCIP_OKAY;
2783 
2784  /* check if all coefficients are integral; if not commentstart multiplier */
2785  for( v = 0; v < nvars; ++v )
2786  {
2787  while( !SCIPisIntegral(scip, vals[v] * (*mult)) )
2788  {
2789  if( ABS(*mult) > ABS(*mult * 10) )
2790  return SCIP_INVALIDDATA;
2791  (*mult) *= 10;
2792  }
2793  }
2794 
2795  while( !SCIPisIntegral(scip, lhs * (*mult)) )
2796  {
2797  if( ABS(*mult) > ABS(*mult * 10) )
2798  return SCIP_INVALIDDATA;
2799  (*mult) *= 10;
2800  }
2801 
2802  /* print comment line if we have to multiply the coefficients to get integrals */
2803  if( ABS(*mult) != 1 )
2804  SCIPinfoMessage(scip, file, "* the following constraint is multiplied by %" SCIP_LONGINT_FORMAT " to get integral coefficients\n", ABS(*mult) );
2805 
2806  /* if we have a soft constraint print the weight*/
2807  if( weight != 0 )
2808  {
2809  (void) SCIPsnprintf(buffer, OPB_MAX_LINELEN, "[%+" SCIP_LONGINT_FORMAT "] ", weight);
2810  appendBuffer(scip, file, linebuffer, &linecnt, buffer);
2811  }
2812 
2813  /* print coefficients */
2814  for( v = 0; v < nvars; ++v )
2815  {
2816  SCIP_Bool negated;
2817 
2818  var = vars[v];
2819  assert( var != NULL );
2820 
2821  negated = SCIPvarIsNegated(var);
2822 
2823  if( vals[v] * (*mult) > SCIP_LONGINT_MAX )
2824  {
2825  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)));
2826  }
2827 
2828  (void) SCIPsnprintf(buffer, OPB_MAX_LINELEN, "%+" SCIP_LONGINT_FORMAT "%s%s%s ",
2829  (SCIP_Longint) SCIPround(scip, vals[v] * (*mult)), multisymbol, negated ? "~" : "", strstr(SCIPvarGetName(negated ? SCIPvarGetNegationVar(var) : var), "x"));
2830  appendBuffer(scip, file, linebuffer, &linecnt, buffer);
2831  }
2832 
2833  /* print left hand side */
2834  if( SCIPisZero(scip, lhs) )
2835  lhs = 0.0;
2836 
2837  (void) SCIPsnprintf(buffer, OPB_MAX_LINELEN, "%s %" SCIP_LONGINT_FORMAT " ;\n", type, (SCIP_Longint) (lhs * (*mult)) );
2838  appendBuffer(scip, file, linebuffer, &linecnt, buffer);
2839 
2840  writeBuffer(scip, file, linebuffer, &linecnt);
2841 
2842  return SCIP_OKAY;
2843 }
2844 
2845 
2846 /** prints given linear constraint information in OPB format to file stream */
2847 static
2849  SCIP* scip, /**< SCIP data structure */
2850  FILE* file, /**< output file (or NULL for standard output) */
2851  SCIP_VAR** vars, /**< array of variables */
2852  SCIP_Real* vals, /**< array of coefficients values (or NULL if all coefficient values are 1) */
2853  int nvars, /**< number of variables */
2854  SCIP_Real lhs, /**< left hand side */
2855  SCIP_Real rhs, /**< right hand side */
2856  SCIP_Longint weight, /**< if we found a soft constraint this is the weight, otherwise 0 */
2857  SCIP_Bool transformed, /**< transformed constraint? */
2858  const char* multisymbol /**< the multiplication symbol to use between coefficient and variable */
2859  )
2860 {
2861  SCIP_VAR** activevars;
2862  SCIP_Real* activevals;
2863  int nactivevars;
2864  SCIP_Real activeconstant;
2865  SCIP_Longint mult;
2866  SCIP_RETCODE retcode;
2867  int v;
2868 
2869  assert( scip != NULL );
2870  assert( vars != NULL );
2871  assert( nvars > 0 );
2872  assert( lhs <= rhs );
2873 
2874  if( SCIPisInfinity(scip, -lhs) && SCIPisInfinity(scip, rhs) )
2875  return SCIP_OKAY;
2876 
2877  activeconstant = 0.0;
2878 
2879  /* duplicate variable and value array */
2880  nactivevars = nvars;
2881  SCIP_CALL( SCIPduplicateBufferArray(scip, &activevars, vars, nactivevars ) );
2882  if( vals != NULL )
2883  {
2884  SCIP_CALL( SCIPduplicateBufferArray(scip, &activevals, vals, nactivevars ) );
2885  }
2886  else
2887  {
2888  SCIP_CALL( SCIPallocBufferArray(scip, &activevals, nactivevars) );
2889 
2890  for( v = 0; v < nactivevars; ++v )
2891  activevals[v] = 1.0;
2892  }
2893 
2894  /* retransform given variables to active variables */
2895  SCIP_CALL( getActiveVariables(scip, activevars, activevals, &nactivevars, &activeconstant, transformed) );
2896 
2897  mult = 1;
2898  retcode = SCIP_OKAY;
2899 
2900  /* print row(s) in OPB format */
2901  if( SCIPisEQ(scip, lhs, rhs) )
2902  {
2903  assert( !SCIPisInfinity(scip, rhs) );
2904 
2905  /* equality constraint */
2906  retcode = printRow(scip, file, "=", activevars, activevals, nactivevars, rhs - activeconstant, weight, &mult,
2907  multisymbol);
2908  }
2909  else
2910  {
2911  if( !SCIPisInfinity(scip, -lhs) )
2912  {
2913  /* print inequality ">=" */
2914  retcode = printRow(scip, file, ">=", activevars, activevals, nactivevars, lhs - activeconstant, weight, &mult,
2915  multisymbol);
2916  }
2917 
2918  if( !SCIPisInfinity(scip, rhs) )
2919  {
2920  mult *= -1;
2921 
2922  /* print inequality ">=" and multiplying all coefficients by -1 */
2923  retcode = printRow(scip, file, ">=", activevars, activevals, nactivevars, rhs - activeconstant, weight, &mult,
2924  multisymbol);
2925  }
2926  }
2927 
2928  /* free buffer arrays */
2929  SCIPfreeBufferArray(scip, &activevars);
2930  SCIPfreeBufferArray(scip, &activevals);
2931 
2932  return retcode;
2933 }
2934 
2935 /* print row in OPB format to file stream */
2936 static
2938  SCIP*const scip, /**< SCIP data structure */
2939  FILE*const file, /**< output file (or NULL for standard output) */
2940  const char* type, /**< row type ("=" or ">=") */
2941  SCIP_VAR**const linvars, /**< array of variables */
2942  SCIP_Real*const linvals, /**< array of values */
2943  int const nlinvars, /**< number of variables */
2944  SCIP_VAR***const termvars, /**< term array with array of variables to print */
2945  int*const ntermvars, /**< array with number of variables in each term */
2946  SCIP_Real*const termvals, /**< array of coefficient values for non-linear variables */
2947  int const ntermvals, /**< number non-linear variables in the problem */
2948  SCIP_Bool**const negatedarrays, /**< array of arrays to know which variable in a non-linear part is negated */
2949  SCIP_VAR*const indvar, /**< indicator variable, or NULL */
2950  SCIP_Real lhs, /**< left hand side */
2951  SCIP_Longint* mult, /**< multiplier for the coefficients */
2952  const char* multisymbol /**< the multiplication symbol to use between coefficient and variable */
2953  )
2954 {
2955  SCIP_VAR* var;
2956  char buffer[OPB_MAX_LINELEN];
2957  char linebuffer[OPB_MAX_LINELEN + 1];
2958  int v;
2959  int t;
2960  int linecnt;
2961 
2962  assert(scip != NULL);
2963  assert(strcmp(type, "=") == 0 || strcmp(type, ">=") == 0);
2964  assert(linvars != NULL || nlinvars == 0);
2965  assert(linvals != NULL || nlinvars == 0);
2966  assert(termvars != NULL || ntermvals == 0);
2967  assert(ntermvars != NULL || ntermvals == 0);
2968  assert(termvals != NULL || ntermvals == 0);
2969  assert(negatedarrays != NULL || ntermvals == 0);
2970  assert(mult != NULL);
2971 
2972  clearBuffer(linebuffer, &linecnt);
2973 
2974  /* if we found the topcost linear inequality which gives us the maximal cost which could be violated by our solution,
2975  * we can stop printing because it is an artificial constraint
2976  */
2977  if( ntermvals == 0 && nlinvars > 0 && strstr(SCIPvarGetName(linvars[0]), INDICATORVARNAME) != NULL ) /*lint !e613 */
2978  return SCIP_OKAY;
2979 
2980  /* check if all linear coefficients are internal; if not commentstart multiplier */
2981  for( v = 0; v < nlinvars; ++v )
2982  {
2983  while( !SCIPisIntegral(scip, linvals[v] * (*mult)) ) /*lint !e613 */
2984  {
2985  if( ABS(*mult) > ABS(*mult * 10) )
2986  return SCIP_INVALIDDATA;
2987  (*mult) *= 10;
2988  }
2989  }
2990 
2991  /* check if all non-linear coefficients are internal; if not commentstart multiplier */
2992  for( v = 0; v < ntermvals; ++v )
2993  {
2994  while( !SCIPisIntegral(scip, termvals[v] * (*mult)) ) /*lint !e613 */
2995  {
2996  if( ABS(*mult) > ABS(*mult * 10) )
2997  return SCIP_INVALIDDATA;
2998  (*mult) *= 10;
2999  }
3000  }
3001 
3002  while( !SCIPisIntegral(scip, lhs * (*mult)) )
3003  {
3004  if( ABS(*mult) > ABS(*mult * 10) )
3005  return SCIP_INVALIDDATA;
3006  (*mult) *= 10;
3007  }
3008 
3009  /* print comment line if we have to multiply the coefficients to get integrals */
3010  if( ABS(*mult) != 1 )
3011  SCIPinfoMessage(scip, file, "* the following constraint is multiplied by %" SCIP_LONGINT_FORMAT " to get integral coefficients\n", ABS(*mult) );
3012 
3013  /* if indicator variable exist we have a soft constraint */
3014  if( indvar != NULL )
3015  {
3016  SCIP_Real weight;
3017 
3018  weight = SCIPvarGetObj(indvar);
3019  (void) SCIPsnprintf(buffer, OPB_MAX_LINELEN, "[%+g] ", weight);
3020  appendBuffer(scip, file, linebuffer, &linecnt, buffer);
3021  }
3022 
3023  /* print linear part */
3024  for( v = 0; v < nlinvars; ++v )
3025  {
3026  SCIP_Bool negated;
3027 
3028  var = linvars[v]; /*lint !e613 */
3029  assert(var != NULL);
3030 
3031  negated = SCIPvarIsNegated(var);
3032 
3033  (void) SCIPsnprintf(buffer, OPB_MAX_LINELEN, "%+" SCIP_LONGINT_FORMAT "%s%s%s ",
3034  (SCIP_Longint) SCIPround(scip, linvals[v] * (*mult)), multisymbol, negated ? "~" : "", strstr(SCIPvarGetName(negated ? SCIPvarGetNegationVar(var) : var), "x")); /*lint !e613 */
3035  appendBuffer(scip, file, linebuffer, &linecnt, buffer);
3036  }
3037 
3038  /* print non-linear part */
3039  for( t = 0; t < ntermvals; ++t )
3040  {
3041  (void) SCIPsnprintf(buffer, OPB_MAX_LINELEN, "%+" SCIP_LONGINT_FORMAT, (SCIP_Longint) SCIPround(scip, termvals[t] * (*mult))); /*lint !e613 */
3042  appendBuffer(scip, file, linebuffer, &linecnt, buffer);
3043 
3044  for( v = 0; v < ntermvars[t]; ++v ) /*lint !e613 */
3045  {
3046  SCIP_Bool negated;
3047 
3048  var = termvars[t][v]; /*lint !e613 */
3049  assert(var != NULL);
3050 
3051  negated = negatedarrays[t][v]; /*lint !e613 */
3052 
3053  (void) SCIPsnprintf(buffer, OPB_MAX_LINELEN, "%s%s%s", multisymbol, negated ? "~" : "", strstr(SCIPvarGetName(negated ? SCIPvarGetNegationVar(var) : var), "x"));
3054  appendBuffer(scip, file, linebuffer, &linecnt, buffer);
3055  }
3056  appendBuffer(scip, file, linebuffer, &linecnt, " ");
3057  }
3058 
3059  /* print left hand side */
3060  if( SCIPisZero(scip, lhs) )
3061  lhs = 0.0;
3062 
3063  (void) SCIPsnprintf(buffer, OPB_MAX_LINELEN, "%s %" SCIP_LONGINT_FORMAT " ;\n", type, (SCIP_Longint) (lhs * (*mult)) );
3064  appendBuffer(scip, file, linebuffer, &linecnt, buffer);
3065 
3066  writeBuffer(scip, file, linebuffer, &linecnt);
3067 
3068  return SCIP_OKAY;
3069 }
3070 
3071 
3072 /** prints given pseudo boolean constraint information in OPB format to file stream */
3073 static
3075  SCIP*const scip, /**< SCIP data structure */
3076  FILE*const file, /**< output file, or NULL if standard output should be used */
3077  SCIP_VAR**const linvars, /**< array with variables of linear part */
3078  SCIP_Real*const linvals, /**< array of coefficients values of linear part */
3079  int const nlinvars, /**< number variables in linear part of the problem */
3080  SCIP_VAR***const termvars, /**< term array with array of variables to print */
3081  int*const ntermvars, /**< array with number of variables in each term */
3082  SCIP_Real*const termvals, /**< array of coefficient values for non-linear variables */
3083  int const ntermvals, /**< number non-linear variables in the problem */
3084  SCIP_VAR*const indvar, /**< indicator variable, or NULL */
3085  SCIP_Real const lhs, /**< left hand side of constraint */
3086  SCIP_Real const rhs, /**< right hand side of constraint */
3087  SCIP_Bool transformed, /**< should the transformed problem be printed ? */
3088  const char* multisymbol /**< the multiplication symbol to use between coefficient and variable */
3089  )
3090 {
3091  SCIP_VAR*** activetermvars;
3092  SCIP_Bool** negatedarrays;
3093  SCIP_VAR** activelinvars;
3094  SCIP_Real* activelinvals;
3095  int nactivelinvars;
3096  SCIP_Real activelinconstant;
3097  SCIP_Longint mult;
3098  SCIP_RETCODE retcode;
3099  int v;
3100 
3101  assert(scip != NULL);
3102  assert(linvars != NULL || nlinvars == 0);
3103  assert(linvals != NULL || nlinvars == 0);
3104  assert(termvars != NULL || 0 == ntermvals);
3105  assert(ntermvars != NULL || 0 == ntermvals);
3106  assert(termvals != NULL || 0 == ntermvals);
3107  assert(lhs <= rhs);
3108 
3109  if( SCIPisInfinity(scip, -lhs) && SCIPisInfinity(scip, rhs) )
3110  return SCIP_OKAY;
3111 
3112  activelinconstant = 0.0;
3113 
3114  /* duplicate variable and value array for linear part */
3115  nactivelinvars = nlinvars;
3116  if( nactivelinvars > 0 )
3117  {
3118  SCIP_CALL( SCIPduplicateBufferArray(scip, &activelinvars, linvars, nactivelinvars ) );
3119  SCIP_CALL( SCIPduplicateBufferArray(scip, &activelinvals, linvals, nactivelinvars ) );
3120 
3121  /* retransform given variables to active variables */
3122  SCIP_CALL( getActiveVariables(scip, activelinvars, activelinvals, &nactivelinvars, &activelinconstant, transformed) );
3123  }
3124  else
3125  {
3126  activelinvars = NULL;
3127  activelinvals = NULL;
3128  }
3129 
3130  /* create non-linear information for printing */
3131  if( ntermvals > 0 )
3132  {
3133  assert(termvars != NULL);
3134  assert(ntermvars != NULL);
3135  assert(termvals != NULL);
3136 
3137  SCIP_CALL( SCIPallocBufferArray(scip, &activetermvars, ntermvals) );
3138  SCIP_CALL( SCIPallocBufferArray(scip, &negatedarrays, ntermvals) );
3139  for( v = ntermvals - 1; v >= 0; --v )
3140  {
3141  assert(ntermvars[v] > 0); /*lint !e613 */
3142 
3143  if( transformed )
3144  {
3145  SCIP_CALL( SCIPallocBufferArray(scip, &(activetermvars[v]), ntermvars[v]) ); /*lint !e866 */
3146  SCIP_CALL( SCIPallocBufferArray(scip, &(negatedarrays[v]), ntermvars[v]) ); /*lint !e866 */
3147 
3148  /* get binary representatives of binary variables in non-linear terms */
3149  SCIP_CALL( SCIPgetBinvarRepresentatives(scip, ntermvars[v], termvars[v], activetermvars[v], negatedarrays[v]) );
3150  }
3151  else
3152  {
3153  SCIP_CALL( SCIPduplicateBufferArray(scip, &(activetermvars[v]), termvars[v], ntermvars[v]) ); /*lint !e866 */
3154  SCIP_CALL( SCIPallocBufferArray(scip, &(negatedarrays[v]), ntermvars[v]) ); /*lint !e866 */
3155  BMSclearMemoryArray(negatedarrays[v], ntermvars[v]); /*lint !e866 */
3156  }
3157  }
3158  }
3159  else
3160  {
3161  activetermvars = NULL;
3162  negatedarrays = NULL;
3163  }
3164 
3165  mult = 1;
3166  retcode = SCIP_OKAY;
3167 
3168  /* print row(s) in OPB format */
3169  if( SCIPisEQ(scip, lhs, rhs) )
3170  {
3171  assert( !SCIPisInfinity(scip, rhs) );
3172 
3173  /* equality constraint */
3174  retcode = printPBRow(scip, file, "=", activelinvars, activelinvals, nactivelinvars, activetermvars,
3175  ntermvars, termvals, ntermvals, negatedarrays, indvar, rhs - activelinconstant, &mult, multisymbol);
3176  }
3177  else
3178  {
3179  if( !SCIPisInfinity(scip, -lhs) )
3180  {
3181  /* print inequality ">=" */
3182  retcode = printPBRow(scip, file, ">=", activelinvars, activelinvals, nactivelinvars, activetermvars,
3183  ntermvars, termvals, ntermvals, negatedarrays, indvar, lhs - activelinconstant, &mult, multisymbol);
3184  }
3185 
3186  if( !SCIPisInfinity(scip, rhs) )
3187  {
3188  mult *= -1;
3189 
3190  /* print inequality ">=" and multiplying all coefficients by -1 */
3191  /* coverity[var_deref_model] */
3192  retcode = printPBRow(scip, file, ">=", activelinvars, activelinvals, nactivelinvars, activetermvars,
3193  ntermvars, termvals, ntermvals, negatedarrays, indvar, rhs - activelinconstant, &mult, multisymbol);
3194  }
3195  }
3196 
3197  /* free buffers for non-linear arrays */
3198  if( ntermvals > 0 )
3199  {
3200  assert(negatedarrays != NULL);
3201  assert(activetermvars != NULL);
3202 
3203  for( v = 0; v < ntermvals; ++v )
3204  {
3205  assert(negatedarrays[v] != NULL);
3206  assert(activetermvars[v] != NULL);
3207  SCIPfreeBufferArray(scip, &(negatedarrays[v]));
3208  SCIPfreeBufferArray(scip, &(activetermvars[v]));
3209  }
3210  SCIPfreeBufferArray(scip, &negatedarrays);
3211  SCIPfreeBufferArray(scip, &activetermvars);
3212  }
3213 
3214  /* free buffer for linear arrays */
3215  if( nactivelinvars > 0 )
3216  {
3217  SCIPfreeBufferArray(scip, &activelinvars);
3218  SCIPfreeBufferArray(scip, &activelinvals);
3219  }
3220 
3221  return retcode;
3222 }
3223 
3224 
3225 static
3227  SCIP*const scip, /**< SCIP data structure */
3228  FILE*const file, /**< output file, or NULL if standard output should be used */
3229  SCIP_CONS**const conss, /**< array with constraints of the problem */
3230  int const nconss, /**< number of constraints in the problem */
3231  SCIP_VAR**const vars, /**< array with active (binary) variables */
3232  int const nvars, /**< number of active variables in the problem */
3233  SCIP_VAR** const resvars, /**< array of resultant variables */
3234  int const nresvars, /**< number of resultant variables */
3235  SCIP_VAR**const*const andvars, /**< corresponding array of and-variables */
3236  int const*const nandvars, /**< array of numbers of corresponding and-variables */
3237  char const*const multisymbol, /**< the multiplication symbol to use between coefficient and variable */
3238  SCIP_Bool const existandconshdlr, /**< does and-constrainthandler exist? */
3239  SCIP_Bool const existands, /**< does some and-constraints exist? */
3240  SCIP_Bool const transformed /**< TRUE iff problem is the transformed problem */
3241  )
3242 {
3243  SCIP_CONSHDLR* conshdlr;
3244  const char* conshdlrname;
3245  SCIP_CONS* cons;
3246  SCIP_VAR** consvars;
3247  SCIP_Real* consvals;
3248  SCIP_RETCODE retcode;
3249  int nconsvars;
3250  int v, c;
3251  SCIP_HASHMAP* linconssofindicatorsmap = NULL;
3252  SCIP_HASHMAP* linconssofpbsmap = NULL;
3253 
3254  assert(scip != NULL);
3255  assert(file != NULL);
3256  assert(conss != NULL || nconss == 0);
3257  assert(vars != NULL || nvars == 0);
3258  assert(resvars != NULL || nresvars == 0);
3259  assert(andvars != NULL || nandvars == 0);
3260  assert(multisymbol != NULL);
3261 
3262  if( transformed )
3263  {
3264  conshdlr = SCIPfindConshdlr(scip, "indicator");
3265 
3266  /* find artificial linear constraints which correspond to indicator constraints to avoid double printing */
3267  if( conshdlr != NULL )
3268  {
3269  SCIP_CONS** indconss;
3270  int nindconss;
3271 
3272  indconss = SCIPconshdlrGetConss(conshdlr);
3273  nindconss = SCIPconshdlrGetNConss(conshdlr);
3274  assert(indconss != NULL || nindconss == 0);
3275 
3276  if( nindconss > 0 )
3277  {
3278  SCIP_CONS* lincons;
3279 
3280  /* create the linear constraint of indicator constraints hash map */
3281  SCIP_CALL( SCIPhashmapCreate(&linconssofindicatorsmap, SCIPblkmem(scip), nindconss) );
3282  assert(indconss != NULL);
3283 
3284  for( c = 0; c < nindconss; ++c )
3285  {
3286  assert(indconss[c] != NULL);
3287  lincons = SCIPgetLinearConsIndicator(indconss[c]);
3288  assert(lincons != NULL);
3289 
3290  /* insert constraint into mapping between */
3291  SCIP_CALL( SCIPhashmapInsert(linconssofindicatorsmap, (void*)lincons, (void*)lincons) );
3292  }
3293  }
3294  }
3295 
3296  conshdlr = SCIPfindConshdlr(scip, "pseudoboolean");
3297 
3298  /* find artifical linear constraints which correspond to indicator constraints to avoid double printing */
3299  if( conshdlr != NULL )
3300  {
3301  SCIP_CONS** pbconss;
3302  int npbconss;
3303 
3304  pbconss = SCIPconshdlrGetConss(conshdlr);
3305  npbconss = SCIPconshdlrGetNConss(conshdlr);
3306  assert(pbconss != NULL || npbconss == 0);
3307 
3308  if( npbconss > 0 )
3309  {
3310  SCIP_CONS* lincons;
3311 
3312  /* create the linear constraint of indicator constraints hash map */
3313  SCIP_CALL( SCIPhashmapCreate(&linconssofpbsmap, SCIPblkmem(scip), npbconss) );
3314 
3315  for( c = 0; c < npbconss; ++c )
3316  {
3317  assert(pbconss[c] != NULL); /*lint !e613*/
3318  lincons = SCIPgetLinearConsPseudoboolean(scip, pbconss[c]); /*lint !e613*/
3319  assert(lincons != NULL);
3320 
3321  /* insert constraint into mapping between */
3322  SCIP_CALL( SCIPhashmapInsert(linconssofpbsmap, (void*)lincons, (void*)lincons) );
3323  }
3324  }
3325  }
3326  }
3327  /* in original space we cannot ask the constraint handler for its constraints, therefore we have to loop over all
3328  * original to check for artificial linear once
3329  */
3330  else
3331  {
3332  SCIP_CONS* lincons;
3333  SCIP_Bool pbhashmapcreated = FALSE;
3334  SCIP_Bool indhashmapcreated = FALSE;
3335 
3336  /* loop over all constraint for printing */
3337  for( c = 0; c < nconss; ++c )
3338  {
3339  conshdlr = SCIPconsGetHdlr(conss[c]); /*lint !e613*/
3340  assert(conshdlr != NULL);
3341 
3342  conshdlrname = SCIPconshdlrGetName(conshdlr);
3343 
3344  if( strcmp(conshdlrname, "pseudoboolean") == 0 )
3345  {
3346  if( !pbhashmapcreated )
3347  {
3348  /* create the linear constraint of indicator constraints hash map */
3349  SCIP_CALL( SCIPhashmapCreate(&linconssofpbsmap, SCIPblkmem(scip), nconss) );
3350  pbhashmapcreated = TRUE;
3351  }
3352 
3353  lincons = SCIPgetLinearConsPseudoboolean(scip, conss[c]); /*lint !e613*/
3354  assert(lincons != NULL);
3355 
3356  /* insert constraint into mapping between */
3357  SCIP_CALL( SCIPhashmapInsert(linconssofpbsmap, (void*)lincons, (void*)lincons) );
3358  }
3359  else if( strcmp(conshdlrname, "indicator") == 0 )
3360  {
3361  if( !indhashmapcreated )
3362  {
3363  /* create the linear constraint of indicator constraints hash map */
3364  SCIP_CALL( SCIPhashmapCreate(&linconssofindicatorsmap, SCIPblkmem(scip), nconss) );
3365  indhashmapcreated = TRUE;
3366  }
3367 
3368  lincons = SCIPgetLinearConsIndicator(conss[c]); /*lint !e613*/
3369  assert(lincons != NULL);
3370 
3371  /* insert constraint into mapping between */
3372  SCIP_CALL( SCIPhashmapInsert(linconssofindicatorsmap, (void*)lincons, (void*)lincons) );
3373  }
3374  }
3375  }
3376 
3377  retcode = SCIP_OKAY;
3378  cons = NULL;
3379 
3380  /* loop over all constraint for printing */
3381  for( c = 0; c < nconss && retcode == SCIP_OKAY; ++c )
3382  {
3383  SCIP_CONS* artcons;
3384 
3385  artcons = NULL;
3386 
3387  cons = conss[c]; /*lint !e613 */
3388  assert(cons != NULL);
3389 
3390  conshdlr = SCIPconsGetHdlr(cons);
3391  assert(conshdlr != NULL);
3392 
3393  conshdlrname = SCIPconshdlrGetName(conshdlr);
3394  assert(transformed == SCIPconsIsTransformed(cons));
3395 
3396  /* in case the transformed is written only constraint are posted which are enabled in the current node */
3397  assert(!transformed || SCIPconsIsEnabled(cons));
3398 
3399  if( linconssofpbsmap != NULL )
3400  artcons = (SCIP_CONS*) SCIPhashmapGetImage(linconssofpbsmap, (void*)cons);
3401  if( artcons == NULL && linconssofindicatorsmap != NULL )
3402  artcons = (SCIP_CONS*) SCIPhashmapGetImage(linconssofindicatorsmap, (void*)cons);
3403 
3404  if( artcons == NULL )
3405  {
3406  if( strcmp(conshdlrname, "linear") == 0 )
3407  {
3408  if( SCIPgetNVarsLinear(scip, cons) == 0 )
3409  {
3410  if( SCIPisGT(scip, SCIPgetLhsLinear(scip, cons), SCIPgetRhsLinear(scip, cons)) )
3411  {
3412  SCIPerrorMessage("Cannot print empty violated constraint %s, %g <= %g is not fulfilled\n",
3413  SCIPconsGetName(cons), SCIPgetLhsLinear(scip, cons), SCIPgetRhsLinear(scip, cons));
3414  }
3415  continue;
3416  }
3417 
3418  if( existands )
3419  {
3420  retcode = printNonLinearCons(scip, file,
3421  SCIPgetVarsLinear(scip, cons), SCIPgetValsLinear(scip, cons), SCIPgetNVarsLinear(scip, cons),
3422  SCIPgetLhsLinear(scip, cons), SCIPgetRhsLinear(scip, cons), resvars, nresvars, andvars, nandvars,
3423  0LL, transformed, multisymbol);
3424  }
3425  else
3426  {
3427  retcode = printLinearCons(scip, file,
3428  SCIPgetVarsLinear(scip, cons), SCIPgetValsLinear(scip, cons), SCIPgetNVarsLinear(scip, cons),
3429  SCIPgetLhsLinear(scip, cons), SCIPgetRhsLinear(scip, cons), 0LL, transformed, multisymbol);
3430  }
3431  }
3432  else if( strcmp(conshdlrname, "setppc") == 0 )
3433  {
3434  consvars = SCIPgetVarsSetppc(scip, cons);
3435  nconsvars = SCIPgetNVarsSetppc(scip, cons);
3436 
3437  if( nconsvars == 0 )
3438  continue;
3439 
3440  switch( SCIPgetTypeSetppc(scip, cons) )
3441  {
3443  if( existands )
3444  {
3445  retcode = printNonLinearCons(scip, file, consvars, NULL, nconsvars, 1.0, 1.0, resvars, nresvars,
3446  andvars, nandvars, 0LL, transformed, multisymbol);
3447  }
3448  else
3449  {
3450  retcode = printLinearCons(scip, file,
3451  consvars, NULL, nconsvars, 1.0, 1.0, 0LL, transformed, multisymbol);
3452  }
3453  break;
3455  if( existands )
3456  {
3457  retcode = printNonLinearCons(scip, file,
3458  consvars, NULL, nconsvars, -SCIPinfinity(scip), 1.0, resvars, nresvars, andvars, nandvars,
3459  0LL, transformed, multisymbol);
3460  }
3461  else
3462  {
3463  retcode = printLinearCons(scip, file,
3464  consvars, NULL, nconsvars, -SCIPinfinity(scip), 1.0, 0LL, transformed, multisymbol);
3465  }
3466  break;
3468  if( existands )
3469  {
3470  retcode = printNonLinearCons(scip, file,
3471  consvars, NULL, nconsvars, 1.0, SCIPinfinity(scip), resvars, nresvars, andvars, nandvars,
3472  0LL, transformed, multisymbol);
3473  }
3474  else
3475  {
3476  retcode = printLinearCons(scip, file,
3477  consvars, NULL, nconsvars, 1.0, SCIPinfinity(scip), 0LL, transformed, multisymbol);
3478  }
3479  break;
3480  }
3481  }
3482  else if( strcmp(conshdlrname, "logicor") == 0 )
3483  {
3484  if( SCIPgetNVarsLogicor(scip, cons) == 0 )
3485  continue;
3486 
3487  if( existands )
3488  {
3489  retcode = printNonLinearCons(scip, file,
3490  SCIPgetVarsLogicor(scip, cons), NULL, SCIPgetNVarsLogicor(scip, cons), 1.0, SCIPinfinity(scip),
3491  resvars, nresvars, andvars, nandvars, 0LL, transformed, multisymbol);
3492  }
3493  else
3494  {
3495  retcode = printLinearCons(scip, file,
3496  SCIPgetVarsLogicor(scip, cons), NULL, SCIPgetNVarsLogicor(scip, cons),
3497  1.0, SCIPinfinity(scip), 0LL, transformed, multisymbol);
3498  }
3499  }
3500  else if( strcmp(conshdlrname, "knapsack") == 0 )
3501  {
3502  SCIP_Longint* weights;
3503 
3504  consvars = SCIPgetVarsKnapsack(scip, cons);
3505  nconsvars = SCIPgetNVarsKnapsack(scip, cons);
3506 
3507  if( nconsvars == 0 )
3508  continue;
3509 
3510  /* copy Longint array to SCIP_Real array */
3511  weights = SCIPgetWeightsKnapsack(scip, cons);
3512  SCIP_CALL( SCIPallocBufferArray(scip, &consvals, nconsvars) );
3513  for( v = 0; v < nconsvars; ++v )
3514  consvals[v] = (SCIP_Real)weights[v];
3515 
3516  if( existands )
3517  {
3518  retcode = printNonLinearCons(scip, file, consvars, consvals, nconsvars, -SCIPinfinity(scip),
3519  (SCIP_Real) SCIPgetCapacityKnapsack(scip, cons), resvars, nresvars, andvars, nandvars,
3520  0LL, transformed, multisymbol);
3521  }
3522  else
3523  {
3524  retcode = printLinearCons(scip, file, consvars, consvals, nconsvars, -SCIPinfinity(scip),
3525  (SCIP_Real) SCIPgetCapacityKnapsack(scip, cons), 0LL, transformed, multisymbol);
3526  }
3527 
3528  SCIPfreeBufferArray(scip, &consvals);
3529  }
3530  else if( strcmp(conshdlrname, "varbound") == 0 )
3531  {
3532  SCIP_CALL( SCIPallocBufferArray(scip, &consvars, 2) );
3533  SCIP_CALL( SCIPallocBufferArray(scip, &consvals, 2) );
3534 
3535  consvars[0] = SCIPgetVarVarbound(scip, cons);
3536  consvars[1] = SCIPgetVbdvarVarbound(scip, cons);
3537 
3538  consvals[0] = 1.0;
3539  consvals[1] = SCIPgetVbdcoefVarbound(scip, cons);
3540 
3541  if( existands )
3542  {
3543  retcode = printNonLinearCons(scip, file, consvars, consvals, 2, SCIPgetLhsVarbound(scip, cons),
3544  SCIPgetRhsVarbound(scip, cons), resvars, nresvars, andvars, nandvars, 0LL, transformed, multisymbol);
3545  }
3546  else
3547  {
3548  retcode = printLinearCons(scip, file, consvars, consvals, 2, SCIPgetLhsVarbound(scip, cons),
3549  SCIPgetRhsVarbound(scip, cons), 0LL, transformed, multisymbol);
3550  }
3551 
3552  SCIPfreeBufferArray(scip, &consvars);
3553  SCIPfreeBufferArray(scip, &consvals);
3554  }
3555  else if( strcmp(conshdlrname, "pseudoboolean") == 0 )
3556  {
3557  SCIP_VAR*** termvars;
3558  int* ntermvars;
3559  int termvarssize;
3560  SCIP_CONS** andconss;
3561  SCIP_Real* andcoefs ;
3562  SCIP_VAR** linvars;
3563  SCIP_Real* lincoefs ;
3564  int nlinvars;
3565  int t;
3566 
3567  /* get the required array size for the variables array and for the number of variables in each variable array */
3568  termvarssize = SCIPgetNAndsPseudoboolean(scip, cons);
3569  assert(termvarssize >= 0);
3570 
3571  /* allocate temporary memory */
3572  SCIP_CALL( SCIPallocBufferArray(scip, &andconss, termvarssize) );
3573  SCIP_CALL( SCIPallocBufferArray(scip, &termvars, termvarssize) );
3574  SCIP_CALL( SCIPallocBufferArray(scip, &andcoefs, termvarssize) );
3575  SCIP_CALL( SCIPallocBufferArray(scip, &ntermvars, termvarssize) );
3576 
3577  /* get all corresponding and-constraints and therefor all variables */
3578  SCIP_CALL( SCIPgetAndDatasPseudoboolean(scip, cons, andconss, andcoefs, &termvarssize) );
3579  for( t = termvarssize - 1; t >= 0; --t )
3580  {
3581  termvars[t] = SCIPgetVarsAnd(scip, andconss[t]);
3582  ntermvars[t] = SCIPgetNVarsAnd(scip, andconss[t]);
3583  }
3584 
3585  /* gets number of linear variables without artificial terms variables of pseudoboolean constraint */
3586  nlinvars = SCIPgetNLinVarsWithoutAndPseudoboolean(scip, cons);
3587 
3588  /* allocate temporary memory */
3589  SCIP_CALL( SCIPallocBufferArray(scip, &linvars, nlinvars) );
3590  SCIP_CALL( SCIPallocBufferArray(scip, &lincoefs, nlinvars) );
3591 
3592  /* gets linear constraint of pseudoboolean constraint */
3593  SCIP_CALL( SCIPgetLinDatasWithoutAndPseudoboolean(scip, cons, linvars, lincoefs, &nlinvars) );
3594 
3595  retcode = printPseudobooleanCons(scip, file, linvars, lincoefs, nlinvars,
3596  termvars, ntermvars, andcoefs, termvarssize, SCIPgetIndVarPseudoboolean(scip, cons),
3597  SCIPgetLhsPseudoboolean(scip, cons), SCIPgetRhsPseudoboolean(scip, cons), transformed, multisymbol);
3598 
3599  /* free temporary memory */
3600  SCIPfreeBufferArray(scip, &lincoefs);
3601  SCIPfreeBufferArray(scip, &linvars);
3602  SCIPfreeBufferArray(scip, &ntermvars);
3603  SCIPfreeBufferArray(scip, &andcoefs);
3604  SCIPfreeBufferArray(scip, &termvars);
3605  SCIPfreeBufferArray(scip, &andconss);
3606  }
3607  else if( strcmp(conshdlrname, "indicator") == 0 )
3608  {
3609  SCIP_CONS* lincons;
3610  SCIP_VAR* indvar;
3611  SCIP_VAR* slackvar;
3612  SCIP_Longint weight;
3613 
3614  /* get artificial binary indicator variables */
3615  indvar = SCIPgetBinaryVarIndicator(cons);
3616  assert(indvar != NULL);
3617 
3618  if( SCIPvarGetStatus(indvar) == SCIP_VARSTATUS_NEGATED )
3619  {
3620  indvar = SCIPvarGetNegationVar(indvar);
3621  assert(indvar != NULL);
3623 
3624  /* get the soft cost of this constraint */
3625  weight = (SCIP_Longint) SCIPvarGetObj(indvar);
3626  }
3627  else
3628  {
3630 
3631  /* get the soft cost of this constraint */
3632  weight = -(SCIP_Longint) SCIPvarGetObj(indvar);
3633  }
3634 
3635  /* get artificial slack variable */
3636  slackvar = SCIPgetSlackVarIndicator(cons);
3637  assert(slackvar != NULL);
3638 
3639  /* only need to print indicator constraints with weights on their indicator variable */
3640  if( weight != 0 )
3641  {
3642  SCIP_VAR** scipvarslinear;
3643  SCIP_Real* scipvalslinear;
3644  SCIP_Bool cont;
3645  int nonbinarypos;
3646 
3647  lincons = SCIPgetLinearConsIndicator(cons);
3648  assert(lincons != NULL);
3649 
3650  nconsvars = SCIPgetNVarsLinear(scip, lincons);
3651  scipvarslinear = SCIPgetVarsLinear(scip, lincons);
3652  scipvalslinear = SCIPgetValsLinear(scip, lincons);
3653 
3654  /* allocate temporary memory */
3655  SCIP_CALL( SCIPduplicateBufferArray(scip, &consvars, scipvarslinear, nconsvars) );
3656  SCIP_CALL( SCIPduplicateBufferArray(scip, &consvals, scipvalslinear, nconsvars) );
3657 
3658  nonbinarypos = -1;
3659  cont = FALSE;
3660 
3661  /* find non-binary variable */
3662  for( v = 0; v < nconsvars; ++v )
3663  {
3664  if( SCIPvarGetType(consvars[v]) != SCIP_VARTYPE_BINARY )
3665  {
3666  if( consvars[v] == slackvar )
3667  {
3668  assert(nonbinarypos == -1);
3669  nonbinarypos = v;
3670  }
3671  else
3672  {
3673  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) );
3674  SCIPinfoMessage(scip, file, "* ");
3675  SCIP_CALL( SCIPprintCons(scip, cons, file) );
3676  SCIPinfoMessage(scip, file, ";\n");
3677  cont = TRUE;
3678  break;
3679  }
3680  }
3681  }
3682 
3683  /* if we have not found any non-binary variable we do not print the constraint, maybe we should ??? */
3684  if( nonbinarypos == -1 )
3685  {
3686  SCIPwarningMessage(scip, "cannot print linear constraint <%s> of indicator constraint <%s> because it has no slack variable\n", SCIPconsGetName(lincons), SCIPconsGetName(cons) );
3687  SCIPinfoMessage(scip, file, "* ");
3688  SCIP_CALL( SCIPprintCons(scip, cons, file) );
3689  SCIPinfoMessage(scip, file, ";\n");
3690 
3691  /* free temporary memory */
3692  SCIPfreeBufferArray(scip, &consvals);
3693  SCIPfreeBufferArray(scip, &consvars);
3694  continue;
3695  }
3696 
3697  /* if the constraint has more than two non-binary variables is not printable and we go to the next */
3698  if( cont )
3699  {
3700  /* free temporary memory */
3701  SCIPfreeBufferArray(scip, &consvals);
3702  SCIPfreeBufferArray(scip, &consvars);
3703  continue;
3704  }
3705 
3706  assert(0 <= nonbinarypos && nonbinarypos < nconsvars);
3707 
3708  /* remove slackvariable in linear constraint for printing */
3709  --nconsvars;
3710  consvars[nonbinarypos] = consvars[nconsvars];
3711  consvals[nonbinarypos] = consvals[nconsvars];
3712 
3713  if( existands )
3714  {
3715  retcode = printNonLinearCons(scip, file,
3716  consvars, consvals, nconsvars, SCIPgetLhsLinear(scip, lincons), SCIPgetRhsLinear(scip, lincons),
3717  resvars, nresvars, andvars, nandvars,
3718  weight, transformed, multisymbol);
3719  }
3720  else
3721  {
3722  retcode = printLinearCons(scip, file,
3723  consvars, consvals, nconsvars, SCIPgetLhsLinear(scip, lincons), SCIPgetRhsLinear(scip, lincons),
3724  weight, transformed, multisymbol);
3725  }
3726 
3727  /* free temporary memory */
3728  SCIPfreeBufferArray(scip, &consvals);
3729  SCIPfreeBufferArray(scip, &consvars);
3730  }
3731  else
3732  {
3733  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) );
3734  SCIPinfoMessage(scip, file, "* ");
3735  SCIP_CALL( SCIPprintCons(scip, cons, file) );
3736  SCIPinfoMessage(scip, file, ";\n");
3737  }
3738  }
3739  else if( strcmp(conshdlrname, "and") == 0 )
3740  {
3741  /* all resultants of the and constraint will be replaced by all corresponding variables of this constraint,
3742  * so no and-constraint will be printed directly */
3743  assert(existandconshdlr);
3744  }
3745  else
3746  {
3747  SCIPwarningMessage(scip, "constraint handler <%s> cannot print requested format\n", conshdlrname );
3748  SCIPinfoMessage(scip, file, "* ");
3749  SCIP_CALL( SCIPprintCons(scip, cons, file) );
3750  SCIPinfoMessage(scip, file, ";\n");
3751  }
3752  }
3753  }
3754 
3755  if( retcode == SCIP_INVALIDDATA )
3756  {
3757  assert(cons != NULL);
3758 
3759  SCIPerrorMessage("Cannot print constraint %s with non-integral coefficient or sides in opb-format\n",
3760  SCIPconsGetName(cons));
3761  SCIP_CALL( SCIPprintCons(scip, cons, stderr) );
3762  SCIPinfoMessage(scip, file, ";\n");
3763  }
3764 
3765  if( linconssofpbsmap != NULL )
3766  {
3767  /* free hash map */
3768  SCIPhashmapFree(&linconssofpbsmap);
3769  }
3770  if( linconssofindicatorsmap != NULL )
3771  {
3772  /* free hash map */
3773  SCIPhashmapFree(&linconssofindicatorsmap);
3774  }
3775 
3776  return retcode;
3777 }
3778 
3779 /* write fixed variables (unless already done because they are an and resultant or and variable) */
3780 static
3782  SCIP*const scip, /**< SCIP data structure */
3783  FILE*const file, /**< output file, or NULL if standard output should be used */
3784  SCIP_VAR** vars, /**< array with active (binary) variables */
3785  int nvars, /**< number of active variables in the problem */
3786  SCIP_HASHTABLE*const printedfixing, /**< hashmap to store if a fixed variable was already printed */
3787  char const*const multisymbol, /**< the multiplication symbol to use between coefficient and variable */
3788  SCIP_Bool const transformed /**< TRUE iff problem is the transformed problem */
3789  )
3790 {
3791  char linebuffer[OPB_MAX_LINELEN+1];
3792  char buffer[OPB_MAX_LINELEN];
3793  int linecnt;
3794  int v;
3795 
3796  assert(scip != NULL);
3797  assert(file != NULL);
3798  assert(vars != NULL || nvars == 0);
3799  assert(printedfixing != NULL);
3800  assert(multisymbol != NULL);
3801 
3802  clearBuffer(linebuffer, &linecnt);
3803 
3804  /* print variables which are fixed */
3805  for( v = 0; v < nvars; ++v )
3806  {
3807  SCIP_VAR* var;
3808  SCIP_Real lb;
3809  SCIP_Real ub;
3810  SCIP_Bool neg = FALSE;
3811 
3812  assert( vars != NULL );
3813  var = vars[v];
3814 
3815  if( transformed )
3816  {
3817  /* in case the transformed is written only local bounds are posted which are valid in the current node */
3818  lb = SCIPvarGetLbLocal(var);
3819  ub = SCIPvarGetUbLocal(var);
3820  }
3821  else
3822  {
3823  lb = SCIPvarGetLbOriginal(var);
3824  ub = SCIPvarGetUbOriginal(var);
3825  }
3826  assert(lb > -0.5 && ub < 1.5);
3827  assert(SCIPisFeasIntegral(scip, lb));
3828  assert(SCIPisFeasIntegral(scip, ub));
3829 
3830  /* print fixed and-resultants */
3831  if( lb > 0.5 || ub < 0.5 )
3832  {
3833  if( transformed ) {
3834  SCIP_CALL( SCIPgetBinvarRepresentative(scip, var, &var, &neg) );
3835  }
3836 
3837  if( SCIPhashtableExists(printedfixing, (void*)var) )
3838  continue;
3839 
3840  (void) SCIPsnprintf(buffer, OPB_MAX_LINELEN, "+1%s%s%s = %g ;\n", multisymbol, neg ? "~" : "", strstr(SCIPvarGetName(neg ? SCIPvarGetNegationVar(var) : var), "x"), lb);
3841  appendBuffer(scip, file, linebuffer, &linecnt, buffer);
3842 
3843  /* add variable to the hashmap */
3844  SCIP_CALL( SCIPhashtableInsert(printedfixing, (void*)var) );
3845  }
3846  }
3847 
3848  writeBuffer(scip, file, linebuffer, &linecnt);
3849 
3850  return SCIP_OKAY;
3851 }
3852 
3853 /* write and constraints of inactive but relevant and-resultants and and variables which are fixed to one */
3854 static
3856  SCIP*const scip, /**< SCIP data structure */
3857  FILE*const file, /**< output file, or NULL if standard output should be used */
3858  SCIP_VAR**const resvars, /**< array of resultant variables */
3859  int const nresvars, /**< number of resultant variables */
3860  SCIP_VAR**const*const andvars, /**< corresponding array of and-variables */
3861  int const*const nandvars, /**< array of numbers of corresponding and-variables */
3862  SCIP_HASHTABLE*const printedfixing, /**< hashmap to store if a fixed variable was already printed */
3863  char const*const multisymbol, /**< the multiplication symbol to use between coefficient and variable */
3864  SCIP_Bool const transformed /**< TRUE iff problem is the transformed problem */
3865  )
3866 {
3867  SCIP_VAR* resvar;
3868  SCIP_Longint rhslhs;
3869  char linebuffer[OPB_MAX_LINELEN+1];
3870  char buffer[OPB_MAX_LINELEN];
3871  int linecnt;
3872  int r, v;
3873 
3874  assert(scip != NULL);
3875  assert(file != NULL);
3876  assert(resvars != NULL || nresvars == 0);
3877  assert(nandvars != NULL || nresvars == 0);
3878  assert(andvars != NULL || nandvars == NULL);
3879  assert(multisymbol != NULL);
3880 
3881  clearBuffer(linebuffer, &linecnt);
3882 
3883  /* print and-variables which are fixed */
3884  /* @todo remove this block here and the hashtable and let writeOpbFixedVars() do the job? */
3885  for( r = nresvars - 1; r >= 0; --r )
3886  {
3887  SCIP_VAR* var;
3888  SCIP_Bool neg;
3889  SCIP_Real lb;
3890  SCIP_Real ub;
3891 
3892  assert( resvars != NULL );
3893  resvar = resvars[r];
3894 
3895  if( transformed )
3896  {
3897  /* in case the transformed is written only local bounds are posted which are valid in the current node */
3898  lb = SCIPvarGetLbLocal(resvar);
3899  ub = SCIPvarGetUbLocal(resvar);
3900  }
3901  else
3902  {
3903  lb = SCIPvarGetLbOriginal(resvar);
3904  ub = SCIPvarGetUbOriginal(resvar);
3905  }
3906 
3907  /* print fixed and-resultants */
3908  if( lb > 0.5 || ub < 0.5 )
3909  {
3910  /* coverity[copy_paste_error] */
3911  SCIP_CALL( SCIPgetBinvarRepresentative(scip, resvar, &var, &neg) );
3912 
3913  assert(SCIPisFeasIntegral(scip, lb));
3914  (void) SCIPsnprintf(buffer, OPB_MAX_LINELEN, "+1%s%s%s = %g ;\n", multisymbol, neg ? "~" : "", strstr(SCIPvarGetName(neg ? SCIPvarGetNegationVar(var) : var), "x"), lb);
3915  appendBuffer(scip, file, linebuffer, &linecnt, buffer);
3916 
3917  /* add variable to the hashmap */
3918  SCIP_CALL( SCIPhashtableInsert(printedfixing, (void*)var) );
3919  }
3920 
3921  assert( andvars != NULL && nandvars != NULL );
3922  assert( andvars[r] != NULL || nandvars[r] == 0 );
3923 
3924  /* print fixed and-variables */
3925  for( v = nandvars[r] - 1; v >= 0; --v ) /*lint !e613 */
3926  {
3927  assert( andvars[r] != NULL );
3928  assert( andvars[r][v] != NULL );
3929 
3930  if( transformed )
3931  {
3932  /* in case the transformed is written only local bounds are posted which are valid in the current node */
3933  lb = SCIPvarGetLbLocal(andvars[r][v]);
3934  ub = SCIPvarGetUbLocal(andvars[r][v]);
3935  }
3936  else
3937  {
3938  lb = SCIPvarGetLbOriginal(andvars[r][v]);
3939  ub = SCIPvarGetUbOriginal(andvars[r][v]);
3940  }
3941 
3942  if( lb > 0.5 || ub < 0.5 )
3943  {
3944  SCIP_CALL( SCIPgetBinvarRepresentative(scip, andvars[r][v], &var, &neg) ); /*lint !e613 */
3945 
3946  assert(SCIPisFeasIntegral(scip, lb));
3947  (void) SCIPsnprintf(buffer, OPB_MAX_LINELEN, "+1%s%s%s = %g ;\n", multisymbol, neg ? "~" : "", strstr(SCIPvarGetName(neg ? SCIPvarGetNegationVar(var) : var), "x"), lb);
3948  appendBuffer(scip, file, linebuffer, &linecnt, buffer);
3949 
3950  /* add variable to the hashmap */
3951  SCIP_CALL( SCIPhashtableInsert(printedfixing, (void*)var) );
3952  }
3953  }
3954  }
3955 
3956  /* print and-constraints with fixed and-resultant to zero and all and-constraints with
3957  * aggregated resultant, otherwise we would loose this information
3958  */
3959  for( r = nresvars - 1; r >= 0; --r )
3960  {
3961  assert( resvars != NULL );
3962  resvar = resvars[r];
3963  rhslhs = (SCIPvarGetUbLocal(resvar) < 0.5) ? 0 : ((SCIPvarGetLbLocal(resvar) > 0.5) ? 1 : -1);
3964 
3965  /* if and resultant is fixed to 0 and at least one and-variable is fixed to zero, we don't print this redundant constraint */
3966  if( rhslhs == 0 )
3967  {
3968  SCIP_Bool cont;
3969 
3970  cont = FALSE;
3971 
3972  assert( andvars != NULL && nandvars != NULL );
3973  assert( andvars[r] != NULL || nandvars[r] == 0 );
3974 
3975  /* if resultant variable and one other and variable is already zero, so we did not need to print this and
3976  * constraint because all other variables are free
3977  */
3978  for( v = nandvars[r] - 1; v >= 0; --v ) /*lint !e613 */
3979  {
3980  assert( andvars[r] != NULL );
3981  assert( andvars[r][v] != NULL );
3982 
3983  if( SCIPvarGetUbLocal(andvars[r][v]) < 0.5 ) /*lint !e613 */
3984  {
3985  cont = TRUE;
3986  break;
3987  }
3988  }
3989 
3990  if( cont )
3991  continue;
3992  }
3993  /* if and resultant is fixed to 1 and all and-variable are fixed to 1 too, we don't print this redundant constraint */
3994  else if( rhslhs == 1 )
3995  {
3996  SCIP_Bool cont;
3997 
3998  cont = TRUE;
3999 
4000  assert( andvars != NULL && nandvars != NULL );
4001  assert( andvars[r] != NULL || nandvars[r] == 0 );
4002 
4003  /* if all variables are already fixed to one, we do not need to print this and constraint */
4004  for( v = nandvars[r] - 1; v >= 0; --v )
4005  {
4006  assert( andvars[r] != NULL );
4007  assert( andvars[r][v] != NULL );
4008 
4009  if( SCIPvarGetLbLocal(andvars[r][v]) < 0.5 ) /*lint !e613 */
4010  {
4011  cont = FALSE;
4012  break;
4013  }
4014  }
4015 
4016  if( cont )
4017  continue;
4018  }
4019 
4020  /* print and with fixed or aggregated and-resultant */
4021  /* rhslhs equals to 0 means the and constraint is relevant due to it's not clear on which values the and variables are
4022  * rhslhs equals to 1 means the and constraint is irrelevant cause all and variables have to be 1 too
4023  * rhslhs equals to -1 means the and constraint is relevant cause the variable is only aggregated */
4024  if( !SCIPvarIsActive(resvar) )
4025  {
4026  SCIP_VAR* var;
4027  SCIP_Bool neg;
4028  SCIP_Bool firstprinted;
4029 
4030  firstprinted = FALSE;
4031 
4032  assert( andvars != NULL && nandvars != NULL );
4033  assert( andvars[r] != NULL || nandvars[r] == 0 );
4034 
4035  for( v = nandvars[r] - 1; v >= 0; --v )
4036  {
4037  assert( andvars[r] != NULL );
4038  assert( andvars[r][v] != NULL );
4039 
4040  SCIP_CALL( SCIPgetBinvarRepresentative(scip, andvars[r][v], &var, &neg) ); /*lint !e613 */
4041 
4042  (void) SCIPsnprintf(buffer, OPB_MAX_LINELEN, "%s%s%s", (firstprinted) ? multisymbol : "", neg ? "~" : "", strstr(SCIPvarGetName(neg ? SCIPvarGetNegationVar(var) : var), "x"));
4043  appendBuffer(scip, file, linebuffer, &linecnt, buffer);
4044 
4045  firstprinted = TRUE;
4046  }
4047 
4048  /* if the resultant is aggregated we need to print his binary representation */
4049  if( rhslhs == -1 )
4050  {
4051  int pos;
4052 
4053  assert(transformed);
4054 
4055  SCIP_CALL( SCIPgetBinvarRepresentative(scip, resvar, &resvar, &neg) );
4056 
4057 #ifndef NDEBUG
4058  if( neg )
4059  assert(SCIPvarIsActive(SCIPvarGetNegationVar(resvar)));
4060  else
4061  assert(SCIPvarIsActive(resvar));
4062 #endif
4063 
4064  /* replace and-resultant with corresponding variables */
4065  if( SCIPsortedvecFindPtr((void**)resvars, SCIPvarComp, neg ? SCIPvarGetNegationVar(resvar) : resvar, nresvars, &pos) )
4066  {
4067  SCIP_Bool negated;
4068  int a;
4069 
4070  assert(andvars != NULL);
4071  assert(nandvars != NULL);
4072  assert(pos >= 0 && nandvars[pos] > 0 && andvars[pos] != NULL);
4073  assert(andvars[pos][nandvars[pos] - 1] != NULL);
4074 
4075  negated = SCIPvarIsNegated(andvars[pos][nandvars[pos] - 1]);
4076 
4077  /* print and-vars */
4078  (void) SCIPsnprintf(buffer, OPB_MAX_LINELEN, neg ? " +1%s%s%s" : " -1%s%s%s", multisymbol, negated ? "~" : "",
4079  strstr(SCIPvarGetName(negated ? SCIPvarGetNegationVar(andvars[pos][nandvars[pos] - 1]) : andvars[pos][nandvars[pos] - 1]), "x"));
4080  appendBuffer(scip, file, linebuffer, &linecnt, buffer);
4081 
4082  for(a = nandvars[pos] - 2; a >= 0; --a )
4083  {
4084  negated = SCIPvarIsNegated(andvars[pos][a]);
4085 
4086  (void) SCIPsnprintf(buffer, OPB_MAX_LINELEN, "%s%s%s", multisymbol, negated ? "~" : "", strstr(SCIPvarGetName(negated ? SCIPvarGetNegationVar(andvars[pos][a]) : andvars[pos][a]), "x"));
4087  appendBuffer(scip, file, linebuffer, &linecnt, buffer);
4088  }
4089 
4090  appendBuffer(scip, file, linebuffer, &linecnt, " ");
4091 
4092  if( neg )
4093  rhslhs = 1;
4094  else
4095  rhslhs = 0;
4096  }
4097  else
4098  {
4099  (void) SCIPsnprintf(buffer, OPB_MAX_LINELEN, " -1%s%s%s", multisymbol, neg ? "~" : "",
4100  strstr(SCIPvarGetName(neg ? SCIPvarGetNegationVar(resvar) : resvar), "x"));
4101  appendBuffer(scip, file, linebuffer, &linecnt, buffer);
4102 
4103  rhslhs = 0;
4104  }
4105  }
4106 
4107  /* print rhslhs */
4108  (void) SCIPsnprintf(buffer, OPB_MAX_LINELEN, " = %" SCIP_LONGINT_FORMAT " ;\n", rhslhs);
4109  appendBuffer(scip, file, linebuffer, &linecnt, buffer);
4110 
4111  writeBuffer(scip, file, linebuffer, &linecnt);
4112  }
4113  }
4114 
4115  return SCIP_OKAY;
4116 }
4117 
4118 /* writes problem to file */
4119 static
4121  SCIP* scip, /**< SCIP data structure */
4122  FILE* file, /**< output file, or NULL if standard output should be used */
4123  const char* name, /**< problem name */
4124  SCIP_Bool transformed, /**< TRUE iff problem is the transformed problem */
4125  SCIP_OBJSENSE objsense, /**< objective sense */
4126  SCIP_Real objscale, /**< scalar applied to objective function; external objective value is
4127  * extobj = objsense * objscale * (intobj + objoffset) */
4128  SCIP_Real objoffset, /**< objective offset from bound shifting and fixing */
4129  SCIP_VAR** vars, /**< array with active (binary) variables */
4130  int nvars, /**< number of active variables in the problem */
4131  SCIP_CONS** conss, /**< array with constraints of the problem */
4132  int nconss, /**< number of constraints in the problem */
4133  SCIP_VAR** const resvars, /**< array of resultant variables */
4134  int const nresvars, /**< number of resultant variables */
4135  SCIP_VAR**const*const andvars, /**< corresponding array of and-variables */
4136  int const*const nandvars, /**< array of numbers of corresponding and-variables */
4137  SCIP_Bool const existandconshdlr, /**< does and-constrainthandler exist? */
4138  SCIP_Bool const existands, /**< does some and-constraints exist? */
4139  SCIP_RESULT* result /**< pointer to store the result of the file writing call */
4140  )
4141 {
4142  char multisymbol[OPB_MAX_LINELEN];
4143  SCIP_HASHTABLE* printedfixing;
4144  SCIP_Bool usesymbol;
4145  SCIP_RETCODE retcode;
4146 
4147  assert( scip != NULL );
4148  assert( vars != NULL || nvars == 0 );
4149  assert( conss != NULL || nconss == 0 );
4150  assert( result != NULL );
4151 
4152  /* check if should use a multipliers symbol star '*' between coefficients and variables */
4153  SCIP_CALL( SCIPgetBoolParam(scip, "reading/" READER_NAME "/multisymbol", &usesymbol) );
4154  (void) SCIPsnprintf(multisymbol, OPB_MAX_LINELEN, "%s", usesymbol ? " * " : " ");
4155 
4156  /* print statistics as comment to file */
4157  SCIPinfoMessage(scip, file, "* SCIP STATISTICS\n");
4158  SCIPinfoMessage(scip, file, "* Problem name : %s\n", name);
4159  SCIPinfoMessage(scip, file, "* Variables : %d (all binary)\n", nvars);
4160  SCIPinfoMessage(scip, file, "* Constraints : %d\n", nconss);
4161 
4162  /* create a hash table */
4163  SCIP_CALL( SCIPhashtableCreate(&printedfixing, SCIPblkmem(scip), nvars,
4164  SCIPvarGetHashkey, SCIPvarIsHashkeyEq, SCIPvarGetHashkeyVal, NULL) );
4165 
4166  /* write objective function */
4167  SCIP_CALL( writeOpbObjective(scip, file, vars, nvars, resvars, nresvars, andvars, nandvars,
4168  objsense, objscale, objoffset, multisymbol, existands, transformed) );
4169 
4170  /* write constraints */
4171  retcode = writeOpbConstraints(scip, file, conss, nconss, vars, nvars, resvars, nresvars, andvars, nandvars,
4172  multisymbol, existandconshdlr, existands, transformed);
4173 
4174  if( existands && (retcode == SCIP_OKAY) )
4175  {
4176  /* write and constraints of inactive but relevant and-resultants and and-variables which are fixed to one
4177  with no fixed and resultant */
4178  SCIP_CALL( writeOpbRelevantAnds(scip, file, resvars, nresvars, andvars, nandvars, printedfixing, multisymbol, transformed) );
4179  }
4180 
4181  /* write fixed variables */
4182  SCIP_CALL( writeOpbFixedVars(scip, file, vars, nvars, printedfixing, multisymbol, transformed) );
4183 
4184  SCIPhashtableFree(&printedfixing);
4185 
4186  *result = SCIP_SUCCESS;
4187 
4188  return retcode;
4189 }
4190 
4191 
4192 /*
4193  * extern methods
4194  */
4195 
4196 /** reads problem from file */
4198  SCIP* scip, /**< SCIP data structure */
4199  SCIP_READER* reader, /**< the file reader itself */
4200  const char* filename, /**< full path and name of file to read, or NULL if stdin should be used */
4201  SCIP_RESULT* result /**< pointer to store the result of the file reading call */
4202  )
4203 { /*lint --e{715}*/
4204  OPBINPUT opbinput;
4205  SCIP_RETCODE retcode;
4206  int i;
4207 
4208  assert(scip != NULL); /* for lint */
4209  assert(reader != NULL);
4210 
4211  /* initialize OPB input data */
4212  opbinput.file = NULL;
4213  opbinput.linebuf[0] = '\0';
4214  SCIP_CALL( SCIPallocBufferArray(scip, &opbinput.token, OPB_MAX_LINELEN) );
4215  opbinput.token[0] = '\0';
4216  SCIP_CALL( SCIPallocBufferArray(scip, &opbinput.tokenbuf, OPB_MAX_LINELEN) );
4217  opbinput.tokenbuf[0] = '\0';
4218  for( i = 0; i < OPB_MAX_PUSHEDTOKENS; ++i )
4219  {
4220  SCIP_CALL( SCIPallocBufferArray(scip, &(opbinput.pushedtokens[i]), OPB_MAX_LINELEN) ); /*lint !e866 */
4221  }
4222 
4223  opbinput.npushedtokens = 0;
4224  opbinput.linenumber = 1;
4225  opbinput.bufpos = 0;
4226  opbinput.linepos = 0;
4227  opbinput.objsense = SCIP_OBJSENSE_MINIMIZE;
4228  opbinput.comment = FALSE;
4229  opbinput.endline = FALSE;
4230  opbinput.eof = FALSE;
4231  opbinput.haserror = FALSE;
4232  opbinput.nproblemcoeffs = 0;
4233  opbinput.wbo = FALSE;
4234  opbinput.topcost = -SCIPinfinity(scip);
4235  opbinput.nindvars = 0;
4236 #if GENCONSNAMES == TRUE
4237  opbinput.consnumber = 0;
4238 #endif
4239 
4240  /* read the file */
4241  retcode = readOPBFile(scip, &opbinput, filename);
4242 
4243  /* free dynamically allocated memory */
4244  for( i = OPB_MAX_PUSHEDTOKENS - 1; i >= 0; --i )
4245  {
4246  SCIPfreeBufferArrayNull(scip, &(opbinput.pushedtokens[i]));
4247  }
4248  SCIPfreeBufferArrayNull(scip, &opbinput.tokenbuf);
4249  SCIPfreeBufferArrayNull(scip, &opbinput.token);
4250 
4251  if( retcode == SCIP_PLUGINNOTFOUND )
4252  retcode = SCIP_READERROR;
4253 
4254  SCIP_CALL( retcode );
4255 
4256  if( opbinput.nproblemcoeffs > 0 )
4257  {
4258  SCIPwarningMessage(scip, "there might be <%d> coefficients or weight out of range!\n", opbinput.nproblemcoeffs);
4259  }
4260 
4261  /* evaluate the result */
4262  if( opbinput.haserror )
4263  return SCIP_READERROR;
4264  else
4265  {
4266  /* set objective sense */
4267  SCIP_CALL( SCIPsetObjsense(scip, opbinput.objsense) );
4268  *result = SCIP_SUCCESS;
4269  }
4270 
4271  return SCIP_OKAY;
4272 }
4273 
4274 /** writes problem to file */
4276  SCIP* scip, /**< SCIP data structure */
4277  FILE* file, /**< output file, or NULL if standard output should be used */
4278  const char* name, /**< problem name */
4279  SCIP_Bool transformed, /**< TRUE iff problem is the transformed problem */
4280  SCIP_OBJSENSE objsense, /**< objective sense */
4281  SCIP_Real objscale, /**< scalar applied to objective function; external objective value is
4282  * extobj = objsense * objscale * (intobj + objoffset) */
4283  SCIP_Real objoffset, /**< objective offset from bound shifting and fixing */
4284  SCIP_VAR** vars, /**< array with active variables ordered binary, integer, implicit, continuous */
4285  int nvars, /**< number of active variables in the problem */
4286  int nbinvars, /**< number of binary variables */
4287  int nintvars, /**< number of general integer variables */
4288  int nimplvars, /**< number of implicit integer variables */
4289  int ncontvars, /**< number of continuous variables */
4290  SCIP_VAR** fixedvars, /**< array with fixed variables */
4291  int nfixedvars, /**< number of fixed and aggregated variables in the problem */
4292  SCIP_CONS** conss, /**< array with constraints of the problem */
4293  int nconss, /**< number of constraints in the problem */
4294  SCIP_Bool genericnames, /**< should generic variable and constraint names be used */
4295  SCIP_RESULT* result /**< pointer to store the result of the file writing call */
4296  )
4297 { /*lint --e{715}*/
4298  SCIP_RETCODE retcode = SCIP_OKAY;
4299 
4300  if( nvars != nbinvars && (nintvars > 0 || SCIPfindConshdlr(scip, "indicator") != NULL
4301  || ncontvars + nimplvars != SCIPconshdlrGetNConss(SCIPfindConshdlr(scip, "indicator"))) )
4302  {
4303  SCIPwarningMessage(scip, "only binary problems can be written in OPB format.\n");
4304  *result = SCIP_DIDNOTRUN;
4305  }
4306  else
4307  {
4308  SCIP_VAR*** andvars;
4309  SCIP_VAR** resvars;
4310  int* nandvars;
4311  SCIP_Bool existands;
4312  SCIP_Bool existandconshdlr;
4313  int nresvars;
4314  int v;
4315 
4316  /* computes all and-resultants and their corresponding constraint variables */
4317  /* coverity[leaked_storage] */
4318  SCIP_CALL( computeAndConstraintInfos(scip, transformed, &resvars, &nresvars, &andvars, &nandvars, &existandconshdlr, &existands) );
4319 
4320  if( genericnames )
4321  {
4322 #ifndef NDEBUG
4323  /* check for correct names for opb-format */
4324  int idx;
4325  int pos;
4326 
4327  for( v = nvars - 1; v >= 0; --v )
4328  {
4329  if( existands )
4330  {
4331  /* and variables are artificial */
4332  if( SCIPsortedvecFindPtr((void**)resvars, SCIPvarComp, vars[v], nresvars, &pos) )
4333  continue;
4334  }
4335 
4336  assert(sscanf(SCIPvarGetName(vars[v]), "x%d", &idx) == 1);
4337  }
4338 #endif
4339  retcode = writeOpb(scip, file, name, transformed, objsense, objscale, objoffset, vars,
4340  nvars, conss, nconss, resvars, nresvars, andvars, nandvars, existandconshdlr, existands, result);
4341  }
4342  else
4343  {
4344  SCIP_Bool printed;
4345  int idx;
4346  int pos;
4347 
4348  printed = FALSE;
4349 
4350  /* check if there are already generic names for all (not fixed variables)*/
4351  for( v = nvars - 1; v >= 0; --v )
4352  if( !existands || !SCIPsortedvecFindPtr((void**)resvars, SCIPvarComp, vars[v], nresvars, &pos) )
4353  {
4354  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 )
4355  {
4356  SCIPwarningMessage(scip, "At least following variable name isn't allowed in opb format.\n");
4357  SCIP_CALL( SCIPprintVar(scip, vars[v], NULL) );
4358  SCIPwarningMessage(scip, "OPB format needs generic variable names!\n");
4359 
4360  if( transformed )
4361  {
4362  SCIPwarningMessage(scip, "write transformed problem with generic variable names.\n");
4363  SCIP_CALL( SCIPprintTransProblem(scip, file, "opb", TRUE) );
4364  }
4365  else
4366  {
4367  SCIPwarningMessage(scip, "write original problem with generic variable names.\n");
4368  SCIP_CALL( SCIPprintOrigProblem(scip, file, "opb", TRUE) );
4369  }
4370  printed = TRUE;
4371  break;
4372  }
4373  }
4374 
4375  if( !printed )
4376  {
4377  /* check if there are already generic names for all (fixed variables)*/
4378  for( v = nfixedvars - 1; v >= 0; --v )
4379  if( !existands || !SCIPsortedvecFindPtr((void**)resvars, SCIPvarComp, vars[v], nresvars, &pos) )
4380  {
4381  /* coverity[secure_coding] */
4382  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 )
4383  {
4384  SCIPwarningMessage(scip, "At least following variable name isn't allowed in opb format.\n");
4385  SCIP_CALL( SCIPprintVar(scip, fixedvars[v], NULL) );
4386  SCIPwarningMessage(scip, "OPB format needs generic variable names!\n");
4387 
4388  if( transformed )
4389  {
4390  SCIPwarningMessage(scip, "write transformed problem with generic variable names.\n");
4391  SCIP_CALL( SCIPprintTransProblem(scip, file, "opb", TRUE) );
4392  }
4393  else
4394  {
4395  SCIPwarningMessage(scip, "write original problem with generic variable names.\n");
4396  SCIP_CALL( SCIPprintOrigProblem(scip, file, "opb", TRUE) );
4397  }
4398  printed = TRUE;
4399  break;
4400  }
4401  }
4402  }
4403 
4404  if( !printed )
4405  {
4406 #ifndef NDEBUG
4407  for( v = nvars - 1; v >= 0; --v )
4408  {
4409  if( existands )
4410  {
4411  if( SCIPsortedvecFindPtr((void**)resvars, SCIPvarComp, vars[v], nresvars, &pos) )
4412  continue;
4413  }
4414 
4415  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 );
4416  }
4417 #endif
4418  retcode = writeOpb(scip, file, name, transformed, objsense, objscale, objoffset, vars,
4419  nvars, conss, nconss, resvars, nresvars, andvars, nandvars, existandconshdlr, existands, result);
4420  }
4421  }
4422 
4423  if( existands )
4424  {
4425  /* free temporary buffers */
4426  assert(resvars != NULL);
4427  assert(andvars != NULL);
4428  assert(nandvars != NULL);
4429 
4430  for( v = nresvars - 1; v >= 0; --v )
4431  {
4432  assert(andvars[v] != NULL);
4433  SCIPfreeMemoryArray(scip, &andvars[v]);
4434  }
4435  SCIPfreeMemoryArray(scip, &nandvars);
4436  SCIPfreeMemoryArray(scip, &andvars);
4437  SCIPfreeMemoryArray(scip, &resvars);
4438  }
4439 
4440  *result = SCIP_SUCCESS;
4441  }
4442 
4443  if( retcode == SCIP_INVALIDDATA )
4444  return SCIP_WRITEERROR;
4445 
4446  return retcode;
4447 }
4448 
4449 /*
4450  * Callback methods of reader
4451  */
4452 
4453 /** copy method for reader plugins (called when SCIP copies plugins) */
4454 static
4455 SCIP_DECL_READERCOPY(readerCopyOpb)
4456 { /*lint --e{715}*/
4457  assert(scip != NULL);
4458  assert(reader != NULL);
4459  assert(strcmp(SCIPreaderGetName(reader), READER_NAME) == 0);
4460 
4461  /* call inclusion method of reader */
4463 
4464  return SCIP_OKAY;
4465 }
4466 
4467 
4468 /** problem reading method of reader */
4469 static
4470 SCIP_DECL_READERREAD(readerReadOpb)
4471 { /*lint --e{715}*/
4472 
4473  SCIP_CALL( SCIPreadOpb(scip, reader, filename, result) );
4474 
4475  return SCIP_OKAY;
4476 }
4477 
4478 
4479 /** problem writing method of reader */
4480 static
4481 SCIP_DECL_READERWRITE(readerWriteOpb)
4482 { /*lint --e{715}*/
4483 
4484  SCIP_CALL( SCIPwriteOpb(scip, file, name, transformed, objsense, objscale, objoffset, vars,
4485  nvars, nbinvars, nintvars, nimplvars, ncontvars, fixedvars, nfixedvars, conss, nconss, genericnames, result) );
4486 
4487  return SCIP_OKAY;
4488 }
4489 
4490 /*
4491  * reader specific interface methods
4492  */
4493 
4494 /** includes the opb file reader in SCIP */
4496  SCIP* scip /**< SCIP data structure */
4497  )
4498 {
4499  SCIP_READER* reader;
4500 
4501  /* include reader */
4503 
4504  /* set non fundamental callbacks via setter functions */
4505  SCIP_CALL( SCIPsetReaderCopy(scip, reader, readerCopyOpb) );
4506  SCIP_CALL( SCIPsetReaderRead(scip, reader, readerReadOpb) );
4507  SCIP_CALL( SCIPsetReaderWrite(scip, reader, readerWriteOpb) );
4508 
4509  /* add opb reader parameters */
4511  "reading/" READER_NAME "/dynamicconss", "should model constraints be subject to aging?",
4512  NULL, FALSE, FALSE/*TRUE*/, NULL, NULL) ); /* have to be FALSE, otherwise an error might inccur in restart during branch and bound */
4514  "reading/" READER_NAME "/multisymbol", "use '*' between coefficients and variables by writing to problem?",
4515  NULL, TRUE, FALSE, NULL, NULL) );
4516 
4517  return SCIP_OKAY;
4518 }
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:3095
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:8186
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:2486
SCIP_EXPORT SCIP_Bool SCIPvarIsNegated(SCIP_VAR *var)
Definition: var.c:17167
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:2522
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:4120
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:9818
SCIP_VAR * SCIPgetIndVarPseudoboolean(SCIP *const scip, SCIP_CONS *const cons)
SCIP_Bool SCIPhashtableExists(SCIP_HASHTABLE *hashtable, void *element)
Definition: misc.c:2598
#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:4594
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:17510
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:17177
#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:9272
void * SCIPhashmapGetImage(SCIP_HASHMAP *hashmap, void *origin)
Definition: misc.c:3200
SCIP_EXPORT SCIP_Bool SCIPvarIsActive(SCIP_VAR *var)
Definition: var.c:17335
public methods for problem variables
SCIP_RETCODE SCIPincludeReaderOpb(SCIP *scip)
Definition: reader_opb.c:4495
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:2937
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:4455
enum OpbExpType OPBEXPTYPE
Definition: reader_opb.c:144
SCIP_EXPORT SCIP_VARSTATUS SCIPvarGetStatus(SCIP_VAR *var)
Definition: var.c:17131
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:3226
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:4470
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:4197
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:2235
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:17012
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:214
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:3781
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:2753
#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:4275
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:17488
void SCIPhashtableFree(SCIP_HASHTABLE **hashtable)
Definition: misc.c:2285
#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:3013
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:3855
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:2656
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:8398
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:2129
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:17608
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:3074
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:17718
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:17728
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:4551
public methods for message output
SCIP_VAR * a
Definition: circlepacking.c:57
int SCIPsnprintf(char *t, int len, const char *s,...)
Definition: misc.c:10590
int SCIPgetNVarsSetppc(SCIP *scip, SCIP_CONS *cons)
Definition: cons_setppc.c:9249
void SCIPhashmapFree(SCIP_HASHMAP **hashmap)
Definition: misc.c:3047
const char * SCIPconsGetName(SCIP_CONS *cons)
Definition: cons.c:8089
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:8109
#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:12540
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:10499
#define SCIP_Longint
Definition: def.h:148
const char * SCIPconshdlrGetName(SCIP_CONSHDLR *conshdlr)
Definition: cons.c:4179
#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:9295
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:2152
#define BMSclearMemoryArray(ptr, num)
Definition: memory.h:122
SCIP_EXPORT SCIP_Real SCIPvarGetUbOriginal(SCIP_VAR *var)
Definition: var.c:17628
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:4481
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:10474
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:2848
SCIP_Longint SCIPgetCapacityKnapsack(SCIP *scip, SCIP_CONS *cons)
SCIP_EXPORT int SCIPvarGetIndex(SCIP_VAR *var)
Definition: var.c:17345
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