Scippy

SCIP

Solving Constraint Integer Programs

reader_pip.c
Go to the documentation of this file.
1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2 /* */
3 /* This file is part of the program and library */
4 /* SCIP --- Solving Constraint Integer Programs */
5 /* */
6 /* Copyright (C) 2002-2014 Konrad-Zuse-Zentrum */
7 /* fuer Informationstechnik Berlin */
8 /* */
9 /* SCIP is distributed under the terms of the ZIB Academic License. */
10 /* */
11 /* You should have received a copy of the ZIB Academic License */
12 /* along with SCIP; see the file COPYING. If not email to scip@zib.de. */
13 /* */
14 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
15 
16 /**@file reader_pip.c
17  * @brief file reader for polynomial mixed-integer programs in PIP format
18  * @author Stefan Vigerske
19  * @author Marc Pfetsch
20  */
21 
22 /*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
23 
24 #include <stdlib.h>
25 #include <assert.h>
26 #include <string.h>
27 #if defined(_WIN32) || defined(_WIN64)
28 #else
29 #include <strings.h> /*lint --e{766}*/ /* needed for strncasecmp() */
30 #endif
31 #include <ctype.h>
32 
33 #include "scip/reader_pip.h"
34 #include "scip/cons_knapsack.h"
35 #include "scip/cons_linear.h"
36 #include "scip/cons_logicor.h"
37 #include "scip/cons_setppc.h"
38 #include "scip/cons_varbound.h"
39 #include "scip/cons_quadratic.h"
40 #include "scip/cons_nonlinear.h"
41 #include "scip/cons_abspower.h"
42 #include "scip/cons_and.h"
43 #include "scip/cons_bivariate.h"
44 #include "scip/pub_misc.h"
45 
46 #define READER_NAME "pipreader"
47 #define READER_DESC "file reader for polynomial mixed-integer programs in PIP format"
48 #define READER_EXTENSION "pip"
49 
50 
51 /*
52  * Data structures
53  */
54 #define PIP_MAX_LINELEN 65536
55 #define PIP_MAX_PUSHEDTOKENS 2
56 #define PIP_INIT_VARSSIZE 256
57 #define PIP_INIT_MONOMIALSSIZE 128
58 #define PIP_INIT_FACTORSSIZE 16
59 #define PIP_MAX_PRINTLEN 561 /**< the maximum length of any line is 560 + '\\0' = 561*/
60 #define PIP_MAX_NAMELEN 256 /**< the maximum length for any name is 255 + '\\0' = 256 */
61 #define PIP_PRINTLEN 100
62 
63 /** Section in PIP File */
65 {
73 };
74 typedef enum PipSection PIPSECTION;
75 
77 {
81 };
82 typedef enum PipExpType PIPEXPTYPE;
83 
85 {
90 };
91 typedef enum PipSense PIPSENSE;
92 
93 /** PIP reading data */
94 struct PipInput
95 {
96  SCIP_FILE* file;
97  char linebuf[PIP_MAX_LINELEN+1];
98  char probname[PIP_MAX_LINELEN];
99  char objname[PIP_MAX_LINELEN];
100  char* token;
101  char* tokenbuf;
102  char* pushedtokens[PIP_MAX_PUSHEDTOKENS];
103  int npushedtokens;
104  int linenumber;
105  int linepos;
106  PIPSECTION section;
107  SCIP_OBJSENSE objsense;
108  SCIP_Bool initialconss; /**< should model constraints be marked as initial? */
109  SCIP_Bool dynamicconss; /**< should model constraints be subject to aging? */
110  SCIP_Bool dynamiccols; /**< should columns be added and removed dynamically to the LP? */
111  SCIP_Bool dynamicrows; /**< should rows be added and removed dynamically to the LP? */
112  SCIP_Bool haserror;
113 };
114 typedef struct PipInput PIPINPUT;
115 
116 static const char delimchars[] = " \f\n\r\t\v";
117 static const char tokenchars[] = "-+:<>=*^";
118 static const char commentchars[] = "\\";
119 
120 
121 /*
122  * Local methods (for reading)
123  */
124 
125 /** issues an error message and marks the PIP data to have errors */
126 static
128  SCIP* scip, /**< SCIP data structure */
129  PIPINPUT* pipinput, /**< PIP reading data */
130  const char* msg /**< error message */
131  )
132 {
133  char formatstr[256];
134 
135  assert(pipinput != NULL);
136 
137  SCIPerrorMessage("Syntax error in line %d: %s ('%s')\n", pipinput->linenumber, msg, pipinput->token);
138  if( pipinput->linebuf[strlen(pipinput->linebuf)-1] == '\n' )
139  {
140  SCIPverbMessage(scip, SCIP_VERBLEVEL_MINIMAL, NULL, " input: %s", pipinput->linebuf);
141  }
142  else
143  {
144  SCIPverbMessage(scip, SCIP_VERBLEVEL_MINIMAL, NULL, " input: %s\n", pipinput->linebuf);
145  }
146  (void) SCIPsnprintf(formatstr, 256, " %%%ds\n", pipinput->linepos);
147  SCIPverbMessage(scip, SCIP_VERBLEVEL_MINIMAL, NULL, formatstr, "^");
148  pipinput->section = PIP_END;
149  pipinput->haserror = TRUE;
150 }
151 
152 /** returns whether a syntax error was detected */
153 static
155  PIPINPUT* pipinput /**< PIP reading data */
156  )
157 {
158  assert(pipinput != NULL);
159 
160  return pipinput->haserror;
161 }
162 
163 /** returns whether the given character is a token delimiter */
164 static
166  char c /**< input character */
167  )
168 {
169  return (c == '\0') || (strchr(delimchars, c) != NULL);
170 }
171 
172 /** returns whether the given character is a single token */
173 static
175  char c /**< input character */
176  )
177 {
178  return (strchr(tokenchars, c) != NULL);
179 }
180 
181 /** returns whether the current character is member of a value string */
182 static
184  char c, /**< input character */
185  char nextc, /**< next input character */
186  SCIP_Bool firstchar, /**< is the given character the first char of the token? */
187  SCIP_Bool* hasdot, /**< pointer to update the dot flag */
188  PIPEXPTYPE* exptype /**< pointer to update the exponent type */
189  )
190 {
191  assert(hasdot != NULL);
192  assert(exptype != NULL);
193 
194  if( isdigit((unsigned char)c) )
195  return TRUE;
196  else if( (*exptype == PIP_EXP_NONE) && !(*hasdot) && (c == '.') && isdigit((unsigned char)nextc) )
197  {
198  *hasdot = TRUE;
199  return TRUE;
200  }
201  else if( !firstchar && (*exptype == PIP_EXP_NONE) && (c == 'e' || c == 'E') )
202  {
203  if( nextc == '+' || nextc == '-' )
204  {
205  *exptype = PIP_EXP_SIGNED;
206  return TRUE;
207  }
208  else if( isdigit((unsigned char)nextc) )
209  {
210  *exptype = PIP_EXP_UNSIGNED;
211  return TRUE;
212  }
213  }
214  else if( (*exptype == PIP_EXP_SIGNED) && (c == '+' || c == '-') )
215  {
216  *exptype = PIP_EXP_UNSIGNED;
217  return TRUE;
218  }
219 
220  return FALSE;
221 }
222 
223 /** reads the next line from the input file into the line buffer; skips comments;
224  * returns whether a line could be read
225  */
226 static
228  SCIP* scip, /**< SCIP data structure */
229  PIPINPUT* pipinput /**< PIP reading data */
230  )
231 {
232  int i;
233 
234  assert(pipinput != NULL);
235 
236  /* clear the line */
237  BMSclearMemoryArray(pipinput->linebuf, PIP_MAX_LINELEN);
238 
239  /* read next line */
240  pipinput->linepos = 0;
241  pipinput->linebuf[PIP_MAX_LINELEN-2] = '\0';
242  if( SCIPfgets(pipinput->linebuf, (int) sizeof(pipinput->linebuf), pipinput->file) == NULL )
243  return FALSE;
244  pipinput->linenumber++;
245  if( pipinput->linebuf[PIP_MAX_LINELEN-2] != '\0' )
246  {
247  SCIPerrorMessage("Error: line %d exceeds %d characters\n", pipinput->linenumber, PIP_MAX_LINELEN-2);
248  pipinput->haserror = TRUE;
249  return FALSE;
250  }
251  pipinput->linebuf[PIP_MAX_LINELEN-1] = '\0'; /* we want to use lookahead of one char -> we need two \0 at the end */
252 
253  /* skip characters after comment symbol */
254  for( i = 0; commentchars[i] != '\0'; ++i )
255  {
256  char* commentstart;
257 
258  commentstart = strchr(pipinput->linebuf, commentchars[i]);
259  if( commentstart != NULL )
260  {
261  *commentstart = '\0';
262  *(commentstart+1) = '\0'; /* we want to use lookahead of one char -> we need two \0 at the end */
263  }
264  }
265 
266  return TRUE;
267 }
268 
269 /** swaps the addresses of two pointers */
270 static
272  char** pointer1, /**< first pointer */
273  char** pointer2 /**< second pointer */
274  )
275 {
276  char* tmp;
277 
278  tmp = *pointer1;
279  *pointer1 = *pointer2;
280  *pointer2 = tmp;
281 }
282 
283 /** reads the next token from the input file into the token buffer; returns whether a token was read */
284 static
286  SCIP* scip, /**< SCIP data structure */
287  PIPINPUT* pipinput /**< PIP reading data */
288  )
289 {
290  SCIP_Bool hasdot;
291  PIPEXPTYPE exptype;
292  char* buf;
293  int tokenlen;
294 
295  assert(pipinput != NULL);
296  assert(pipinput->linepos < PIP_MAX_LINELEN);
297 
298  /* check the token stack */
299  if( pipinput->npushedtokens > 0 )
300  {
301  swapPointers(&pipinput->token, &pipinput->pushedtokens[pipinput->npushedtokens-1]);
302  pipinput->npushedtokens--;
303  SCIPdebugMessage("(line %d) read token again: '%s'\n", pipinput->linenumber, pipinput->token);
304  return TRUE;
305  }
306 
307  /* skip delimiters */
308  buf = pipinput->linebuf;
309  while( isDelimChar(buf[pipinput->linepos]) )
310  {
311  if( buf[pipinput->linepos] == '\0' )
312  {
313  if( !getNextLine(scip, pipinput) )
314  {
315  pipinput->section = PIP_END;
316  SCIPdebugMessage("(line %d) end of file\n", pipinput->linenumber);
317  return FALSE;
318  }
319  assert(pipinput->linepos == 0);
320  }
321  else
322  pipinput->linepos++;
323  }
324  assert(pipinput->linepos < PIP_MAX_LINELEN);
325  assert(!isDelimChar(buf[pipinput->linepos]));
326 
327  /* check if the token is a value */
328  hasdot = FALSE;
329  exptype = PIP_EXP_NONE;
330  if( isValueChar(buf[pipinput->linepos], buf[pipinput->linepos+1], TRUE, &hasdot, &exptype) )
331  {
332  /* read value token */
333  tokenlen = 0;
334  do
335  {
336  assert(tokenlen < PIP_MAX_LINELEN);
337  assert(!isDelimChar(buf[pipinput->linepos]));
338  pipinput->token[tokenlen] = buf[pipinput->linepos];
339  tokenlen++;
340  pipinput->linepos++;
341  }
342  while( isValueChar(buf[pipinput->linepos], buf[pipinput->linepos+1], FALSE, &hasdot, &exptype) );
343  }
344  else
345  {
346  /* read non-value token */
347  tokenlen = 0;
348  do
349  {
350  assert(tokenlen < PIP_MAX_LINELEN);
351  pipinput->token[tokenlen] = buf[pipinput->linepos];
352  tokenlen++;
353  pipinput->linepos++;
354  if( tokenlen == 1 && isTokenChar(pipinput->token[0]) )
355  break;
356  }
357  while( !isDelimChar(buf[pipinput->linepos]) && !isTokenChar(buf[pipinput->linepos]) );
358 
359  /* if the token is an equation sense '<', '>', or '=', skip a following '='
360  * if the token is an equality token '=' and the next character is a '<' or '>', replace the token by the inequality sense
361  */
362  if( tokenlen >= 1
363  && (pipinput->token[tokenlen-1] == '<' || pipinput->token[tokenlen-1] == '>' || pipinput->token[tokenlen-1] == '=')
364  && buf[pipinput->linepos] == '=' )
365  {
366  pipinput->linepos++;
367  }
368  else if( pipinput->token[tokenlen-1] == '=' && (buf[pipinput->linepos] == '<' || buf[pipinput->linepos] == '>') )
369  {
370  pipinput->token[tokenlen-1] = buf[pipinput->linepos];
371  pipinput->linepos++;
372  }
373  }
374  assert(tokenlen < PIP_MAX_LINELEN);
375  pipinput->token[tokenlen] = '\0';
376 
377  SCIPdebugMessage("(line %d) read token: '%s'\n", pipinput->linenumber, pipinput->token);
378 
379  return TRUE;
380 }
381 
382 /** puts the current token on the token stack, such that it is read at the next call to getNextToken() */
383 static
385  PIPINPUT* pipinput /**< PIP reading data */
386  )
387 {
388  assert(pipinput != NULL);
389  assert(pipinput->npushedtokens < PIP_MAX_PUSHEDTOKENS);
390 
391  swapPointers(&pipinput->pushedtokens[pipinput->npushedtokens], &pipinput->token);
392  pipinput->npushedtokens++;
393 }
394 
395 /** puts the buffered token on the token stack, such that it is read at the next call to getNextToken() */
396 static
398  PIPINPUT* pipinput /**< PIP reading data */
399  )
400 {
401  assert(pipinput != NULL);
402  assert(pipinput->npushedtokens < PIP_MAX_PUSHEDTOKENS);
403 
404  swapPointers(&pipinput->pushedtokens[pipinput->npushedtokens], &pipinput->tokenbuf);
405  pipinput->npushedtokens++;
406 }
407 
408 /** swaps the current token with the token buffer */
409 static
411  PIPINPUT* pipinput /**< PIP reading data */
412  )
413 {
414  assert(pipinput != NULL);
415 
416  swapPointers(&pipinput->token, &pipinput->tokenbuf);
417 }
418 
419 /** checks whether the current token is a section identifier, and if yes, switches to the corresponding section */
420 static
422  SCIP* scip, /**< SCIP data structure */
423  PIPINPUT* pipinput /**< PIP reading data */
424  )
425 {
426  SCIP_Bool iscolon;
427 
428  assert(pipinput != NULL);
429 
430  /* remember first token by swapping the token buffer */
431  swapTokenBuffer(pipinput);
432 
433  /* look at next token: if this is a ':', the first token is a name and no section keyword */
434  iscolon = FALSE;
435  if( getNextToken(scip, pipinput) )
436  {
437  iscolon = (strcmp(pipinput->token, ":") == 0);
438  pushToken(pipinput);
439  }
440 
441  /* reinstall the previous token by swapping back the token buffer */
442  swapTokenBuffer(pipinput);
443 
444  /* check for ':' */
445  if( iscolon )
446  return FALSE;
447 
448  if( strcasecmp(pipinput->token, "MINIMIZE") == 0
449  || strcasecmp(pipinput->token, "MINIMUM") == 0
450  || strcasecmp(pipinput->token, "MIN") == 0 )
451  {
452  SCIPdebugMessage("(line %d) new section: OBJECTIVE\n", pipinput->linenumber);
453  pipinput->section = PIP_OBJECTIVE;
454  pipinput->objsense = SCIP_OBJSENSE_MINIMIZE;
455  return TRUE;
456  }
457 
458  if( strcasecmp(pipinput->token, "MAXIMIZE") == 0
459  || strcasecmp(pipinput->token, "MAXIMUM") == 0
460  || strcasecmp(pipinput->token, "MAX") == 0 )
461  {
462  SCIPdebugMessage("(line %d) new section: OBJECTIVE\n", pipinput->linenumber);
463  pipinput->section = PIP_OBJECTIVE;
464  pipinput->objsense = SCIP_OBJSENSE_MAXIMIZE;
465  return TRUE;
466  }
467 
468  if( strcasecmp(pipinput->token, "SUBJECT") == 0 )
469  {
470  /* check if the next token is 'TO' */
471  swapTokenBuffer(pipinput);
472  if( getNextToken(scip, pipinput) )
473  {
474  if( strcasecmp(pipinput->token, "TO") == 0 )
475  {
476  SCIPdebugMessage("(line %d) new section: CONSTRAINTS\n", pipinput->linenumber);
477  pipinput->section = PIP_CONSTRAINTS;
478  return TRUE;
479  }
480  else
481  pushToken(pipinput);
482  }
483  swapTokenBuffer(pipinput);
484  }
485 
486  if( strcasecmp(pipinput->token, "SUCH") == 0 )
487  {
488  /* check if the next token is 'THAT' */
489  swapTokenBuffer(pipinput);
490  if( getNextToken(scip, pipinput) )
491  {
492  if( strcasecmp(pipinput->token, "THAT") == 0 )
493  {
494  SCIPdebugMessage("(line %d) new section: CONSTRAINTS\n", pipinput->linenumber);
495  pipinput->section = PIP_CONSTRAINTS;
496  return TRUE;
497  }
498  else
499  pushToken(pipinput);
500  }
501  swapTokenBuffer(pipinput);
502  }
503 
504  if( strcasecmp(pipinput->token, "st") == 0
505  || strcasecmp(pipinput->token, "S.T.") == 0
506  || strcasecmp(pipinput->token, "ST.") == 0 )
507  {
508  SCIPdebugMessage("(line %d) new section: CONSTRAINTS\n", pipinput->linenumber);
509  pipinput->section = PIP_CONSTRAINTS;
510  return TRUE;
511  }
512 
513  if( strcasecmp(pipinput->token, "BOUNDS") == 0
514  || strcasecmp(pipinput->token, "BOUND") == 0 )
515  {
516  SCIPdebugMessage("(line %d) new section: BOUNDS\n", pipinput->linenumber);
517  pipinput->section = PIP_BOUNDS;
518  return TRUE;
519  }
520 
521  if( strcasecmp(pipinput->token, "GENERAL") == 0
522  || strcasecmp(pipinput->token, "GENERALS") == 0
523  || strcasecmp(pipinput->token, "GEN") == 0
524  || strcasecmp(pipinput->token, "INTEGER") == 0
525  || strcasecmp(pipinput->token, "INTEGERS") == 0
526  || strcasecmp(pipinput->token, "INT") == 0 )
527  {
528  SCIPdebugMessage("(line %d) new section: GENERALS\n", pipinput->linenumber);
529  pipinput->section = PIP_GENERALS;
530  return TRUE;
531  }
532 
533  if( strcasecmp(pipinput->token, "BINARY") == 0
534  || strcasecmp(pipinput->token, "BINARIES") == 0
535  || strcasecmp(pipinput->token, "BIN") == 0 )
536  {
537  SCIPdebugMessage("(line %d) new section: BINARIES\n", pipinput->linenumber);
538  pipinput->section = PIP_BINARIES;
539  return TRUE;
540  }
541 
542  if( strcasecmp(pipinput->token, "END") == 0 )
543  {
544  SCIPdebugMessage("(line %d) new section: END\n", pipinput->linenumber);
545  pipinput->section = PIP_END;
546  return TRUE;
547  }
548 
549  return FALSE;
550 }
551 
552 /** returns whether the current token is a sign */
553 static
555  PIPINPUT* pipinput, /**< PIP reading data */
556  int* sign /**< pointer to update the sign */
557  )
558 {
559  assert(pipinput != NULL);
560  assert(sign != NULL);
561  assert(*sign == +1 || *sign == -1);
562 
563  if( pipinput->token[1] == '\0' )
564  {
565  if( *pipinput->token == '+' )
566  return TRUE;
567  else if( *pipinput->token == '-' )
568  {
569  *sign *= -1;
570  return TRUE;
571  }
572  }
573 
574  return FALSE;
575 }
576 
577 /** returns whether the current token is a value */
578 static
580  SCIP* scip, /**< SCIP data structure */
581  PIPINPUT* pipinput, /**< PIP reading data */
582  SCIP_Real* value /**< pointer to store the value (unchanged, if token is no value) */
583  )
584 {
585  assert(pipinput != NULL);
586  assert(value != NULL);
587 
588  if( strcasecmp(pipinput->token, "INFINITY") == 0 || strcasecmp(pipinput->token, "INF") == 0 )
589  {
590  *value = SCIPinfinity(scip);
591  return TRUE;
592  }
593  else
594  {
595  double val;
596  char* endptr;
597 
598  val = strtod(pipinput->token, &endptr);
599  if( endptr != pipinput->token && *endptr == '\0' )
600  {
601  *value = val;
602  return TRUE;
603  }
604  }
605 
606  return FALSE;
607 }
608 
609 /** returns whether the current token is an equation sense */
610 static
612  PIPINPUT* pipinput, /**< PIP reading data */
613  PIPSENSE* sense /**< pointer to store the equation sense, or NULL */
614  )
615 {
616  assert(pipinput != NULL);
617 
618  if( strcmp(pipinput->token, "<") == 0 )
619  {
620  if( sense != NULL )
621  *sense = PIP_SENSE_LE;
622  return TRUE;
623  }
624  else if( strcmp(pipinput->token, ">") == 0 )
625  {
626  if( sense != NULL )
627  *sense = PIP_SENSE_GE;
628  return TRUE;
629  }
630  else if( strcmp(pipinput->token, "=") == 0 )
631  {
632  if( sense != NULL )
633  *sense = PIP_SENSE_EQ;
634  return TRUE;
635  }
636 
637  return FALSE;
638 }
639 
640 /** returns the variable with the given name, or creates a new variable if it does not exist */
641 static
643  SCIP* scip, /**< SCIP data structure */
644  char* name, /**< name of the variable */
645  SCIP_Bool dynamiccols, /**< should columns be added and removed dynamically to the LP? */
646  SCIP_VAR** var, /**< pointer to store the variable */
647  SCIP_Bool* created /**< pointer to store whether a new variable was created, or NULL */
648  )
649 {
650  assert(name != NULL);
651  assert(var != NULL);
652 
653  *var = SCIPfindVar(scip, name);
654  if( *var == NULL )
655  {
656  SCIP_VAR* newvar;
657 
658  /* create new variable of the given name */
659  SCIPdebugMessage("creating new variable: <%s>\n", name);
660  SCIP_CALL( SCIPcreateVar(scip, &newvar, name, 0.0, SCIPinfinity(scip), 0.0, SCIP_VARTYPE_CONTINUOUS,
661  !dynamiccols, dynamiccols, NULL, NULL, NULL, NULL, NULL) );
662  SCIP_CALL( SCIPaddVar(scip, newvar) );
663  *var = newvar;
664 
665  /* because the variable was added to the problem, it is captured by SCIP and we can safely release it right now
666  * without making the returned *var invalid
667  */
668  SCIP_CALL( SCIPreleaseVar(scip, &newvar) );
669 
670  if( created != NULL )
671  *created = TRUE;
672  }
673  else if( created != NULL )
674  *created = FALSE;
675 
676  return SCIP_OKAY;
677 }
678 
679 /** reads the header of the file */
680 static
682  SCIP* scip, /**< SCIP data structure */
683  PIPINPUT* pipinput /**< PIP reading data */
684  )
685 {
686  assert(pipinput != NULL);
687 
688  /* everything before first section is treated as comment */
689  do
690  {
691  /* get token */
692  if( !getNextToken(scip, pipinput) )
693  return SCIP_OKAY;
694  }
695  while( !isNewSection(scip, pipinput) );
696 
697  return SCIP_OKAY;
698 }
699 
700 /** ensure that an array of monomials can hold a minimum number of entries */
701 static
703  SCIP* scip, /**< SCIP data structure */
704  SCIP_EXPRDATA_MONOMIAL*** monomials, /**< pointer to current array of monomials */
705  int* monomialssize, /**< current size of monomials array at input; new size at exit */
706  int minnmonomials /**< required minimal size of monomials array */
707  )
708 {
709  int newsize;
710 
711  assert(scip != NULL);
712  assert(monomials != NULL);
713  assert(monomialssize != NULL);
714  assert(*monomials != NULL || *monomialssize == 0);
715 
716  if( minnmonomials <= *monomialssize )
717  return SCIP_OKAY;
718 
719  newsize = SCIPcalcMemGrowSize(scip, minnmonomials);
720 
721  if( *monomials != NULL )
722  {
723  SCIP_CALL( SCIPreallocBufferArray(scip, monomials, newsize) );
724  }
725  else
726  {
727  SCIP_CALL( SCIPallocBufferArray(scip, monomials, newsize) );
728  }
729  *monomialssize = newsize;
730 
731  return SCIP_OKAY;
732 }
733 
734 /** ensure that arrays of exponents and variable indices can hold a minimum number of entries */
735 static
737  SCIP* scip, /**< SCIP data structure */
738  SCIP_Real** exponents, /**< pointer to current array of exponents */
739  int** varidxs, /**< pointer to current array of variable indices */
740  int* factorssize, /**< current size of arrays at input; new size at exit */
741  int minnfactors /**< required minimal size of arrays */
742  )
743 {
744  int newsize;
745 
746  assert(scip != NULL);
747  assert(exponents != NULL);
748  assert(varidxs != NULL);
749  assert(factorssize != NULL);
750  assert(*exponents != NULL || *factorssize == 0);
751  assert(*varidxs != NULL || *factorssize == 0);
752  assert((*exponents != NULL) == (*varidxs != NULL));
753 
754  if( minnfactors <= *factorssize )
755  return SCIP_OKAY;
756 
757  newsize = SCIPcalcMemGrowSize(scip, minnfactors);
758 
759  if( *exponents != NULL )
760  {
761  SCIP_CALL( SCIPreallocBufferArray(scip, exponents, newsize) );
762  SCIP_CALL( SCIPreallocBufferArray(scip, varidxs, newsize) );
763  }
764  else
765  {
766  SCIP_CALL( SCIPallocBufferArray(scip, exponents, newsize) );
767  SCIP_CALL( SCIPallocBufferArray(scip, varidxs, newsize) );
768  }
769  *factorssize = newsize;
770 
771  return SCIP_OKAY;
772 }
773 
774 /** gives index of variable in vars array, inserts it at the end if not existing yet */
775 static
777  SCIP* scip, /**< SCIP data structure */
778  SCIP_VAR*** vars, /**< pointer to current array of variables */
779  int* varssize, /**< current size of variables array at input; new size at exit */
780  int* nvars, /**< number of variables stored in array */
781  SCIP_HASHMAP* varhash, /**< hashmap variables -> indices */
782  SCIP_VAR* var, /**< the variable which index we need */
783  int* varidx /**< pointer to store index of variable in *vars */
784  )
785 {
786  assert(scip != NULL);
787  assert(varssize != NULL);
788  assert(vars != NULL || *varssize == 0);
789  assert(nvars != NULL);
790  assert(*nvars <= *varssize);
791  assert(varhash != NULL);
792  assert(var != NULL);
793  assert(varidx != NULL);
794 
795  /* check if we saw this variable before */
796  if( SCIPhashmapExists(varhash, (void*)var) )
797  {
798  *varidx = (int)(size_t)SCIPhashmapGetImage(varhash, (void*)var);
799  assert(*varidx >= 0);
800  assert(*varidx < *nvars);
801 
802  return SCIP_OKAY;
803  }
804 
805  /* since variable is new, add it to the end of vars array and into hashmap */
806 
807  /* ensure enough space in vars array */
808  if( *nvars + 1 > *varssize )
809  {
810  *varssize = SCIPcalcMemGrowSize(scip, *nvars + 1);
811  if( vars == NULL )
812  {
813  SCIP_CALL( SCIPallocBufferArray(scip, vars, *varssize) );
814  }
815  else
816  {
817  SCIP_CALL( SCIPreallocBufferArray(scip, vars, *varssize) );
818  }
819  }
820  assert(*vars != NULL); /*lint !e613*/
821 
822  (*vars)[*nvars] = var; /*lint !e613*/
823  SCIP_CALL( SCIPhashmapInsert(varhash, (void*)var, (void*)(size_t)*nvars) );
824  *varidx = *nvars;
825 
826  ++*nvars;
827 
828  return SCIP_OKAY;
829 }
830 
831 /** reads an objective or constraint with name and coefficients */
832 static
834  SCIP* scip, /**< SCIP data structure */
835  PIPINPUT* pipinput, /**< PIP reading data */
836  char* name, /**< pointer to store the name of the line; must be at least of size
837  * PIP_MAX_LINELEN */
838  SCIP_EXPRTREE** exprtree, /**< pointer to store constraint function as polynomial expression */
839  int* degree, /**< pointer to store degree of polynomial */
840  SCIP_Bool* newsection /**< pointer to store whether a new section was encountered */
841  )
842 {
843  SCIP_EXPR* expression;
844  SCIP_Bool havesign;
845  SCIP_Bool havevalue;
846  SCIP_Real coef;
847  int coefsign;
848  int nextcoefsign;
849  int monomialdegree;
850  SCIP_EXPR** varexprs;
851  int i;
852 
853  SCIP_VAR** vars;
854  int varssize;
855  int nvars;
856  SCIP_HASHMAP* varhash;
857 
858  SCIP_Real constant;
859 
860  SCIP_EXPRDATA_MONOMIAL** monomials;
861  int monomialssize;
862  int nmonomials;
863 
864  int nfactors;
865  int factorssize;
866  SCIP_Real* exponents;
867  int* varidxs;
868 
869  assert(scip != NULL);
870  assert(pipinput != NULL);
871  assert(name != NULL);
872  assert(exprtree != NULL);
873  assert(degree != NULL);
874  assert(newsection != NULL);
875 
876  *name = '\0';
877  *exprtree = NULL;
878  *degree = 0;
879  *newsection = FALSE;
880 
881  /* read the first token, which may be the name of the line */
882  if( getNextToken(scip, pipinput) )
883  {
884  /* check if we reached a new section */
885  if( isNewSection(scip, pipinput) )
886  {
887  *newsection = TRUE;
888  return SCIP_OKAY;
889  }
890 
891  /* remember the token in the token buffer */
892  swapTokenBuffer(pipinput);
893 
894  /* get the next token and check, whether it is a colon */
895  if( getNextToken(scip, pipinput) )
896  {
897  if( strcmp(pipinput->token, ":") == 0 )
898  {
899  /* the second token was a colon: the first token is the line name */
900  (void)strncpy(name, pipinput->tokenbuf, PIP_MAX_LINELEN);
901  name[PIP_MAX_LINELEN - 1] = '\0';
902  SCIPdebugMessage("(line %d) read constraint name: '%s'\n", pipinput->linenumber, name);
903  }
904  else
905  {
906  /* the second token was no colon: push the tokens back onto the token stack and parse them as coefficients */
907  pushToken(pipinput);
908  pushBufferToken(pipinput);
909  }
910  }
911  else
912  {
913  /* there was only one token left: push it back onto the token stack and parse it as coefficient */
914  pushBufferToken(pipinput);
915  }
916  }
917 
918  /* initialize buffer for storing the variables */
919  varssize = PIP_INIT_VARSSIZE;
920  SCIP_CALL( SCIPallocBufferArray(scip, &vars, varssize) );
922 
923  /* initialize buffer for storing the monomials */
924  monomialssize = PIP_INIT_MONOMIALSSIZE;
925  SCIP_CALL( SCIPallocBufferArray(scip, &monomials, monomialssize) );
926 
927  /* initialize buffer for storing the factors in a monomial */
928  factorssize = PIP_INIT_FACTORSSIZE;
929  SCIP_CALL( SCIPallocBufferArray(scip, &exponents, factorssize) );
930  SCIP_CALL( SCIPallocBufferArray(scip, &varidxs, factorssize) );
931 
932  /* read the coefficients */
933  coefsign = +1;
934  nextcoefsign = +1;
935  coef = 1.0;
936  havesign = FALSE;
937  havevalue = FALSE;
938  nmonomials = 0;
939  nvars = 0;
940  nfactors = 0;
941  monomialdegree = 0;
942  constant = 0.0;
943  while( getNextToken(scip, pipinput) )
944  {
945  SCIP_VAR* var;
946  int varidx;
947  SCIP_Bool issense;
948  SCIP_Bool issign;
949  SCIP_Bool isnewsection;
950  SCIP_Real exponent;
951 
952  issign = FALSE; /* fix compiler warning */
953  issense = FALSE; /* fix lint warning */
954  if( (isnewsection = isNewSection(scip, pipinput)) || /*lint !e820*/
955  (issense = isSense(pipinput, NULL)) || /*lint !e820*/
956  ((nfactors > 0 || havevalue) && (issign = isSign(pipinput, &nextcoefsign))) ) /*lint !e820*/
957  {
958  /* finish the current monomial */
959  if( nfactors > 0 )
960  {
961  SCIP_CALL( ensureMonomialsSize(scip, &monomials, &monomialssize, nmonomials + 1) );
963  &monomials[nmonomials], coefsign * coef, nfactors, varidxs, exponents) );
964  ++nmonomials;
965  }
966  else if( havevalue)
967  {
968  constant += coefsign * coef;
969  }
970 
971  if( monomialdegree > *degree )
972  *degree = monomialdegree;
973 
974  /* reset variables */
975  nfactors = 0;
976  coef = 1.0;
977  coefsign = +1;
978  havesign = FALSE;
979  havevalue = FALSE;
980  monomialdegree = 0;
981 
982  if( isnewsection )
983  {
984  *newsection = TRUE;
985  break;
986  }
987 
988  if( issense )
989  {
990  /* put the sense back onto the token stack */
991  pushToken(pipinput);
992  break;
993  }
994 
995  if( issign )
996  {
997  coefsign = nextcoefsign;
998  SCIPdebugMessage("(line %d) read coefficient sign: %+d\n", pipinput->linenumber, coefsign);
999  havesign = TRUE;
1000  nextcoefsign = +1;
1001  continue;
1002  }
1003  }
1004 
1005  /* check if we read a sign */
1006  if( isSign(pipinput, &coefsign) )
1007  {
1008  SCIPdebugMessage("(line %d) read coefficient sign: %+d\n", pipinput->linenumber, coefsign);
1009 
1010  if( nfactors > 0 || havevalue )
1011  {
1012  syntaxError(scip, pipinput, "sign can only be at beginning of monomial");
1013  goto TERMINATE_READPOLYNOMIAL;
1014  }
1015 
1016  havesign = TRUE;
1017  continue;
1018  }
1019 
1020  /* check if we are in between factors of a monomial */
1021  if( strcmp(pipinput->token, "*") == 0 )
1022  {
1023  if( nfactors == 0 )
1024  {
1025  syntaxError(scip, pipinput, "cannot have '*' before first variable in monomial");
1026  goto TERMINATE_READPOLYNOMIAL;
1027  }
1028 
1029  continue;
1030  }
1031 
1032  /* all but the first monomial need a sign */
1033  if( nmonomials > 0 && !havesign )
1034  {
1035  syntaxError(scip, pipinput, "expected sign ('+' or '-') or sense ('<' or '>')");
1036  goto TERMINATE_READPOLYNOMIAL;
1037  }
1038 
1039  /* check if we are at an exponent for the last variable */
1040  if( strcmp(pipinput->token, "^") == 0 )
1041  {
1042  if( !getNextToken(scip, pipinput) || !isValue(scip, pipinput, &exponent) )
1043  {
1044  syntaxError(scip, pipinput, "expected exponent value after '^'");
1045  goto TERMINATE_READPOLYNOMIAL;
1046  }
1047  if( nfactors == 0 )
1048  {
1049  syntaxError(scip, pipinput, "cannot have '^' before first variable in monomial");
1050  goto TERMINATE_READPOLYNOMIAL;
1051  }
1052  exponents[nfactors-1] = exponent;
1053  if( SCIPisIntegral(scip, exponent) && exponent > 0.0 )
1054  monomialdegree += (int)exponent - 1; /* -1, because we added +1 when we put the variable into varidxs */
1055  else
1056  monomialdegree = SCIP_EXPR_DEGREEINFINITY;
1057 
1058  SCIPdebugMessage("(line %d) read exponent value %g for variable %s\n", pipinput->linenumber, exponent,
1059  SCIPvarGetName(vars[varidxs[nfactors-1]]));
1060  continue;
1061  }
1062 
1063  /* check if we read a value */
1064  if( isValue(scip, pipinput, &coef) )
1065  {
1066  SCIPdebugMessage("(line %d) read coefficient value: %g with sign %+d\n", pipinput->linenumber, coef, coefsign);
1067 
1068  if( havevalue )
1069  {
1070  syntaxError(scip, pipinput, "two consecutive values");
1071  goto TERMINATE_READPOLYNOMIAL;
1072  }
1073 
1074  if( nfactors > 0 )
1075  {
1076  syntaxError(scip, pipinput, "coefficients can only be at the beginning of a monomial");
1077  goto TERMINATE_READPOLYNOMIAL;
1078  }
1079 
1080  havevalue = TRUE;
1081  continue;
1082  }
1083 
1084  /* the token is a variable name: get the corresponding variable (or create a new one) */
1085  SCIP_CALL( getVariable(scip, pipinput->token, pipinput->dynamiccols, &var, NULL) );
1086 
1087  /* get the index of the variable in the vars array, or add there if not in it yet */
1088  SCIP_CALL( getVariableIndex(scip, &vars, &varssize, &nvars, varhash, var, &varidx) );
1089 
1090  SCIP_CALL( ensureFactorsSize(scip, &exponents, &varidxs, &factorssize, nfactors + 1) );
1091 
1092  exponents[nfactors] = 1.0;
1093  varidxs[nfactors] = varidx;
1094  ++nfactors;
1095  ++monomialdegree;
1096  }
1097 
1098  if( nfactors > 0 )
1099  {
1100  syntaxError(scip, pipinput, "string ended before monomial has finished");
1101  goto TERMINATE_READPOLYNOMIAL;
1102  }
1103 
1104  /* create variable expressions */
1105  SCIP_CALL( SCIPallocBufferArray(scip, &varexprs, nvars) );
1106  for( i = 0; i < nvars; ++i )
1107  {
1108  SCIP_CALL( SCIPexprCreate(SCIPblkmem(scip), &varexprs[i], SCIP_EXPR_VARIDX, i) );
1109  }
1110 
1111  /* create polynomial expression, let polynomial take over ownership of monomials */
1112  SCIP_CALL( SCIPexprCreatePolynomial(SCIPblkmem(scip), &expression, nvars, varexprs,
1113  nmonomials, monomials, constant, FALSE) );
1114 
1115  SCIPfreeBufferArray(scip, &varexprs);
1116 
1117  SCIP_CALL( SCIPexprtreeCreate(SCIPblkmem(scip), exprtree, expression, 0, 0, NULL) );
1118  SCIP_CALL( SCIPexprtreeSetVars(*exprtree, nvars, vars) );
1119 
1120  SCIPdebugMessage("read polynomial of degree %d: ", *degree);
1122  SCIPdebugPrintf("\n");
1123 
1124  TERMINATE_READPOLYNOMIAL:
1125  SCIPfreeBufferArray(scip, &vars);
1126  SCIPfreeBufferArray(scip, &monomials);
1127  SCIPfreeBufferArray(scip, &exponents);
1128  SCIPfreeBufferArray(scip, &varidxs);
1129  SCIPhashmapFree(&varhash);
1130 
1131  return SCIP_OKAY;
1132 }
1133 
1134 /** given an expression tree that holds a polynomial expression of degree at most two,
1135  * gives the coefficients of the constant, linear, and quadratic part of this expression
1136  */
1137 static
1139  SCIP* scip, /**< SCIP data structure */
1140  SCIP_EXPRTREE* exprtree, /**< expression tree holding polynomial expression */
1141  SCIP_Real* constant, /**< buffer to store constant monomials */
1142  int* nlinvars, /**< buffer to store number of linear coefficients */
1143  SCIP_VAR** linvars, /**< array to fill with linear variables */
1144  SCIP_Real* lincoefs, /**< array to fill with coefficients of linear variables */
1145  int* nquadterms, /**< buffer to store number of quadratic terms */
1146  SCIP_VAR** quadvars1, /**< array to fill with quadratic variables */
1147  SCIP_VAR** quadvars2, /**< array to fill with quadratic variables */
1148  SCIP_Real* quadcoefs /**< array to fill with coefficients of quadratic terms */
1149  )
1150 {
1151  SCIP_EXPR* expr;
1152  SCIP_EXPRDATA_MONOMIAL** monomials;
1153  int nmonomials;
1154  int varidx;
1155  int i;
1156 
1157  expr = SCIPexprtreeGetRoot(exprtree);
1158  assert(expr != NULL);
1159  assert(SCIPexprGetOperator(expr) == SCIP_EXPR_POLYNOMIAL);
1160  assert(SCIPexprGetNChildren(expr) == SCIPexprtreeGetNVars(exprtree));
1161 
1162  nmonomials = SCIPexprGetNMonomials(expr);
1163  monomials = SCIPexprGetMonomials(expr);
1164 
1165  *constant = SCIPexprGetPolynomialConstant(expr);
1166  *nlinvars = 0;
1167  *nquadterms = 0;
1168  for( i = 0; i < nmonomials; ++i )
1169  {
1170  assert(SCIPexprGetMonomialNFactors(monomials[i]) >= 0);
1171  assert(SCIPexprGetMonomialNFactors(monomials[i]) <= 2);
1172  assert(SCIPexprGetMonomialExponents(monomials[i]) != NULL || SCIPexprGetMonomialNFactors(monomials[i]) == 0);
1173  assert(SCIPexprGetMonomialChildIndices(monomials[i]) != NULL || SCIPexprGetMonomialNFactors(monomials[i]) == 0);
1174 
1175  if( SCIPexprGetMonomialNFactors(monomials[i]) == 0 )
1176  {
1177  /* constant monomial */
1178  *constant += SCIPexprGetMonomialCoef(monomials[i]);
1179  }
1180  else if( SCIPexprGetMonomialNFactors(monomials[i]) == 1 && SCIPexprGetMonomialExponents(monomials[i])[0] == 1.0 )
1181  {
1182  /* linear monomial */
1183  varidx = SCIPexprGetMonomialChildIndices(monomials[i])[0];
1184  assert(varidx >= 0);
1185  assert(varidx < SCIPexprtreeGetNVars(exprtree));
1186  assert(SCIPexprGetOperator(SCIPexprGetChildren(expr)[varidx]) == SCIP_EXPR_VARIDX);
1187  assert(SCIPexprGetOpIndex(SCIPexprGetChildren(expr)[varidx]) == varidx); /* assume that child varidx corresponds to variable varidx */
1188 
1189  lincoefs[*nlinvars] = SCIPexprGetMonomialCoef(monomials[i]);
1190  linvars[*nlinvars] = SCIPexprtreeGetVars(exprtree)[varidx];
1191  ++*nlinvars;
1192  }
1193  else if( SCIPexprGetMonomialNFactors(monomials[i]) == 1 )
1194  {
1195  /* square monomial */
1196  assert(SCIPexprGetMonomialExponents(monomials[i])[0] == 2.0);
1197 
1198  varidx = SCIPexprGetMonomialChildIndices(monomials[i])[0];
1199  assert(varidx >= 0);
1200  assert(varidx < SCIPexprtreeGetNVars(exprtree));
1201  assert(SCIPexprGetOperator(SCIPexprGetChildren(expr)[varidx]) == SCIP_EXPR_VARIDX);
1202  assert(SCIPexprGetOpIndex(SCIPexprGetChildren(expr)[varidx]) == varidx); /* assume that child varidx corresponds to variable varidx */
1203 
1204  quadcoefs[*nquadterms] = SCIPexprGetMonomialCoef(monomials[i]);
1205  quadvars1[*nquadterms] = SCIPexprtreeGetVars(exprtree)[varidx];
1206  quadvars2[*nquadterms] = quadvars1[*nquadterms];
1207  ++*nquadterms;
1208  }
1209  else
1210  {
1211  /* bilinear monomial */
1212  assert(SCIPexprGetMonomialExponents(monomials[i])[0] == 1.0);
1213  assert(SCIPexprGetMonomialExponents(monomials[i])[1] == 1.0);
1214 
1215  quadcoefs[*nquadterms] = SCIPexprGetMonomialCoef(monomials[i]);
1216 
1217  varidx = SCIPexprGetMonomialChildIndices(monomials[i])[0];
1218  assert(varidx >= 0);
1219  assert(varidx < SCIPexprtreeGetNVars(exprtree));
1220  assert(SCIPexprGetOperator(SCIPexprGetChildren(expr)[varidx]) == SCIP_EXPR_VARIDX);
1221  assert(SCIPexprGetOpIndex(SCIPexprGetChildren(expr)[varidx]) == varidx); /* assume that child varidx corresponds to variable varidx */
1222  quadvars1[*nquadterms] = SCIPexprtreeGetVars(exprtree)[varidx];
1223 
1224  varidx = SCIPexprGetMonomialChildIndices(monomials[i])[1];
1225  assert(varidx >= 0);
1226  assert(varidx < SCIPexprtreeGetNVars(exprtree));
1227  assert(SCIPexprGetOperator(SCIPexprGetChildren(expr)[varidx]) == SCIP_EXPR_VARIDX);
1228  assert(SCIPexprGetOpIndex(SCIPexprGetChildren(expr)[varidx]) == varidx); /* assume that child varidx corresponds to variable varidx */
1229  quadvars2[*nquadterms] = SCIPexprtreeGetVars(exprtree)[varidx];
1230 
1231  ++*nquadterms;
1232  }
1233  }
1234 }
1235 
1236 /** reads the objective section */
1237 static
1239  SCIP* scip, /**< SCIP data structure */
1240  PIPINPUT* pipinput /**< PIP reading data */
1241  )
1242 {
1243  char name[PIP_MAX_LINELEN];
1244  SCIP_EXPRTREE* exprtree;
1245  SCIP_EXPR* expr;
1246  int degree;
1247  SCIP_Bool newsection;
1248  int varidx;
1249  int nmonomials;
1250  SCIP_Bool initial;
1251  SCIP_Bool separate;
1252  SCIP_Bool enforce;
1253  SCIP_Bool check;
1254  SCIP_Bool propagate;
1255  SCIP_Bool local;
1256  SCIP_Bool modifiable;
1257  SCIP_Bool dynamic;
1258  SCIP_Bool removable;
1259 
1260  assert(pipinput != NULL);
1261 
1262  /* determine settings; note that reading/{initialconss,dynamicconss,dynamicrows,dynamiccols} apply only to model
1263  * constraints and variables, not to an auxiliary objective constraint (otherwise it can happen that an auxiliary
1264  * objective variable is loose with infinite best bound, triggering the problem that an LP that is unbounded because
1265  * of loose variables with infinite best bound cannot be solved)
1266  */
1267  initial = TRUE;
1268  separate = TRUE;
1269  enforce = TRUE;
1270  check = TRUE;
1271  propagate = TRUE;
1272  local = FALSE;
1273  modifiable = FALSE;
1274  dynamic = FALSE;
1275  removable = FALSE;
1276 
1277  /* read the objective coefficients */
1278  SCIP_CALL( readPolynomial(scip, pipinput, name, &exprtree, &degree, &newsection) );
1279  if( !hasError(pipinput) )
1280  {
1281  int i;
1282 
1283  expr = SCIPexprtreeGetRoot(exprtree);
1284  assert(expr != NULL);
1285  assert(SCIPexprGetOperator(expr) == SCIP_EXPR_POLYNOMIAL);
1286 
1287  nmonomials = SCIPexprGetNMonomials(expr);
1288 
1289  if( SCIPexprGetPolynomialConstant(expr) != 0.0 )
1290  {
1291  SCIP_VAR* objconst;
1292  SCIP_CALL( SCIPcreateVarBasic(scip, &objconst, "objconst", 1.0, 1.0, SCIPexprGetPolynomialConstant(expr), SCIP_VARTYPE_CONTINUOUS) );
1293  SCIP_CALL( SCIPaddVar(scip, objconst) );
1294  SCIP_CALL( SCIPreleaseVar(scip, &objconst) );
1295  }
1296 
1297  assert(degree >= 0);
1298  if( degree == 1 )
1299  {
1300  SCIP_Real coef;
1301  SCIP_VAR* var;
1302  SCIP_EXPRDATA_MONOMIAL** monomials;
1303 
1304  assert(SCIPexprtreeGetVars(exprtree) != NULL);
1305  assert(SCIPexprGetNChildren(expr) == SCIPexprtreeGetNVars(exprtree));
1306 
1307  monomials = SCIPexprGetMonomials(expr);
1308 
1309  for( i = 0; i < nmonomials; ++i )
1310  {
1311  assert(SCIPexprGetMonomialNFactors(monomials[i]) == 1);
1312  assert(SCIPexprGetMonomialExponents(monomials[i]) != NULL);
1313  assert(SCIPexprGetMonomialExponents(monomials[i])[0] == 1.0);
1314  assert(SCIPexprGetMonomialChildIndices(monomials[i]) != NULL);
1315 
1316  varidx = SCIPexprGetMonomialChildIndices(monomials[i])[0];
1317  assert(varidx >= 0);
1318  assert(varidx < SCIPexprGetNChildren(expr));
1319  assert(SCIPexprGetOperator(SCIPexprGetChildren(expr)[varidx]) == SCIP_EXPR_VARIDX);
1320  assert(SCIPexprGetOpIndex(SCIPexprGetChildren(expr)[varidx]) == varidx); /* assume that child varidx corresponds to variable varidx */
1321 
1322  coef = SCIPexprGetMonomialCoef(monomials[i]);
1323  var = SCIPexprtreeGetVars(exprtree)[varidx];
1324 
1325  SCIP_CALL( SCIPchgVarObj(scip, var, SCIPvarGetObj(var) + coef) );
1326  }
1327  }
1328  else if( degree == 2 )
1329  {
1330  /* insert dummy variable and constraint to represent quadratic part of objective */
1331 
1332  SCIP_VAR* quadobjvar;
1333  SCIP_CONS* quadobjcons;
1334  SCIP_Real lhs;
1335  SCIP_Real rhs;
1336 
1337  SCIP_Real constant;
1338  int nlinvars;
1339  SCIP_VAR** linvars;
1340  SCIP_Real* lincoefs;
1341  int nquadterms;
1342  SCIP_VAR** quadvars1;
1343  SCIP_VAR** quadvars2;
1344  SCIP_Real* quadcoefs;
1345 
1346  SCIP_CALL( SCIPallocBufferArray(scip, &linvars, nmonomials) );
1347  SCIP_CALL( SCIPallocBufferArray(scip, &lincoefs, nmonomials) );
1348  SCIP_CALL( SCIPallocBufferArray(scip, &quadvars1, nmonomials) );
1349  SCIP_CALL( SCIPallocBufferArray(scip, &quadvars2, nmonomials) );
1350  SCIP_CALL( SCIPallocBufferArray(scip, &quadcoefs, nmonomials) );
1351 
1352  getLinearAndQuadraticCoefs(scip, exprtree, &constant, &nlinvars, linvars, lincoefs, &nquadterms, quadvars1, quadvars2, quadcoefs);
1353 
1354  SCIP_CALL( SCIPcreateVar(scip, &quadobjvar, "quadobjvar", -SCIPinfinity(scip), SCIPinfinity(scip), 1.0,
1356  SCIP_CALL( SCIPaddVar(scip, quadobjvar) );
1357 
1358  if ( pipinput->objsense == SCIP_OBJSENSE_MINIMIZE )
1359  {
1360  lhs = -SCIPinfinity(scip);
1361  rhs = -constant;
1362  }
1363  else
1364  {
1365  lhs = -constant;
1366  rhs = SCIPinfinity(scip);
1367  }
1368 
1369  SCIP_CALL( SCIPcreateConsQuadratic(scip, &quadobjcons, "quadobj", nlinvars, linvars, lincoefs, nquadterms, quadvars1, quadvars2, quadcoefs, lhs, rhs,
1370  initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable) );
1371 
1372  SCIP_CALL( SCIPaddLinearVarQuadratic(scip, quadobjcons, quadobjvar, -1.0) );
1373 
1374  SCIP_CALL( SCIPaddCons(scip, quadobjcons) );
1375  SCIPdebugMessage("(line %d) added constraint <%s> to represent quadratic objective: ", pipinput->linenumber, SCIPconsGetName(quadobjcons));
1376  SCIPdebugPrintCons(scip, quadobjcons, NULL);
1377 
1378  SCIP_CALL( SCIPreleaseCons(scip, &quadobjcons) );
1379  SCIP_CALL( SCIPreleaseVar(scip, &quadobjvar) );
1380 
1381  /* free memory */
1382  SCIPfreeBufferArray(scip, &linvars);
1383  SCIPfreeBufferArray(scip, &lincoefs);
1384  SCIPfreeBufferArray(scip, &quadvars1);
1385  SCIPfreeBufferArray(scip, &quadvars2);
1386  SCIPfreeBufferArray(scip, &quadcoefs);
1387  }
1388  else if( degree > 2 )
1389  {
1390  /* insert dummy variable and constraint to represent nonlinear part of objective */
1391 
1392  SCIP_VAR* nonlinobjvar;
1393  SCIP_CONS* nonlinobjcons;
1394  SCIP_Real minusone;
1395  SCIP_Real lhs;
1396  SCIP_Real rhs;
1397 
1398  SCIP_CALL( SCIPcreateVar(scip, &nonlinobjvar, "nonlinobjvar", -SCIPinfinity(scip), SCIPinfinity(scip), 1.0,
1400  SCIP_CALL( SCIPaddVar(scip, nonlinobjvar) );
1401 
1402  minusone = -1.0;
1403 
1404  if ( pipinput->objsense == SCIP_OBJSENSE_MINIMIZE )
1405  {
1406  lhs = -SCIPinfinity(scip);
1407  rhs = 0.0;
1408  }
1409  else
1410  {
1411  lhs = 0.0;
1412  rhs = SCIPinfinity(scip);
1413  }
1414 
1415  SCIP_CALL( SCIPcreateConsNonlinear(scip, &nonlinobjcons, "nonlinobj", 1, &nonlinobjvar, &minusone, 1, &exprtree, NULL, lhs, rhs,
1416  initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, FALSE) );
1417  SCIP_CALL( SCIPexprtreeFree(&exprtree) );
1418 
1419  SCIP_CALL( SCIPaddCons(scip, nonlinobjcons) );
1420  SCIPdebugMessage("(line %d) added constraint <%s> to represent nonlinear objective: ", pipinput->linenumber, SCIPconsGetName(nonlinobjcons));
1421  SCIPdebugPrintCons(scip, nonlinobjcons, NULL);
1422 
1423  SCIP_CALL( SCIPreleaseCons(scip, &nonlinobjcons) );
1424  SCIP_CALL( SCIPreleaseVar(scip, &nonlinobjvar) );
1425  }
1426  }
1427 
1428  if( exprtree != NULL )
1429  {
1430  SCIP_CALL( SCIPexprtreeFree(&exprtree) );
1431  }
1432 
1433  return SCIP_OKAY;
1434 }
1435 
1436 /** reads the constraints section
1437  */
1438 static
1440  SCIP* scip, /**< SCIP data structure */
1441  PIPINPUT* pipinput /**< PIP reading data */
1442  )
1443 {
1444  char name[PIP_MAX_LINELEN];
1445  SCIP_CONS* cons;
1446  SCIP_EXPRTREE* exprtree;
1447  SCIP_EXPR* expr;
1448  int degree;
1449 
1450  SCIP_Real constant;
1451 
1452  int nlinvars;
1453  SCIP_VAR** linvars;
1454  SCIP_Real* lincoefs;
1455 
1456  int nquadcoefs;
1457  SCIP_VAR** quadvars1;
1458  SCIP_VAR** quadvars2;
1459  SCIP_Real* quadcoefs;
1460 
1461  SCIP_Bool newsection;
1462  PIPSENSE sense;
1463  SCIP_Real sidevalue;
1464  SCIP_Real lhs;
1465  SCIP_Real rhs;
1466  SCIP_Bool initial;
1467  SCIP_Bool separate;
1468  SCIP_Bool enforce;
1469  SCIP_Bool check;
1470  SCIP_Bool propagate;
1471  SCIP_Bool local;
1472  SCIP_Bool modifiable;
1473  SCIP_Bool dynamic;
1474  SCIP_Bool removable;
1475  int sidesign;
1476  int nmonomials;
1477 
1478  assert(pipinput != NULL);
1479 
1480  /* read polynomial */
1481  SCIP_CALL( readPolynomial(scip, pipinput, name, &exprtree, &degree, &newsection) );
1482  if ( hasError(pipinput) )
1483  goto TERMINATE;
1484  if ( newsection )
1485  {
1486  if ( exprtree != NULL )
1487  syntaxError(scip, pipinput, "expected constraint sense '<=', '=', or '>='");
1488  goto TERMINATE;
1489  }
1490 
1491  /* read the constraint sense */
1492  if ( !getNextToken(scip, pipinput) || !isSense(pipinput, &sense) )
1493  {
1494  syntaxError(scip, pipinput, "expected constraint sense '<=', '=', or '>='");
1495  goto TERMINATE;
1496  }
1497 
1498  /* read the right hand side */
1499  sidesign = +1;
1500  if ( !getNextToken(scip, pipinput) )
1501  {
1502  syntaxError(scip, pipinput, "missing right hand side");
1503  goto TERMINATE;
1504  }
1505  if ( isSign(pipinput, &sidesign) )
1506  {
1507  if( !getNextToken(scip, pipinput) )
1508  {
1509  syntaxError(scip, pipinput, "missing value of right hand side");
1510  goto TERMINATE;
1511  }
1512  }
1513  if ( !isValue(scip, pipinput, &sidevalue) )
1514  {
1515  syntaxError(scip, pipinput, "expected value as right hand side");
1516  goto TERMINATE;
1517  }
1518  sidevalue *= sidesign;
1519 
1520  /* determine settings */
1521  initial = pipinput->initialconss;
1522  separate = TRUE;
1523  enforce = TRUE;
1524  check = TRUE;
1525  propagate = TRUE;
1526  local = FALSE;
1527  modifiable = FALSE;
1528  dynamic = pipinput->dynamicconss;
1529  removable = pipinput->dynamicrows;
1530 
1531  if( degree > 2 )
1532  {
1533  /* assign the left and right hand side, depending on the constraint sense */
1534  switch ( sense )
1535  {
1536  case PIP_SENSE_GE:
1537  lhs = sidevalue;
1538  rhs = SCIPinfinity(scip);
1539  break;
1540  case PIP_SENSE_LE:
1541  lhs = -SCIPinfinity(scip);
1542  rhs = sidevalue;
1543  break;
1544  case PIP_SENSE_EQ:
1545  lhs = sidevalue;
1546  rhs = sidevalue;
1547  break;
1548  case PIP_SENSE_NOTHING:
1549  default:
1550  SCIPerrorMessage("invalid constraint sense <%d>\n", sense);
1551  return SCIP_INVALIDDATA;
1552  }
1553 
1554  SCIP_CALL( SCIPcreateConsNonlinear(scip, &cons, name, 0, NULL, NULL, 1, &exprtree, NULL, lhs, rhs,
1555  initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, FALSE) );
1556  SCIP_CALL( SCIPexprtreeFree(&exprtree) );
1557  }
1558  else
1559  {
1560  expr = SCIPexprtreeGetRoot(exprtree);
1561  assert(expr != NULL);
1562  assert(SCIPexprGetOperator(expr) == SCIP_EXPR_POLYNOMIAL);
1563  nmonomials = SCIPexprGetNMonomials(expr);
1564 
1565  SCIP_CALL( SCIPallocBufferArray(scip, &linvars, nmonomials) );
1566  SCIP_CALL( SCIPallocBufferArray(scip, &lincoefs, nmonomials) );
1567  SCIP_CALL( SCIPallocBufferArray(scip, &quadvars1, nmonomials) );
1568  SCIP_CALL( SCIPallocBufferArray(scip, &quadvars2, nmonomials) );
1569  SCIP_CALL( SCIPallocBufferArray(scip, &quadcoefs, nmonomials) );
1570 
1571  getLinearAndQuadraticCoefs(scip, exprtree, &constant, &nlinvars, linvars, lincoefs, &nquadcoefs, quadvars1, quadvars2, quadcoefs);
1572 
1573  /* assign the left and right hand side, depending on the constraint sense */
1574  switch( sense )
1575  {
1576  case PIP_SENSE_GE:
1577  lhs = sidevalue - constant;
1578  rhs = SCIPinfinity(scip);
1579  break;
1580  case PIP_SENSE_LE:
1581  lhs = -SCIPinfinity(scip);
1582  rhs = sidevalue - constant;
1583  break;
1584  case PIP_SENSE_EQ:
1585  lhs = sidevalue - constant;
1586  rhs = sidevalue - constant;
1587  break;
1588  case PIP_SENSE_NOTHING:
1589  default:
1590  SCIPerrorMessage("invalid constraint sense <%d>\n", sense);
1591  return SCIP_INVALIDDATA;
1592  }
1593 
1594  if( nquadcoefs == 0 )
1595  {
1596  SCIP_CALL( SCIPcreateConsLinear(scip, &cons, name, nlinvars, linvars, lincoefs, lhs, rhs,
1597  initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, FALSE) );
1598  }
1599  else
1600  {
1601  SCIP_CALL( SCIPcreateConsQuadratic(scip, &cons, name, nlinvars, linvars, lincoefs,
1602  nquadcoefs, quadvars1, quadvars2, quadcoefs, lhs, rhs,
1603  initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable) );
1604  }
1605 
1606  /* free memory */
1607  SCIPfreeBufferArray(scip, &linvars);
1608  SCIPfreeBufferArray(scip, &lincoefs);
1609  SCIPfreeBufferArray(scip, &quadvars1);
1610  SCIPfreeBufferArray(scip, &quadvars2);
1611  SCIPfreeBufferArray(scip, &quadcoefs);
1612  }
1613 
1614  SCIP_CALL( SCIPaddCons(scip, cons) );
1615  SCIPdebugMessage("(line %d) created constraint: ", pipinput->linenumber);
1616  SCIPdebugPrintCons(scip, cons, NULL);
1617  SCIP_CALL( SCIPreleaseCons(scip, &cons) );
1618 
1619  TERMINATE:
1620  if( exprtree != NULL )
1621  {
1622  SCIP_CALL( SCIPexprtreeFree(&exprtree) );
1623  }
1624 
1625  return SCIP_OKAY;
1626 }
1627 
1628 /** reads the bounds section */
1629 static
1631  SCIP* scip, /**< SCIP data structure */
1632  PIPINPUT* pipinput /**< PIP reading data */
1633  )
1634 {
1635  assert(pipinput != NULL);
1636 
1637  while( getNextToken(scip, pipinput) )
1638  {
1639  SCIP_VAR* var;
1640  SCIP_Real value;
1641  SCIP_Real lb;
1642  SCIP_Real ub;
1643  int sign;
1644  SCIP_Bool hassign;
1645  PIPSENSE leftsense;
1646 
1647  /* check if we reached a new section */
1648  if( isNewSection(scip, pipinput) )
1649  return SCIP_OKAY;
1650 
1651  /* default bounds are [0,+inf] */
1652  lb = 0.0;
1653  ub = SCIPinfinity(scip);
1654  leftsense = PIP_SENSE_NOTHING;
1655 
1656  /* check if the first token is a sign */
1657  sign = +1;
1658  hassign = isSign(pipinput, &sign);
1659  if( hassign && !getNextToken(scip, pipinput) )
1660  {
1661  syntaxError(scip, pipinput, "expected value");
1662  return SCIP_OKAY;
1663  }
1664 
1665  /* the first token must be either a value or a variable name */
1666  if( isValue(scip, pipinput, &value) )
1667  {
1668  /* first token is a value: the second token must be a sense */
1669  if( !getNextToken(scip, pipinput) || !isSense(pipinput, &leftsense) )
1670  {
1671  syntaxError(scip, pipinput, "expected bound sense '<=', '=', or '>='");
1672  return SCIP_OKAY;
1673  }
1674 
1675  /* update the bound corresponding to the sense */
1676  switch( leftsense )
1677  {
1678  case PIP_SENSE_GE:
1679  ub = sign * value;
1680  break;
1681  case PIP_SENSE_LE:
1682  lb = sign * value;
1683  break;
1684  case PIP_SENSE_EQ:
1685  lb = sign * value;
1686  ub = sign * value;
1687  break;
1688  case PIP_SENSE_NOTHING:
1689  default:
1690  SCIPerrorMessage("invalid bound sense <%d>\n", leftsense);
1691  return SCIP_INVALIDDATA;
1692  }
1693  }
1694  else if( hassign )
1695  {
1696  syntaxError(scip, pipinput, "expected value");
1697  return SCIP_OKAY;
1698  }
1699  else
1700  pushToken(pipinput);
1701 
1702  /* the next token must be a variable name */
1703  if( !getNextToken(scip, pipinput) )
1704  {
1705  syntaxError(scip, pipinput, "expected variable name");
1706  return SCIP_OKAY;
1707  }
1708  SCIP_CALL( getVariable(scip, pipinput->token, pipinput->dynamiccols, &var, NULL) );
1709 
1710  /* the next token might be another sense, or the word "free" */
1711  if( getNextToken(scip, pipinput) )
1712  {
1713  PIPSENSE rightsense;
1714 
1715  if( isSense(pipinput, &rightsense) )
1716  {
1717  /* check, if the senses fit */
1718  if( leftsense == PIP_SENSE_NOTHING
1719  || (leftsense == PIP_SENSE_LE && rightsense == PIP_SENSE_LE)
1720  || (leftsense == PIP_SENSE_GE && rightsense == PIP_SENSE_GE) )
1721  {
1722  if( !getNextToken(scip, pipinput) )
1723  {
1724  syntaxError(scip, pipinput, "expected value or sign");
1725  return SCIP_OKAY;
1726  }
1727 
1728  /* check if the next token is a sign */
1729  sign = +1;
1730  hassign = isSign(pipinput, &sign);
1731  if( hassign && !getNextToken(scip, pipinput) )
1732  {
1733  syntaxError(scip, pipinput, "expected value");
1734  return SCIP_OKAY;
1735  }
1736 
1737  /* the next token must be a value */
1738  if( !isValue(scip, pipinput, &value) )
1739  {
1740  syntaxError(scip, pipinput, "expected value");
1741  return SCIP_OKAY;
1742  }
1743 
1744  /* update the bound corresponding to the sense */
1745  switch( rightsense )
1746  {
1747  case PIP_SENSE_GE:
1748  lb = sign * value;
1749  break;
1750  case PIP_SENSE_LE:
1751  ub = sign * value;
1752  break;
1753  case PIP_SENSE_EQ:
1754  lb = sign * value;
1755  ub = sign * value;
1756  break;
1757  case PIP_SENSE_NOTHING:
1758  default:
1759  SCIPerrorMessage("invalid bound sense <%d>\n", leftsense);
1760  return SCIP_INVALIDDATA;
1761  }
1762  }
1763  else
1764  {
1765  syntaxError(scip, pipinput, "the two bound senses do not fit");
1766  return SCIP_OKAY;
1767  }
1768  }
1769  else if( strcasecmp(pipinput->token, "FREE") == 0 )
1770  {
1771  if( leftsense != PIP_SENSE_NOTHING )
1772  {
1773  syntaxError(scip, pipinput, "variable with bound is marked as 'free'");
1774  return SCIP_OKAY;
1775  }
1776  lb = -SCIPinfinity(scip);
1777  ub = SCIPinfinity(scip);
1778  }
1779  else
1780  {
1781  /* the token was no sense: push it back to the token stack */
1782  pushToken(pipinput);
1783  }
1784  }
1785 
1786  /* change the bounds of the variable if bounds have been given (do not destroy earlier specification of bounds) */
1787  if ( lb != 0.0 )
1788  SCIP_CALL( SCIPchgVarLb(scip, var, lb) );
1789  /*lint --e{777}*/
1790  if ( ub != SCIPinfinity(scip) )
1791  SCIP_CALL( SCIPchgVarUb(scip, var, ub) );
1792  SCIPdebugMessage("(line %d) new bounds: <%s>[%g,%g]\n", pipinput->linenumber, SCIPvarGetName(var),
1794  }
1795 
1796  return SCIP_OKAY;
1797 }
1798 
1799 /** reads the generals section */
1800 static
1802  SCIP* scip, /**< SCIP data structure */
1803  PIPINPUT* pipinput /**< PIP reading data */
1804  )
1805 {
1806  assert(pipinput != NULL);
1807 
1808  while( getNextToken(scip, pipinput) )
1809  {
1810  SCIP_VAR* var;
1811  SCIP_Bool created;
1812  SCIP_Bool infeasible;
1813 
1814  /* check if we reached a new section */
1815  if( isNewSection(scip, pipinput) )
1816  return SCIP_OKAY;
1817 
1818  /* the token must be the name of an existing variable */
1819  SCIP_CALL( getVariable(scip, pipinput->token, pipinput->dynamiccols, &var, &created) );
1820  if( created )
1821  {
1822  syntaxError(scip, pipinput, "unknown variable in generals section");
1823  return SCIP_OKAY;
1824  }
1825 
1826  /* mark the variable to be integral */
1827  SCIP_CALL( SCIPchgVarType(scip, var, SCIP_VARTYPE_INTEGER, &infeasible) );
1828  /* don't assert feasibility here because the presolver will and should detect a infeasibility */
1829  }
1830 
1831  return SCIP_OKAY;
1832 }
1833 
1834 /** reads the binaries section */
1835 static
1837  SCIP* scip, /**< SCIP data structure */
1838  PIPINPUT* pipinput /**< PIP reading data */
1839  )
1840 {
1841  assert(pipinput != NULL);
1842 
1843  while( getNextToken(scip, pipinput) )
1844  {
1845  SCIP_VAR* var;
1846  SCIP_Bool created;
1847  SCIP_Bool infeasible;
1848 
1849  /* check if we reached a new section */
1850  if( isNewSection(scip, pipinput) )
1851  return SCIP_OKAY;
1852 
1853  /* the token must be the name of an existing variable */
1854  SCIP_CALL( getVariable(scip, pipinput->token, pipinput->dynamiccols, &var, &created) );
1855  if( created )
1856  {
1857  syntaxError(scip, pipinput, "unknown variable in binaries section");
1858  return SCIP_OKAY;
1859  }
1860 
1861  /* mark the variable to be binary and change its bounds appropriately */
1862  if( SCIPvarGetLbGlobal(var) < 0.0 )
1863  {
1864  SCIP_CALL( SCIPchgVarLb(scip, var, 0.0) );
1865  }
1866  if( SCIPvarGetUbGlobal(var) > 1.0 )
1867  {
1868  SCIP_CALL( SCIPchgVarUb(scip, var, 1.0) );
1869  }
1870  SCIP_CALL( SCIPchgVarType(scip, var, SCIP_VARTYPE_BINARY, &infeasible) );
1871  /* don't assert feasibility here because the presolver will and should detect a infeasibility */
1872  }
1873 
1874  return SCIP_OKAY;
1875 }
1876 
1877 /** reads a PIP file
1878  */
1879 static
1881  SCIP* scip, /**< SCIP data structure */
1882  PIPINPUT* pipinput, /**< PIP reading data */
1883  const char* filename /**< name of the input file */
1884  )
1885 {
1886  assert(pipinput != NULL);
1887 
1888  /* open file */
1889  pipinput->file = SCIPfopen(filename, "r");
1890  if( pipinput->file == NULL )
1891  {
1892  SCIPerrorMessage("cannot open file <%s> for reading\n", filename);
1893  SCIPprintSysError(filename);
1894  return SCIP_NOFILE;
1895  }
1896 
1897  /* create problem */
1898  SCIP_CALL( SCIPcreateProb(scip, filename, NULL, NULL, NULL, NULL, NULL, NULL, NULL) );
1899 
1900  /* parse the file */
1901  pipinput->section = PIP_START;
1902  while( pipinput->section != PIP_END && !hasError(pipinput) )
1903  {
1904  switch( pipinput->section )
1905  {
1906  case PIP_START:
1907  SCIP_CALL( readStart(scip, pipinput) );
1908  break;
1909 
1910  case PIP_OBJECTIVE:
1911  SCIP_CALL( readObjective(scip, pipinput) );
1912  break;
1913 
1914  case PIP_CONSTRAINTS:
1915  SCIP_CALL( readConstraints(scip, pipinput) );
1916  break;
1917 
1918  case PIP_BOUNDS:
1919  SCIP_CALL( readBounds(scip, pipinput) );
1920  break;
1921 
1922  case PIP_GENERALS:
1923  SCIP_CALL( readGenerals(scip, pipinput) );
1924  break;
1925 
1926  case PIP_BINARIES:
1927  SCIP_CALL( readBinaries(scip, pipinput) );
1928  break;
1929 
1930  case PIP_END: /* this is already handled in the while() loop */
1931  default:
1932  SCIPerrorMessage("invalid PIP file section <%d>\n", pipinput->section);
1933  return SCIP_INVALIDDATA;
1934  }
1935  }
1936 
1937  /* close file */
1938  SCIPfclose(pipinput->file);
1939 
1940  return SCIP_OKAY;
1941 }
1942 
1943 
1944 /*
1945  * Local methods (for writing)
1946  */
1947 
1948 /** hash key retrieval function for variables */
1949 static
1950 SCIP_DECL_HASHGETKEY(hashGetKeyVar)
1951 { /*lint --e{715}*/
1952  return elem;
1953 }
1954 
1955 /** returns TRUE iff the indices of both variables are equal */
1956 static
1957 SCIP_DECL_HASHKEYEQ(hashKeyEqVar)
1958 { /*lint --e{715}*/
1959  if ( key1 == key2 )
1960  return TRUE;
1961  return FALSE;
1962 }
1963 
1964 /** returns the hash value of the key */
1965 static
1966 SCIP_DECL_HASHKEYVAL(hashKeyValVar)
1967 { /*lint --e{715}*/
1968  assert( SCIPvarGetIndex((SCIP_VAR*) key) >= 0 );
1969  return (unsigned int) SCIPvarGetIndex((SCIP_VAR*) key);
1970 }
1971 
1972 /** transforms given variables, scalars, and constant to the corresponding active variables, scalars, and constant */
1973 static
1975  SCIP* scip, /**< SCIP data structure */
1976  SCIP_VAR** vars, /**< vars array to get active variables for */
1977  SCIP_Real* scalars, /**< scalars a_1, ..., a_n in linear sum a_1*x_1 + ... + a_n*x_n + c */
1978  int* nvars, /**< pointer to number of variables and values in vars and vals array */
1979  SCIP_Real* constant, /**< pointer to constant c in linear sum a_1*x_1 + ... + a_n*x_n + c */
1980  SCIP_Bool transformed /**< transformed constraint? */
1981  )
1982 {
1983  int requiredsize;
1984  int v;
1985 
1986  assert( scip != NULL );
1987  assert( vars != NULL );
1988  assert( scalars != NULL );
1989  assert( nvars != NULL );
1990  assert( constant != NULL );
1991 
1992  if( transformed )
1993  {
1994  SCIP_CALL( SCIPgetProbvarLinearSum(scip, vars, scalars, nvars, *nvars, constant, &requiredsize, TRUE) );
1995 
1996  if( requiredsize > *nvars )
1997  {
1998  SCIP_CALL( SCIPreallocBufferArray(scip, &vars, requiredsize) );
1999  SCIP_CALL( SCIPreallocBufferArray(scip, &scalars, requiredsize) );
2000 
2001  SCIP_CALL( SCIPgetProbvarLinearSum(scip, vars, scalars, nvars, requiredsize, constant, &requiredsize, TRUE) );
2002  assert( requiredsize <= *nvars );
2003  }
2004  }
2005  else
2006  {
2007  for( v = 0; v < *nvars; ++v )
2008  SCIP_CALL( SCIPvarGetOrigvarSum(&vars[v], &scalars[v], constant) );
2009  }
2010  return SCIP_OKAY;
2011 }
2012 
2013 /** clears the given line buffer */
2014 static
2016  char* linebuffer, /**< line */
2017  int* linecnt /**< number of characters in line */
2018  )
2019 {
2020  assert( linebuffer != NULL );
2021  assert( linecnt != NULL );
2022 
2023  (*linecnt) = 0;
2024  linebuffer[0] = '\0';
2025 }
2026 
2027 /** ends the given line with '\\0' and prints it to the given file stream */
2028 static
2029 void endLine(
2030  SCIP* scip, /**< SCIP data structure */
2031  FILE* file, /**< output file (or NULL for standard output) */
2032  char* linebuffer, /**< line */
2033  int* linecnt /**< number of characters in line */
2034  )
2035 {
2036  assert( scip != NULL );
2037  assert( linebuffer != NULL );
2038  assert( linecnt != NULL );
2039 
2040  if( (*linecnt) > 0 )
2041  {
2042  linebuffer[(*linecnt)] = '\0';
2043  SCIPinfoMessage(scip, file, "%s\n", linebuffer);
2044  clearLine(linebuffer, linecnt);
2045  }
2046 }
2047 
2048 /** appends extension to line and prints it to the give file stream if the
2049  * line exceeded the length given in the define PIP_PRINTLEN */
2050 static
2052  SCIP* scip, /**< SCIP data structure */
2053  FILE* file, /**< output file (or NULL for standard output) */
2054  char* linebuffer, /**< line */
2055  int* linecnt, /**< number of characters in line */
2056  const char* extension /**< string to extent the line */
2057  )
2058 {
2059  assert( scip != NULL );
2060  assert( linebuffer != NULL );
2061  assert( linecnt != NULL );
2062  assert( extension != NULL );
2063  assert( strlen(linebuffer) + strlen(extension) < PIP_MAX_PRINTLEN );
2064 
2065  /* NOTE: avoid
2066  * sprintf(linebuffer, "%s%s", linebuffer, extension);
2067  * because of overlapping memory areas in memcpy used in sprintf.
2068  */
2069  strncat(linebuffer, extension, PIP_MAX_PRINTLEN - strlen(linebuffer));
2070 
2071  (*linecnt) += (int) strlen(extension);
2072 
2073  SCIPdebugMessage("linebuffer <%s>, length = %lu\n", linebuffer, (unsigned long)strlen(linebuffer));
2074 
2075  if( (*linecnt) > PIP_PRINTLEN )
2076  endLine(scip, file, linebuffer, linecnt);
2077 }
2078 
2079 
2080 /* print row in PIP format to file stream */
2081 static
2083  SCIP* scip, /**< SCIP data structure */
2084  FILE* file, /**< output file (or NULL for standard output) */
2085  const char* rowname, /**< row name */
2086  const char* rownameextension, /**< row name extension */
2087  const char* type, /**< row type ("=", "<=", or ">=") */
2088  SCIP_VAR** linvars, /**< array of linear variables */
2089  SCIP_Real* linvals, /**< array of linear coefficient values */
2090  int nlinvars, /**< number of linear variables */
2091  SCIP_QUADVARTERM* quadvarterms, /**< quadratic variable terms */
2092  int nquadvarterms, /**< number of quadratic variable terms */
2093  SCIP_BILINTERM* bilinterms, /**< bilinear terms */
2094  int nbilinterms, /**< number of bilinear terms */
2095  SCIP_Real rhs /**< right hand side */
2096  )
2097 {
2098  int v;
2099  char linebuffer[PIP_MAX_PRINTLEN] = { '\0' };
2100  int linecnt;
2101 
2102  SCIP_VAR* var;
2103  char varname[PIP_MAX_NAMELEN];
2104  char varname2[PIP_MAX_NAMELEN];
2105  char consname[PIP_MAX_NAMELEN + 1]; /* an extra character for ':' */
2106  char buffer[PIP_MAX_PRINTLEN];
2107 
2108  assert( scip != NULL );
2109  assert( strcmp(type, "=") == 0 || strcmp(type, "<=") == 0 || strcmp(type, ">=") == 0 );
2110  assert( nlinvars == 0 || (linvars != NULL && linvals != NULL) );
2111  assert( nquadvarterms == 0 || quadvarterms != NULL );
2112 
2113  /* if there is a bilinear term, then there need to be at least two quadratic variables */
2114  assert( nbilinterms == 0 || (bilinterms != NULL && nquadvarterms >= 2) );
2115 
2116  clearLine(linebuffer, &linecnt);
2117 
2118  /* start each line with a space */
2119  appendLine(scip, file, linebuffer, &linecnt, " ");
2120 
2121  /* print row name */
2122  if ( strlen(rowname) > 0 || strlen(rownameextension) > 0 )
2123  {
2124  (void) SCIPsnprintf(consname, PIP_MAX_NAMELEN + 1, "%s%s:", rowname, rownameextension);
2125  appendLine(scip, file, linebuffer, &linecnt, consname);
2126  }
2127 
2128  /* print coefficients */
2129  for( v = 0; v < nlinvars; ++v )
2130  {
2131  var = linvars[v];
2132  assert( var != NULL );
2133 
2134  /* we start a new line; therefore we tab this line */
2135  if ( linecnt == 0 )
2136  appendLine(scip, file, linebuffer, &linecnt, " ");
2137 
2138  (void) SCIPsnprintf(varname, PIP_MAX_NAMELEN, "%s", SCIPvarGetName(var));
2139  (void) SCIPsnprintf(buffer, PIP_MAX_PRINTLEN, " %+.15g %s", linvals[v], varname);
2140 
2141  appendLine(scip, file, linebuffer, &linecnt, buffer);
2142  }
2143 
2144  /* print quadratic part */
2145  if( nquadvarterms > 0 )
2146  {
2147  /* print linear coefficients of quadratic variables */
2148  for( v = 0; v < nquadvarterms; ++v )
2149  {
2150  if( quadvarterms[v].lincoef == 0.0 )
2151  continue;
2152 
2153  /* we start a new line; therefore we tab this line */
2154  if (linecnt == 0 )
2155  appendLine(scip, file, linebuffer, &linecnt, " ");
2156 
2157  (void) SCIPsnprintf(varname, PIP_MAX_NAMELEN, "%s", SCIPvarGetName(quadvarterms[v].var));
2158  (void) SCIPsnprintf(buffer, PIP_MAX_PRINTLEN, " %+.15g %s", quadvarterms[v].lincoef, varname);
2159 
2160  appendLine(scip, file, linebuffer, &linecnt, buffer);
2161  }
2162 
2163  /* start quadratic part */
2164 
2165  /* print square terms */
2166  for( v = 0; v < nquadvarterms; ++v )
2167  {
2168  if( quadvarterms[v].sqrcoef == 0.0 )
2169  continue;
2170 
2171  /* we start a new line; therefore we tab this line */
2172  if (linecnt == 0 )
2173  appendLine(scip, file, linebuffer, &linecnt, " ");
2174 
2175  (void) SCIPsnprintf(varname, PIP_MAX_NAMELEN, "%s", SCIPvarGetName(quadvarterms[v].var));
2176  (void) SCIPsnprintf(buffer, PIP_MAX_PRINTLEN, " %+.15g %s^2", quadvarterms[v].sqrcoef, varname);
2177 
2178  appendLine(scip, file, linebuffer, &linecnt, buffer);
2179  }
2180 
2181  /* print bilinear terms */
2182  for( v = 0; v < nbilinterms; ++v )
2183  {
2184  /* we start a new line; therefore we tab this line */
2185  if (linecnt == 0 )
2186  appendLine(scip, file, linebuffer, &linecnt, " ");
2187 
2188  (void) SCIPsnprintf(varname, PIP_MAX_NAMELEN, "%s", SCIPvarGetName(bilinterms[v].var1));
2189  (void) SCIPsnprintf(varname2, PIP_MAX_NAMELEN, "%s", SCIPvarGetName(bilinterms[v].var2));
2190  (void) SCIPsnprintf(buffer, PIP_MAX_PRINTLEN, " %+.15g %s * %s", bilinterms[v].coef, varname, varname2);
2191 
2192  appendLine(scip, file, linebuffer, &linecnt, buffer);
2193  }
2194  }
2195 
2196  /* print right hand side */
2197  if( SCIPisZero(scip, rhs) )
2198  rhs = 0.0;
2199 
2200  (void) SCIPsnprintf(buffer, PIP_MAX_PRINTLEN, " %s %+.15g", type, rhs);
2201 
2202  /* we start a new line; therefore we tab this line */
2203  if (linecnt == 0 )
2204  appendLine(scip, file, linebuffer, &linecnt, " ");
2205  appendLine(scip, file, linebuffer, &linecnt, buffer);
2206 
2207  endLine(scip, file, linebuffer, &linecnt);
2208 }
2209 
2210 
2211 /* print row in PIP format to file stream */
2212 static
2214  SCIP* scip, /**< SCIP data structure */
2215  FILE* file, /**< output file (or NULL for standard output) */
2216  const char* rowname, /**< row name */
2217  const char* rownameextension, /**< row name extension */
2218  const char* type, /**< row type ("=", "<=", or ">=") */
2219  SCIP_VAR** linvars, /**< array of linear variables */
2220  SCIP_Real* linvals, /**< array of linear coefficient values */
2221  int nlinvars, /**< number of linear variables */
2222  SCIP_EXPRTREE** exprtrees, /**< expression trees */
2223  SCIP_Real* exprtreecoefs, /**< coefficients of expression trees */
2224  int nexprtrees, /**< number of expression trees */
2225  SCIP_Real rhs /**< right hand side */
2226  )
2227 {
2228  int v;
2229  int c;
2230  int e;
2231  char linebuffer[PIP_MAX_PRINTLEN] = { '\0' };
2232  int linecnt;
2233 
2234  SCIP_VAR* var;
2235  char varname[PIP_MAX_NAMELEN];
2236  char varname2[PIP_MAX_NAMELEN];
2237  char consname[PIP_MAX_NAMELEN + 1]; /* an extra character for ':' */
2238  char buffer[PIP_MAX_PRINTLEN];
2239 
2240  assert( scip != NULL );
2241  assert( strcmp(type, "=") == 0 || strcmp(type, "<=") == 0 || strcmp(type, ">=") == 0 );
2242  assert( nlinvars == 0 || (linvars != NULL && linvals != NULL) );
2243  assert( nexprtrees == 0 || exprtrees != NULL );
2244  assert( nexprtrees == 0 || exprtreecoefs != NULL );
2245 
2246  clearLine(linebuffer, &linecnt);
2247 
2248  /* start each line with a space */
2249  appendLine(scip, file, linebuffer, &linecnt, " ");
2250 
2251  /* print row name */
2252  if ( strlen(rowname) > 0 || strlen(rownameextension) > 0 )
2253  {
2254  (void) SCIPsnprintf(consname, PIP_MAX_NAMELEN + 1, "%s%s:", rowname, rownameextension);
2255  appendLine(scip, file, linebuffer, &linecnt, consname);
2256  }
2257 
2258  /* print coefficients */
2259  for( v = 0; v < nlinvars; ++v )
2260  {
2261  var = linvars[v];
2262  assert( var != NULL );
2263 
2264  /* we start a new line; therefore we tab this line */
2265  if ( linecnt == 0 )
2266  appendLine(scip, file, linebuffer, &linecnt, " ");
2267 
2268  (void) SCIPsnprintf(varname, PIP_MAX_NAMELEN, "%s", SCIPvarGetName(var));
2269  (void) SCIPsnprintf(buffer, PIP_MAX_PRINTLEN, " %+.15g %s", linvals[v], varname);
2270 
2271  appendLine(scip, file, linebuffer, &linecnt, buffer);
2272  }
2273 
2274  /* print nonlinear part */
2275  for( e = 0; e < nexprtrees; ++e )
2276  {
2277  SCIP_VAR** vars;
2278  SCIP_EXPR* expr;
2279  SCIP_EXPR** children;
2280  int nchildren;
2281 
2282  vars = SCIPexprtreeGetVars(exprtrees[e]);
2283  expr = SCIPexprtreeGetRoot(exprtrees[e]);
2284  children = SCIPexprGetChildren(expr);
2285  nchildren = SCIPexprGetNChildren(expr);
2286  assert(nchildren == 0 || children != NULL);
2287 
2288  /* we start a new line; therefore we tab this line */
2289  if( linecnt == 0 )
2290  appendLine(scip, file, linebuffer, &linecnt, " ");
2291 
2292  /* assert that all children of expr correspond to variables */
2293 #ifndef NDEBUG
2294  for( c = 0; c < nchildren; ++c )
2295  {
2296  assert(SCIPexprGetOperator(children[c]) == SCIP_EXPR_VARIDX);
2297  assert(SCIPexprGetOpIndex(children[c]) >= 0);
2298  assert(SCIPexprGetOpIndex(children[c]) < SCIPexprtreeGetNVars(exprtrees[e]));
2299  }
2300 #endif
2301 
2302  switch( SCIPexprGetOperator(expr) )
2303  {
2304  case SCIP_EXPR_CONST:
2305  {
2306  (void) SCIPsnprintf(buffer, PIP_MAX_PRINTLEN, " %+.15g", exprtreecoefs[e] * SCIPexprGetOpReal(expr));
2307  appendLine(scip, file, linebuffer, &linecnt, buffer);
2308 
2309  break;
2310  }
2311 
2312  case SCIP_EXPR_VARIDX:
2313  {
2314  assert(SCIPexprGetOpIndex(expr) >= 0);
2315  assert(SCIPexprGetOpIndex(expr) < SCIPexprtreeGetNVars(exprtrees[e]));
2316  (void) SCIPsnprintf(varname, PIP_MAX_NAMELEN, "%s", SCIPvarGetName(vars[SCIPexprGetOpIndex(expr)]));
2317  (void) SCIPsnprintf(buffer, PIP_MAX_PRINTLEN, " %+.15g %s", exprtreecoefs[e], varname);
2318 
2319  appendLine(scip, file, linebuffer, &linecnt, buffer);
2320  break;
2321  }
2322 
2323  case SCIP_EXPR_PLUS:
2324  {
2325  (void) SCIPsnprintf(varname, PIP_MAX_NAMELEN, "%s", SCIPvarGetName(vars[SCIPexprGetOpIndex(children[0])]));
2326  (void) SCIPsnprintf(varname2, PIP_MAX_NAMELEN, "%s", SCIPvarGetName(vars[SCIPexprGetOpIndex(children[1])]));
2327  (void) SCIPsnprintf(buffer, PIP_MAX_PRINTLEN, " %+.15g %s %+.15g %s", exprtreecoefs[e], varname, exprtreecoefs[e], varname2);
2328 
2329  appendLine(scip, file, linebuffer, &linecnt, buffer);
2330  break;
2331  }
2332 
2333  case SCIP_EXPR_MINUS:
2334  {
2335  (void) SCIPsnprintf(varname, PIP_MAX_NAMELEN, "%s", SCIPvarGetName(vars[SCIPexprGetOpIndex(children[0])]));
2336  (void) SCIPsnprintf(varname2, PIP_MAX_NAMELEN, "%s", SCIPvarGetName(vars[SCIPexprGetOpIndex(children[1])]));
2337  (void) SCIPsnprintf(buffer, PIP_MAX_PRINTLEN, " %+.15g %s %+.15g %s", exprtreecoefs[e], varname, -exprtreecoefs[e], varname2);
2338 
2339  appendLine(scip, file, linebuffer, &linecnt, buffer);
2340  break;
2341  }
2342 
2343  case SCIP_EXPR_MUL:
2344  {
2345  (void) SCIPsnprintf(varname, PIP_MAX_NAMELEN, "%s", SCIPvarGetName(vars[SCIPexprGetOpIndex(children[0])]));
2346  (void) SCIPsnprintf(varname2, PIP_MAX_NAMELEN, "%s", SCIPvarGetName(vars[SCIPexprGetOpIndex(children[1])]));
2347  (void) SCIPsnprintf(buffer, PIP_MAX_PRINTLEN, " %+.15g %s %s", exprtreecoefs[e], varname, varname2);
2348 
2349  appendLine(scip, file, linebuffer, &linecnt, buffer);
2350  break;
2351  }
2352 
2353  case SCIP_EXPR_SQUARE:
2354  {
2355  (void) SCIPsnprintf(varname, PIP_MAX_NAMELEN, "%s", SCIPvarGetName(vars[SCIPexprGetOpIndex(children[0])]));
2356  (void) SCIPsnprintf(buffer, PIP_MAX_PRINTLEN, " %+.15g %s^2", exprtreecoefs[e], varname);
2357 
2358  appendLine(scip, file, linebuffer, &linecnt, buffer);
2359  break;
2360  }
2361 
2362  case SCIP_EXPR_SQRT:
2363  {
2364  (void) SCIPsnprintf(varname, PIP_MAX_NAMELEN, "%s", SCIPvarGetName(vars[SCIPexprGetOpIndex(children[0])]));
2365  (void) SCIPsnprintf(buffer, PIP_MAX_PRINTLEN, " %+.15g %s^0.5", exprtreecoefs[e], varname);
2366 
2367  appendLine(scip, file, linebuffer, &linecnt, buffer);
2368  break;
2369  }
2370 
2371  case SCIP_EXPR_INTPOWER:
2372  {
2373  (void) SCIPsnprintf(varname, PIP_MAX_NAMELEN, "%s", SCIPvarGetName(vars[SCIPexprGetOpIndex(children[0])]));
2374  (void) SCIPsnprintf(buffer, PIP_MAX_PRINTLEN, " %+.15g %s^%d", exprtreecoefs[e], varname, SCIPexprGetIntPowerExponent(expr));
2375 
2376  appendLine(scip, file, linebuffer, &linecnt, buffer);
2377  break;
2378  }
2379 
2380  case SCIP_EXPR_REALPOWER:
2381  {
2382  (void) SCIPsnprintf(varname, PIP_MAX_NAMELEN, "%s", SCIPvarGetName(vars[SCIPexprGetOpIndex(children[0])]));
2383  (void) SCIPsnprintf(buffer, PIP_MAX_PRINTLEN, " %+.15g %s^%.15g", exprtreecoefs[e], varname, SCIPexprGetRealPowerExponent(expr));
2384 
2385  appendLine(scip, file, linebuffer, &linecnt, buffer);
2386  break;
2387  }
2388 
2389  case SCIP_EXPR_SUM:
2390  {
2391  for( c = 0; c < nchildren; ++c )
2392  {
2393  /* we start a new line; therefore we tab this line */
2394  if( linecnt == 0 )
2395  appendLine(scip, file, linebuffer, &linecnt, " ");
2396 
2397  (void) SCIPsnprintf(varname, PIP_MAX_NAMELEN, "%s", SCIPvarGetName(vars[SCIPexprGetOpIndex(children[c])]));
2398  (void) SCIPsnprintf(buffer, PIP_MAX_PRINTLEN, " %+.15g %s", exprtreecoefs[e], varname);
2399 
2400  appendLine(scip, file, linebuffer, &linecnt, buffer);
2401  }
2402 
2403  break;
2404  }
2405 
2406  case SCIP_EXPR_PRODUCT:
2407  {
2408  (void) SCIPsnprintf(buffer, PIP_MAX_PRINTLEN, " %+.15g", exprtreecoefs[e]);
2409  appendLine(scip, file, linebuffer, &linecnt, buffer);
2410 
2411  for( c = 0; c < nchildren; ++c )
2412  {
2413  /* we start a new line; therefore we tab this line */
2414  if( linecnt == 0 )
2415  appendLine(scip, file, linebuffer, &linecnt, " ");
2416 
2417  (void) SCIPsnprintf(varname, PIP_MAX_NAMELEN, " %s", SCIPvarGetName(vars[SCIPexprGetOpIndex(children[c])]));
2418  (void) SCIPsnprintf(buffer, PIP_MAX_PRINTLEN, varname);
2419 
2420  appendLine(scip, file, linebuffer, &linecnt, buffer);
2421  }
2422 
2423  break;
2424  }
2425 
2426  case SCIP_EXPR_LINEAR:
2427  {
2428  if( SCIPexprGetLinearConstant(expr) != 0.0 )
2429  {
2430  (void) SCIPsnprintf(buffer, PIP_MAX_PRINTLEN, " %+.15g ", exprtreecoefs[e] * SCIPexprGetLinearConstant(expr));
2431  appendLine(scip, file, linebuffer, &linecnt, buffer);
2432  }
2433 
2434  for( c = 0; c < nchildren; ++c )
2435  {
2436  /* we start a new line; therefore we tab this line */
2437  if( linecnt == 0 )
2438  appendLine(scip, file, linebuffer, &linecnt, " ");
2439 
2440  (void) SCIPsnprintf(varname, PIP_MAX_NAMELEN, "%s", SCIPvarGetName(vars[SCIPexprGetOpIndex(children[c])]));
2441  (void) SCIPsnprintf(buffer, PIP_MAX_PRINTLEN, " %+.15g %s", exprtreecoefs[e] * SCIPexprGetLinearCoefs(expr)[c], varname);
2442 
2443  appendLine(scip, file, linebuffer, &linecnt, buffer);
2444  }
2445 
2446  break;
2447  }
2448 
2449  case SCIP_EXPR_QUADRATIC:
2450  {
2451  int q;
2452 
2453  if( SCIPexprGetQuadConstant(expr) != 0.0 )
2454  {
2455  (void) SCIPsnprintf(buffer, PIP_MAX_PRINTLEN, " %+.15g ", exprtreecoefs[e] * SCIPexprGetQuadConstant(expr));
2456  appendLine(scip, file, linebuffer, &linecnt, buffer);
2457  }
2458 
2459  if( SCIPexprGetQuadLinearCoefs(expr) != NULL )
2460  {
2461  for( c = 0; c < nchildren; ++c )
2462  {
2463  if( SCIPexprGetQuadLinearCoefs(expr)[c] == 0.0 )
2464  continue;
2465 
2466  /* we start a new line; therefore we tab this line */
2467  if( linecnt == 0 )
2468  appendLine(scip, file, linebuffer, &linecnt, " ");
2469 
2470  (void) SCIPsnprintf(varname, PIP_MAX_NAMELEN, "%s", SCIPvarGetName(vars[SCIPexprGetOpIndex(children[c])]));
2471  (void) SCIPsnprintf(buffer, PIP_MAX_PRINTLEN, " %+.15g %s", exprtreecoefs[e] * SCIPexprGetQuadLinearCoefs(expr)[c], varname);
2472 
2473  appendLine(scip, file, linebuffer, &linecnt, buffer);
2474  }
2475  }
2476 
2477  for( q = 0; q < SCIPexprGetNQuadElements(expr); ++q )
2478  {
2479  /* we start a new line; therefore we tab this line */
2480  if( linecnt == 0 )
2481  appendLine(scip, file, linebuffer, &linecnt, " ");
2482 
2483  (void) SCIPsnprintf(varname, PIP_MAX_NAMELEN, "%s", SCIPvarGetName(vars[SCIPexprGetOpIndex(children[SCIPexprGetQuadElements(expr)[q].idx1])]));
2484 
2485  if( SCIPexprGetQuadElements(expr)[q].idx1 == SCIPexprGetQuadElements(expr)[q].idx2 )
2486  {
2487  /* square term */
2488  (void) SCIPsnprintf(buffer, PIP_MAX_PRINTLEN, " %+.15g %s^2", exprtreecoefs[e] * SCIPexprGetQuadElements(expr)[q].coef, varname);
2489  }
2490  else
2491  {
2492  /* bilinear term */
2493  (void) SCIPsnprintf(varname2, PIP_MAX_NAMELEN, "%s", SCIPvarGetName(vars[SCIPexprGetOpIndex(children[SCIPexprGetQuadElements(expr)[q].idx2])]));
2494  (void) SCIPsnprintf(buffer, PIP_MAX_PRINTLEN, " %+.15g %s %s", exprtreecoefs[e] * SCIPexprGetQuadElements(expr)[q].coef, varname, varname2);
2495  }
2496 
2497  appendLine(scip, file, linebuffer, &linecnt, buffer);
2498  }
2499 
2500  break;
2501  }
2502 
2503  case SCIP_EXPR_POLYNOMIAL:
2504  {
2505  SCIP_EXPRDATA_MONOMIAL* monomial;
2506  int m;
2507  int f;
2508 
2509  if( SCIPexprGetPolynomialConstant(expr) != 0.0 )
2510  {
2511  (void) SCIPsnprintf(buffer, PIP_MAX_PRINTLEN, " %+.15g ", exprtreecoefs[e] * SCIPexprGetPolynomialConstant(expr));
2512  appendLine(scip, file, linebuffer, &linecnt, buffer);
2513  }
2514 
2515  for( m = 0; m < SCIPexprGetNMonomials(expr); ++m )
2516  {
2517  monomial = SCIPexprGetMonomials(expr)[m];
2518  assert(monomial != NULL);
2519 
2520  (void) SCIPsnprintf(buffer, PIP_MAX_PRINTLEN, " %+.15g", exprtreecoefs[e] * SCIPexprGetMonomialCoef(monomial));
2521  appendLine(scip, file, linebuffer, &linecnt, buffer);
2522 
2523  for( f = 0; f < SCIPexprGetMonomialNFactors(monomial); ++f )
2524  {
2525  /* we start a new line; therefore we tab this line */
2526  if( linecnt == 0 )
2527  appendLine(scip, file, linebuffer, &linecnt, " ");
2528 
2529  (void) SCIPsnprintf(varname, PIP_MAX_NAMELEN, "%s", SCIPvarGetName(vars[SCIPexprGetOpIndex(children[SCIPexprGetMonomialChildIndices(monomial)[f]])]));
2530  if( SCIPexprGetMonomialExponents(monomial)[f] != 1.0 )
2531  (void) SCIPsnprintf(buffer, PIP_MAX_PRINTLEN, " %s^%.15g", varname, SCIPexprGetMonomialExponents(monomial)[f]);
2532  else
2533  (void) SCIPsnprintf(buffer, PIP_MAX_PRINTLEN, " %s", varname);
2534  appendLine(scip, file, linebuffer, &linecnt, buffer);
2535  }
2536  }
2537 
2538  break;
2539  }
2540 
2541  default:
2542  {
2543  /* this should have been caught in SCIPwritePip before */
2544  SCIPerrorMessage("unsupported operator <%s> in writing of polynomial nonlinear constraint\n", SCIPexpropGetName(SCIPexprGetOperator(expr)));
2545  return;
2546  } /*lint !e788*/
2547  } /*lint !e788*/
2548  }
2549 
2550  /* print right hand side */
2551  if( SCIPisZero(scip, rhs) )
2552  rhs = 0.0;
2553 
2554  (void) SCIPsnprintf(buffer, PIP_MAX_PRINTLEN, " %s %+.15g", type, rhs);
2555 
2556  /* we start a new line; therefore we tab this line */
2557  if (linecnt == 0 )
2558  appendLine(scip, file, linebuffer, &linecnt, " ");
2559  appendLine(scip, file, linebuffer, &linecnt, buffer);
2560 
2561  endLine(scip, file, linebuffer, &linecnt);
2562 }
2563 
2564 
2565 /** prints given (linear or) quadratic constraint information in LP format to file stream */
2566 static
2568  SCIP* scip, /**< SCIP data structure */
2569  FILE* file, /**< output file (or NULL for standard output) */
2570  const char* rowname, /**< name of the row */
2571  SCIP_VAR** linvars, /**< array of linear variables */
2572  SCIP_Real* linvals, /**< array of linear coefficients values (or NULL if all linear coefficient values are 1) */
2573  int nlinvars, /**< number of linear variables */
2574  SCIP_QUADVARTERM* quadvarterms, /**< quadratic variable terms */
2575  int nquadvarterms, /**< number of quadratic variable terms */
2576  SCIP_BILINTERM* bilinterms, /**< bilinear terms */
2577  int nbilinterms, /**< number of bilinear terms */
2578  SCIP_Real lhs, /**< left hand side */
2579  SCIP_Real rhs, /**< right hand side */
2580  SCIP_Bool transformed /**< transformed constraint? */
2581  )
2582 {
2583  int v;
2584  SCIP_VAR** activevars = NULL;
2585  SCIP_Real* activevals = NULL;
2586  int nactivevars;
2587  SCIP_Real activeconstant = 0.0;
2588 
2589  assert( scip != NULL );
2590  assert( rowname != NULL );
2591 
2592  assert( nlinvars == 0 || linvars != NULL );
2593  assert( nquadvarterms == 0 || quadvarterms != NULL );
2594  assert( nbilinterms == 0 || bilinterms != NULL );
2595 
2596  assert( lhs <= rhs );
2597 
2598  if( SCIPisInfinity(scip, -lhs) && SCIPisInfinity(scip, rhs) )
2599  return SCIP_OKAY;
2600 
2601  nactivevars = nlinvars;
2602  if( nlinvars > 0 )
2603  {
2604  /* duplicate variable and value array */
2605  SCIP_CALL( SCIPduplicateBufferArray(scip, &activevars, linvars, nactivevars ) );
2606  if( linvals != NULL )
2607  {
2608  SCIP_CALL( SCIPduplicateBufferArray(scip, &activevals, linvals, nactivevars ) );
2609  }
2610  else
2611  {
2612  SCIP_CALL( SCIPallocBufferArray(scip, &activevals, nactivevars) );
2613 
2614  for( v = 0; v < nactivevars; ++v )
2615  activevals[v] = 1.0;
2616  }
2617 
2618  /* retransform given variables to active variables */
2619  SCIP_CALL( getActiveVariables(scip, activevars, activevals, &nactivevars, &activeconstant, transformed) );
2620  }
2621 
2622  /* print row(s) in LP format */
2623  if( SCIPisEQ(scip, lhs, rhs) )
2624  {
2625  assert( !SCIPisInfinity(scip, rhs) );
2626 
2627  /* equal constraint */
2628  printRow(scip, file, rowname, "", "=", activevars, activevals, nactivevars,
2629  quadvarterms, nquadvarterms, bilinterms, nbilinterms,
2630  rhs - activeconstant);
2631  }
2632  else
2633  {
2634  if( !SCIPisInfinity(scip, -lhs) )
2635  {
2636  /* print inequality ">=" */
2637  printRow(scip, file, rowname, SCIPisInfinity(scip, rhs) ? "" : "_lhs", ">=",
2638  activevars, activevals, nactivevars,
2639  quadvarterms, nquadvarterms, bilinterms, nbilinterms,
2640  lhs - activeconstant);
2641  }
2642  if( !SCIPisInfinity(scip, rhs) )
2643  {
2644  /* print inequality "<=" */
2645  printRow(scip, file, rowname, SCIPisInfinity(scip, -lhs) ? "" : "_rhs", "<=",
2646  activevars, activevals, nactivevars,
2647  quadvarterms, nquadvarterms, bilinterms, nbilinterms,
2648  rhs - activeconstant);
2649  }
2650  }
2651 
2652  if( nlinvars > 0 )
2653  {
2654  /* free buffer arrays */
2655  SCIPfreeBufferArray(scip, &activevars);
2656  SCIPfreeBufferArray(scip, &activevals);
2657  }
2658 
2659  return SCIP_OKAY;
2660 }
2661 
2662 /** prints given nonlinear constraint information in LP format to file stream */
2663 static
2665  SCIP* scip, /**< SCIP data structure */
2666  FILE* file, /**< output file (or NULL for standard output) */
2667  const char* rowname, /**< name of the row */
2668  SCIP_VAR** linvars, /**< array of linear variables */
2669  SCIP_Real* linvals, /**< array of linear coefficients values (or NULL if all linear coefficient values are 1) */
2670  int nlinvars, /**< number of linear variables */
2671  SCIP_EXPRTREE** exprtrees, /**< expression trees */
2672  SCIP_Real* exprtreecoefs, /**< coefficients of expression trees */
2673  int nexprtrees, /**< number of expression trees */
2674  SCIP_Real lhs, /**< left hand side */
2675  SCIP_Real rhs, /**< right hand side */
2676  SCIP_Bool transformed /**< transformed constraint? */
2677  )
2678 {
2679  int v;
2680  SCIP_VAR** activevars = NULL;
2681  SCIP_Real* activevals = NULL;
2682  int nactivevars;
2683  SCIP_Real activeconstant = 0.0;
2684 
2685  assert( scip != NULL );
2686  assert( rowname != NULL );
2687 
2688  assert( nlinvars == 0 || linvars != NULL );
2689  assert( nexprtrees == 0 || exprtrees != NULL );
2690  assert( nexprtrees == 0 || exprtreecoefs != NULL );
2691 
2692  assert( lhs <= rhs );
2693 
2694  if( SCIPisInfinity(scip, -lhs) && SCIPisInfinity(scip, rhs) )
2695  return SCIP_OKAY;
2696 
2697  nactivevars = nlinvars;
2698  if( nlinvars > 0 )
2699  {
2700  /* duplicate variable and value array */
2701  SCIP_CALL( SCIPduplicateBufferArray(scip, &activevars, linvars, nactivevars ) );
2702  if( linvals != NULL )
2703  {
2704  SCIP_CALL( SCIPduplicateBufferArray(scip, &activevals, linvals, nactivevars ) );
2705  }
2706  else
2707  {
2708  SCIP_CALL( SCIPallocBufferArray(scip, &activevals, nactivevars) );
2709 
2710  for( v = 0; v < nactivevars; ++v )
2711  activevals[v] = 1.0;
2712  }
2713 
2714  /* retransform given variables to active variables */
2715  SCIP_CALL( getActiveVariables(scip, activevars, activevals, &nactivevars, &activeconstant, transformed) );
2716  }
2717 
2718  /* print row(s) in LP format */
2719  if( SCIPisEQ(scip, lhs, rhs) )
2720  {
2721  assert( !SCIPisInfinity(scip, rhs) );
2722 
2723  /* equal constraint */
2724  printRowNl(scip, file, rowname, "", "=", activevars, activevals, nactivevars,
2725  exprtrees, exprtreecoefs, nexprtrees,
2726  rhs - activeconstant);
2727  }
2728  else
2729  {
2730  if( !SCIPisInfinity(scip, -lhs) )
2731  {
2732  /* print inequality ">=" */
2733  printRowNl(scip, file, rowname, SCIPisInfinity(scip, rhs) ? "" : "_lhs", ">=",
2734  activevars, activevals, nactivevars,
2735  exprtrees, exprtreecoefs, nexprtrees,
2736  lhs - activeconstant);
2737  }
2738  if( !SCIPisInfinity(scip, rhs) )
2739  {
2740  /* print inequality "<=" */
2741  printRowNl(scip, file, rowname, SCIPisInfinity(scip, -lhs) ? "" : "_rhs", "<=",
2742  activevars, activevals, nactivevars,
2743  exprtrees, exprtreecoefs, nexprtrees,
2744  rhs - activeconstant);
2745  }
2746  }
2747 
2748  if( nlinvars > 0 )
2749  {
2750  /* free buffer arrays */
2751  SCIPfreeBufferArray(scip, &activevars);
2752  SCIPfreeBufferArray(scip, &activevals);
2753  }
2754 
2755  return SCIP_OKAY;
2756 }
2757 
2758 /** check whether given variables are aggregated and put them into an array without duplication */
2759 static
2761  SCIP* scip, /**< SCIP data structure */
2762  int nvars, /**< number of active variables in the problem */
2763  SCIP_VAR** vars, /**< variable array */
2764  int* nAggregatedVars, /**< number of aggregated variables on output */
2765  SCIP_VAR*** aggregatedVars, /**< array storing the aggregated variables on output */
2766  SCIP_HASHTABLE** varAggregated /**< hashtable for checking duplicates */
2767  )
2768 {
2769  int j;
2770 
2771  /* check variables */
2772  for (j = 0; j < nvars; ++j)
2773  {
2774  SCIP_VARSTATUS status;
2775  SCIP_VAR* var;
2776 
2777  var = vars[j];
2778  status = SCIPvarGetStatus(var);
2779 
2780  /* collect aggregated variables in a list */
2781  if( status >= SCIP_VARSTATUS_AGGREGATED )
2782  {
2783  assert( status == SCIP_VARSTATUS_AGGREGATED ||
2784  status == SCIP_VARSTATUS_MULTAGGR ||
2785  status == SCIP_VARSTATUS_NEGATED );
2786 
2787  if ( ! SCIPhashtableExists(*varAggregated, (void*) var) )
2788  {
2789  (*aggregatedVars)[(*nAggregatedVars)++] = var;
2790  SCIP_CALL( SCIPhashtableInsert(*varAggregated, (void*) var) );
2791  }
2792  }
2793  }
2794 
2795  return SCIP_OKAY;
2796 }
2797 
2798 
2799 /** print aggregated variable-constraints */
2800 static
2802  SCIP* scip, /**< SCIP data structure */
2803  FILE* file, /**< output file (or NULL for standard output) */
2804  SCIP_Bool transformed, /**< TRUE iff problem is the transformed problem */
2805  int nvars, /**< number of active variables in the problem */
2806  int nAggregatedVars, /**< number of aggregated variables */
2807  SCIP_VAR** aggregatedVars /**< array storing the aggregated variables */
2808  )
2809 {
2810  int j;
2811 
2812  SCIP_VAR** activevars;
2813  SCIP_Real* activevals;
2814  int nactivevars;
2815  SCIP_Real activeconstant = 0.0;
2816  char consname[PIP_MAX_NAMELEN];
2817 
2818  assert( scip != NULL );
2819 
2820  /* write aggregation constraints */
2821  SCIP_CALL( SCIPallocBufferArray(scip, &activevars, nvars) );
2822  SCIP_CALL( SCIPallocBufferArray(scip, &activevals, nvars) );
2823 
2824  for (j = 0; j < nAggregatedVars; ++j)
2825  {
2826  /* set up list to obtain substitution variables */
2827  nactivevars = 1;
2828 
2829  activevars[0] = aggregatedVars[j];
2830  activevals[0] = 1.0;
2831  activeconstant = 0.0;
2832 
2833  /* retransform given variables to active variables */
2834  SCIP_CALL( getActiveVariables(scip, activevars, activevals, &nactivevars, &activeconstant, transformed) );
2835 
2836  activevals[nactivevars] = -1.0;
2837  activevars[nactivevars] = aggregatedVars[j];
2838  ++nactivevars;
2839 
2840  /* output constraint */
2841  (void) SCIPsnprintf(consname, PIP_MAX_NAMELEN, "aggr_%s", SCIPvarGetName(aggregatedVars[j]));
2842  printRow(scip, file, consname, "", "=", activevars, activevals, nactivevars, NULL, 0, NULL, 0, - activeconstant);
2843  }
2844 
2845  /* free buffer arrays */
2846  SCIPfreeBufferArray(scip, &activevars);
2847  SCIPfreeBufferArray(scip, &activevals);
2848 
2849  return SCIP_OKAY;
2850 }
2851 
2852 /** method check if the variable names are not longer than PIP_MAX_NAMELEN */
2853 static
2855  SCIP* scip, /**< SCIP data structure */
2856  SCIP_VAR** vars, /**< array of variables */
2857  int nvars /**< number of variables */
2858  )
2859 {
2860  int v;
2861 
2862  assert(scip != NULL);
2863  assert(vars != NULL || nvars == 0);
2864 
2865  /* check if the variable names are not to long */
2866  for( v = 0; v < nvars; ++v )
2867  {
2868  if( strlen(SCIPvarGetName(vars[v])) > PIP_MAX_NAMELEN ) /*lint !e613*/
2869  {
2870  SCIPwarningMessage(scip, "there is a variable name which has to be cut down to %d characters; LP might be corrupted\n",
2871  PIP_MAX_NAMELEN - 1);
2872  return;
2873  }
2874  }
2875 }
2876 
2877 /** method check if the constraint names are not longer than PIP_MAX_NAMELEN */
2878 static
2880  SCIP* scip, /**< SCIP data structure */
2881  SCIP_CONS** conss, /**< array of constraints */
2882  int nconss, /**< number of constraints */
2883  SCIP_Bool transformed /**< TRUE iff problem is the transformed problem */
2884  )
2885 {
2886  int c;
2887  SCIP_CONS* cons;
2888  SCIP_CONSHDLR* conshdlr;
2889  const char* conshdlrname;
2890 
2891  assert( scip != NULL );
2892  assert( conss != NULL );
2893 
2894  for( c = 0; c < nconss; ++c )
2895  {
2896  cons = conss[c];
2897  assert(cons != NULL );
2898 
2899  /* in case the transformed is written only constraints are posted which are enabled in the current node */
2900  assert(!transformed || SCIPconsIsEnabled(cons));
2901 
2902  conshdlr = SCIPconsGetHdlr(cons);
2903  assert( conshdlr != NULL );
2904 
2905  conshdlrname = SCIPconshdlrGetName(conshdlr);
2906  assert( transformed == SCIPconsIsTransformed(cons) );
2907 
2908  if( strcmp(conshdlrname, "linear") == 0 )
2909  {
2910  SCIP_Real lhs = SCIPgetLhsLinear(scip, cons);
2911  SCIP_Real rhs = SCIPgetLhsLinear(scip, cons);
2912 
2913  if( (SCIPisEQ(scip, lhs, rhs) && strlen(SCIPconsGetName(conss[c])) > PIP_MAX_NAMELEN)
2914  || ( !SCIPisEQ(scip, lhs, rhs) && strlen(SCIPconsGetName(conss[c])) > PIP_MAX_NAMELEN - 4) )
2915  {
2916  SCIPwarningMessage(scip, "there is a constraint name which has to be cut down to %d characters;\n",
2917  PIP_MAX_NAMELEN - 1);
2918  return;
2919  }
2920  }
2921  else if( strlen(SCIPconsGetName(conss[c])) > PIP_MAX_NAMELEN )
2922  {
2923  SCIPwarningMessage(scip, "there is a constraint name which has to be cut down to %d characters;\n",
2924  PIP_MAX_NAMELEN - 1);
2925  return;
2926  }
2927  }
2928 }
2929 
2930 /** writes problem to file
2931  * @todo add writing cons_pseudoboolean
2932  */
2934  SCIP* scip, /**< SCIP data structure */
2935  FILE* file, /**< output file, or NULL if standard output should be used */
2936  const char* name, /**< problem name */
2937  SCIP_Bool transformed, /**< TRUE iff problem is the transformed problem */
2938  SCIP_OBJSENSE objsense, /**< objective sense */
2939  SCIP_Real objscale, /**< scalar applied to objective function; external objective value is
2940  * extobj = objsense * objscale * (intobj + objoffset) */
2941  SCIP_Real objoffset, /**< objective offset from bound shifting and fixing */
2942  SCIP_VAR** vars, /**< array with active variables ordered binary, integer, implicit, continuous */
2943  int nvars, /**< number of active variables in the problem */
2944  int nbinvars, /**< number of binary variables */
2945  int nintvars, /**< number of general integer variables */
2946  int nimplvars, /**< number of implicit integer variables */
2947  int ncontvars, /**< number of continuous variables */
2948  SCIP_CONS** conss, /**< array with constraints of the problem */
2949  int nconss, /**< number of constraints in the problem */
2950  SCIP_RESULT* result /**< pointer to store the result of the file writing call */
2951  )
2952 {
2953  int c;
2954  int v;
2955  int e;
2956 
2957  int linecnt;
2958  char linebuffer[PIP_MAX_PRINTLEN];
2959 
2960  char varname[PIP_MAX_NAMELEN];
2961  char buffer[PIP_MAX_PRINTLEN];
2962 
2963  SCIP_CONSHDLR* conshdlr;
2964  const char* conshdlrname;
2965  SCIP_CONS* cons;
2966  SCIP_CONS** consQuadratic;
2967  int nConsQuadratic;
2968  SCIP_CONS** consNonlinear;
2969  int nConsNonlinear;
2970  SCIP_CONS** consAbspower;
2971  int nConsAbspower;
2972  SCIP_CONS** consAnd;
2973  int nConsAnd;
2974  SCIP_CONS** consBivariate;
2975  int nConsBivariate;
2976  char consname[PIP_MAX_NAMELEN];
2977 
2978  SCIP_VAR** aggregatedVars;
2979  int nAggregatedVars;
2980  SCIP_HASHTABLE* varAggregated;
2981 
2982  SCIP_VAR** consvars;
2983  SCIP_Real* consvals;
2984  int nconsvars;
2985 
2986  SCIP_VAR* var;
2987  SCIP_Real lb;
2988  SCIP_Real ub;
2989 
2990  SCIP_EXPRTREE* exprtree;
2991  SCIP_EXPR* expr;
2992 
2993  assert( scip != NULL );
2994 
2995  nAggregatedVars = 0;
2996  nConsQuadratic = 0;
2997  nConsNonlinear = 0;
2998  nConsAbspower = 0;
2999  nConsAnd = 0;
3000  nConsBivariate = 0;
3001 
3002  /* check if the variable names are not to long */
3003  checkVarnames(scip, vars, nvars);
3004 
3005  /* check if the constraint names are to long */
3006  checkConsnames(scip, conss, nconss, transformed);
3007 
3008  /* print statistics as comment to file */
3009  SCIPinfoMessage(scip, file, "\\ SCIP STATISTICS\n");
3010  SCIPinfoMessage(scip, file, "\\ Problem name : %s\n", name);
3011  SCIPinfoMessage(scip, file, "\\ Variables : %d (%d binary, %d integer, %d implicit integer, %d continuous)\n",
3012  nvars, nbinvars, nintvars, nimplvars, ncontvars);
3013  SCIPinfoMessage(scip, file, "\\ Constraints : %d\n", nconss);
3014  SCIPinfoMessage(scip, file, "\\ Obj. scale : %.15g\n", objscale);
3015  SCIPinfoMessage(scip, file, "\\ Obj. offset : %.15g\n", objoffset);
3016 
3017  /* print objective sense */
3018  SCIPinfoMessage(scip, file, "%s\n", objsense == SCIP_OBJSENSE_MINIMIZE ? "Minimize" : "Maximize");
3019 
3020  clearLine(linebuffer, &linecnt);
3021  appendLine(scip, file, linebuffer, &linecnt, " Obj:");
3022 
3023  for (v = 0; v < nvars; ++v)
3024  {
3025  var = vars[v];
3026 
3027 #ifndef NDEBUG
3028  /* in case the original problem has to be posted the variables have to be either "original" or "negated" */
3029  if ( !transformed )
3031 #endif
3032 
3033  if ( SCIPisZero(scip, SCIPvarGetObj(var)) )
3034  continue;
3035 
3036  /* we start a new line; therefore we tab this line */
3037  if ( linecnt == 0 )
3038  appendLine(scip, file, linebuffer, &linecnt, " ");
3039 
3040  (void) SCIPsnprintf(varname, PIP_MAX_NAMELEN, "%s", SCIPvarGetName(var));
3041  (void) SCIPsnprintf(buffer, PIP_MAX_PRINTLEN, " %+.15g %s", SCIPvarGetObj(var), varname );
3042 
3043  appendLine(scip, file, linebuffer, &linecnt, buffer);
3044  }
3045 
3046  endLine(scip, file, linebuffer, &linecnt);
3047 
3048  /* print "Subject to" section */
3049  SCIPinfoMessage(scip, file, "Subject to\n");
3050 
3051  /* collect quadratic, nonlinear, absolute power, and, and bivariate constraints in arrays */
3052  SCIP_CALL( SCIPallocBufferArray(scip, &consQuadratic, nconss) );
3053  SCIP_CALL( SCIPallocBufferArray(scip, &consNonlinear, nconss) );
3054  SCIP_CALL( SCIPallocBufferArray(scip, &consAbspower, nconss) );
3055  SCIP_CALL( SCIPallocBufferArray(scip, &consAnd, nconss) );
3056  SCIP_CALL( SCIPallocBufferArray(scip, &consBivariate, nconss) );
3057 
3058  for (c = 0; c < nconss; ++c)
3059  {
3060  cons = conss[c];
3061  assert( cons != NULL);
3062 
3063  /* in case the transformed is written only constraints are posted which are enabled in the current node */
3064  assert(!transformed || SCIPconsIsEnabled(cons));
3065 
3066  conshdlr = SCIPconsGetHdlr(cons);
3067  assert( conshdlr != NULL );
3068 
3069  (void) SCIPsnprintf(consname, PIP_MAX_NAMELEN, "%s", SCIPconsGetName(cons));
3070  conshdlrname = SCIPconshdlrGetName(conshdlr);
3071  assert( transformed == SCIPconsIsTransformed(cons) );
3072 
3073  if( strcmp(conshdlrname, "linear") == 0 )
3074  {
3075  SCIP_CALL( printQuadraticCons(scip, file, consname,
3076  SCIPgetVarsLinear(scip, cons), SCIPgetValsLinear(scip, cons), SCIPgetNVarsLinear(scip, cons),
3077  NULL, 0, NULL, 0, SCIPgetLhsLinear(scip, cons), SCIPgetRhsLinear(scip, cons), transformed) );
3078  }
3079  else if( strcmp(conshdlrname, "setppc") == 0 )
3080  {
3081  consvars = SCIPgetVarsSetppc(scip, cons);
3082  nconsvars = SCIPgetNVarsSetppc(scip, cons);
3083 
3084  switch( SCIPgetTypeSetppc(scip, cons) )
3085  {
3087  SCIP_CALL( printQuadraticCons(scip, file, consname,
3088  consvars, NULL, nconsvars, NULL, 0, NULL, 0, 1.0, 1.0, transformed) );
3089  break;
3091  SCIP_CALL( printQuadraticCons(scip, file, consname,
3092  consvars, NULL, nconsvars, NULL, 0, NULL, 0, -SCIPinfinity(scip), 1.0, transformed) );
3093  break;
3095  SCIP_CALL( printQuadraticCons(scip, file, consname,
3096  consvars, NULL, nconsvars, NULL, 0, NULL, 0, 1.0, SCIPinfinity(scip), transformed) );
3097  break;
3098  }
3099  }
3100  else if ( strcmp(conshdlrname, "logicor") == 0 )
3101  {
3102  SCIP_CALL( printQuadraticCons(scip, file, consname,
3103  SCIPgetVarsLogicor(scip, cons), NULL, SCIPgetNVarsLogicor(scip, cons),
3104  NULL, 0, NULL, 0, 1.0, SCIPinfinity(scip), transformed) );
3105  }
3106  else if ( strcmp(conshdlrname, "knapsack") == 0 )
3107  {
3108  SCIP_Longint* weights;
3109 
3110  consvars = SCIPgetVarsKnapsack(scip, cons);
3111  nconsvars = SCIPgetNVarsKnapsack(scip, cons);
3112 
3113  /* copy Longint array to SCIP_Real array */
3114  weights = SCIPgetWeightsKnapsack(scip, cons);
3115  SCIP_CALL( SCIPallocBufferArray(scip, &consvals, nconsvars) );
3116  for( v = 0; v < nconsvars; ++v )
3117  consvals[v] = (SCIP_Real)weights[v];
3118 
3119  SCIP_CALL( printQuadraticCons(scip, file, consname, consvars, consvals, nconsvars,
3120  NULL, 0, NULL, 0, -SCIPinfinity(scip), (SCIP_Real) SCIPgetCapacityKnapsack(scip, cons), transformed) );
3121 
3122  SCIPfreeBufferArray(scip, &consvals);
3123  }
3124  else if ( strcmp(conshdlrname, "varbound") == 0 )
3125  {
3126  SCIP_CALL( SCIPallocBufferArray(scip, &consvars, 2) );
3127  SCIP_CALL( SCIPallocBufferArray(scip, &consvals, 2) );
3128 
3129  consvars[0] = SCIPgetVarVarbound(scip, cons);
3130  consvars[1] = SCIPgetVbdvarVarbound(scip, cons);
3131 
3132  consvals[0] = 1.0;
3133  consvals[1] = SCIPgetVbdcoefVarbound(scip, cons);
3134 
3135  SCIP_CALL( printQuadraticCons(scip, file, consname, consvars, consvals, 2, NULL, 0, NULL, 0,
3136  SCIPgetLhsVarbound(scip, cons), SCIPgetRhsVarbound(scip, cons), transformed) );
3137 
3138  SCIPfreeBufferArray(scip, &consvars);
3139  SCIPfreeBufferArray(scip, &consvals);
3140  }
3141  else if( strcmp(conshdlrname, "quadratic") == 0 )
3142  {
3143  SCIP_CALL( printQuadraticCons(scip, file, consname,
3147  SCIPgetNBilinTermsQuadratic(scip, cons), SCIPgetLhsQuadratic(scip, cons),
3148  SCIPgetRhsQuadratic(scip, cons), transformed) );
3149 
3150  consQuadratic[nConsQuadratic++] = cons;
3151  }
3152  else if( strcmp(conshdlrname, "nonlinear") == 0 )
3153  {
3154  SCIP_Bool ispolynomial;
3155  int nexprtrees = SCIPgetNExprtreesNonlinear(scip, cons);
3156 
3157  /* check whether expressions are polynomials (assumed simplified exprtrees) */
3158  ispolynomial = TRUE;
3159  for( e = 0; e < nexprtrees && ispolynomial; ++e )
3160  {
3161  exprtree = SCIPgetExprtreesNonlinear(scip, cons)[e];
3162  expr = SCIPexprtreeGetRoot(exprtree);
3163  assert(expr != NULL);
3164 
3165  /* check if operator is something polynomial */
3166  switch( SCIPexprGetOperator(expr) )
3167  {
3168  case SCIP_EXPR_CONST:
3169  case SCIP_EXPR_VARIDX:
3170  case SCIP_EXPR_PLUS:
3171  case SCIP_EXPR_MINUS:
3172  case SCIP_EXPR_MUL:
3173  case SCIP_EXPR_SQUARE:
3174  case SCIP_EXPR_SQRT:
3175  case SCIP_EXPR_SUM:
3176  case SCIP_EXPR_PRODUCT:
3177  case SCIP_EXPR_LINEAR:
3178  case SCIP_EXPR_QUADRATIC:
3179  break;
3180 
3181  case SCIP_EXPR_INTPOWER:
3182  {
3183  if( SCIPexprGetIntPowerExponent(expr) < 0 )
3184  {
3185  SCIPwarningMessage(scip, "negative exponent %d in intpower in %dth expression tree of constraint <%s> cannot be written in pip format\n", SCIPexprGetIntPowerExponent(expr), e, SCIPconsGetName(cons));
3186  ispolynomial = FALSE;
3187  }
3188 
3189  break;
3190  }
3191 
3192  case SCIP_EXPR_REALPOWER:
3193  {
3194  if( SCIPexprGetRealPowerExponent(expr) < 0.0 )
3195  {
3196  SCIPwarningMessage(scip, "negative exponent %g in realpower in %dth expression tree of constraint <%s> cannot be written in pip format\n", SCIPexprGetRealPowerExponent(expr), e, SCIPconsGetName(cons));
3197  ispolynomial = FALSE;
3198  }
3199 
3200  break;
3201  }
3202 
3203  case SCIP_EXPR_POLYNOMIAL:
3204  {
3205  SCIP_EXPRDATA_MONOMIAL* monomial;
3206  int m;
3207  int f;
3208 
3209  for( m = 0; m < SCIPexprGetNMonomials(expr) && ispolynomial; ++m )
3210  {
3211  monomial = SCIPexprGetMonomials(expr)[m];
3212  for( f = 0; f < SCIPexprGetMonomialNFactors(monomial); ++f )
3213  {
3214  if( SCIPexprGetMonomialExponents(monomial)[f] < 0.0 )
3215  {
3216  SCIPwarningMessage(scip, "negative exponent %g in polynomial in %dth expression tree of constraint <%s> cannot be written in pip format\n", SCIPexprGetMonomialExponents(monomial)[f], e, SCIPconsGetName(cons));
3217  ispolynomial = FALSE;
3218  break;
3219  }
3220  }
3221  }
3222 
3223  break;
3224  }
3225 
3226  default:
3227  SCIPwarningMessage(scip, "expression operand <%s> in %dth expression tree of constraint <%s> cannot be written in pip format\n", SCIPexpropGetName(SCIPexprGetOperator(expr)), e, SCIPconsGetName(cons));
3228  ispolynomial = FALSE;
3229  break;
3230  } /*lint !e788*/
3231 
3232  /* check if all children of root expression correspond to variables */
3233  for( v = 0; v < SCIPexprGetNChildren(expr) && ispolynomial; ++v )
3234  {
3236  {
3237  SCIPwarningMessage(scip, "%dth expression tree of constraint <%s> is not simplified, cannot write in pip format\n", e, SCIPconsGetName(cons));
3238  ispolynomial = FALSE;
3239  }
3240  }
3241  }
3242 
3243  if( ispolynomial )
3244  {
3245  SCIP_CALL( printNonlinearCons(scip, file, consname,
3247  SCIPgetNLinearVarsNonlinear(scip, cons), SCIPgetExprtreesNonlinear(scip, cons),
3249  SCIPgetLhsNonlinear(scip, cons), SCIPgetRhsNonlinear(scip, cons), transformed) );
3250 
3251  consNonlinear[nConsNonlinear++] = cons;
3252  }
3253  else
3254  {
3255  SCIPinfoMessage(scip, file, "\\ ");
3256  SCIP_CALL( SCIPprintCons(scip, cons, file) );
3257  SCIPinfoMessage(scip, file, ";\n");
3258  }
3259  }
3260  else if( strcmp(conshdlrname, "abspower") == 0 )
3261  {
3262  SCIP_VAR* x;
3263  SCIP_Real xoffset;
3264  SCIP_Real exponent;
3265  SCIP_Real treecoef;
3266 
3267  expr = NULL;
3268  treecoef = 1.0;
3269 
3270  x = SCIPgetNonlinearVarAbspower(scip, cons);
3271  xoffset = SCIPgetOffsetAbspower(scip, cons);
3272  exponent = SCIPgetExponentAbspower(scip, cons);
3273 
3274  /* see if we formulate signpower(x+offset,exponent) as usual polynomial */
3275  if( !SCIPisZero(scip, xoffset) )
3276  {
3277  SCIPwarningMessage(scip, "nonzero offset for nonlinear variable in constraint <%s>, cannot write in pip format\n", SCIPconsGetName(cons));
3278  }
3279  if( SCIPisIntegral(scip, exponent) && ((int)SCIPround(scip, exponent) % 2 == 1) )
3280  {
3281  /* exponent is odd integer, so signpower(x,exponent) = x^exponent */
3282  SCIP_CALL( SCIPexprCreate(SCIPblkmem(scip), &expr, SCIP_EXPR_VARIDX, 0) );
3283  SCIP_CALL( SCIPexprCreate(SCIPblkmem(scip), &expr, SCIP_EXPR_INTPOWER, expr, (int)SCIPround(scip, exponent)) );
3284  }
3285  else if( SCIPisIntegral(scip, exponent) && ((int)SCIPround(scip, exponent) % 2 == 0) && !SCIPisPositive(scip, SCIPvarGetUbGlobal(x)) )
3286  {
3287  /* exponent is even integer and x is negative, so signpower(x,exponent) = -x^exponent */
3288  SCIP_CALL( SCIPexprCreate(SCIPblkmem(scip), &expr, SCIP_EXPR_VARIDX, 0) );
3289  SCIP_CALL( SCIPexprCreate(SCIPblkmem(scip), &expr, SCIP_EXPR_INTPOWER, expr, (int)SCIPround(scip, exponent)) );
3290  treecoef = -1.0;
3291  }
3292  else if( !SCIPisNegative(scip, SCIPvarGetLbGlobal(x)) )
3293  {
3294  /* x is positive, so signpower(x,exponent) = x^exponent */
3295  SCIP_CALL( SCIPexprCreate(SCIPblkmem(scip), &expr, SCIP_EXPR_VARIDX, 0) );
3296  SCIP_CALL( SCIPexprCreate(SCIPblkmem(scip), &expr, SCIP_EXPR_REALPOWER, expr, exponent) );
3297  }
3298  else
3299  {
3300  SCIPwarningMessage(scip, "cannot formulate signpower(<%s>, %g) in constraint <%s> as polynomial, cannot write in pip format\n", SCIPvarGetName(x), exponent, SCIPconsGetName(cons));
3301  }
3302 
3303  if( expr != NULL )
3304  {
3305  SCIP_VAR* z;
3306  SCIP_Real zcoef;
3307 
3308  SCIP_CALL( SCIPexprtreeCreate(SCIPblkmem(scip), &exprtree, expr, 1, 0, NULL) );
3309  SCIP_CALL( SCIPexprtreeSetVars(exprtree, 1, &x) );
3310 
3311  z = SCIPgetLinearVarAbspower(scip, cons);
3312  zcoef = SCIPgetCoefLinearAbspower(scip, cons);
3313 
3314  SCIP_CALL( printNonlinearCons(scip, file, consname,
3315  &z, &zcoef, 1, &exprtree, &treecoef, 1,
3316  SCIPgetLhsAbspower(scip, cons), SCIPgetRhsAbspower(scip, cons), transformed) );
3317 
3318  SCIP_CALL( SCIPexprtreeFree(&exprtree) );
3319 
3320  consAbspower[nConsAbspower++] = cons;
3321  }
3322  else
3323  {
3324  SCIPinfoMessage(scip, file, "\\ ");
3325  SCIP_CALL( SCIPprintCons(scip, cons, file) );
3326  SCIPinfoMessage(scip, file, ";\n");
3327  }
3328  }
3329  else if( strcmp(conshdlrname, "bivariate") == 0 )
3330  {
3331  SCIP_Bool ispolynomial;
3332 
3333  /* check whether expression is polynomial (simplified exprtree assumed) */
3334  ispolynomial = TRUE;
3335  exprtree = SCIPgetExprtreeBivariate(scip, cons);
3336  expr = SCIPexprtreeGetRoot(exprtree);
3337  assert(expr != NULL);
3338 
3339  /* check if operator is something polynomial */
3340  switch( SCIPexprGetOperator(expr) )
3341  {
3342  case SCIP_EXPR_CONST:
3343  case SCIP_EXPR_VARIDX:
3344  case SCIP_EXPR_PLUS:
3345  case SCIP_EXPR_MINUS:
3346  case SCIP_EXPR_MUL:
3347  case SCIP_EXPR_SQUARE:
3348  case SCIP_EXPR_SQRT:
3349  case SCIP_EXPR_SUM:
3350  case SCIP_EXPR_PRODUCT:
3351  case SCIP_EXPR_LINEAR:
3352  case SCIP_EXPR_QUADRATIC:
3353  break;
3354 
3355  case SCIP_EXPR_INTPOWER:
3356  {
3357  if( SCIPexprGetIntPowerExponent(expr) < 0 )
3358  {
3359  SCIPwarningMessage(scip, "negative exponent %d in intpower of constraint <%s> cannot be written in pip format\n", SCIPexprGetIntPowerExponent(expr), SCIPconsGetName(cons));
3360  ispolynomial = FALSE;
3361  }
3362 
3363  break;
3364  }
3365 
3366  case SCIP_EXPR_REALPOWER:
3367  {
3368  if( SCIPexprGetRealPowerExponent(expr) < 0.0 )
3369  {
3370  SCIPwarningMessage(scip, "negative exponent %g in realpower of constraint <%s> cannot be written in pip format\n", SCIPexprGetRealPowerExponent(expr), SCIPconsGetName(cons));
3371  ispolynomial = FALSE;
3372  }
3373 
3374  break;
3375  }
3376 
3377  case SCIP_EXPR_POLYNOMIAL:
3378  {
3379  SCIP_EXPRDATA_MONOMIAL* monomial;
3380  int m;
3381  int f;
3382 
3383  for( m = 0; m < SCIPexprGetNMonomials(expr) && ispolynomial; ++m )
3384  {
3385  monomial = SCIPexprGetMonomials(expr)[m];
3386  for( f = 0; f < SCIPexprGetMonomialNFactors(monomial); ++f )
3387  {
3388  if( SCIPexprGetMonomialExponents(monomial)[f] < 0.0 )
3389  {
3390  SCIPwarningMessage(scip, "negative exponent %g in polynomial of constraint <%s> cannot be written in pip format\n", SCIPexprGetMonomialExponents(monomial)[f], SCIPconsGetName(cons));
3391  ispolynomial = FALSE;
3392  break;
3393  }
3394  }
3395  }
3396 
3397  break;
3398  }
3399 
3400  default:
3401  SCIPwarningMessage(scip, "expression operand <%s> in constraint <%s> cannot be written in pip format\n", SCIPexpropGetName(SCIPexprGetOperator(expr)), SCIPconsGetName(cons));
3402  ispolynomial = FALSE;
3403  break;
3404  } /*lint !e788*/
3405 
3406  if( ispolynomial )
3407  {
3408  /* check if all children of root expression correspond to variables */
3409  for( v = 0; v < SCIPexprGetNChildren(expr); ++v )
3410  {
3412  {
3413  SCIPwarningMessage(scip, "expression tree of constraint <%s> is not simplified, cannot write in pip format\n", SCIPconsGetName(cons));
3414  ispolynomial = FALSE;
3415  break;
3416  }
3417  }
3418  }
3419 
3420  if( ispolynomial )
3421  {
3422  SCIP_VAR* z;
3423  SCIP_Real zcoef;
3424  SCIP_Real one;
3425 
3426  z = SCIPgetLinearVarBivariate(scip, cons);
3427  zcoef = SCIPgetLinearCoefBivariate(scip, cons);
3428 
3429  one = 1.0;
3430  SCIP_CALL( printNonlinearCons(scip, file, consname,
3431  &z, &zcoef, z == NULL ? 0 : 1, &exprtree, &one, 1,
3432  SCIPgetLhsBivariate(scip, cons), SCIPgetRhsBivariate(scip, cons), transformed) );
3433 
3434  consBivariate[nConsBivariate++] = cons;
3435  }
3436  else
3437  {
3438  SCIPinfoMessage(scip, file, "\\ ");
3439  SCIP_CALL( SCIPprintCons(scip, cons, file) );
3440  SCIPinfoMessage(scip, file, ";\n");
3441  }
3442  }
3443  else if( strcmp(conshdlrname, "and") == 0 )
3444  {
3445  SCIP_EXPR** children;
3446  SCIP_VAR* resultant;
3447  SCIP_Real minusone;
3448  SCIP_Real one;
3449 
3450  /* create expression for product of binaries */
3451  SCIP_CALL( SCIPallocBufferArray(scip, &children, SCIPgetNVarsAnd(scip, cons)) );
3452  for( v = 0; v < SCIPgetNVarsAnd(scip, cons); ++v )
3453  {
3454  SCIP_CALL( SCIPexprCreate(SCIPblkmem(scip), &children[v], SCIP_EXPR_VARIDX, v) );
3455  }
3456  SCIP_CALL( SCIPexprCreate(SCIPblkmem(scip), &expr, SCIP_EXPR_PRODUCT, SCIPgetNVarsAnd(scip, cons), children) );
3457  SCIP_CALL( SCIPexprtreeCreate(SCIPblkmem(scip), &exprtree, expr, SCIPgetNVarsAnd(scip, cons), 0, NULL) );
3458  SCIP_CALL( SCIPexprtreeSetVars(exprtree, SCIPgetNVarsAnd(scip, cons), SCIPgetVarsAnd(scip, cons)) );
3459 
3460  resultant = SCIPgetResultantAnd(scip, cons);
3461  minusone = -1.0;
3462 
3463  one = 1.0;
3464  SCIP_CALL( printNonlinearCons(scip, file, consname, &resultant, &minusone, 1, &exprtree, &one, 1, 0.0, 0.0, transformed) );
3465 
3466  SCIP_CALL( SCIPexprtreeFree(&exprtree) );
3467  SCIPfreeBufferArray(scip, &children);
3468 
3469  consAnd[nConsAnd++] = cons;
3470  }
3471  else
3472  {
3473  SCIPwarningMessage(scip, "constraint handler <%s> cannot print requested format\n", conshdlrname );
3474  SCIPinfoMessage(scip, file, "\\ ");
3475  SCIP_CALL( SCIPprintCons(scip, cons, file) );
3476  SCIPinfoMessage(scip, file, ";\n");
3477  }
3478  }
3479 
3480  /* create hashtable for storing aggregated variables */
3481  SCIP_CALL( SCIPallocBufferArray(scip, &aggregatedVars, nvars) );
3482  SCIP_CALL( SCIPhashtableCreate(&varAggregated, SCIPblkmem(scip), 1000, hashGetKeyVar, hashKeyEqVar, hashKeyValVar, NULL) );
3483 
3484  /* check for aggregated variables in quadratic parts of quadratic constraints and output aggregations as linear constraints */
3485  for (c = 0; c < nConsQuadratic; ++c)
3486  {
3487  cons = consQuadratic[c];
3488  for( v = 0; v < SCIPgetNQuadVarTermsQuadratic(scip, cons); ++v )
3489  {
3490  SCIP_CALL( collectAggregatedVars(scip, 1, &SCIPgetQuadVarTermsQuadratic(scip, cons)[v].var,
3491  &nAggregatedVars, &aggregatedVars, &varAggregated) );
3492  }
3493  }
3494 
3495  /* check for aggregated variables in expression trees of nonlinear constraints and output aggregations as linear constraints */
3496  for (c = 0; c < nConsNonlinear; ++c)
3497  {
3498  cons = consNonlinear[c];
3499  for( e = 0; e < SCIPgetNExprtreesNonlinear(scip, cons); ++e )
3500  {
3501  exprtree = SCIPgetExprtreesNonlinear(scip, cons)[e];
3502  assert(exprtree != NULL);
3503 
3504  for( v = 0; v < SCIPexprtreeGetNVars(exprtree); ++v )
3505  {
3506  SCIP_CALL( collectAggregatedVars(scip, 1, &SCIPexprtreeGetVars(exprtree)[v],
3507  &nAggregatedVars, &aggregatedVars, &varAggregated) );
3508  }
3509  }
3510  }
3511 
3512  /* check for aggregated variables in absolute power constraints and output aggregations as linear constraints */
3513  for (c = 0; c < nConsAbspower; ++c)
3514  {
3515  SCIP_VAR* spvars[2];
3516 
3517  cons = consAbspower[c];
3518 
3519  spvars[0] = SCIPgetNonlinearVarAbspower(scip, cons);
3520  spvars[1] = SCIPgetLinearVarAbspower(scip, cons);
3521  SCIP_CALL( collectAggregatedVars(scip, 2, spvars, &nAggregatedVars, &aggregatedVars, &varAggregated) );
3522  }
3523 
3524  /* check for aggregated variables in and constraints and output aggregations as linear constraints */
3525  for (c = 0; c < nConsAnd; ++c)
3526  {
3527  SCIP_VAR* resultant;
3528 
3529  cons = consAnd[c];
3530 
3531  SCIP_CALL( collectAggregatedVars(scip, SCIPgetNVarsAnd(scip, cons), SCIPgetVarsAnd(scip, cons), &nAggregatedVars, &aggregatedVars, &varAggregated) );
3532 
3533  resultant = SCIPgetResultantAnd(scip, cons);
3534  SCIP_CALL( collectAggregatedVars(scip, 1, &resultant, &nAggregatedVars, &aggregatedVars, &varAggregated) );
3535  }
3536 
3537  /* check for aggregated variables in bivariate constraints and output aggregations as linear constraints */
3538  for (c = 0; c < nConsBivariate; ++c)
3539  {
3540  SCIP_VAR* z;
3541 
3542  cons = consBivariate[c];
3543 
3544  assert(SCIPexprtreeGetNVars(SCIPgetExprtreeBivariate(scip, cons)) == 2);
3545  SCIP_CALL( collectAggregatedVars(scip, 2, SCIPexprtreeGetVars(SCIPgetExprtreeBivariate(scip, cons)), &nAggregatedVars, &aggregatedVars, &varAggregated) );
3546 
3547  z = SCIPgetLinearVarBivariate(scip, cons);
3548  if( z != NULL )
3549  {
3550  SCIP_CALL( collectAggregatedVars(scip, 1, &z, &nAggregatedVars, &aggregatedVars, &varAggregated) );
3551  }
3552  }
3553 
3554  /* print aggregation constraints */
3555  SCIP_CALL( printAggregatedCons(scip, file, transformed, nvars, nAggregatedVars, aggregatedVars) );
3556 
3557  /* print "Bounds" section */
3558  SCIPinfoMessage(scip, file, "Bounds\n");
3559  for (v = 0; v < nvars; ++v)
3560  {
3561  var = vars[v];
3562  assert( var != NULL );
3563  (void) SCIPsnprintf(varname, PIP_MAX_NAMELEN, "%s", SCIPvarGetName(var) );
3564 
3565  if( transformed )
3566  {
3567  /* in case the transformed is written only local bounds are posted which are valid in the current node */
3568  lb = SCIPvarGetLbLocal(var);
3569  ub = SCIPvarGetUbLocal(var);
3570  }
3571  else
3572  {
3573  lb = SCIPvarGetLbOriginal(var);
3574  ub = SCIPvarGetUbOriginal(var);
3575  }
3576 
3577  if ( SCIPisInfinity(scip, -lb) && SCIPisInfinity(scip, ub) )
3578  SCIPinfoMessage(scip, file, " %s free\n", varname);
3579  else
3580  {
3581  /* print lower bound */
3582  if ( SCIPisInfinity(scip, -lb) )
3583  SCIPinfoMessage(scip, file, " -inf <= ");
3584  else
3585  {
3586  if ( SCIPisZero(scip, lb) )
3587  {
3588  /* variables are nonnegative by default - so we skip these variables */
3589  if ( SCIPisInfinity(scip, ub) )
3590  continue;
3591  lb = 0.0;
3592  }
3593 
3594  SCIPinfoMessage(scip, file, " %.15g <= ", lb);
3595  }
3596  /* print variable name */
3597  SCIPinfoMessage(scip, file, "%s", varname);
3598 
3599  /* print upper bound as far this one is not infinity */
3600  if( !SCIPisInfinity(scip, ub) )
3601  SCIPinfoMessage(scip, file, " <= %.15g", ub);
3602 
3603  SCIPinfoMessage(scip, file, "\n");
3604  }
3605  }
3606 
3607  /* output aggregated variables as 'free' */
3608  for (v = 0; v < nAggregatedVars; ++v)
3609  {
3610  var = aggregatedVars[v];
3611  assert( var != NULL );
3612  (void) SCIPsnprintf(varname, PIP_MAX_NAMELEN, "%s", SCIPvarGetName(var) );
3613 
3614  SCIPinfoMessage(scip, file, " %s free\n", varname);
3615  }
3616 
3617  /* free space */
3618  SCIPfreeBufferArray(scip, &aggregatedVars);
3619  SCIPhashtableFree(&varAggregated);
3620 
3621  /* print binaries section */
3622  if ( nbinvars > 0 )
3623  {
3624  SCIPinfoMessage(scip, file, "Binaries\n");
3625 
3626  clearLine(linebuffer, &linecnt);
3627 
3628  for (v = 0; v < nvars; ++v)
3629  {
3630  var = vars[v];
3631  assert( var != NULL );
3632 
3633  if ( SCIPvarGetType(var) == SCIP_VARTYPE_BINARY )
3634  {
3635  (void) SCIPsnprintf(varname, PIP_MAX_NAMELEN, "%s", SCIPvarGetName(var) );
3636  (void) SCIPsnprintf(buffer, PIP_MAX_PRINTLEN, " %s", varname);
3637  appendLine(scip, file, linebuffer, &linecnt, buffer);
3638  }
3639  }
3640 
3641  endLine(scip, file, linebuffer, &linecnt);
3642  }
3643 
3644  /* print generals section */
3645  if ( nintvars > 0 )
3646  {
3647  SCIPinfoMessage(scip, file, "Generals\n");
3648 
3649  for (v = 0; v < nvars; ++v)
3650  {
3651  var = vars[v];
3652  assert( var != NULL );
3653 
3654  if ( SCIPvarGetType(var) == SCIP_VARTYPE_INTEGER )
3655  {
3656  (void) SCIPsnprintf(varname, PIP_MAX_NAMELEN, "%s", SCIPvarGetName(var) );
3657  (void) SCIPsnprintf(buffer, PIP_MAX_PRINTLEN, " %s", varname);
3658  appendLine(scip, file, linebuffer, &linecnt, buffer);
3659  }
3660  }
3661  endLine(scip, file, linebuffer, &linecnt);
3662  }
3663 
3664  /* free space */
3665  SCIPfreeBufferArray(scip, &consQuadratic);
3666  SCIPfreeBufferArray(scip, &consNonlinear);
3667  SCIPfreeBufferArray(scip, &consAbspower);
3668  SCIPfreeBufferArray(scip, &consAnd);
3669  SCIPfreeBufferArray(scip, &consBivariate);
3670 
3671  /* end of lp format */
3672  SCIPinfoMessage(scip, file, "%s\n", "End");
3673 
3674  *result = SCIP_SUCCESS;
3675 
3676  return SCIP_OKAY;
3677 }
3678 
3679 /*
3680  * Callback methods of reader
3681  */
3682 
3683 /** copy method for reader plugins (called when SCIP copies plugins) */
3684 static
3685 SCIP_DECL_READERCOPY(readerCopyPip)
3686 { /*lint --e{715}*/
3687  assert(scip != NULL);
3688  assert(reader != NULL);
3689  assert(strcmp(SCIPreaderGetName(reader), READER_NAME) == 0);
3690 
3691  /* call inclusion method of reader */
3693 
3694  return SCIP_OKAY;
3695 }
3696 
3697 
3698 /** problem reading method of reader */
3699 static
3700 SCIP_DECL_READERREAD(readerReadPip)
3701 { /*lint --e{715}*/
3702 
3703  SCIP_CALL( SCIPreadPip(scip, reader, filename, result) );
3704 
3705  return SCIP_OKAY;
3706 }
3707 
3708 
3709 /** problem writing method of reader */
3710 static
3711 SCIP_DECL_READERWRITE(readerWritePip)
3712 { /*lint --e{715}*/
3713  SCIP_CALL( SCIPwritePip(scip, file, name, transformed, objsense, objscale, objoffset, vars,
3714  nvars, nbinvars, nintvars, nimplvars, ncontvars, conss, nconss, result) );
3715 
3716  return SCIP_OKAY;
3717 }
3718 
3719 
3720 /*
3721  * reader specific interface methods
3722  */
3723 
3724 /** includes the pip file reader in SCIP */
3726  SCIP* scip /**< SCIP data structure */
3727  )
3728 {
3729  SCIP_READERDATA* readerdata;
3730  SCIP_READER* reader;
3731 
3732  /* create reader data */
3733  readerdata = NULL;
3734 
3735  /* include reader */
3736  SCIP_CALL( SCIPincludeReaderBasic(scip, &reader, READER_NAME, READER_DESC, READER_EXTENSION, readerdata) );
3737 
3738  /* set non fundamental callbacks via setter functions */
3739  SCIP_CALL( SCIPsetReaderCopy(scip, reader, readerCopyPip) );
3740  SCIP_CALL( SCIPsetReaderRead(scip, reader, readerReadPip) );
3741  SCIP_CALL( SCIPsetReaderWrite(scip, reader, readerWritePip) );
3742 
3743  return SCIP_OKAY;
3744 }
3745 
3746 
3747 /** reads problem from file */
3749  SCIP* scip, /**< SCIP data structure */
3750  SCIP_READER* reader, /**< the file reader itself */
3751  const char* filename, /**< full path and name of file to read, or NULL if stdin should be used */
3752  SCIP_RESULT* result /**< pointer to store the result of the file reading call */
3753  )
3754 { /*lint --e{715}*/
3755  PIPINPUT pipinput;
3756  int i;
3757 
3758  /* initialize PIP input data */
3759  pipinput.file = NULL;
3760  pipinput.linebuf[0] = '\0';
3761  pipinput.probname[0] = '\0';
3762  pipinput.objname[0] = '\0';
3763  SCIP_CALL( SCIPallocMemoryArray(scip, &pipinput.token, PIP_MAX_LINELEN) ); /*lint !e506*/
3764  pipinput.token[0] = '\0';
3765  SCIP_CALL( SCIPallocMemoryArray(scip, &pipinput.tokenbuf, PIP_MAX_LINELEN) ); /*lint !e506*/
3766  pipinput.tokenbuf[0] = '\0';
3767  for( i = 0; i < PIP_MAX_PUSHEDTOKENS; ++i )
3768  {
3769  SCIP_CALL( SCIPallocMemoryArray(scip, &((pipinput.pushedtokens)[i]), PIP_MAX_LINELEN) ); /*lint !e866 !e506*/
3770  }
3771 
3772  pipinput.npushedtokens = 0;
3773  pipinput.linenumber = 0;
3774  pipinput.linepos = 0;
3775  pipinput.section = PIP_START;
3776  pipinput.objsense = SCIP_OBJSENSE_MINIMIZE;
3777  pipinput.haserror = FALSE;
3778 
3779  SCIP_CALL( SCIPgetBoolParam(scip, "reading/initialconss", &(pipinput.initialconss)) );
3780  SCIP_CALL( SCIPgetBoolParam(scip, "reading/dynamicconss", &(pipinput.dynamicconss)) );
3781  SCIP_CALL( SCIPgetBoolParam(scip, "reading/dynamiccols", &(pipinput.dynamiccols)) );
3782  SCIP_CALL( SCIPgetBoolParam(scip, "reading/dynamicrows", &(pipinput.dynamicrows)) );
3783 
3784  /* read the file */
3785  SCIP_CALL( readPIPFile(scip, &pipinput, filename) );
3786 
3787  /* free dynamically allocated memory */
3788  SCIPfreeMemoryArray(scip, &pipinput.token);
3789  SCIPfreeMemoryArray(scip, &pipinput.tokenbuf);
3790  for( i = 0; i < PIP_MAX_PUSHEDTOKENS; ++i )
3791  {
3792  SCIPfreeMemoryArray(scip, &pipinput.pushedtokens[i]);
3793  }
3794 
3795  /* evaluate the result */
3796  if( pipinput.haserror )
3797  return SCIP_READERROR;
3798  else
3799  {
3800  /* set objective sense */
3801  SCIP_CALL( SCIPsetObjsense(scip, pipinput.objsense) );
3802  *result = SCIP_SUCCESS;
3803  }
3804 
3805  return SCIP_OKAY;
3806 }
3807