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