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