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-2016 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);
789  assert(*vars != NULL || *varssize == 0);
790  assert(nvars != NULL);
791  assert(*nvars <= *varssize);
792  assert(varhash != NULL);
793  assert(var != NULL);
794  assert(varidx != NULL);
795 
796  /* check if we saw this variable before */
797  if( SCIPhashmapExists(varhash, (void*)var) )
798  {
799  *varidx = (int)(size_t)SCIPhashmapGetImage(varhash, (void*)var);
800  assert(*varidx >= 0);
801  assert(*varidx < *nvars);
802 
803  return SCIP_OKAY;
804  }
805 
806  /* since variable is new, add it to the end of vars array and into hashmap */
807 
808  /* ensure enough space in vars array */
809  if( *nvars + 1 > *varssize )
810  {
811  *varssize = SCIPcalcMemGrowSize(scip, *nvars + 1);
812  if( *vars == NULL )
813  {
814  SCIP_CALL( SCIPallocBufferArray(scip, vars, *varssize) );
815  }
816  else
817  {
818  SCIP_CALL( SCIPreallocBufferArray(scip, vars, *varssize) );
819  }
820  }
821  assert(*vars != NULL); /*lint !e613*/
822 
823  (*vars)[*nvars] = var; /*lint !e613*/
824  SCIP_CALL( SCIPhashmapInsert(varhash, (void*)var, (void*)(size_t)*nvars) );
825  *varidx = *nvars;
826 
827  ++*nvars;
828 
829  return SCIP_OKAY;
830 }
831 
832 /** reads an objective or constraint with name and coefficients */
833 static
835  SCIP* scip, /**< SCIP data structure */
836  PIPINPUT* pipinput, /**< PIP reading data */
837  char* name, /**< pointer to store the name of the line; must be at least of size
838  * PIP_MAX_LINELEN */
839  SCIP_EXPRTREE** exprtree, /**< pointer to store constraint function as polynomial expression */
840  int* degree, /**< pointer to store degree of polynomial */
841  SCIP_Bool* newsection /**< pointer to store whether a new section was encountered */
842  )
843 {
844  SCIP_EXPR* expression;
845  SCIP_Bool havesign;
846  SCIP_Bool havevalue;
847  SCIP_Real coef;
848  int coefsign;
849  int nextcoefsign;
850  int monomialdegree;
851  SCIP_EXPR** varexprs;
852  int i;
853 
854  SCIP_VAR** vars;
855  int varssize;
856  int nvars;
857  SCIP_HASHMAP* varhash;
858 
859  SCIP_Real constant;
860 
861  SCIP_EXPRDATA_MONOMIAL** monomials;
862  int monomialssize;
863  int nmonomials;
864 
865  int nfactors;
866  int factorssize;
867  SCIP_Real* exponents;
868  int* varidxs;
869 
870  assert(scip != NULL);
871  assert(pipinput != NULL);
872  assert(name != NULL);
873  assert(exprtree != NULL);
874  assert(degree != NULL);
875  assert(newsection != NULL);
876 
877  *name = '\0';
878  *exprtree = NULL;
879  *degree = 0;
880  *newsection = FALSE;
881 
882  /* read the first token, which may be the name of the line */
883  if( getNextToken(scip, pipinput) )
884  {
885  /* check if we reached a new section */
886  if( isNewSection(scip, pipinput) )
887  {
888  *newsection = TRUE;
889  return SCIP_OKAY;
890  }
891 
892  /* remember the token in the token buffer */
893  swapTokenBuffer(pipinput);
894 
895  /* get the next token and check, whether it is a colon */
896  if( getNextToken(scip, pipinput) )
897  {
898  if( strcmp(pipinput->token, ":") == 0 )
899  {
900  /* the second token was a colon: the first token is the line name */
901  (void)strncpy(name, pipinput->tokenbuf, PIP_MAX_LINELEN);
902  name[PIP_MAX_LINELEN - 1] = '\0';
903  SCIPdebugMessage("(line %d) read constraint name: '%s'\n", pipinput->linenumber, name);
904  }
905  else
906  {
907  /* the second token was no colon: push the tokens back onto the token stack and parse them as coefficients */
908  pushToken(pipinput);
909  pushBufferToken(pipinput);
910  }
911  }
912  else
913  {
914  /* there was only one token left: push it back onto the token stack and parse it as coefficient */
915  pushBufferToken(pipinput);
916  }
917  }
918 
919  /* initialize buffer for storing the variables */
920  varssize = PIP_INIT_VARSSIZE;
921  SCIP_CALL( SCIPallocBufferArray(scip, &vars, varssize) );
923 
924  /* initialize buffer for storing the monomials */
925  monomialssize = PIP_INIT_MONOMIALSSIZE;
926  SCIP_CALL( SCIPallocBufferArray(scip, &monomials, monomialssize) );
927 
928  /* initialize buffer for storing the factors in a monomial */
929  factorssize = PIP_INIT_FACTORSSIZE;
930  SCIP_CALL( SCIPallocBufferArray(scip, &exponents, factorssize) );
931  SCIP_CALL( SCIPallocBufferArray(scip, &varidxs, factorssize) );
932 
933  /* read the coefficients */
934  coefsign = +1;
935  nextcoefsign = +1;
936  coef = 1.0;
937  havesign = FALSE;
938  havevalue = FALSE;
939  nmonomials = 0;
940  nvars = 0;
941  nfactors = 0;
942  monomialdegree = 0;
943  constant = 0.0;
944  while( getNextToken(scip, pipinput) )
945  {
946  SCIP_VAR* var;
947  int varidx;
948  SCIP_Bool issense;
949  SCIP_Bool issign;
950  SCIP_Bool isnewsection;
951  SCIP_Real exponent;
952 
953  issign = FALSE; /* fix compiler warning */
954  issense = FALSE; /* fix lint warning */
955  if( (isnewsection = isNewSection(scip, pipinput)) || /*lint !e820*/
956  (issense = isSense(pipinput, NULL)) || /*lint !e820*/
957  ((nfactors > 0 || havevalue) && (issign = isSign(pipinput, &nextcoefsign))) ) /*lint !e820*/
958  {
959  /* finish the current monomial */
960  if( nfactors > 0 )
961  {
962  SCIP_CALL( ensureMonomialsSize(scip, &monomials, &monomialssize, nmonomials + 1) );
964  &monomials[nmonomials], coefsign * coef, nfactors, varidxs, exponents) );
965  ++nmonomials;
966  }
967  else if( havevalue)
968  {
969  constant += coefsign * coef;
970  }
971 
972  if( monomialdegree > *degree )
973  *degree = monomialdegree;
974 
975  /* reset variables */
976  nfactors = 0;
977  coef = 1.0;
978  coefsign = +1;
979  havesign = FALSE;
980  havevalue = FALSE;
981  monomialdegree = 0;
982 
983  if( isnewsection )
984  {
985  *newsection = TRUE;
986  break;
987  }
988 
989  if( issense )
990  {
991  /* put the sense back onto the token stack */
992  pushToken(pipinput);
993  break;
994  }
995 
996  if( issign )
997  {
998  coefsign = nextcoefsign;
999  SCIPdebugMessage("(line %d) read coefficient sign: %+d\n", pipinput->linenumber, coefsign);
1000  havesign = TRUE;
1001  nextcoefsign = +1;
1002  continue;
1003  }
1004  }
1005 
1006  /* check if we read a sign */
1007  if( isSign(pipinput, &coefsign) )
1008  {
1009  SCIPdebugMessage("(line %d) read coefficient sign: %+d\n", pipinput->linenumber, coefsign);
1010 
1011  if( nfactors > 0 || havevalue )
1012  {
1013  syntaxError(scip, pipinput, "sign can only be at beginning of monomial");
1014  goto TERMINATE_READPOLYNOMIAL;
1015  }
1016 
1017  havesign = TRUE;
1018  continue;
1019  }
1020 
1021  /* check if we are in between factors of a monomial */
1022  if( strcmp(pipinput->token, "*") == 0 )
1023  {
1024  if( nfactors == 0 )
1025  {
1026  syntaxError(scip, pipinput, "cannot have '*' before first variable in monomial");
1027  goto TERMINATE_READPOLYNOMIAL;
1028  }
1029 
1030  continue;
1031  }
1032 
1033  /* all but the first monomial need a sign */
1034  if( nmonomials > 0 && !havesign )
1035  {
1036  syntaxError(scip, pipinput, "expected sign ('+' or '-') or sense ('<' or '>')");
1037  goto TERMINATE_READPOLYNOMIAL;
1038  }
1039 
1040  /* check if we are at an exponent for the last variable */
1041  if( strcmp(pipinput->token, "^") == 0 )
1042  {
1043  if( !getNextToken(scip, pipinput) || !isValue(scip, pipinput, &exponent) )
1044  {
1045  syntaxError(scip, pipinput, "expected exponent value after '^'");
1046  goto TERMINATE_READPOLYNOMIAL;
1047  }
1048  if( nfactors == 0 )
1049  {
1050  syntaxError(scip, pipinput, "cannot have '^' before first variable in monomial");
1051  goto TERMINATE_READPOLYNOMIAL;
1052  }
1053  exponents[nfactors-1] = exponent;
1054  if( SCIPisIntegral(scip, exponent) && exponent > 0.0 )
1055  monomialdegree += (int)exponent - 1; /* -1, because we added +1 when we put the variable into varidxs */
1056  else
1057  monomialdegree = SCIP_EXPR_DEGREEINFINITY;
1058 
1059  SCIPdebugMessage("(line %d) read exponent value %g for variable %s\n", pipinput->linenumber, exponent,
1060  SCIPvarGetName(vars[varidxs[nfactors-1]]));
1061  continue;
1062  }
1063 
1064  /* check if we read a value */
1065  if( isValue(scip, pipinput, &coef) )
1066  {
1067  SCIPdebugMessage("(line %d) read coefficient value: %g with sign %+d\n", pipinput->linenumber, coef, coefsign);
1068 
1069  if( havevalue )
1070  {
1071  syntaxError(scip, pipinput, "two consecutive values");
1072  goto TERMINATE_READPOLYNOMIAL;
1073  }
1074 
1075  if( nfactors > 0 )
1076  {
1077  syntaxError(scip, pipinput, "coefficients can only be at the beginning of a monomial");
1078  goto TERMINATE_READPOLYNOMIAL;
1079  }
1080 
1081  havevalue = TRUE;
1082  continue;
1083  }
1084 
1085  /* the token is a variable name: get the corresponding variable (or create a new one) */
1086  SCIP_CALL( getVariable(scip, pipinput->token, pipinput->dynamiccols, &var, NULL) );
1087 
1088  /* get the index of the variable in the vars array, or add there if not in it yet */
1089  SCIP_CALL( getVariableIndex(scip, &vars, &varssize, &nvars, varhash, var, &varidx) );
1090 
1091  SCIP_CALL( ensureFactorsSize(scip, &exponents, &varidxs, &factorssize, nfactors + 1) );
1092 
1093  exponents[nfactors] = 1.0;
1094  varidxs[nfactors] = varidx;
1095  ++nfactors;
1096  ++monomialdegree;
1097  }
1098 
1099  if( nfactors > 0 )
1100  {
1101  syntaxError(scip, pipinput, "string ended before monomial has finished");
1102  goto TERMINATE_READPOLYNOMIAL;
1103  }
1104 
1105  /* create variable expressions */
1106  SCIP_CALL( SCIPallocBufferArray(scip, &varexprs, nvars) );
1107  for( i = 0; i < nvars; ++i )
1108  {
1109  SCIP_CALL( SCIPexprCreate(SCIPblkmem(scip), &varexprs[i], SCIP_EXPR_VARIDX, i) );
1110  }
1111 
1112  /* create polynomial expression, let polynomial take over ownership of monomials */
1113  SCIP_CALL( SCIPexprCreatePolynomial(SCIPblkmem(scip), &expression, nvars, varexprs,
1114  nmonomials, monomials, constant, FALSE) );
1115 
1116  SCIPfreeBufferArray(scip, &varexprs);
1117 
1118  SCIP_CALL( SCIPexprtreeCreate(SCIPblkmem(scip), exprtree, expression, 0, 0, NULL) );
1119  SCIP_CALL( SCIPexprtreeSetVars(*exprtree, nvars, vars) );
1120 
1121  SCIPdebugMessage("read polynomial of degree %d: ", *degree);
1123  SCIPdebugPrintf("\n");
1124 
1125  TERMINATE_READPOLYNOMIAL:
1126  SCIPfreeBufferArray(scip, &vars);
1127  SCIPfreeBufferArray(scip, &monomials);
1128  SCIPfreeBufferArray(scip, &exponents);
1129  SCIPfreeBufferArray(scip, &varidxs);
1130  SCIPhashmapFree(&varhash);
1131 
1132  return SCIP_OKAY;
1133 }
1134 
1135 /** given an expression tree that holds a polynomial expression of degree at most two,
1136  * gives the coefficients of the constant, linear, and quadratic part of this expression
1137  */
1138 static
1140  SCIP* scip, /**< SCIP data structure */
1141  SCIP_EXPRTREE* exprtree, /**< expression tree holding polynomial expression */
1142  SCIP_Real* constant, /**< buffer to store constant monomials */
1143  int* nlinvars, /**< buffer to store number of linear coefficients */
1144  SCIP_VAR** linvars, /**< array to fill with linear variables */
1145  SCIP_Real* lincoefs, /**< array to fill with coefficients of linear variables */
1146  int* nquadterms, /**< buffer to store number of quadratic terms */
1147  SCIP_VAR** quadvars1, /**< array to fill with quadratic variables */
1148  SCIP_VAR** quadvars2, /**< array to fill with quadratic variables */
1149  SCIP_Real* quadcoefs /**< array to fill with coefficients of quadratic terms */
1150  )
1151 {
1152  SCIP_EXPR* expr;
1153  SCIP_EXPRDATA_MONOMIAL** monomials;
1154  int nmonomials;
1155  int varidx;
1156  int i;
1157 
1158  expr = SCIPexprtreeGetRoot(exprtree);
1159  assert(expr != NULL);
1160  assert(SCIPexprGetOperator(expr) == SCIP_EXPR_POLYNOMIAL);
1161  assert(SCIPexprGetNChildren(expr) == SCIPexprtreeGetNVars(exprtree));
1162 
1163  nmonomials = SCIPexprGetNMonomials(expr);
1164  monomials = SCIPexprGetMonomials(expr);
1165 
1166  *constant = SCIPexprGetPolynomialConstant(expr);
1167  *nlinvars = 0;
1168  *nquadterms = 0;
1169  for( i = 0; i < nmonomials; ++i )
1170  {
1171  assert(SCIPexprGetMonomialNFactors(monomials[i]) >= 0);
1172  assert(SCIPexprGetMonomialNFactors(monomials[i]) <= 2);
1173  assert(SCIPexprGetMonomialExponents(monomials[i]) != NULL || SCIPexprGetMonomialNFactors(monomials[i]) == 0);
1174  assert(SCIPexprGetMonomialChildIndices(monomials[i]) != NULL || SCIPexprGetMonomialNFactors(monomials[i]) == 0);
1175 
1176  if( SCIPexprGetMonomialNFactors(monomials[i]) == 0 )
1177  {
1178  /* constant monomial */
1179  *constant += SCIPexprGetMonomialCoef(monomials[i]);
1180  }
1181  else if( SCIPexprGetMonomialNFactors(monomials[i]) == 1 && SCIPexprGetMonomialExponents(monomials[i])[0] == 1.0 )
1182  {
1183  /* linear monomial */
1184  varidx = SCIPexprGetMonomialChildIndices(monomials[i])[0];
1185  assert(varidx >= 0);
1186  assert(varidx < SCIPexprtreeGetNVars(exprtree));
1187  assert(SCIPexprGetOperator(SCIPexprGetChildren(expr)[varidx]) == SCIP_EXPR_VARIDX);
1188  assert(SCIPexprGetOpIndex(SCIPexprGetChildren(expr)[varidx]) == varidx); /* assume that child varidx corresponds to variable varidx */
1189 
1190  lincoefs[*nlinvars] = SCIPexprGetMonomialCoef(monomials[i]);
1191  linvars[*nlinvars] = SCIPexprtreeGetVars(exprtree)[varidx];
1192  ++*nlinvars;
1193  }
1194  else if( SCIPexprGetMonomialNFactors(monomials[i]) == 1 )
1195  {
1196  /* square monomial */
1197  assert(SCIPexprGetMonomialExponents(monomials[i])[0] == 2.0);
1198 
1199  varidx = SCIPexprGetMonomialChildIndices(monomials[i])[0];
1200  assert(varidx >= 0);
1201  assert(varidx < SCIPexprtreeGetNVars(exprtree));
1202  assert(SCIPexprGetOperator(SCIPexprGetChildren(expr)[varidx]) == SCIP_EXPR_VARIDX);
1203  assert(SCIPexprGetOpIndex(SCIPexprGetChildren(expr)[varidx]) == varidx); /* assume that child varidx corresponds to variable varidx */
1204 
1205  quadcoefs[*nquadterms] = SCIPexprGetMonomialCoef(monomials[i]);
1206  quadvars1[*nquadterms] = SCIPexprtreeGetVars(exprtree)[varidx];
1207  quadvars2[*nquadterms] = quadvars1[*nquadterms];
1208  ++*nquadterms;
1209  }
1210  else
1211  {
1212  /* bilinear monomial */
1213  assert(SCIPexprGetMonomialExponents(monomials[i])[0] == 1.0);
1214  assert(SCIPexprGetMonomialExponents(monomials[i])[1] == 1.0);
1215 
1216  quadcoefs[*nquadterms] = SCIPexprGetMonomialCoef(monomials[i]);
1217 
1218  varidx = SCIPexprGetMonomialChildIndices(monomials[i])[0];
1219  assert(varidx >= 0);
1220  assert(varidx < SCIPexprtreeGetNVars(exprtree));
1221  assert(SCIPexprGetOperator(SCIPexprGetChildren(expr)[varidx]) == SCIP_EXPR_VARIDX);
1222  assert(SCIPexprGetOpIndex(SCIPexprGetChildren(expr)[varidx]) == varidx); /* assume that child varidx corresponds to variable varidx */
1223  quadvars1[*nquadterms] = SCIPexprtreeGetVars(exprtree)[varidx];
1224 
1225  varidx = SCIPexprGetMonomialChildIndices(monomials[i])[1];
1226  assert(varidx >= 0);
1227  assert(varidx < SCIPexprtreeGetNVars(exprtree));
1228  assert(SCIPexprGetOperator(SCIPexprGetChildren(expr)[varidx]) == SCIP_EXPR_VARIDX);
1229  assert(SCIPexprGetOpIndex(SCIPexprGetChildren(expr)[varidx]) == varidx); /* assume that child varidx corresponds to variable varidx */
1230  quadvars2[*nquadterms] = SCIPexprtreeGetVars(exprtree)[varidx];
1231 
1232  ++*nquadterms;
1233  }
1234  }
1235 }
1236 
1237 /** reads the objective section */
1238 static
1240  SCIP* scip, /**< SCIP data structure */
1241  PIPINPUT* pipinput /**< PIP reading data */
1242  )
1243 {
1244  char name[PIP_MAX_LINELEN];
1245  SCIP_EXPRTREE* exprtree;
1246  SCIP_EXPR* expr;
1247  int degree;
1248  SCIP_Bool newsection;
1249  int varidx;
1250  int nmonomials;
1251  SCIP_Bool initial;
1252  SCIP_Bool separate;
1253  SCIP_Bool enforce;
1254  SCIP_Bool check;
1255  SCIP_Bool propagate;
1256  SCIP_Bool local;
1257  SCIP_Bool modifiable;
1258  SCIP_Bool dynamic;
1259  SCIP_Bool removable;
1260 
1261  assert(pipinput != NULL);
1262 
1263  /* determine settings; note that reading/{initialconss,dynamicconss,dynamicrows,dynamiccols} apply only to model
1264  * constraints and variables, not to an auxiliary objective constraint (otherwise it can happen that an auxiliary
1265  * objective variable is loose with infinite best bound, triggering the problem that an LP that is unbounded because
1266  * of loose variables with infinite best bound cannot be solved)
1267  */
1268  initial = TRUE;
1269  separate = TRUE;
1270  enforce = TRUE;
1271  check = TRUE;
1272  propagate = TRUE;
1273  local = FALSE;
1274  modifiable = FALSE;
1275  dynamic = FALSE;
1276  removable = FALSE;
1277 
1278  /* read the objective coefficients */
1279  SCIP_CALL( readPolynomial(scip, pipinput, name, &exprtree, &degree, &newsection) );
1280  if( !hasError(pipinput) )
1281  {
1282  int i;
1283 
1284  expr = SCIPexprtreeGetRoot(exprtree);
1285  assert(expr != NULL);
1286  assert(SCIPexprGetOperator(expr) == SCIP_EXPR_POLYNOMIAL);
1287 
1288  nmonomials = SCIPexprGetNMonomials(expr);
1289 
1290  if( SCIPexprGetPolynomialConstant(expr) != 0.0 )
1291  {
1292  SCIP_VAR* objconst;
1293  SCIP_CALL( SCIPcreateVarBasic(scip, &objconst, "objconst", 1.0, 1.0, SCIPexprGetPolynomialConstant(expr), SCIP_VARTYPE_CONTINUOUS) );
1294  SCIP_CALL( SCIPaddVar(scip, objconst) );
1295  SCIP_CALL( SCIPreleaseVar(scip, &objconst) );
1296  }
1297 
1298  assert(degree >= 0);
1299  if( degree == 1 )
1300  {
1301  SCIP_Real coef;
1302  SCIP_VAR* var;
1303  SCIP_EXPRDATA_MONOMIAL** monomials;
1304 
1305  assert(SCIPexprtreeGetVars(exprtree) != NULL);
1306  assert(SCIPexprGetNChildren(expr) == SCIPexprtreeGetNVars(exprtree));
1307 
1308  monomials = SCIPexprGetMonomials(expr);
1309 
1310  for( i = 0; i < nmonomials; ++i )
1311  {
1312  assert(SCIPexprGetMonomialNFactors(monomials[i]) == 1);
1313  assert(SCIPexprGetMonomialExponents(monomials[i]) != NULL);
1314  assert(SCIPexprGetMonomialExponents(monomials[i])[0] == 1.0);
1315  assert(SCIPexprGetMonomialChildIndices(monomials[i]) != NULL);
1316 
1317  varidx = SCIPexprGetMonomialChildIndices(monomials[i])[0];
1318  assert(varidx >= 0);
1319  assert(varidx < SCIPexprGetNChildren(expr));
1320  assert(SCIPexprGetOperator(SCIPexprGetChildren(expr)[varidx]) == SCIP_EXPR_VARIDX);
1321  assert(SCIPexprGetOpIndex(SCIPexprGetChildren(expr)[varidx]) == varidx); /* assume that child varidx corresponds to variable varidx */
1322 
1323  coef = SCIPexprGetMonomialCoef(monomials[i]);
1324  var = SCIPexprtreeGetVars(exprtree)[varidx];
1325 
1326  SCIP_CALL( SCIPchgVarObj(scip, var, SCIPvarGetObj(var) + coef) );
1327  }
1328  }
1329  else if( degree == 2 )
1330  {
1331  /* insert dummy variable and constraint to represent quadratic part of objective */
1332 
1333  SCIP_VAR* quadobjvar;
1334  SCIP_CONS* quadobjcons;
1335  SCIP_Real lhs;
1336  SCIP_Real rhs;
1337 
1338  SCIP_Real constant;
1339  int nlinvars;
1340  SCIP_VAR** linvars;
1341  SCIP_Real* lincoefs;
1342  int nquadterms;
1343  SCIP_VAR** quadvars1;
1344  SCIP_VAR** quadvars2;
1345  SCIP_Real* quadcoefs;
1346 
1347  SCIP_CALL( SCIPallocBufferArray(scip, &linvars, nmonomials) );
1348  SCIP_CALL( SCIPallocBufferArray(scip, &lincoefs, nmonomials) );
1349  SCIP_CALL( SCIPallocBufferArray(scip, &quadvars1, nmonomials) );
1350  SCIP_CALL( SCIPallocBufferArray(scip, &quadvars2, nmonomials) );
1351  SCIP_CALL( SCIPallocBufferArray(scip, &quadcoefs, nmonomials) );
1352 
1353  getLinearAndQuadraticCoefs(scip, exprtree, &constant, &nlinvars, linvars, lincoefs, &nquadterms, quadvars1, quadvars2, quadcoefs);
1354 
1355  SCIP_CALL( SCIPcreateVar(scip, &quadobjvar, "quadobjvar", -SCIPinfinity(scip), SCIPinfinity(scip), 1.0,
1357  SCIP_CALL( SCIPaddVar(scip, quadobjvar) );
1358 
1359  if ( pipinput->objsense == SCIP_OBJSENSE_MINIMIZE )
1360  {
1361  lhs = -SCIPinfinity(scip);
1362  rhs = -constant;
1363  }
1364  else
1365  {
1366  lhs = -constant;
1367  rhs = SCIPinfinity(scip);
1368  }
1369 
1370  SCIP_CALL( SCIPcreateConsQuadratic(scip, &quadobjcons, "quadobj", nlinvars, linvars, lincoefs, nquadterms, quadvars1, quadvars2, quadcoefs, lhs, rhs,
1371  initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable) );
1372 
1373  SCIP_CALL( SCIPaddLinearVarQuadratic(scip, quadobjcons, quadobjvar, -1.0) );
1374 
1375  SCIP_CALL( SCIPaddCons(scip, quadobjcons) );
1376  SCIPdebugMessage("(line %d) added constraint <%s> to represent quadratic objective: ", pipinput->linenumber, SCIPconsGetName(quadobjcons));
1377  SCIPdebugPrintCons(scip, quadobjcons, NULL);
1378 
1379  SCIP_CALL( SCIPreleaseCons(scip, &quadobjcons) );
1380  SCIP_CALL( SCIPreleaseVar(scip, &quadobjvar) );
1381 
1382  /* free memory */
1383  SCIPfreeBufferArray(scip, &linvars);
1384  SCIPfreeBufferArray(scip, &lincoefs);
1385  SCIPfreeBufferArray(scip, &quadvars1);
1386  SCIPfreeBufferArray(scip, &quadvars2);
1387  SCIPfreeBufferArray(scip, &quadcoefs);
1388  }
1389  else if( degree > 2 )
1390  {
1391  /* insert dummy variable and constraint to represent nonlinear part of objective */
1392 
1393  SCIP_VAR* nonlinobjvar;
1394  SCIP_CONS* nonlinobjcons;
1395  SCIP_Real minusone;
1396  SCIP_Real lhs;
1397  SCIP_Real rhs;
1398 
1399  SCIP_CALL( SCIPcreateVar(scip, &nonlinobjvar, "nonlinobjvar", -SCIPinfinity(scip), SCIPinfinity(scip), 1.0,
1401  SCIP_CALL( SCIPaddVar(scip, nonlinobjvar) );
1402 
1403  minusone = -1.0;
1404 
1405  if ( pipinput->objsense == SCIP_OBJSENSE_MINIMIZE )
1406  {
1407  lhs = -SCIPinfinity(scip);
1408  rhs = 0.0;
1409  }
1410  else
1411  {
1412  lhs = 0.0;
1413  rhs = SCIPinfinity(scip);
1414  }
1415 
1416  SCIP_CALL( SCIPcreateConsNonlinear(scip, &nonlinobjcons, "nonlinobj", 1, &nonlinobjvar, &minusone, 1, &exprtree, NULL, lhs, rhs,
1417  initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, FALSE) );
1418  SCIP_CALL( SCIPexprtreeFree(&exprtree) );
1419 
1420  SCIP_CALL( SCIPaddCons(scip, nonlinobjcons) );
1421  SCIPdebugMessage("(line %d) added constraint <%s> to represent nonlinear objective: ", pipinput->linenumber, SCIPconsGetName(nonlinobjcons));
1422  SCIPdebugPrintCons(scip, nonlinobjcons, NULL);
1423 
1424  SCIP_CALL( SCIPreleaseCons(scip, &nonlinobjcons) );
1425  SCIP_CALL( SCIPreleaseVar(scip, &nonlinobjvar) );
1426  }
1427  }
1428 
1429  if( exprtree != NULL )
1430  {
1431  SCIP_CALL( SCIPexprtreeFree(&exprtree) );
1432  }
1433 
1434  return SCIP_OKAY;
1435 }
1436 
1437 /** reads the constraints section
1438  */
1439 static
1441  SCIP* scip, /**< SCIP data structure */
1442  PIPINPUT* pipinput /**< PIP reading data */
1443  )
1444 {
1445  char name[PIP_MAX_LINELEN];
1446  SCIP_CONS* cons;
1447  SCIP_EXPRTREE* exprtree;
1448  SCIP_EXPR* expr;
1449  int degree;
1450 
1451  SCIP_Real constant;
1452 
1453  int nlinvars;
1454  SCIP_VAR** linvars;
1455  SCIP_Real* lincoefs;
1456 
1457  int nquadcoefs;
1458  SCIP_VAR** quadvars1;
1459  SCIP_VAR** quadvars2;
1460  SCIP_Real* quadcoefs;
1461 
1462  PIPSENSE sense;
1463  SCIP_RETCODE retcode = SCIP_OKAY;
1464  SCIP_Real sidevalue;
1465  SCIP_Real lhs;
1466  SCIP_Real rhs;
1467  SCIP_Bool newsection;
1468  SCIP_Bool initial;
1469  SCIP_Bool separate;
1470  SCIP_Bool enforce;
1471  SCIP_Bool check;
1472  SCIP_Bool propagate;
1473  SCIP_Bool local;
1474  SCIP_Bool modifiable;
1475  SCIP_Bool dynamic;
1476  SCIP_Bool removable;
1477  int sidesign;
1478  int nmonomials;
1479 
1480  assert(pipinput != NULL);
1481 
1482  /* read polynomial */
1483  SCIP_CALL( readPolynomial(scip, pipinput, name, &exprtree, &degree, &newsection) );
1484  if ( hasError(pipinput) )
1485  goto TERMINATE;
1486  if ( newsection )
1487  {
1488  if ( exprtree != NULL )
1489  syntaxError(scip, pipinput, "expected constraint sense '<=', '=', or '>='");
1490  goto TERMINATE;
1491  }
1492 
1493  /* read the constraint sense */
1494  if ( !getNextToken(scip, pipinput) || !isSense(pipinput, &sense) )
1495  {
1496  syntaxError(scip, pipinput, "expected constraint sense '<=', '=', or '>='");
1497  goto TERMINATE;
1498  }
1499 
1500  /* read the right hand side */
1501  sidesign = +1;
1502  if ( !getNextToken(scip, pipinput) )
1503  {
1504  syntaxError(scip, pipinput, "missing right hand side");
1505  goto TERMINATE;
1506  }
1507  if ( isSign(pipinput, &sidesign) )
1508  {
1509  if( !getNextToken(scip, pipinput) )
1510  {
1511  syntaxError(scip, pipinput, "missing value of right hand side");
1512  goto TERMINATE;
1513  }
1514  }
1515  if ( !isValue(scip, pipinput, &sidevalue) )
1516  {
1517  syntaxError(scip, pipinput, "expected value as right hand side");
1518  goto TERMINATE;
1519  }
1520  sidevalue *= sidesign;
1521 
1522  /* determine settings */
1523  initial = pipinput->initialconss;
1524  separate = TRUE;
1525  enforce = TRUE;
1526  check = TRUE;
1527  propagate = TRUE;
1528  local = FALSE;
1529  modifiable = FALSE;
1530  dynamic = pipinput->dynamicconss;
1531  removable = pipinput->dynamicrows;
1532 
1533  if( degree > 2 )
1534  {
1535  /* assign the left and right hand side, depending on the constraint sense */
1536  switch ( sense )
1537  {
1538  case PIP_SENSE_GE:
1539  lhs = sidevalue;
1540  rhs = SCIPinfinity(scip);
1541  break;
1542  case PIP_SENSE_LE:
1543  lhs = -SCIPinfinity(scip);
1544  rhs = sidevalue;
1545  break;
1546  case PIP_SENSE_EQ:
1547  lhs = sidevalue;
1548  rhs = sidevalue;
1549  break;
1550  case PIP_SENSE_NOTHING:
1551  default:
1552  SCIPerrorMessage("invalid constraint sense <%d>\n", sense);
1553  return SCIP_INVALIDDATA;
1554  }
1555 
1556  SCIP_CALL_TERMINATE( retcode, SCIPcreateConsNonlinear(scip, &cons, name, 0, NULL, NULL, 1, &exprtree, NULL, lhs, rhs,
1557  initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, FALSE), TERMINATE );
1558  }
1559  else
1560  {
1561  expr = SCIPexprtreeGetRoot(exprtree);
1562  assert(expr != NULL);
1563  assert(SCIPexprGetOperator(expr) == SCIP_EXPR_POLYNOMIAL);
1564  nmonomials = SCIPexprGetNMonomials(expr);
1565 
1566  SCIP_CALL( SCIPallocBufferArray(scip, &linvars, nmonomials) );
1567  SCIP_CALL( SCIPallocBufferArray(scip, &lincoefs, nmonomials) );
1568  SCIP_CALL( SCIPallocBufferArray(scip, &quadvars1, nmonomials) );
1569  SCIP_CALL( SCIPallocBufferArray(scip, &quadvars2, nmonomials) );
1570  SCIP_CALL( SCIPallocBufferArray(scip, &quadcoefs, nmonomials) );
1571 
1572  getLinearAndQuadraticCoefs(scip, exprtree, &constant, &nlinvars, linvars, lincoefs, &nquadcoefs, quadvars1, quadvars2, quadcoefs);
1573 
1574  /* assign the left and right hand side, depending on the constraint sense */
1575  switch( sense )
1576  {
1577  case PIP_SENSE_GE:
1578  lhs = sidevalue - constant;
1579  rhs = SCIPinfinity(scip);
1580  break;
1581  case PIP_SENSE_LE:
1582  lhs = -SCIPinfinity(scip);
1583  rhs = sidevalue - constant;
1584  break;
1585  case PIP_SENSE_EQ:
1586  lhs = sidevalue - constant;
1587  rhs = sidevalue - constant;
1588  break;
1589  case PIP_SENSE_NOTHING:
1590  default:
1591  SCIPerrorMessage("invalid constraint sense <%d>\n", sense);
1592  return SCIP_INVALIDDATA;
1593  }
1594 
1595  if( nquadcoefs == 0 )
1596  {
1597  retcode = SCIPcreateConsLinear(scip, &cons, name, nlinvars, linvars, lincoefs, lhs, rhs,
1598  initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, FALSE);
1599  }
1600  else
1601  {
1602  retcode = SCIPcreateConsQuadratic(scip, &cons, name, nlinvars, linvars, lincoefs,
1603  nquadcoefs, quadvars1, quadvars2, quadcoefs, lhs, rhs,
1604  initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable);
1605  }
1606 
1607  /* free memory */
1608  SCIPfreeBufferArray(scip, &linvars);
1609  SCIPfreeBufferArray(scip, &lincoefs);
1610  SCIPfreeBufferArray(scip, &quadvars1);
1611  SCIPfreeBufferArray(scip, &quadvars2);
1612  SCIPfreeBufferArray(scip, &quadcoefs);
1613  }
1614 
1615  if( retcode == SCIP_OKAY )
1616  {
1617  SCIP_CALL( SCIPaddCons(scip, cons) );
1618  SCIPdebugMessage("(line %d) created constraint: ", pipinput->linenumber);
1619  SCIPdebugPrintCons(scip, cons, NULL);
1620  SCIP_CALL( SCIPreleaseCons(scip, &cons) );
1621  }
1622 
1623  TERMINATE:
1624  if( exprtree != NULL )
1625  {
1626  SCIP_CALL( SCIPexprtreeFree(&exprtree) );
1627  }
1628 
1629  if( hasError(pipinput) )
1630  retcode = SCIP_READERROR;
1631 
1632  SCIP_CALL( retcode );
1633 
1634  return SCIP_OKAY;
1635 }
1636 
1637 /** reads the bounds section */
1638 static
1640  SCIP* scip, /**< SCIP data structure */
1641  PIPINPUT* pipinput /**< PIP reading data */
1642  )
1643 {
1644  assert(pipinput != NULL);
1645 
1646  while( getNextToken(scip, pipinput) )
1647  {
1648  SCIP_VAR* var;
1649  SCIP_Real value;
1650  SCIP_Real lb;
1651  SCIP_Real ub;
1652  int sign;
1653  SCIP_Bool hassign;
1654  PIPSENSE leftsense;
1655 
1656  /* check if we reached a new section */
1657  if( isNewSection(scip, pipinput) )
1658  return SCIP_OKAY;
1659 
1660  /* default bounds are [0,+inf] */
1661  lb = 0.0;
1662  ub = SCIPinfinity(scip);
1663  leftsense = PIP_SENSE_NOTHING;
1664 
1665  /* check if the first token is a sign */
1666  sign = +1;
1667  hassign = isSign(pipinput, &sign);
1668  if( hassign && !getNextToken(scip, pipinput) )
1669  {
1670  syntaxError(scip, pipinput, "expected value");
1671  return SCIP_OKAY;
1672  }
1673 
1674  /* the first token must be either a value or a variable name */
1675  if( isValue(scip, pipinput, &value) )
1676  {
1677  /* first token is a value: the second token must be a sense */
1678  if( !getNextToken(scip, pipinput) || !isSense(pipinput, &leftsense) )
1679  {
1680  syntaxError(scip, pipinput, "expected bound sense '<=', '=', or '>='");
1681  return SCIP_OKAY;
1682  }
1683 
1684  /* update the bound corresponding to the sense */
1685  switch( leftsense )
1686  {
1687  case PIP_SENSE_GE:
1688  ub = sign * value;
1689  break;
1690  case PIP_SENSE_LE:
1691  lb = sign * value;
1692  break;
1693  case PIP_SENSE_EQ:
1694  lb = sign * value;
1695  ub = sign * value;
1696  break;
1697  case PIP_SENSE_NOTHING:
1698  default:
1699  SCIPerrorMessage("invalid bound sense <%d>\n", leftsense);
1700  return SCIP_INVALIDDATA;
1701  }
1702  }
1703  else if( hassign )
1704  {
1705  syntaxError(scip, pipinput, "expected value");
1706  return SCIP_OKAY;
1707  }
1708  else
1709  pushToken(pipinput);
1710 
1711  /* the next token must be a variable name */
1712  if( !getNextToken(scip, pipinput) )
1713  {
1714  syntaxError(scip, pipinput, "expected variable name");
1715  return SCIP_OKAY;
1716  }
1717  SCIP_CALL( getVariable(scip, pipinput->token, pipinput->dynamiccols, &var, NULL) );
1718 
1719  /* the next token might be another sense, or the word "free" */
1720  if( getNextToken(scip, pipinput) )
1721  {
1722  PIPSENSE rightsense;
1723 
1724  if( isSense(pipinput, &rightsense) )
1725  {
1726  /* check, if the senses fit */
1727  if( leftsense == PIP_SENSE_NOTHING
1728  || (leftsense == PIP_SENSE_LE && rightsense == PIP_SENSE_LE)
1729  || (leftsense == PIP_SENSE_GE && rightsense == PIP_SENSE_GE) )
1730  {
1731  if( !getNextToken(scip, pipinput) )
1732  {
1733  syntaxError(scip, pipinput, "expected value or sign");
1734  return SCIP_OKAY;
1735  }
1736 
1737  /* check if the next token is a sign */
1738  sign = +1;
1739  hassign = isSign(pipinput, &sign);
1740  if( hassign && !getNextToken(scip, pipinput) )
1741  {
1742  syntaxError(scip, pipinput, "expected value");
1743  return SCIP_OKAY;
1744  }
1745 
1746  /* the next token must be a value */
1747  if( !isValue(scip, pipinput, &value) )
1748  {
1749  syntaxError(scip, pipinput, "expected value");
1750  return SCIP_OKAY;
1751  }
1752 
1753  /* update the bound corresponding to the sense */
1754  switch( rightsense )
1755  {
1756  case PIP_SENSE_GE:
1757  lb = sign * value;
1758  break;
1759  case PIP_SENSE_LE:
1760  ub = sign * value;
1761  break;
1762  case PIP_SENSE_EQ:
1763  lb = sign * value;
1764  ub = sign * value;
1765  break;
1766  case PIP_SENSE_NOTHING:
1767  default:
1768  SCIPerrorMessage("invalid bound sense <%d>\n", leftsense);
1769  return SCIP_INVALIDDATA;
1770  }
1771  }
1772  else
1773  {
1774  syntaxError(scip, pipinput, "the two bound senses do not fit");
1775  return SCIP_OKAY;
1776  }
1777  }
1778  else if( strcasecmp(pipinput->token, "FREE") == 0 )
1779  {
1780  if( leftsense != PIP_SENSE_NOTHING )
1781  {
1782  syntaxError(scip, pipinput, "variable with bound is marked as 'free'");
1783  return SCIP_OKAY;
1784  }
1785  lb = -SCIPinfinity(scip);
1786  ub = SCIPinfinity(scip);
1787  }
1788  else
1789  {
1790  /* the token was no sense: push it back to the token stack */
1791  pushToken(pipinput);
1792  }
1793  }
1794 
1795  /* change the bounds of the variable if bounds have been given (do not destroy earlier specification of bounds) */
1796  if ( lb != 0.0 )
1797  SCIP_CALL( SCIPchgVarLb(scip, var, lb) );
1798  /*lint --e{777}*/
1799  if ( ub != SCIPinfinity(scip) )
1800  SCIP_CALL( SCIPchgVarUb(scip, var, ub) );
1801  SCIPdebugMessage("(line %d) new bounds: <%s>[%g,%g]\n", pipinput->linenumber, SCIPvarGetName(var),
1803  }
1804 
1805  return SCIP_OKAY;
1806 }
1807 
1808 /** reads the generals section */
1809 static
1811  SCIP* scip, /**< SCIP data structure */
1812  PIPINPUT* pipinput /**< PIP reading data */
1813  )
1814 {
1815  assert(pipinput != NULL);
1816 
1817  while( getNextToken(scip, pipinput) )
1818  {
1819  SCIP_VAR* var;
1820  SCIP_Bool created;
1821  SCIP_Bool infeasible;
1822 
1823  /* check if we reached a new section */
1824  if( isNewSection(scip, pipinput) )
1825  return SCIP_OKAY;
1826 
1827  /* the token must be the name of an existing variable */
1828  SCIP_CALL( getVariable(scip, pipinput->token, pipinput->dynamiccols, &var, &created) );
1829  if( created )
1830  {
1831  syntaxError(scip, pipinput, "unknown variable in generals section");
1832  return SCIP_OKAY;
1833  }
1834 
1835  /* mark the variable to be integral */
1836  SCIP_CALL( SCIPchgVarType(scip, var, SCIP_VARTYPE_INTEGER, &infeasible) );
1837  /* don't assert feasibility here because the presolver will and should detect a infeasibility */
1838  }
1839 
1840  return SCIP_OKAY;
1841 }
1842 
1843 /** reads the binaries section */
1844 static
1846  SCIP* scip, /**< SCIP data structure */
1847  PIPINPUT* pipinput /**< PIP reading data */
1848  )
1849 {
1850  assert(pipinput != NULL);
1851 
1852  while( getNextToken(scip, pipinput) )
1853  {
1854  SCIP_VAR* var;
1855  SCIP_Bool created;
1856  SCIP_Bool infeasible;
1857 
1858  /* check if we reached a new section */
1859  if( isNewSection(scip, pipinput) )
1860  return SCIP_OKAY;
1861 
1862  /* the token must be the name of an existing variable */
1863  SCIP_CALL( getVariable(scip, pipinput->token, pipinput->dynamiccols, &var, &created) );
1864  if( created )
1865  {
1866  syntaxError(scip, pipinput, "unknown variable in binaries section");
1867  return SCIP_OKAY;
1868  }
1869 
1870  /* mark the variable to be binary and change its bounds appropriately */
1871  if( SCIPvarGetLbGlobal(var) < 0.0 )
1872  {
1873  SCIP_CALL( SCIPchgVarLb(scip, var, 0.0) );
1874  }
1875  if( SCIPvarGetUbGlobal(var) > 1.0 )
1876  {
1877  SCIP_CALL( SCIPchgVarUb(scip, var, 1.0) );
1878  }
1879  SCIP_CALL( SCIPchgVarType(scip, var, SCIP_VARTYPE_BINARY, &infeasible) );
1880  /* don't assert feasibility here because the presolver will and should detect a infeasibility */
1881  }
1882 
1883  return SCIP_OKAY;
1884 }
1885 
1886 /** reads a PIP file
1887  */
1888 static
1890  SCIP* scip, /**< SCIP data structure */
1891  PIPINPUT* pipinput, /**< PIP reading data */
1892  const char* filename /**< name of the input file */
1893  )
1894 {
1895  assert(pipinput != NULL);
1896 
1897  /* open file */
1898  pipinput->file = SCIPfopen(filename, "r");
1899  if( pipinput->file == NULL )
1900  {
1901  SCIPerrorMessage("cannot open file <%s> for reading\n", filename);
1902  SCIPprintSysError(filename);
1903  return SCIP_NOFILE;
1904  }
1905 
1906  /* create problem */
1907  SCIP_CALL( SCIPcreateProb(scip, filename, NULL, NULL, NULL, NULL, NULL, NULL, NULL) );
1908 
1909  /* parse the file */
1910  pipinput->section = PIP_START;
1911  while( pipinput->section != PIP_END && !hasError(pipinput) )
1912  {
1913  switch( pipinput->section )
1914  {
1915  case PIP_START:
1916  SCIP_CALL( readStart(scip, pipinput) );
1917  break;
1918 
1919  case PIP_OBJECTIVE:
1920  SCIP_CALL( readObjective(scip, pipinput) );
1921  break;
1922 
1923  case PIP_CONSTRAINTS:
1924  SCIP_CALL( readConstraints(scip, pipinput) );
1925  break;
1926 
1927  case PIP_BOUNDS:
1928  SCIP_CALL( readBounds(scip, pipinput) );
1929  break;
1930 
1931  case PIP_GENERALS:
1932  SCIP_CALL( readGenerals(scip, pipinput) );
1933  break;
1934 
1935  case PIP_BINARIES:
1936  SCIP_CALL( readBinaries(scip, pipinput) );
1937  break;
1938 
1939  case PIP_END: /* this is already handled in the while() loop */
1940  default:
1941  SCIPerrorMessage("invalid PIP file section <%d>\n", pipinput->section);
1942  return SCIP_INVALIDDATA;
1943  }
1944  }
1945 
1946  /* close file */
1947  SCIPfclose(pipinput->file);
1948 
1949  return SCIP_OKAY;
1950 }
1951 
1952 
1953 /*
1954  * Local methods (for writing)
1955  */
1956 
1957 /** hash key retrieval function for variables */
1958 static
1959 SCIP_DECL_HASHGETKEY(hashGetKeyVar)
1960 { /*lint --e{715}*/
1961  return elem;
1962 }
1963 
1964 /** returns TRUE iff the indices of both variables are equal */
1965 static
1966 SCIP_DECL_HASHKEYEQ(hashKeyEqVar)
1967 { /*lint --e{715}*/
1968  if ( key1 == key2 )
1969  return TRUE;
1970  return FALSE;
1971 }
1972 
1973 /** returns the hash value of the key */
1974 static
1975 SCIP_DECL_HASHKEYVAL(hashKeyValVar)
1976 { /*lint --e{715}*/
1977  assert( SCIPvarGetIndex((SCIP_VAR*) key) >= 0 );
1978  return (unsigned int) SCIPvarGetIndex((SCIP_VAR*) key);
1979 }
1980 
1981 /** transforms given variables, scalars, and constant to the corresponding active variables, scalars, and constant */
1982 static
1984  SCIP* scip, /**< SCIP data structure */
1985  SCIP_VAR** vars, /**< vars array to get active variables for */
1986  SCIP_Real* scalars, /**< scalars a_1, ..., a_n in linear sum a_1*x_1 + ... + a_n*x_n + c */
1987  int* nvars, /**< pointer to number of variables and values in vars and vals array */
1988  SCIP_Real* constant, /**< pointer to constant c in linear sum a_1*x_1 + ... + a_n*x_n + c */
1989  SCIP_Bool transformed /**< transformed constraint? */
1990  )
1991 {
1992  int requiredsize;
1993  int v;
1994 
1995  assert( scip != NULL );
1996  assert( vars != NULL );
1997  assert( scalars != NULL );
1998  assert( nvars != NULL );
1999  assert( constant != NULL );
2000 
2001  if( transformed )
2002  {
2003  SCIP_CALL( SCIPgetProbvarLinearSum(scip, vars, scalars, nvars, *nvars, constant, &requiredsize, TRUE) );
2004 
2005  if( requiredsize > *nvars )
2006  {
2007  SCIP_CALL( SCIPreallocBufferArray(scip, &vars, requiredsize) );
2008  SCIP_CALL( SCIPreallocBufferArray(scip, &scalars, requiredsize) );
2009 
2010  SCIP_CALL( SCIPgetProbvarLinearSum(scip, vars, scalars, nvars, requiredsize, constant, &requiredsize, TRUE) );
2011  assert( requiredsize <= *nvars );
2012  }
2013  }
2014  else
2015  {
2016  for( v = 0; v < *nvars; ++v )
2017  SCIP_CALL( SCIPvarGetOrigvarSum(&vars[v], &scalars[v], constant) );
2018  }
2019  return SCIP_OKAY;
2020 }
2021 
2022 /** clears the given line buffer */
2023 static
2025  char* linebuffer, /**< line */
2026  int* linecnt /**< number of characters in line */
2027  )
2028 {
2029  assert( linebuffer != NULL );
2030  assert( linecnt != NULL );
2031 
2032  (*linecnt) = 0;
2033  linebuffer[0] = '\0';
2034 }
2035 
2036 /** ends the given line with '\\0' and prints it to the given file stream */
2037 static
2038 void endLine(
2039  SCIP* scip, /**< SCIP data structure */
2040  FILE* file, /**< output file (or NULL for standard output) */
2041  char* linebuffer, /**< line */
2042  int* linecnt /**< number of characters in line */
2043  )
2044 {
2045  assert( scip != NULL );
2046  assert( linebuffer != NULL );
2047  assert( linecnt != NULL );
2048 
2049  if( (*linecnt) > 0 )
2050  {
2051  linebuffer[(*linecnt)] = '\0';
2052  SCIPinfoMessage(scip, file, "%s\n", linebuffer);
2053  clearLine(linebuffer, linecnt);
2054  }
2055 }
2056 
2057 /** appends extension to line and prints it to the give file stream if the
2058  * line exceeded the length given in the define PIP_PRINTLEN */
2059 static
2061  SCIP* scip, /**< SCIP data structure */
2062  FILE* file, /**< output file (or NULL for standard output) */
2063  char* linebuffer, /**< line */
2064  int* linecnt, /**< number of characters in line */
2065  const char* extension /**< string to extent the line */
2066  )
2067 {
2068  assert( scip != NULL );
2069  assert( linebuffer != NULL );
2070  assert( linecnt != NULL );
2071  assert( extension != NULL );
2072  assert( strlen(linebuffer) + strlen(extension) < PIP_MAX_PRINTLEN );
2073 
2074  /* NOTE: avoid
2075  * sprintf(linebuffer, "%s%s", linebuffer, extension);
2076  * because of overlapping memory areas in memcpy used in sprintf.
2077  */
2078  strncat(linebuffer, extension, PIP_MAX_PRINTLEN - strlen(linebuffer));
2079 
2080  (*linecnt) += (int) strlen(extension);
2081 
2082  SCIPdebugMessage("linebuffer <%s>, length = %lu\n", linebuffer, (unsigned long)strlen(linebuffer));
2083 
2084  if( (*linecnt) > PIP_PRINTLEN )
2085  endLine(scip, file, linebuffer, linecnt);
2086 }
2087 
2088 
2089 /* print row in PIP format to file stream */
2090 static
2092  SCIP* scip, /**< SCIP data structure */
2093  FILE* file, /**< output file (or NULL for standard output) */
2094  const char* rowname, /**< row name */
2095  const char* rownameextension, /**< row name extension */
2096  const char* type, /**< row type ("=", "<=", or ">=") */
2097  SCIP_VAR** linvars, /**< array of linear variables */
2098  SCIP_Real* linvals, /**< array of linear coefficient values */
2099  int nlinvars, /**< number of linear variables */
2100  SCIP_QUADVARTERM* quadvarterms, /**< quadratic variable terms */
2101  int nquadvarterms, /**< number of quadratic variable terms */
2102  SCIP_BILINTERM* bilinterms, /**< bilinear terms */
2103  int nbilinterms, /**< number of bilinear terms */
2104  SCIP_Real rhs /**< right hand side */
2105  )
2106 {
2107  int v;
2108  char linebuffer[PIP_MAX_PRINTLEN] = { '\0' };
2109  int linecnt;
2110 
2111  SCIP_VAR* var;
2112  char varname[PIP_MAX_NAMELEN];
2113  char varname2[PIP_MAX_NAMELEN];
2114  char consname[PIP_MAX_NAMELEN + 1]; /* an extra character for ':' */
2115  char buffer[PIP_MAX_PRINTLEN];
2116 
2117  assert( scip != NULL );
2118  assert( strcmp(type, "=") == 0 || strcmp(type, "<=") == 0 || strcmp(type, ">=") == 0 );
2119  assert( nlinvars == 0 || (linvars != NULL && linvals != NULL) );
2120  assert( nquadvarterms == 0 || quadvarterms != NULL );
2121 
2122  /* if there is a bilinear term, then there need to be at least two quadratic variables */
2123  assert( nbilinterms == 0 || (bilinterms != NULL && nquadvarterms >= 2) );
2124 
2125  clearLine(linebuffer, &linecnt);
2126 
2127  /* start each line with a space */
2128  appendLine(scip, file, linebuffer, &linecnt, " ");
2129 
2130  /* print row name */
2131  if ( strlen(rowname) > 0 || strlen(rownameextension) > 0 )
2132  {
2133  (void) SCIPsnprintf(consname, PIP_MAX_NAMELEN + 1, "%s%s:", rowname, rownameextension);
2134  appendLine(scip, file, linebuffer, &linecnt, consname);
2135  }
2136 
2137  /* print coefficients */
2138  for( v = 0; v < nlinvars; ++v )
2139  {
2140  var = linvars[v];
2141  assert( var != NULL );
2142 
2143  /* we start a new line; therefore we tab this line */
2144  if ( linecnt == 0 )
2145  appendLine(scip, file, linebuffer, &linecnt, " ");
2146 
2147  (void) SCIPsnprintf(varname, PIP_MAX_NAMELEN, "%s", SCIPvarGetName(var));
2148  (void) SCIPsnprintf(buffer, PIP_MAX_PRINTLEN, " %+.15g %s", linvals[v], varname);
2149 
2150  appendLine(scip, file, linebuffer, &linecnt, buffer);
2151  }
2152 
2153  /* print quadratic part */
2154  if( nquadvarterms > 0 )
2155  {
2156  /* print linear coefficients of quadratic variables */
2157  for( v = 0; v < nquadvarterms; ++v )
2158  {
2159  if( quadvarterms[v].lincoef == 0.0 )
2160  continue;
2161 
2162  /* we start a new line; therefore we tab this line */
2163  if (linecnt == 0 )
2164  appendLine(scip, file, linebuffer, &linecnt, " ");
2165 
2166  (void) SCIPsnprintf(varname, PIP_MAX_NAMELEN, "%s", SCIPvarGetName(quadvarterms[v].var));
2167  (void) SCIPsnprintf(buffer, PIP_MAX_PRINTLEN, " %+.15g %s", quadvarterms[v].lincoef, varname);
2168 
2169  appendLine(scip, file, linebuffer, &linecnt, buffer);
2170  }
2171 
2172  /* start quadratic part */
2173 
2174  /* print square terms */
2175  for( v = 0; v < nquadvarterms; ++v )
2176  {
2177  if( quadvarterms[v].sqrcoef == 0.0 )
2178  continue;
2179 
2180  /* we start a new line; therefore we tab this line */
2181  if (linecnt == 0 )
2182  appendLine(scip, file, linebuffer, &linecnt, " ");
2183 
2184  (void) SCIPsnprintf(varname, PIP_MAX_NAMELEN, "%s", SCIPvarGetName(quadvarterms[v].var));
2185  (void) SCIPsnprintf(buffer, PIP_MAX_PRINTLEN, " %+.15g %s^2", quadvarterms[v].sqrcoef, varname);
2186 
2187  appendLine(scip, file, linebuffer, &linecnt, buffer);
2188  }
2189 
2190  /* print bilinear terms */
2191  for( v = 0; v < nbilinterms; ++v )
2192  {
2193  /* we start a new line; therefore we tab this line */
2194  if (linecnt == 0 )
2195  appendLine(scip, file, linebuffer, &linecnt, " ");
2196 
2197  (void) SCIPsnprintf(varname, PIP_MAX_NAMELEN, "%s", SCIPvarGetName(bilinterms[v].var1));
2198  (void) SCIPsnprintf(varname2, PIP_MAX_NAMELEN, "%s", SCIPvarGetName(bilinterms[v].var2));
2199  (void) SCIPsnprintf(buffer, PIP_MAX_PRINTLEN, " %+.15g %s * %s", bilinterms[v].coef, varname, varname2);
2200 
2201  appendLine(scip, file, linebuffer, &linecnt, buffer);
2202  }
2203  }
2204 
2205  /* print right hand side */
2206  if( SCIPisZero(scip, rhs) )
2207  rhs = 0.0;
2208 
2209  (void) SCIPsnprintf(buffer, PIP_MAX_PRINTLEN, " %s %+.15g", type, rhs);
2210 
2211  /* we start a new line; therefore we tab this line */
2212  if (linecnt == 0 )
2213  appendLine(scip, file, linebuffer, &linecnt, " ");
2214  appendLine(scip, file, linebuffer, &linecnt, buffer);
2215 
2216  endLine(scip, file, linebuffer, &linecnt);
2217 }
2218 
2219 
2220 /* print row in PIP format to file stream */
2221 static
2223  SCIP* scip, /**< SCIP data structure */
2224  FILE* file, /**< output file (or NULL for standard output) */
2225  const char* rowname, /**< row name */
2226  const char* rownameextension, /**< row name extension */
2227  const char* type, /**< row type ("=", "<=", or ">=") */
2228  SCIP_VAR** linvars, /**< array of linear variables */
2229  SCIP_Real* linvals, /**< array of linear coefficient values */
2230  int nlinvars, /**< number of linear variables */
2231  SCIP_EXPRTREE** exprtrees, /**< expression trees */
2232  SCIP_Real* exprtreecoefs, /**< coefficients of expression trees */
2233  int nexprtrees, /**< number of expression trees */
2234  SCIP_Real rhs /**< right hand side */
2235  )
2236 {
2237  int v;
2238  int c;
2239  int e;
2240  char linebuffer[PIP_MAX_PRINTLEN] = { '\0' };
2241  int linecnt;
2242 
2243  SCIP_VAR* var;
2244  char varname[PIP_MAX_NAMELEN];
2245  char varname2[PIP_MAX_NAMELEN];
2246  char consname[PIP_MAX_NAMELEN + 1]; /* an extra character for ':' */
2247  char buffer[PIP_MAX_PRINTLEN];
2248 
2249  assert( scip != NULL );
2250  assert( strcmp(type, "=") == 0 || strcmp(type, "<=") == 0 || strcmp(type, ">=") == 0 );
2251  assert( nlinvars == 0 || (linvars != NULL && linvals != NULL) );
2252  assert( nexprtrees == 0 || exprtrees != NULL );
2253  assert( nexprtrees == 0 || exprtreecoefs != NULL );
2254 
2255  clearLine(linebuffer, &linecnt);
2256 
2257  /* start each line with a space */
2258  appendLine(scip, file, linebuffer, &linecnt, " ");
2259 
2260  /* print row name */
2261  if ( strlen(rowname) > 0 || strlen(rownameextension) > 0 )
2262  {
2263  (void) SCIPsnprintf(consname, PIP_MAX_NAMELEN + 1, "%s%s:", rowname, rownameextension);
2264  appendLine(scip, file, linebuffer, &linecnt, consname);
2265  }
2266 
2267  /* print coefficients */
2268  for( v = 0; v < nlinvars; ++v )
2269  {
2270  var = linvars[v];
2271  assert( var != NULL );
2272 
2273  /* we start a new line; therefore we tab this line */
2274  if ( linecnt == 0 )
2275  appendLine(scip, file, linebuffer, &linecnt, " ");
2276 
2277  (void) SCIPsnprintf(varname, PIP_MAX_NAMELEN, "%s", SCIPvarGetName(var));
2278  (void) SCIPsnprintf(buffer, PIP_MAX_PRINTLEN, " %+.15g %s", linvals[v], varname);
2279 
2280  appendLine(scip, file, linebuffer, &linecnt, buffer);
2281  }
2282 
2283  /* print nonlinear part */
2284  for( e = 0; e < nexprtrees; ++e )
2285  {
2286  SCIP_VAR** vars;
2287  SCIP_EXPR* expr;
2288  SCIP_EXPR** children;
2289  int nchildren;
2290 
2291  vars = SCIPexprtreeGetVars(exprtrees[e]);
2292  expr = SCIPexprtreeGetRoot(exprtrees[e]);
2293  children = SCIPexprGetChildren(expr);
2294  nchildren = SCIPexprGetNChildren(expr);
2295  assert(nchildren == 0 || children != NULL);
2296 
2297  /* we start a new line; therefore we tab this line */
2298  if( linecnt == 0 )
2299  appendLine(scip, file, linebuffer, &linecnt, " ");
2300 
2301  /* assert that all children of expr correspond to variables */
2302 #ifndef NDEBUG
2303  for( c = 0; c < nchildren; ++c )
2304  {
2305  assert(SCIPexprGetOperator(children[c]) == SCIP_EXPR_VARIDX);
2306  assert(SCIPexprGetOpIndex(children[c]) >= 0);
2307  assert(SCIPexprGetOpIndex(children[c]) < SCIPexprtreeGetNVars(exprtrees[e]));
2308  }
2309 #endif
2310 
2311  switch( SCIPexprGetOperator(expr) )
2312  {
2313  case SCIP_EXPR_CONST:
2314  {
2315  (void) SCIPsnprintf(buffer, PIP_MAX_PRINTLEN, " %+.15g", exprtreecoefs[e] * SCIPexprGetOpReal(expr));
2316  appendLine(scip, file, linebuffer, &linecnt, buffer);
2317 
2318  break;
2319  }
2320 
2321  case SCIP_EXPR_VARIDX:
2322  {
2323  assert(SCIPexprGetOpIndex(expr) >= 0);
2324  assert(SCIPexprGetOpIndex(expr) < SCIPexprtreeGetNVars(exprtrees[e]));
2325  (void) SCIPsnprintf(varname, PIP_MAX_NAMELEN, "%s", SCIPvarGetName(vars[SCIPexprGetOpIndex(expr)]));
2326  (void) SCIPsnprintf(buffer, PIP_MAX_PRINTLEN, " %+.15g %s", exprtreecoefs[e], varname);
2327 
2328  appendLine(scip, file, linebuffer, &linecnt, buffer);
2329  break;
2330  }
2331 
2332  case SCIP_EXPR_PLUS:
2333  {
2334  (void) SCIPsnprintf(varname, PIP_MAX_NAMELEN, "%s", SCIPvarGetName(vars[SCIPexprGetOpIndex(children[0])]));
2335  (void) SCIPsnprintf(varname2, PIP_MAX_NAMELEN, "%s", SCIPvarGetName(vars[SCIPexprGetOpIndex(children[1])]));
2336  (void) SCIPsnprintf(buffer, PIP_MAX_PRINTLEN, " %+.15g %s %+.15g %s", exprtreecoefs[e], varname, exprtreecoefs[e], varname2);
2337 
2338  appendLine(scip, file, linebuffer, &linecnt, buffer);
2339  break;
2340  }
2341 
2342  case SCIP_EXPR_MINUS:
2343  {
2344  (void) SCIPsnprintf(varname, PIP_MAX_NAMELEN, "%s", SCIPvarGetName(vars[SCIPexprGetOpIndex(children[0])]));
2345  (void) SCIPsnprintf(varname2, PIP_MAX_NAMELEN, "%s", SCIPvarGetName(vars[SCIPexprGetOpIndex(children[1])]));
2346  (void) SCIPsnprintf(buffer, PIP_MAX_PRINTLEN, " %+.15g %s %+.15g %s", exprtreecoefs[e], varname, -exprtreecoefs[e], varname2);
2347 
2348  appendLine(scip, file, linebuffer, &linecnt, buffer);
2349  break;
2350  }
2351 
2352  case SCIP_EXPR_MUL:
2353  {
2354  (void) SCIPsnprintf(varname, PIP_MAX_NAMELEN, "%s", SCIPvarGetName(vars[SCIPexprGetOpIndex(children[0])]));
2355  (void) SCIPsnprintf(varname2, PIP_MAX_NAMELEN, "%s", SCIPvarGetName(vars[SCIPexprGetOpIndex(children[1])]));
2356  (void) SCIPsnprintf(buffer, PIP_MAX_PRINTLEN, " %+.15g %s %s", exprtreecoefs[e], varname, varname2);
2357 
2358  appendLine(scip, file, linebuffer, &linecnt, buffer);
2359  break;
2360  }
2361 
2362  case SCIP_EXPR_SQUARE:
2363  {
2364  (void) SCIPsnprintf(varname, PIP_MAX_NAMELEN, "%s", SCIPvarGetName(vars[SCIPexprGetOpIndex(children[0])]));
2365  (void) SCIPsnprintf(buffer, PIP_MAX_PRINTLEN, " %+.15g %s^2", exprtreecoefs[e], varname);
2366 
2367  appendLine(scip, file, linebuffer, &linecnt, buffer);
2368  break;
2369  }
2370 
2371  case SCIP_EXPR_SQRT:
2372  {
2373  (void) SCIPsnprintf(varname, PIP_MAX_NAMELEN, "%s", SCIPvarGetName(vars[SCIPexprGetOpIndex(children[0])]));
2374  (void) SCIPsnprintf(buffer, PIP_MAX_PRINTLEN, " %+.15g %s^0.5", exprtreecoefs[e], varname);
2375 
2376  appendLine(scip, file, linebuffer, &linecnt, buffer);
2377  break;
2378  }
2379 
2380  case SCIP_EXPR_INTPOWER:
2381  {
2382  (void) SCIPsnprintf(varname, PIP_MAX_NAMELEN, "%s", SCIPvarGetName(vars[SCIPexprGetOpIndex(children[0])]));
2383  (void) SCIPsnprintf(buffer, PIP_MAX_PRINTLEN, " %+.15g %s^%d", exprtreecoefs[e], varname, SCIPexprGetIntPowerExponent(expr));
2384 
2385  appendLine(scip, file, linebuffer, &linecnt, buffer);
2386  break;
2387  }
2388 
2389  case SCIP_EXPR_REALPOWER:
2390  {
2391  (void) SCIPsnprintf(varname, PIP_MAX_NAMELEN, "%s", SCIPvarGetName(vars[SCIPexprGetOpIndex(children[0])]));
2392  (void) SCIPsnprintf(buffer, PIP_MAX_PRINTLEN, " %+.15g %s^%.15g", exprtreecoefs[e], varname, SCIPexprGetRealPowerExponent(expr));
2393 
2394  appendLine(scip, file, linebuffer, &linecnt, buffer);
2395  break;
2396  }
2397 
2398  case SCIP_EXPR_SUM:
2399  {
2400  for( c = 0; c < nchildren; ++c )
2401  {
2402  /* we start a new line; therefore we tab this line */
2403  if( linecnt == 0 )
2404  appendLine(scip, file, linebuffer, &linecnt, " ");
2405 
2406  (void) SCIPsnprintf(varname, PIP_MAX_NAMELEN, "%s", SCIPvarGetName(vars[SCIPexprGetOpIndex(children[c])]));
2407  (void) SCIPsnprintf(buffer, PIP_MAX_PRINTLEN, " %+.15g %s", exprtreecoefs[e], varname);
2408 
2409  appendLine(scip, file, linebuffer, &linecnt, buffer);
2410  }
2411 
2412  break;
2413  }
2414 
2415  case SCIP_EXPR_PRODUCT:
2416  {
2417  (void) SCIPsnprintf(buffer, PIP_MAX_PRINTLEN, " %+.15g", exprtreecoefs[e]);
2418  appendLine(scip, file, linebuffer, &linecnt, buffer);
2419 
2420  for( c = 0; c < nchildren; ++c )
2421  {
2422  /* we start a new line; therefore we tab this line */
2423  if( linecnt == 0 )
2424  appendLine(scip, file, linebuffer, &linecnt, " ");
2425 
2426  (void) SCIPsnprintf(varname, PIP_MAX_NAMELEN, " %s", SCIPvarGetName(vars[SCIPexprGetOpIndex(children[c])]));
2427  (void) SCIPsnprintf(buffer, PIP_MAX_PRINTLEN, varname);
2428 
2429  appendLine(scip, file, linebuffer, &linecnt, buffer);
2430  }
2431 
2432  break;
2433  }
2434 
2435  case SCIP_EXPR_LINEAR:
2436  {
2437  if( SCIPexprGetLinearConstant(expr) != 0.0 )
2438  {
2439  (void) SCIPsnprintf(buffer, PIP_MAX_PRINTLEN, " %+.15g ", exprtreecoefs[e] * SCIPexprGetLinearConstant(expr));
2440  appendLine(scip, file, linebuffer, &linecnt, buffer);
2441  }
2442 
2443  for( c = 0; c < nchildren; ++c )
2444  {
2445  /* we start a new line; therefore we tab this line */
2446  if( linecnt == 0 )
2447  appendLine(scip, file, linebuffer, &linecnt, " ");
2448 
2449  (void) SCIPsnprintf(varname, PIP_MAX_NAMELEN, "%s", SCIPvarGetName(vars[SCIPexprGetOpIndex(children[c])]));
2450  (void) SCIPsnprintf(buffer, PIP_MAX_PRINTLEN, " %+.15g %s", exprtreecoefs[e] * SCIPexprGetLinearCoefs(expr)[c], varname);
2451 
2452  appendLine(scip, file, linebuffer, &linecnt, buffer);
2453  }
2454 
2455  break;
2456  }
2457 
2458  case SCIP_EXPR_QUADRATIC:
2459  {
2460  int q;
2461 
2462  if( SCIPexprGetQuadConstant(expr) != 0.0 )
2463  {
2464  (void) SCIPsnprintf(buffer, PIP_MAX_PRINTLEN, " %+.15g ", exprtreecoefs[e] * SCIPexprGetQuadConstant(expr));
2465  appendLine(scip, file, linebuffer, &linecnt, buffer);
2466  }
2467 
2468  if( SCIPexprGetQuadLinearCoefs(expr) != NULL )
2469  {
2470  for( c = 0; c < nchildren; ++c )
2471  {
2472  if( SCIPexprGetQuadLinearCoefs(expr)[c] == 0.0 )
2473  continue;
2474 
2475  /* we start a new line; therefore we tab this line */
2476  if( linecnt == 0 )
2477  appendLine(scip, file, linebuffer, &linecnt, " ");
2478 
2479  (void) SCIPsnprintf(varname, PIP_MAX_NAMELEN, "%s", SCIPvarGetName(vars[SCIPexprGetOpIndex(children[c])]));
2480  (void) SCIPsnprintf(buffer, PIP_MAX_PRINTLEN, " %+.15g %s", exprtreecoefs[e] * SCIPexprGetQuadLinearCoefs(expr)[c], varname);
2481 
2482  appendLine(scip, file, linebuffer, &linecnt, buffer);
2483  }
2484  }
2485 
2486  for( q = 0; q < SCIPexprGetNQuadElements(expr); ++q )
2487  {
2488  /* we start a new line; therefore we tab this line */
2489  if( linecnt == 0 )
2490  appendLine(scip, file, linebuffer, &linecnt, " ");
2491 
2492  (void) SCIPsnprintf(varname, PIP_MAX_NAMELEN, "%s", SCIPvarGetName(vars[SCIPexprGetOpIndex(children[SCIPexprGetQuadElements(expr)[q].idx1])]));
2493 
2494  if( SCIPexprGetQuadElements(expr)[q].idx1 == SCIPexprGetQuadElements(expr)[q].idx2 )
2495  {
2496  /* square term */
2497  (void) SCIPsnprintf(buffer, PIP_MAX_PRINTLEN, " %+.15g %s^2", exprtreecoefs[e] * SCIPexprGetQuadElements(expr)[q].coef, varname);
2498  }
2499  else
2500  {
2501  /* bilinear term */
2502  (void) SCIPsnprintf(varname2, PIP_MAX_NAMELEN, "%s", SCIPvarGetName(vars[SCIPexprGetOpIndex(children[SCIPexprGetQuadElements(expr)[q].idx2])]));
2503  (void) SCIPsnprintf(buffer, PIP_MAX_PRINTLEN, " %+.15g %s %s", exprtreecoefs[e] * SCIPexprGetQuadElements(expr)[q].coef, varname, varname2);
2504  }
2505 
2506  appendLine(scip, file, linebuffer, &linecnt, buffer);
2507  }
2508 
2509  break;
2510  }
2511 
2512  case SCIP_EXPR_POLYNOMIAL:
2513  {
2514  SCIP_EXPRDATA_MONOMIAL* monomial;
2515  int m;
2516  int f;
2517 
2518  if( SCIPexprGetPolynomialConstant(expr) != 0.0 )
2519  {
2520  (void) SCIPsnprintf(buffer, PIP_MAX_PRINTLEN, " %+.15g ", exprtreecoefs[e] * SCIPexprGetPolynomialConstant(expr));
2521  appendLine(scip, file, linebuffer, &linecnt, buffer);
2522  }
2523 
2524  for( m = 0; m < SCIPexprGetNMonomials(expr); ++m )
2525  {
2526  monomial = SCIPexprGetMonomials(expr)[m];
2527  assert(monomial != NULL);
2528 
2529  (void) SCIPsnprintf(buffer, PIP_MAX_PRINTLEN, " %+.15g", exprtreecoefs[e] * SCIPexprGetMonomialCoef(monomial));
2530  appendLine(scip, file, linebuffer, &linecnt, buffer);
2531 
2532  for( f = 0; f < SCIPexprGetMonomialNFactors(monomial); ++f )
2533  {
2534  /* we start a new line; therefore we tab this line */
2535  if( linecnt == 0 )
2536  appendLine(scip, file, linebuffer, &linecnt, " ");
2537 
2538  (void) SCIPsnprintf(varname, PIP_MAX_NAMELEN, "%s", SCIPvarGetName(vars[SCIPexprGetOpIndex(children[SCIPexprGetMonomialChildIndices(monomial)[f]])]));
2539  if( SCIPexprGetMonomialExponents(monomial)[f] != 1.0 )
2540  (void) SCIPsnprintf(buffer, PIP_MAX_PRINTLEN, " %s^%.15g", varname, SCIPexprGetMonomialExponents(monomial)[f]);
2541  else
2542  (void) SCIPsnprintf(buffer, PIP_MAX_PRINTLEN, " %s", varname);
2543  appendLine(scip, file, linebuffer, &linecnt, buffer);
2544  }
2545  }
2546 
2547  break;
2548  }
2549 
2550  default:
2551  {
2552  /* this should have been caught in SCIPwritePip before */
2553  SCIPerrorMessage("unsupported operator <%s> in writing of polynomial nonlinear constraint\n", SCIPexpropGetName(SCIPexprGetOperator(expr)));
2554  return;
2555  } /*lint !e788*/
2556  } /*lint !e788*/
2557  }
2558 
2559  /* print right hand side */
2560  if( SCIPisZero(scip, rhs) )
2561  rhs = 0.0;
2562 
2563  (void) SCIPsnprintf(buffer, PIP_MAX_PRINTLEN, " %s %+.15g", type, rhs);
2564 
2565  /* we start a new line; therefore we tab this line */
2566  if (linecnt == 0 )
2567  appendLine(scip, file, linebuffer, &linecnt, " ");
2568  appendLine(scip, file, linebuffer, &linecnt, buffer);
2569 
2570  endLine(scip, file, linebuffer, &linecnt);
2571 }
2572 
2573 
2574 /** prints given (linear or) quadratic constraint information in LP format to file stream */
2575 static
2577  SCIP* scip, /**< SCIP data structure */
2578  FILE* file, /**< output file (or NULL for standard output) */
2579  const char* rowname, /**< name of the row */
2580  SCIP_VAR** linvars, /**< array of linear variables */
2581  SCIP_Real* linvals, /**< array of linear coefficients values (or NULL if all linear coefficient values are 1) */
2582  int nlinvars, /**< number of linear variables */
2583  SCIP_QUADVARTERM* quadvarterms, /**< quadratic variable terms */
2584  int nquadvarterms, /**< number of quadratic variable terms */
2585  SCIP_BILINTERM* bilinterms, /**< bilinear terms */
2586  int nbilinterms, /**< number of bilinear terms */
2587  SCIP_Real lhs, /**< left hand side */
2588  SCIP_Real rhs, /**< right hand side */
2589  SCIP_Bool transformed /**< transformed constraint? */
2590  )
2591 {
2592  int v;
2593  SCIP_VAR** activevars = NULL;
2594  SCIP_Real* activevals = NULL;
2595  int nactivevars;
2596  SCIP_Real activeconstant = 0.0;
2597 
2598  assert( scip != NULL );
2599  assert( rowname != NULL );
2600 
2601  assert( nlinvars == 0 || linvars != NULL );
2602  assert( nquadvarterms == 0 || quadvarterms != NULL );
2603  assert( nbilinterms == 0 || bilinterms != NULL );
2604 
2605  assert( lhs <= rhs );
2606 
2607  if( SCIPisInfinity(scip, -lhs) && SCIPisInfinity(scip, rhs) )
2608  return SCIP_OKAY;
2609 
2610  nactivevars = nlinvars;
2611  if( nlinvars > 0 )
2612  {
2613  /* duplicate variable and value array */
2614  SCIP_CALL( SCIPduplicateBufferArray(scip, &activevars, linvars, nactivevars ) );
2615  if( linvals != NULL )
2616  {
2617  SCIP_CALL( SCIPduplicateBufferArray(scip, &activevals, linvals, nactivevars ) );
2618  }
2619  else
2620  {
2621  SCIP_CALL( SCIPallocBufferArray(scip, &activevals, nactivevars) );
2622 
2623  for( v = 0; v < nactivevars; ++v )
2624  activevals[v] = 1.0;
2625  }
2626 
2627  /* retransform given variables to active variables */
2628  SCIP_CALL( getActiveVariables(scip, activevars, activevals, &nactivevars, &activeconstant, transformed) );
2629  }
2630 
2631  /* print row(s) in LP format */
2632  if( SCIPisEQ(scip, lhs, rhs) )
2633  {
2634  assert( !SCIPisInfinity(scip, rhs) );
2635 
2636  /* equal constraint */
2637  printRow(scip, file, rowname, "", "=", activevars, activevals, nactivevars,
2638  quadvarterms, nquadvarterms, bilinterms, nbilinterms,
2639  rhs - activeconstant);
2640  }
2641  else
2642  {
2643  if( !SCIPisInfinity(scip, -lhs) )
2644  {
2645  /* print inequality ">=" */
2646  printRow(scip, file, rowname, SCIPisInfinity(scip, rhs) ? "" : "_lhs", ">=",
2647  activevars, activevals, nactivevars,
2648  quadvarterms, nquadvarterms, bilinterms, nbilinterms,
2649  lhs - activeconstant);
2650  }
2651  if( !SCIPisInfinity(scip, rhs) )
2652  {
2653  /* print inequality "<=" */
2654  printRow(scip, file, rowname, SCIPisInfinity(scip, -lhs) ? "" : "_rhs", "<=",
2655  activevars, activevals, nactivevars,
2656  quadvarterms, nquadvarterms, bilinterms, nbilinterms,
2657  rhs - activeconstant);
2658  }
2659  }
2660 
2661  if( nlinvars > 0 )
2662  {
2663  /* free buffer arrays */
2664  SCIPfreeBufferArray(scip, &activevars);
2665  SCIPfreeBufferArray(scip, &activevals);
2666  }
2667 
2668  return SCIP_OKAY;
2669 }
2670 
2671 /** prints given nonlinear constraint information in LP format to file stream */
2672 static
2674  SCIP* scip, /**< SCIP data structure */
2675  FILE* file, /**< output file (or NULL for standard output) */
2676  const char* rowname, /**< name of the row */
2677  SCIP_VAR** linvars, /**< array of linear variables */
2678  SCIP_Real* linvals, /**< array of linear coefficients values (or NULL if all linear coefficient values are 1) */
2679  int nlinvars, /**< number of linear variables */
2680  SCIP_EXPRTREE** exprtrees, /**< expression trees */
2681  SCIP_Real* exprtreecoefs, /**< coefficients of expression trees */
2682  int nexprtrees, /**< number of expression trees */
2683  SCIP_Real lhs, /**< left hand side */
2684  SCIP_Real rhs, /**< right hand side */
2685  SCIP_Bool transformed /**< transformed constraint? */
2686  )
2687 {
2688  int v;
2689  SCIP_VAR** activevars = NULL;
2690  SCIP_Real* activevals = NULL;
2691  int nactivevars;
2692  SCIP_Real activeconstant = 0.0;
2693 
2694  assert( scip != NULL );
2695  assert( rowname != NULL );
2696 
2697  assert( nlinvars == 0 || linvars != NULL );
2698  assert( nexprtrees == 0 || exprtrees != NULL );
2699  assert( nexprtrees == 0 || exprtreecoefs != NULL );
2700 
2701  assert( lhs <= rhs );
2702 
2703  if( SCIPisInfinity(scip, -lhs) && SCIPisInfinity(scip, rhs) )
2704  return SCIP_OKAY;
2705 
2706  nactivevars = nlinvars;
2707  if( nlinvars > 0 )
2708  {
2709  /* duplicate variable and value array */
2710  SCIP_CALL( SCIPduplicateBufferArray(scip, &activevars, linvars, nactivevars ) );
2711  if( linvals != NULL )
2712  {
2713  SCIP_CALL( SCIPduplicateBufferArray(scip, &activevals, linvals, nactivevars ) );
2714  }
2715  else
2716  {
2717  SCIP_CALL( SCIPallocBufferArray(scip, &activevals, nactivevars) );
2718 
2719  for( v = 0; v < nactivevars; ++v )
2720  activevals[v] = 1.0;
2721  }
2722 
2723  /* retransform given variables to active variables */
2724  SCIP_CALL( getActiveVariables(scip, activevars, activevals, &nactivevars, &activeconstant, transformed) );
2725  }
2726 
2727  /* print row(s) in LP format */
2728  if( SCIPisEQ(scip, lhs, rhs) )
2729  {
2730  assert( !SCIPisInfinity(scip, rhs) );
2731 
2732  /* equal constraint */
2733  printRowNl(scip, file, rowname, "", "=", activevars, activevals, nactivevars,
2734  exprtrees, exprtreecoefs, nexprtrees,
2735  rhs - activeconstant);
2736  }
2737  else
2738  {
2739  if( !SCIPisInfinity(scip, -lhs) )
2740  {
2741  /* print inequality ">=" */
2742  printRowNl(scip, file, rowname, SCIPisInfinity(scip, rhs) ? "" : "_lhs", ">=",
2743  activevars, activevals, nactivevars,
2744  exprtrees, exprtreecoefs, nexprtrees,
2745  lhs - activeconstant);
2746  }
2747  if( !SCIPisInfinity(scip, rhs) )
2748  {
2749  /* print inequality "<=" */
2750  printRowNl(scip, file, rowname, SCIPisInfinity(scip, -lhs) ? "" : "_rhs", "<=",
2751  activevars, activevals, nactivevars,
2752  exprtrees, exprtreecoefs, nexprtrees,
2753  rhs - activeconstant);
2754  }
2755  }
2756 
2757  if( nlinvars > 0 )
2758  {
2759  /* free buffer arrays */
2760  SCIPfreeBufferArray(scip, &activevars);
2761  SCIPfreeBufferArray(scip, &activevals);
2762  }
2763 
2764  return SCIP_OKAY;
2765 }
2766 
2767 /** check whether given variables are aggregated and put them into an array without duplication */
2768 static
2770  SCIP* scip, /**< SCIP data structure */
2771  int nvars, /**< number of active variables in the problem */
2772  SCIP_VAR** vars, /**< variable array */
2773  int* nAggregatedVars, /**< number of aggregated variables on output */
2774  SCIP_VAR*** aggregatedVars, /**< array storing the aggregated variables on output */
2775  SCIP_HASHTABLE** varAggregated /**< hashtable for checking duplicates */
2776  )
2777 {
2778  int j;
2779 
2780  /* check variables */
2781  for (j = 0; j < nvars; ++j)
2782  {
2783  SCIP_VARSTATUS status;
2784  SCIP_VAR* var;
2785 
2786  var = vars[j];
2787  status = SCIPvarGetStatus(var);
2788 
2789  /* collect aggregated variables in a list */
2790  if( status >= SCIP_VARSTATUS_AGGREGATED )
2791  {
2792  assert( status == SCIP_VARSTATUS_AGGREGATED ||
2793  status == SCIP_VARSTATUS_MULTAGGR ||
2794  status == SCIP_VARSTATUS_NEGATED );
2795 
2796  if ( ! SCIPhashtableExists(*varAggregated, (void*) var) )
2797  {
2798  (*aggregatedVars)[(*nAggregatedVars)++] = var;
2799  SCIP_CALL( SCIPhashtableInsert(*varAggregated, (void*) var) );
2800  }
2801  }
2802  }
2803 
2804  return SCIP_OKAY;
2805 }
2806 
2807 
2808 /** print aggregated variable-constraints */
2809 static
2811  SCIP* scip, /**< SCIP data structure */
2812  FILE* file, /**< output file (or NULL for standard output) */
2813  SCIP_Bool transformed, /**< TRUE iff problem is the transformed problem */
2814  int nvars, /**< number of active variables in the problem */
2815  int nAggregatedVars, /**< number of aggregated variables */
2816  SCIP_VAR** aggregatedVars /**< array storing the aggregated variables */
2817  )
2818 {
2819  int j;
2820 
2821  SCIP_VAR** activevars;
2822  SCIP_Real* activevals;
2823  int nactivevars;
2824  SCIP_Real activeconstant = 0.0;
2825  char consname[PIP_MAX_NAMELEN];
2826 
2827  assert( scip != NULL );
2828 
2829  /* write aggregation constraints */
2830  SCIP_CALL( SCIPallocBufferArray(scip, &activevars, nvars) );
2831  SCIP_CALL( SCIPallocBufferArray(scip, &activevals, nvars) );
2832 
2833  for (j = 0; j < nAggregatedVars; ++j)
2834  {
2835  /* set up list to obtain substitution variables */
2836  nactivevars = 1;
2837 
2838  activevars[0] = aggregatedVars[j];
2839  activevals[0] = 1.0;
2840  activeconstant = 0.0;
2841 
2842  /* retransform given variables to active variables */
2843  SCIP_CALL( getActiveVariables(scip, activevars, activevals, &nactivevars, &activeconstant, transformed) );
2844 
2845  activevals[nactivevars] = -1.0;
2846  activevars[nactivevars] = aggregatedVars[j];
2847  ++nactivevars;
2848 
2849  /* output constraint */
2850  (void) SCIPsnprintf(consname, PIP_MAX_NAMELEN, "aggr_%s", SCIPvarGetName(aggregatedVars[j]));
2851  printRow(scip, file, consname, "", "=", activevars, activevals, nactivevars, NULL, 0, NULL, 0, - activeconstant);
2852  }
2853 
2854  /* free buffer arrays */
2855  SCIPfreeBufferArray(scip, &activevars);
2856  SCIPfreeBufferArray(scip, &activevals);
2857 
2858  return SCIP_OKAY;
2859 }
2860 
2861 /** method check if the variable names are not longer than PIP_MAX_NAMELEN */
2862 static
2864  SCIP* scip, /**< SCIP data structure */
2865  SCIP_VAR** vars, /**< array of variables */
2866  int nvars /**< number of variables */
2867  )
2868 {
2869  int v;
2870 
2871  assert(scip != NULL);
2872  assert(vars != NULL || nvars == 0);
2873 
2874  /* check if the variable names are not to long */
2875  for( v = 0; v < nvars; ++v )
2876  {
2877  if( strlen(SCIPvarGetName(vars[v])) > PIP_MAX_NAMELEN ) /*lint !e613*/
2878  {
2879  SCIPwarningMessage(scip, "there is a variable name which has to be cut down to %d characters; LP might be corrupted\n",
2880  PIP_MAX_NAMELEN - 1);
2881  return;
2882  }
2883  }
2884 }
2885 
2886 /** method check if the constraint names are not longer than PIP_MAX_NAMELEN */
2887 static
2889  SCIP* scip, /**< SCIP data structure */
2890  SCIP_CONS** conss, /**< array of constraints */
2891  int nconss, /**< number of constraints */
2892  SCIP_Bool transformed /**< TRUE iff problem is the transformed problem */
2893  )
2894 {
2895  int c;
2896  SCIP_CONS* cons;
2897  SCIP_CONSHDLR* conshdlr;
2898  const char* conshdlrname;
2899 
2900  assert( scip != NULL );
2901  assert( conss != NULL );
2902 
2903  for( c = 0; c < nconss; ++c )
2904  {
2905  cons = conss[c];
2906  assert(cons != NULL );
2907 
2908  /* in case the transformed is written only constraints are posted which are enabled in the current node */
2909  assert(!transformed || SCIPconsIsEnabled(cons));
2910 
2911  conshdlr = SCIPconsGetHdlr(cons);
2912  assert( conshdlr != NULL );
2913 
2914  conshdlrname = SCIPconshdlrGetName(conshdlr);
2915  assert( transformed == SCIPconsIsTransformed(cons) );
2916 
2917  if( strcmp(conshdlrname, "linear") == 0 )
2918  {
2919  SCIP_Real lhs = SCIPgetLhsLinear(scip, cons);
2920  SCIP_Real rhs = SCIPgetLhsLinear(scip, cons);
2921 
2922  if( (SCIPisEQ(scip, lhs, rhs) && strlen(SCIPconsGetName(conss[c])) > PIP_MAX_NAMELEN)
2923  || ( !SCIPisEQ(scip, lhs, rhs) && strlen(SCIPconsGetName(conss[c])) > PIP_MAX_NAMELEN - 4) )
2924  {
2925  SCIPwarningMessage(scip, "there is a constraint name which has to be cut down to %d characters;\n",
2926  PIP_MAX_NAMELEN - 1);
2927  return;
2928  }
2929  }
2930  else if( strlen(SCIPconsGetName(conss[c])) > PIP_MAX_NAMELEN )
2931  {
2932  SCIPwarningMessage(scip, "there is a constraint name which has to be cut down to %d characters;\n",
2933  PIP_MAX_NAMELEN - 1);
2934  return;
2935  }
2936  }
2937 }
2938 
2939 /** writes problem to file
2940  * @todo add writing cons_pseudoboolean
2941  */
2943  SCIP* scip, /**< SCIP data structure */
2944  FILE* file, /**< output file, or NULL if standard output should be used */
2945  const char* name, /**< problem name */
2946  SCIP_Bool transformed, /**< TRUE iff problem is the transformed problem */
2947  SCIP_OBJSENSE objsense, /**< objective sense */
2948  SCIP_Real objscale, /**< scalar applied to objective function; external objective value is
2949  * extobj = objsense * objscale * (intobj + objoffset) */
2950  SCIP_Real objoffset, /**< objective offset from bound shifting and fixing */
2951  SCIP_VAR** vars, /**< array with active variables ordered binary, integer, implicit, continuous */
2952  int nvars, /**< number of active variables in the problem */
2953  int nbinvars, /**< number of binary variables */
2954  int nintvars, /**< number of general integer variables */
2955  int nimplvars, /**< number of implicit integer variables */
2956  int ncontvars, /**< number of continuous variables */
2957  SCIP_CONS** conss, /**< array with constraints of the problem */
2958  int nconss, /**< number of constraints in the problem */
2959  SCIP_RESULT* result /**< pointer to store the result of the file writing call */
2960  )
2961 {
2962  int c;
2963  int v;
2964  int e;
2965 
2966  int linecnt;
2967  char linebuffer[PIP_MAX_PRINTLEN];
2968 
2969  char varname[PIP_MAX_NAMELEN];
2970  char buffer[PIP_MAX_PRINTLEN];
2971 
2972  SCIP_CONSHDLR* conshdlr;
2973  const char* conshdlrname;
2974  SCIP_CONS* cons;
2975  SCIP_CONS** consQuadratic;
2976  int nConsQuadratic;
2977  SCIP_CONS** consNonlinear;
2978  int nConsNonlinear;
2979  SCIP_CONS** consAbspower;
2980  int nConsAbspower;
2981  SCIP_CONS** consAnd;
2982  int nConsAnd;
2983  SCIP_CONS** consBivariate;
2984  int nConsBivariate;
2985  char consname[PIP_MAX_NAMELEN];
2986 
2987  SCIP_VAR** aggregatedVars;
2988  int nAggregatedVars;
2989  SCIP_HASHTABLE* varAggregated;
2990 
2991  SCIP_VAR** consvars;
2992  SCIP_Real* consvals;
2993  int nconsvars;
2994 
2995  SCIP_VAR* var;
2996  SCIP_Real lb;
2997  SCIP_Real ub;
2998 
2999  SCIP_EXPRTREE* exprtree;
3000  SCIP_EXPR* expr;
3001 
3002  assert( scip != NULL );
3003 
3004  nAggregatedVars = 0;
3005  nConsQuadratic = 0;
3006  nConsNonlinear = 0;
3007  nConsAbspower = 0;
3008  nConsAnd = 0;
3009  nConsBivariate = 0;
3010 
3011  /* check if the variable names are not to long */
3012  checkVarnames(scip, vars, nvars);
3013 
3014  /* check if the constraint names are to long */
3015  checkConsnames(scip, conss, nconss, transformed);
3016 
3017  /* print statistics as comment to file */
3018  SCIPinfoMessage(scip, file, "\\ SCIP STATISTICS\n");
3019  SCIPinfoMessage(scip, file, "\\ Problem name : %s\n", name);
3020  SCIPinfoMessage(scip, file, "\\ Variables : %d (%d binary, %d integer, %d implicit integer, %d continuous)\n",
3021  nvars, nbinvars, nintvars, nimplvars, ncontvars);
3022  SCIPinfoMessage(scip, file, "\\ Constraints : %d\n", nconss);
3023  SCIPinfoMessage(scip, file, "\\ Obj. scale : %.15g\n", objscale);
3024  SCIPinfoMessage(scip, file, "\\ Obj. offset : %.15g\n", objoffset);
3025 
3026  /* print objective sense */
3027  SCIPinfoMessage(scip, file, "%s\n", objsense == SCIP_OBJSENSE_MINIMIZE ? "Minimize" : "Maximize");
3028 
3029  clearLine(linebuffer, &linecnt);
3030  appendLine(scip, file, linebuffer, &linecnt, " Obj:");
3031 
3032  for (v = 0; v < nvars; ++v)
3033  {
3034  var = vars[v];
3035 
3036 #ifndef NDEBUG
3037  /* in case the original problem has to be posted the variables have to be either "original" or "negated" */
3038  if ( !transformed )
3040 #endif
3041 
3042  if ( SCIPisZero(scip, SCIPvarGetObj(var)) )
3043  continue;
3044 
3045  /* we start a new line; therefore we tab this line */
3046  if ( linecnt == 0 )
3047  appendLine(scip, file, linebuffer, &linecnt, " ");
3048 
3049  (void) SCIPsnprintf(varname, PIP_MAX_NAMELEN, "%s", SCIPvarGetName(var));
3050  (void) SCIPsnprintf(buffer, PIP_MAX_PRINTLEN, " %+.15g %s", SCIPvarGetObj(var), varname );
3051 
3052  appendLine(scip, file, linebuffer, &linecnt, buffer);
3053  }
3054 
3055  endLine(scip, file, linebuffer, &linecnt);
3056 
3057  /* print "Subject to" section */
3058  SCIPinfoMessage(scip, file, "Subject to\n");
3059 
3060  /* collect quadratic, nonlinear, absolute power, and, and bivariate constraints in arrays */
3061  SCIP_CALL( SCIPallocBufferArray(scip, &consQuadratic, nconss) );
3062  SCIP_CALL( SCIPallocBufferArray(scip, &consNonlinear, nconss) );
3063  SCIP_CALL( SCIPallocBufferArray(scip, &consAbspower, nconss) );
3064  SCIP_CALL( SCIPallocBufferArray(scip, &consAnd, nconss) );
3065  SCIP_CALL( SCIPallocBufferArray(scip, &consBivariate, nconss) );
3066 
3067  for (c = 0; c < nconss; ++c)
3068  {
3069  cons = conss[c];
3070  assert( cons != NULL);
3071 
3072  /* in case the transformed is written only constraints are posted which are enabled in the current node */
3073  assert(!transformed || SCIPconsIsEnabled(cons));
3074 
3075  conshdlr = SCIPconsGetHdlr(cons);
3076  assert( conshdlr != NULL );
3077 
3078  (void) SCIPsnprintf(consname, PIP_MAX_NAMELEN, "%s", SCIPconsGetName(cons));
3079  conshdlrname = SCIPconshdlrGetName(conshdlr);
3080  assert( transformed == SCIPconsIsTransformed(cons) );
3081 
3082  if( strcmp(conshdlrname, "linear") == 0 )
3083  {
3084  SCIP_CALL( printQuadraticCons(scip, file, consname,
3085  SCIPgetVarsLinear(scip, cons), SCIPgetValsLinear(scip, cons), SCIPgetNVarsLinear(scip, cons),
3086  NULL, 0, NULL, 0, SCIPgetLhsLinear(scip, cons), SCIPgetRhsLinear(scip, cons), transformed) );
3087  }
3088  else if( strcmp(conshdlrname, "setppc") == 0 )
3089  {
3090  consvars = SCIPgetVarsSetppc(scip, cons);
3091  nconsvars = SCIPgetNVarsSetppc(scip, cons);
3092 
3093  switch( SCIPgetTypeSetppc(scip, cons) )
3094  {
3096  SCIP_CALL( printQuadraticCons(scip, file, consname,
3097  consvars, NULL, nconsvars, NULL, 0, NULL, 0, 1.0, 1.0, transformed) );
3098  break;
3100  SCIP_CALL( printQuadraticCons(scip, file, consname,
3101  consvars, NULL, nconsvars, NULL, 0, NULL, 0, -SCIPinfinity(scip), 1.0, transformed) );
3102  break;
3104  SCIP_CALL( printQuadraticCons(scip, file, consname,
3105  consvars, NULL, nconsvars, NULL, 0, NULL, 0, 1.0, SCIPinfinity(scip), transformed) );
3106  break;
3107  }
3108  }
3109  else if ( strcmp(conshdlrname, "logicor") == 0 )
3110  {
3111  SCIP_CALL( printQuadraticCons(scip, file, consname,
3112  SCIPgetVarsLogicor(scip, cons), NULL, SCIPgetNVarsLogicor(scip, cons),
3113  NULL, 0, NULL, 0, 1.0, SCIPinfinity(scip), transformed) );
3114  }
3115  else if ( strcmp(conshdlrname, "knapsack") == 0 )
3116  {
3117  SCIP_Longint* weights;
3118 
3119  consvars = SCIPgetVarsKnapsack(scip, cons);
3120  nconsvars = SCIPgetNVarsKnapsack(scip, cons);
3121 
3122  /* copy Longint array to SCIP_Real array */
3123  weights = SCIPgetWeightsKnapsack(scip, cons);
3124  SCIP_CALL( SCIPallocBufferArray(scip, &consvals, nconsvars) );
3125  for( v = 0; v < nconsvars; ++v )
3126  consvals[v] = (SCIP_Real)weights[v];
3127 
3128  SCIP_CALL( printQuadraticCons(scip, file, consname, consvars, consvals, nconsvars,
3129  NULL, 0, NULL, 0, -SCIPinfinity(scip), (SCIP_Real) SCIPgetCapacityKnapsack(scip, cons), transformed) );
3130 
3131  SCIPfreeBufferArray(scip, &consvals);
3132  }
3133  else if ( strcmp(conshdlrname, "varbound") == 0 )
3134  {
3135  SCIP_CALL( SCIPallocBufferArray(scip, &consvars, 2) );
3136  SCIP_CALL( SCIPallocBufferArray(scip, &consvals, 2) );
3137 
3138  consvars[0] = SCIPgetVarVarbound(scip, cons);
3139  consvars[1] = SCIPgetVbdvarVarbound(scip, cons);
3140 
3141  consvals[0] = 1.0;
3142  consvals[1] = SCIPgetVbdcoefVarbound(scip, cons);
3143 
3144  SCIP_CALL( printQuadraticCons(scip, file, consname, consvars, consvals, 2, NULL, 0, NULL, 0,
3145  SCIPgetLhsVarbound(scip, cons), SCIPgetRhsVarbound(scip, cons), transformed) );
3146 
3147  SCIPfreeBufferArray(scip, &consvars);
3148  SCIPfreeBufferArray(scip, &consvals);
3149  }
3150  else if( strcmp(conshdlrname, "quadratic") == 0 )
3151  {
3152  SCIP_CALL( printQuadraticCons(scip, file, consname,
3156  SCIPgetNBilinTermsQuadratic(scip, cons), SCIPgetLhsQuadratic(scip, cons),
3157  SCIPgetRhsQuadratic(scip, cons), transformed) );
3158 
3159  consQuadratic[nConsQuadratic++] = cons;
3160  }
3161  else if( strcmp(conshdlrname, "nonlinear") == 0 )
3162  {
3163  SCIP_Bool ispolynomial;
3164  int nexprtrees = SCIPgetNExprtreesNonlinear(scip, cons);
3165 
3166  /* check whether expressions are polynomials (assumed simplified exprtrees) */
3167  ispolynomial = TRUE;
3168  for( e = 0; e < nexprtrees && ispolynomial; ++e )
3169  {
3170  exprtree = SCIPgetExprtreesNonlinear(scip, cons)[e];
3171  expr = SCIPexprtreeGetRoot(exprtree);
3172  assert(expr != NULL);
3173 
3174  /* check if operator is something polynomial */
3175  switch( SCIPexprGetOperator(expr) )
3176  {
3177  case SCIP_EXPR_CONST:
3178  case SCIP_EXPR_VARIDX:
3179  case SCIP_EXPR_PLUS:
3180  case SCIP_EXPR_MINUS:
3181  case SCIP_EXPR_MUL:
3182  case SCIP_EXPR_SQUARE:
3183  case SCIP_EXPR_SQRT:
3184  case SCIP_EXPR_SUM:
3185  case SCIP_EXPR_PRODUCT:
3186  case SCIP_EXPR_LINEAR:
3187  case SCIP_EXPR_QUADRATIC:
3188  break;
3189 
3190  case SCIP_EXPR_INTPOWER:
3191  {
3192  if( SCIPexprGetIntPowerExponent(expr) < 0 )
3193  {
3194  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));
3195  ispolynomial = FALSE;
3196  }
3197 
3198  break;
3199  }
3200 
3201  case SCIP_EXPR_REALPOWER:
3202  {
3203  if( SCIPexprGetRealPowerExponent(expr) < 0.0 )
3204  {
3205  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));
3206  ispolynomial = FALSE;
3207  }
3208 
3209  break;
3210  }
3211 
3212  case SCIP_EXPR_POLYNOMIAL:
3213  {
3214  SCIP_EXPRDATA_MONOMIAL* monomial;
3215  int m;
3216  int f;
3217 
3218  for( m = 0; m < SCIPexprGetNMonomials(expr) && ispolynomial; ++m )
3219  {
3220  monomial = SCIPexprGetMonomials(expr)[m];
3221  for( f = 0; f < SCIPexprGetMonomialNFactors(monomial); ++f )
3222  {
3223  if( SCIPexprGetMonomialExponents(monomial)[f] < 0.0 )
3224  {
3225  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));
3226  ispolynomial = FALSE;
3227  break;
3228  }
3229  }
3230  }
3231 
3232  break;
3233  }
3234 
3235  default:
3236  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));
3237  ispolynomial = FALSE;
3238  break;
3239  } /*lint !e788*/
3240 
3241  /* check if all children of root expression correspond to variables */
3242  for( v = 0; v < SCIPexprGetNChildren(expr) && ispolynomial; ++v )
3243  {
3245  {
3246  SCIPwarningMessage(scip, "%dth expression tree of constraint <%s> is not simplified, cannot write in pip format\n", e, SCIPconsGetName(cons));
3247  ispolynomial = FALSE;
3248  }
3249  }
3250  }
3251 
3252  if( ispolynomial )
3253  {
3254  SCIP_CALL( printNonlinearCons(scip, file, consname,
3256  SCIPgetNLinearVarsNonlinear(scip, cons), SCIPgetExprtreesNonlinear(scip, cons),
3258  SCIPgetLhsNonlinear(scip, cons), SCIPgetRhsNonlinear(scip, cons), transformed) );
3259 
3260  consNonlinear[nConsNonlinear++] = cons;
3261  }
3262  else
3263  {
3264  SCIPinfoMessage(scip, file, "\\ ");
3265  SCIP_CALL( SCIPprintCons(scip, cons, file) );
3266  SCIPinfoMessage(scip, file, ";\n");
3267  }
3268  }
3269  else if( strcmp(conshdlrname, "abspower") == 0 )
3270  {
3271  SCIP_VAR* x;
3272  SCIP_Real xoffset;
3273  SCIP_Real exponent;
3274  SCIP_Real treecoef;
3275 
3276  expr = NULL;
3277  treecoef = 1.0;
3278 
3279  x = SCIPgetNonlinearVarAbspower(scip, cons);
3280  xoffset = SCIPgetOffsetAbspower(scip, cons);
3281  exponent = SCIPgetExponentAbspower(scip, cons);
3282 
3283  /* see if we formulate signpower(x+offset,exponent) as usual polynomial */
3284  if( !SCIPisZero(scip, xoffset) )
3285  {
3286  SCIPwarningMessage(scip, "nonzero offset for nonlinear variable in constraint <%s>, cannot write in pip format\n", SCIPconsGetName(cons));
3287  }
3288  if( SCIPisIntegral(scip, exponent) && ((int)SCIPround(scip, exponent) % 2 == 1) )
3289  {
3290  /* exponent is odd integer, so signpower(x,exponent) = x^exponent */
3291  SCIP_CALL( SCIPexprCreate(SCIPblkmem(scip), &expr, SCIP_EXPR_VARIDX, 0) );
3292  SCIP_CALL( SCIPexprCreate(SCIPblkmem(scip), &expr, SCIP_EXPR_INTPOWER, expr, (int)SCIPround(scip, exponent)) );
3293  }
3294  else if( SCIPisIntegral(scip, exponent) && ((int)SCIPround(scip, exponent) % 2 == 0) && !SCIPisPositive(scip, SCIPvarGetUbGlobal(x)) )
3295  {
3296  /* exponent is even integer and x is negative, so signpower(x,exponent) = -x^exponent */
3297  SCIP_CALL( SCIPexprCreate(SCIPblkmem(scip), &expr, SCIP_EXPR_VARIDX, 0) );
3298  SCIP_CALL( SCIPexprCreate(SCIPblkmem(scip), &expr, SCIP_EXPR_INTPOWER, expr, (int)SCIPround(scip, exponent)) );
3299  treecoef = -1.0;
3300  }
3301  else if( !SCIPisNegative(scip, SCIPvarGetLbGlobal(x)) )
3302  {
3303  /* x is positive, so signpower(x,exponent) = x^exponent */
3304  SCIP_CALL( SCIPexprCreate(SCIPblkmem(scip), &expr, SCIP_EXPR_VARIDX, 0) );
3305  SCIP_CALL( SCIPexprCreate(SCIPblkmem(scip), &expr, SCIP_EXPR_REALPOWER, expr, exponent) );
3306  }
3307  else
3308  {
3309  SCIPwarningMessage(scip, "cannot formulate signpower(<%s>, %g) in constraint <%s> as polynomial, cannot write in pip format\n", SCIPvarGetName(x), exponent, SCIPconsGetName(cons));
3310  }
3311 
3312  if( expr != NULL )
3313  {
3314  SCIP_VAR* z;
3315  SCIP_Real zcoef;
3316 
3317  SCIP_CALL( SCIPexprtreeCreate(SCIPblkmem(scip), &exprtree, expr, 1, 0, NULL) );
3318  SCIP_CALL( SCIPexprtreeSetVars(exprtree, 1, &x) );
3319 
3320  z = SCIPgetLinearVarAbspower(scip, cons);
3321  zcoef = SCIPgetCoefLinearAbspower(scip, cons);
3322 
3323  SCIP_CALL( printNonlinearCons(scip, file, consname,
3324  &z, &zcoef, 1, &exprtree, &treecoef, 1,
3325  SCIPgetLhsAbspower(scip, cons), SCIPgetRhsAbspower(scip, cons), transformed) );
3326 
3327  SCIP_CALL( SCIPexprtreeFree(&exprtree) );
3328 
3329  consAbspower[nConsAbspower++] = cons;
3330  }
3331  else
3332  {
3333  SCIPinfoMessage(scip, file, "\\ ");
3334  SCIP_CALL( SCIPprintCons(scip, cons, file) );
3335  SCIPinfoMessage(scip, file, ";\n");
3336  }
3337  }
3338  else if( strcmp(conshdlrname, "bivariate") == 0 )
3339  {
3340  SCIP_Bool ispolynomial;
3341 
3342  /* check whether expression is polynomial (simplified exprtree assumed) */
3343  ispolynomial = TRUE;
3344  exprtree = SCIPgetExprtreeBivariate(scip, cons);
3345  expr = SCIPexprtreeGetRoot(exprtree);
3346  assert(expr != NULL);
3347 
3348  /* check if operator is something polynomial */
3349  switch( SCIPexprGetOperator(expr) )
3350  {
3351  case SCIP_EXPR_CONST:
3352  case SCIP_EXPR_VARIDX:
3353  case SCIP_EXPR_PLUS:
3354  case SCIP_EXPR_MINUS:
3355  case SCIP_EXPR_MUL:
3356  case SCIP_EXPR_SQUARE:
3357  case SCIP_EXPR_SQRT:
3358  case SCIP_EXPR_SUM:
3359  case SCIP_EXPR_PRODUCT:
3360  case SCIP_EXPR_LINEAR:
3361  case SCIP_EXPR_QUADRATIC:
3362  break;
3363 
3364  case SCIP_EXPR_INTPOWER:
3365  {
3366  if( SCIPexprGetIntPowerExponent(expr) < 0 )
3367  {
3368  SCIPwarningMessage(scip, "negative exponent %d in intpower of constraint <%s> cannot be written in pip format\n", SCIPexprGetIntPowerExponent(expr), SCIPconsGetName(cons));
3369  ispolynomial = FALSE;
3370  }
3371 
3372  break;
3373  }
3374 
3375  case SCIP_EXPR_REALPOWER:
3376  {
3377  if( SCIPexprGetRealPowerExponent(expr) < 0.0 )
3378  {
3379  SCIPwarningMessage(scip, "negative exponent %g in realpower of constraint <%s> cannot be written in pip format\n", SCIPexprGetRealPowerExponent(expr), SCIPconsGetName(cons));
3380  ispolynomial = FALSE;
3381  }
3382 
3383  break;
3384  }
3385 
3386  case SCIP_EXPR_POLYNOMIAL:
3387  {
3388  SCIP_EXPRDATA_MONOMIAL* monomial;
3389  int m;
3390  int f;
3391 
3392  for( m = 0; m < SCIPexprGetNMonomials(expr) && ispolynomial; ++m )
3393  {
3394  monomial = SCIPexprGetMonomials(expr)[m];
3395  for( f = 0; f < SCIPexprGetMonomialNFactors(monomial); ++f )
3396  {
3397  if( SCIPexprGetMonomialExponents(monomial)[f] < 0.0 )
3398  {
3399  SCIPwarningMessage(scip, "negative exponent %g in polynomial of constraint <%s> cannot be written in pip format\n", SCIPexprGetMonomialExponents(monomial)[f], SCIPconsGetName(cons));
3400  ispolynomial = FALSE;
3401  break;
3402  }
3403  }
3404  }
3405 
3406  break;
3407  }
3408 
3409  default:
3410  SCIPwarningMessage(scip, "expression operand <%s> in constraint <%s> cannot be written in pip format\n", SCIPexpropGetName(SCIPexprGetOperator(expr)), SCIPconsGetName(cons));
3411  ispolynomial = FALSE;
3412  break;
3413  } /*lint !e788*/
3414 
3415  if( ispolynomial )
3416  {
3417  /* check if all children of root expression correspond to variables */
3418  for( v = 0; v < SCIPexprGetNChildren(expr); ++v )
3419  {
3421  {
3422  SCIPwarningMessage(scip, "expression tree of constraint <%s> is not simplified, cannot write in pip format\n", SCIPconsGetName(cons));
3423  ispolynomial = FALSE;
3424  break;
3425  }
3426  }
3427  }
3428 
3429  if( ispolynomial )
3430  {
3431  SCIP_VAR* z;
3432  SCIP_Real zcoef;
3433  SCIP_Real one;
3434 
3435  z = SCIPgetLinearVarBivariate(scip, cons);
3436  zcoef = SCIPgetLinearCoefBivariate(scip, cons);
3437 
3438  one = 1.0;
3439  SCIP_CALL( printNonlinearCons(scip, file, consname,
3440  &z, &zcoef, z == NULL ? 0 : 1, &exprtree, &one, 1,
3441  SCIPgetLhsBivariate(scip, cons), SCIPgetRhsBivariate(scip, cons), transformed) );
3442 
3443  consBivariate[nConsBivariate++] = cons;
3444  }
3445  else
3446  {
3447  SCIPinfoMessage(scip, file, "\\ ");
3448  SCIP_CALL( SCIPprintCons(scip, cons, file) );
3449  SCIPinfoMessage(scip, file, ";\n");
3450  }
3451  }
3452  else if( strcmp(conshdlrname, "and") == 0 )
3453  {
3454  SCIP_EXPR** children;
3455  SCIP_VAR* resultant;
3456  SCIP_Real minusone;
3457  SCIP_Real one;
3458 
3459  /* create expression for product of binaries */
3460  SCIP_CALL( SCIPallocBufferArray(scip, &children, SCIPgetNVarsAnd(scip, cons)) );
3461  for( v = 0; v < SCIPgetNVarsAnd(scip, cons); ++v )
3462  {
3463  SCIP_CALL( SCIPexprCreate(SCIPblkmem(scip), &children[v], SCIP_EXPR_VARIDX, v) );
3464  }
3465  SCIP_CALL( SCIPexprCreate(SCIPblkmem(scip), &expr, SCIP_EXPR_PRODUCT, SCIPgetNVarsAnd(scip, cons), children) );
3466  SCIP_CALL( SCIPexprtreeCreate(SCIPblkmem(scip), &exprtree, expr, SCIPgetNVarsAnd(scip, cons), 0, NULL) );
3467  SCIP_CALL( SCIPexprtreeSetVars(exprtree, SCIPgetNVarsAnd(scip, cons), SCIPgetVarsAnd(scip, cons)) );
3468 
3469  resultant = SCIPgetResultantAnd(scip, cons);
3470  minusone = -1.0;
3471 
3472  one = 1.0;
3473  SCIP_CALL( printNonlinearCons(scip, file, consname, &resultant, &minusone, 1, &exprtree, &one, 1, 0.0, 0.0, transformed) );
3474 
3475  SCIP_CALL( SCIPexprtreeFree(&exprtree) );
3476  SCIPfreeBufferArray(scip, &children);
3477 
3478  consAnd[nConsAnd++] = cons;
3479  }
3480  else
3481  {
3482  SCIPwarningMessage(scip, "constraint handler <%s> cannot print requested format\n", conshdlrname );
3483  SCIPinfoMessage(scip, file, "\\ ");
3484  SCIP_CALL( SCIPprintCons(scip, cons, file) );
3485  SCIPinfoMessage(scip, file, ";\n");
3486  }
3487  }
3488 
3489  /* create hashtable for storing aggregated variables */
3490  SCIP_CALL( SCIPallocBufferArray(scip, &aggregatedVars, nvars) );
3491  SCIP_CALL( SCIPhashtableCreate(&varAggregated, SCIPblkmem(scip), 1000, hashGetKeyVar, hashKeyEqVar, hashKeyValVar, NULL) );
3492 
3493  /* check for aggregated variables in quadratic parts of quadratic constraints and output aggregations as linear constraints */
3494  for (c = 0; c < nConsQuadratic; ++c)
3495  {
3496  cons = consQuadratic[c];
3497  for( v = 0; v < SCIPgetNQuadVarTermsQuadratic(scip, cons); ++v )
3498  {
3499  SCIP_CALL( collectAggregatedVars(scip, 1, &SCIPgetQuadVarTermsQuadratic(scip, cons)[v].var,
3500  &nAggregatedVars, &aggregatedVars, &varAggregated) );
3501  }
3502  }
3503 
3504  /* check for aggregated variables in expression trees of nonlinear constraints and output aggregations as linear constraints */
3505  for (c = 0; c < nConsNonlinear; ++c)
3506  {
3507  cons = consNonlinear[c];
3508  for( e = 0; e < SCIPgetNExprtreesNonlinear(scip, cons); ++e )
3509  {
3510  exprtree = SCIPgetExprtreesNonlinear(scip, cons)[e];
3511  assert(exprtree != NULL);
3512 
3513  for( v = 0; v < SCIPexprtreeGetNVars(exprtree); ++v )
3514  {
3515  SCIP_CALL( collectAggregatedVars(scip, 1, &SCIPexprtreeGetVars(exprtree)[v],
3516  &nAggregatedVars, &aggregatedVars, &varAggregated) );
3517  }
3518  }
3519  }
3520 
3521  /* check for aggregated variables in absolute power constraints and output aggregations as linear constraints */
3522  for (c = 0; c < nConsAbspower; ++c)
3523  {
3524  SCIP_VAR* spvars[2];
3525 
3526  cons = consAbspower[c];
3527 
3528  spvars[0] = SCIPgetNonlinearVarAbspower(scip, cons);
3529  spvars[1] = SCIPgetLinearVarAbspower(scip, cons);
3530  SCIP_CALL( collectAggregatedVars(scip, 2, spvars, &nAggregatedVars, &aggregatedVars, &varAggregated) );
3531  }
3532 
3533  /* check for aggregated variables in and constraints and output aggregations as linear constraints */
3534  for (c = 0; c < nConsAnd; ++c)
3535  {
3536  SCIP_VAR* resultant;
3537 
3538  cons = consAnd[c];
3539 
3540  SCIP_CALL( collectAggregatedVars(scip, SCIPgetNVarsAnd(scip, cons), SCIPgetVarsAnd(scip, cons), &nAggregatedVars, &aggregatedVars, &varAggregated) );
3541 
3542  resultant = SCIPgetResultantAnd(scip, cons);
3543  SCIP_CALL( collectAggregatedVars(scip, 1, &resultant, &nAggregatedVars, &aggregatedVars, &varAggregated) );
3544  }
3545 
3546  /* check for aggregated variables in bivariate constraints and output aggregations as linear constraints */
3547  for (c = 0; c < nConsBivariate; ++c)
3548  {
3549  SCIP_VAR* z;
3550 
3551  cons = consBivariate[c];
3552 
3553  assert(SCIPexprtreeGetNVars(SCIPgetExprtreeBivariate(scip, cons)) == 2);
3554  SCIP_CALL( collectAggregatedVars(scip, 2, SCIPexprtreeGetVars(SCIPgetExprtreeBivariate(scip, cons)), &nAggregatedVars, &aggregatedVars, &varAggregated) );
3555 
3556  z = SCIPgetLinearVarBivariate(scip, cons);
3557  if( z != NULL )
3558  {
3559  SCIP_CALL( collectAggregatedVars(scip, 1, &z, &nAggregatedVars, &aggregatedVars, &varAggregated) );
3560  }
3561  }
3562 
3563  /* print aggregation constraints */
3564  SCIP_CALL( printAggregatedCons(scip, file, transformed, nvars, nAggregatedVars, aggregatedVars) );
3565 
3566  /* print "Bounds" section */
3567  SCIPinfoMessage(scip, file, "Bounds\n");
3568  for (v = 0; v < nvars; ++v)
3569  {
3570  var = vars[v];
3571  assert( var != NULL );
3572  (void) SCIPsnprintf(varname, PIP_MAX_NAMELEN, "%s", SCIPvarGetName(var) );
3573 
3574  if( transformed )
3575  {
3576  /* in case the transformed is written only local bounds are posted which are valid in the current node */
3577  lb = SCIPvarGetLbLocal(var);
3578  ub = SCIPvarGetUbLocal(var);
3579  }
3580  else
3581  {
3582  lb = SCIPvarGetLbOriginal(var);
3583  ub = SCIPvarGetUbOriginal(var);
3584  }
3585 
3586  if ( SCIPisInfinity(scip, -lb) && SCIPisInfinity(scip, ub) )
3587  SCIPinfoMessage(scip, file, " %s free\n", varname);
3588  else
3589  {
3590  /* print lower bound */
3591  if ( SCIPisInfinity(scip, -lb) )
3592  SCIPinfoMessage(scip, file, " -inf <= ");
3593  else
3594  {
3595  if ( SCIPisZero(scip, lb) )
3596  {
3597  /* variables are nonnegative by default - so we skip these variables */
3598  if ( SCIPisInfinity(scip, ub) )
3599  continue;
3600  lb = 0.0;
3601  }
3602 
3603  SCIPinfoMessage(scip, file, " %.15g <= ", lb);
3604  }
3605  /* print variable name */
3606  SCIPinfoMessage(scip, file, "%s", varname);
3607 
3608  /* print upper bound as far this one is not infinity */
3609  if( !SCIPisInfinity(scip, ub) )
3610  SCIPinfoMessage(scip, file, " <= %.15g", ub);
3611 
3612  SCIPinfoMessage(scip, file, "\n");
3613  }
3614  }
3615 
3616  /* output aggregated variables as 'free' */
3617  for (v = 0; v < nAggregatedVars; ++v)
3618  {
3619  var = aggregatedVars[v];
3620  assert( var != NULL );
3621  (void) SCIPsnprintf(varname, PIP_MAX_NAMELEN, "%s", SCIPvarGetName(var) );
3622 
3623  SCIPinfoMessage(scip, file, " %s free\n", varname);
3624  }
3625 
3626  /* free space */
3627  SCIPfreeBufferArray(scip, &aggregatedVars);
3628  SCIPhashtableFree(&varAggregated);
3629 
3630  /* print binaries section */
3631  if ( nbinvars > 0 )
3632  {
3633  SCIPinfoMessage(scip, file, "Binaries\n");
3634 
3635  clearLine(linebuffer, &linecnt);
3636 
3637  for (v = 0; v < nvars; ++v)
3638  {
3639  var = vars[v];
3640  assert( var != NULL );
3641 
3642  if ( SCIPvarGetType(var) == SCIP_VARTYPE_BINARY )
3643  {
3644  (void) SCIPsnprintf(varname, PIP_MAX_NAMELEN, "%s", SCIPvarGetName(var) );
3645  (void) SCIPsnprintf(buffer, PIP_MAX_PRINTLEN, " %s", varname);
3646  appendLine(scip, file, linebuffer, &linecnt, buffer);
3647  }
3648  }
3649 
3650  endLine(scip, file, linebuffer, &linecnt);
3651  }
3652 
3653  /* print generals section */
3654  if ( nintvars > 0 )
3655  {
3656  SCIPinfoMessage(scip, file, "Generals\n");
3657 
3658  for (v = 0; v < nvars; ++v)
3659  {
3660  var = vars[v];
3661  assert( var != NULL );
3662 
3663  if ( SCIPvarGetType(var) == SCIP_VARTYPE_INTEGER )
3664  {
3665  (void) SCIPsnprintf(varname, PIP_MAX_NAMELEN, "%s", SCIPvarGetName(var) );
3666  (void) SCIPsnprintf(buffer, PIP_MAX_PRINTLEN, " %s", varname);
3667  appendLine(scip, file, linebuffer, &linecnt, buffer);
3668  }
3669  }
3670  endLine(scip, file, linebuffer, &linecnt);
3671  }
3672 
3673  /* free space */
3674  SCIPfreeBufferArray(scip, &consQuadratic);
3675  SCIPfreeBufferArray(scip, &consNonlinear);
3676  SCIPfreeBufferArray(scip, &consAbspower);
3677  SCIPfreeBufferArray(scip, &consAnd);
3678  SCIPfreeBufferArray(scip, &consBivariate);
3679 
3680  /* end of lp format */
3681  SCIPinfoMessage(scip, file, "%s\n", "End");
3682 
3683  *result = SCIP_SUCCESS;
3684 
3685  return SCIP_OKAY;
3686 }
3687 
3688 /*
3689  * Callback methods of reader
3690  */
3691 
3692 /** copy method for reader plugins (called when SCIP copies plugins) */
3693 static
3694 SCIP_DECL_READERCOPY(readerCopyPip)
3695 { /*lint --e{715}*/
3696  assert(scip != NULL);
3697  assert(reader != NULL);
3698  assert(strcmp(SCIPreaderGetName(reader), READER_NAME) == 0);
3699 
3700  /* call inclusion method of reader */
3702 
3703  return SCIP_OKAY;
3704 }
3705 
3706 
3707 /** problem reading method of reader */
3708 static
3709 SCIP_DECL_READERREAD(readerReadPip)
3710 { /*lint --e{715}*/
3711 
3712  SCIP_CALL( SCIPreadPip(scip, reader, filename, result) );
3713 
3714  return SCIP_OKAY;
3715 }
3716 
3717 
3718 /** problem writing method of reader */
3719 static
3720 SCIP_DECL_READERWRITE(readerWritePip)
3721 { /*lint --e{715}*/
3722  SCIP_CALL( SCIPwritePip(scip, file, name, transformed, objsense, objscale, objoffset, vars,
3723  nvars, nbinvars, nintvars, nimplvars, ncontvars, conss, nconss, result) );
3724 
3725  return SCIP_OKAY;
3726 }
3727 
3728 
3729 /*
3730  * reader specific interface methods
3731  */
3732 
3733 /** includes the pip file reader in SCIP */
3735  SCIP* scip /**< SCIP data structure */
3736  )
3737 {
3738  SCIP_READERDATA* readerdata;
3739  SCIP_READER* reader;
3740 
3741  /* create reader data */
3742  readerdata = NULL;
3743 
3744  /* include reader */
3745  SCIP_CALL( SCIPincludeReaderBasic(scip, &reader, READER_NAME, READER_DESC, READER_EXTENSION, readerdata) );
3746 
3747  /* set non fundamental callbacks via setter functions */
3748  SCIP_CALL( SCIPsetReaderCopy(scip, reader, readerCopyPip) );
3749  SCIP_CALL( SCIPsetReaderRead(scip, reader, readerReadPip) );
3750  SCIP_CALL( SCIPsetReaderWrite(scip, reader, readerWritePip) );
3751 
3752  return SCIP_OKAY;
3753 }
3754 
3755 
3756 /** reads problem from file */
3758  SCIP* scip, /**< SCIP data structure */
3759  SCIP_READER* reader, /**< the file reader itself */
3760  const char* filename, /**< full path and name of file to read, or NULL if stdin should be used */
3761  SCIP_RESULT* result /**< pointer to store the result of the file reading call */
3762  )
3763 { /*lint --e{715}*/
3764  PIPINPUT pipinput;
3765  SCIP_RETCODE retcode;
3766  int i;
3767 
3768  /* initialize PIP input data */
3769  pipinput.file = NULL;
3770  pipinput.linebuf[0] = '\0';
3771  pipinput.probname[0] = '\0';
3772  pipinput.objname[0] = '\0';
3773  SCIP_CALL( SCIPallocMemoryArray(scip, &pipinput.token, PIP_MAX_LINELEN) ); /*lint !e506*/
3774  pipinput.token[0] = '\0';
3775  SCIP_CALL( SCIPallocMemoryArray(scip, &pipinput.tokenbuf, PIP_MAX_LINELEN) ); /*lint !e506*/
3776  pipinput.tokenbuf[0] = '\0';
3777  for( i = 0; i < PIP_MAX_PUSHEDTOKENS; ++i )
3778  {
3779  SCIP_CALL( SCIPallocMemoryArray(scip, &((pipinput.pushedtokens)[i]), PIP_MAX_LINELEN) ); /*lint !e866 !e506*/
3780  }
3781 
3782  pipinput.npushedtokens = 0;
3783  pipinput.linenumber = 0;
3784  pipinput.linepos = 0;
3785  pipinput.section = PIP_START;
3786  pipinput.objsense = SCIP_OBJSENSE_MINIMIZE;
3787  pipinput.haserror = FALSE;
3788 
3789  SCIP_CALL( SCIPgetBoolParam(scip, "reading/initialconss", &(pipinput.initialconss)) );
3790  SCIP_CALL( SCIPgetBoolParam(scip, "reading/dynamicconss", &(pipinput.dynamicconss)) );
3791  SCIP_CALL( SCIPgetBoolParam(scip, "reading/dynamiccols", &(pipinput.dynamiccols)) );
3792  SCIP_CALL( SCIPgetBoolParam(scip, "reading/dynamicrows", &(pipinput.dynamicrows)) );
3793 
3794  /* read the file */
3795  retcode = readPIPFile(scip, &pipinput, filename);
3796 
3797  /* free dynamically allocated memory */
3798  for( i = PIP_MAX_PUSHEDTOKENS - 1; i >= 0 ; --i )
3799  {
3800  SCIPfreeMemoryArray(scip, &pipinput.pushedtokens[i]);
3801  }
3802  SCIPfreeMemoryArray(scip, &pipinput.tokenbuf);
3803  SCIPfreeMemoryArray(scip, &pipinput.token);
3804 
3805  if( retcode == SCIP_PLUGINNOTFOUND )
3806  retcode = SCIP_READERROR;
3807 
3808  /* evaluate the result */
3809  if( pipinput.haserror )
3810  retcode = SCIP_READERROR;
3811  else
3812  {
3813  /* set objective sense */
3814  SCIP_CALL( SCIPsetObjsense(scip, pipinput.objsense) );
3815  *result = SCIP_SUCCESS;
3816  }
3817 
3818  SCIP_CALL( retcode );
3819 
3820  return SCIP_OKAY;
3821 }
enum SCIP_Result SCIP_RESULT
Definition: type_result.h:51
SCIP_Bool SCIPisEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:41572
static SCIP_RETCODE printNonlinearCons(SCIP *scip, FILE *file, const char *rowname, SCIP_VAR **linvars, SCIP_Real *linvals, int nlinvars, SCIP_EXPRTREE **exprtrees, SCIP_Real *exprtreecoefs, int nexprtrees, SCIP_Real lhs, SCIP_Real rhs, SCIP_Bool transformed)
Definition: reader_pip.c:2673
static SCIP_RETCODE ensureFactorsSize(SCIP *scip, SCIP_Real **exponents, int **varidxs, int *factorssize, int minnfactors)
Definition: reader_pip.c:736
SCIP_Bool SCIPisZero(SCIP *scip, SCIP_Real val)
Definition: scip.c:41685
static SCIP_DECL_HASHGETKEY(hashGetKeyVar)
Definition: reader_pip.c:1959
SCIP_BILINTERM * SCIPgetBilinTermsQuadratic(SCIP *scip, SCIP_CONS *cons)
const char * SCIPvarGetName(SCIP_VAR *var)
Definition: var.c:16443
SCIP_RETCODE SCIPchgVarLb(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound)
Definition: scip.c:19748
int * SCIPexprGetMonomialChildIndices(SCIP_EXPRDATA_MONOMIAL *monomial)
Definition: expr.c:5800
SCIP_RETCODE SCIPgetProbvarLinearSum(SCIP *scip, SCIP_VAR **vars, SCIP_Real *scalars, int *nvars, int varssize, SCIP_Real *constant, int *requiredsize, SCIP_Bool mergemultiples)
Definition: scip.c:17373
#define PIP_INIT_MONOMIALSSIZE
Definition: reader_pip.c:57
Constraint handler for variable bound constraints .
#define SCIPreallocBufferArray(scip, ptr, num)
Definition: scip.h:20589
SCIP_Bool SCIPisInfinity(SCIP *scip, SCIP_Real val)
Definition: scip.c:41648
#define PIP_INIT_FACTORSSIZE
Definition: reader_pip.c:58
SCIP_RETCODE SCIPvarGetOrigvarSum(SCIP_VAR **var, SCIP_Real *scalar, SCIP_Real *constant)
Definition: var.c:12033
const char * SCIPreaderGetName(SCIP_READER *reader)
Definition: reader.c:510
SCIP_RETCODE SCIPhashtableInsert(SCIP_HASHTABLE *hashtable, void *element)
Definition: misc.c:1567
SCIP_QUADVARTERM * SCIPgetQuadVarTermsQuadratic(SCIP *scip, SCIP_CONS *cons)
SCIP_RETCODE SCIPaddVar(SCIP *scip, SCIP_VAR *var)
Definition: scip.c:10378
#define PIP_MAX_NAMELEN
Definition: reader_pip.c:60
SCIP_EXPROP SCIPexprGetOperator(SCIP_EXPR *expr)
Definition: expr.c:5573
void SCIPwarningMessage(SCIP *scip, const char *formatstr,...)
Definition: scip.c:1248
SCIP_RETCODE SCIPcreateVar(SCIP *scip, SCIP_VAR **var, const char *name, SCIP_Real lb, SCIP_Real ub, SCIP_Real obj, SCIP_VARTYPE vartype, SCIP_Bool initial, SCIP_Bool removable, SCIP_DECL_VARDELORIG((*vardelorig)), SCIP_DECL_VARTRANS((*vartrans)), SCIP_DECL_VARDELTRANS((*vardeltrans)), SCIP_DECL_VARCOPY((*varcopy)), SCIP_VARDATA *vardata)
Definition: scip.c:15737
#define NULL
Definition: lpi_spx.cpp:130
PipSense
Definition: reader_pip.c:84
static SCIP_RETCODE printAggregatedCons(SCIP *scip, FILE *file, SCIP_Bool transformed, int nvars, int nAggregatedVars, SCIP_VAR **aggregatedVars)
Definition: reader_pip.c:2810
SCIP_Real SCIPvarGetLbLocal(SCIP_VAR *var)
Definition: var.c:17113
static SCIP_RETCODE readConstraints(SCIP *scip, PIPINPUT *pipinput)
Definition: reader_pip.c:1440
const char * SCIPexpropGetName(SCIP_EXPROP op)
Definition: expr.c:3237
#define PIP_MAX_PUSHEDTOKENS
Definition: reader_pip.c:55
SCIP_Real SCIPvarGetUbGlobal(SCIP_VAR *var)
Definition: var.c:17067
SCIP_RETCODE SCIPexprCreateMonomial(BMS_BLKMEM *blkmem, SCIP_EXPRDATA_MONOMIAL **monomial, SCIP_Real coef, int nfactors, int *childidxs, SCIP_Real *exponents)
Definition: expr.c:6913
int SCIPgetNVarsSetppc(SCIP *scip, SCIP_CONS *cons)
Definition: cons_setppc.c:9086
SCIP_Longint SCIPgetCapacityKnapsack(SCIP *scip, SCIP_CONS *cons)
static SCIP_RETCODE readObjective(SCIP *scip, PIPINPUT *pipinput)
Definition: reader_pip.c:1239
static void getLinearAndQuadraticCoefs(SCIP *scip, SCIP_EXPRTREE *exprtree, SCIP_Real *constant, int *nlinvars, SCIP_VAR **linvars, SCIP_Real *lincoefs, int *nquadterms, SCIP_VAR **quadvars1, SCIP_VAR **quadvars2, SCIP_Real *quadcoefs)
Definition: reader_pip.c:1139
#define SCIPfreeMemoryArray(scip, ptr)
Definition: scip.h:20544
SCIP_Real SCIPexprGetRealPowerExponent(SCIP_EXPR *expr)
Definition: expr.c:5636
int SCIPexprGetOpIndex(SCIP_EXPR *expr)
Definition: expr.c:5603
SCIP_Real SCIPgetExponentAbspower(SCIP *scip, SCIP_CONS *cons)
static SCIP_RETCODE ensureMonomialsSize(SCIP *scip, SCIP_EXPRDATA_MONOMIAL ***monomials, int *monomialssize, int minnmonomials)
Definition: reader_pip.c:702
SCIP_Real SCIPexprGetPolynomialConstant(SCIP_EXPR *expr)
Definition: expr.c:5768
static void endLine(SCIP *scip, FILE *file, char *linebuffer, int *linecnt)
Definition: reader_pip.c:2038
#define SCIPallocMemoryArray(scip, ptr, num)
Definition: scip.h:20528
SCIP_RETCODE SCIPcreateVarBasic(SCIP *scip, SCIP_VAR **var, const char *name, SCIP_Real lb, SCIP_Real ub, SCIP_Real obj, SCIP_VARTYPE vartype)
Definition: scip.c:15817
SCIP_Bool SCIPconsIsTransformed(SCIP_CONS *cons)
Definition: cons.c:7909
#define FALSE
Definition: def.h:56
SCIP_RETCODE SCIPhashmapCreate(SCIP_HASHMAP **hashmap, BMS_BLKMEM *blkmem, int mapsize)
Definition: misc.c:2057
static void printRow(SCIP *scip, FILE *file, const char *rowname, const char *rownameextension, const char *type, SCIP_VAR **linvars, SCIP_Real *linvals, int nlinvars, SCIP_QUADVARTERM *quadvarterms, int nquadvarterms, SCIP_BILINTERM *bilinterms, int nbilinterms, SCIP_Real rhs)
Definition: reader_pip.c:2091
SCIP_RETCODE SCIPexprtreeSetVars(SCIP_EXPRTREE *tree, int nvars, SCIP_VAR **vars)
Definition: nlp.c:111
SCIP_Real SCIPgetLhsVarbound(SCIP *scip, SCIP_CONS *cons)
int SCIPgetNVarsLinear(SCIP *scip, SCIP_CONS *cons)
int SCIPsnprintf(char *t, int len, const char *s,...)
Definition: misc.c:8174
#define TRUE
Definition: def.h:55
SCIP_CONSHDLR * SCIPconsGetHdlr(SCIP_CONS *cons)
Definition: cons.c:7640
enum SCIP_Retcode SCIP_RETCODE
Definition: type_retcode.h:53
static void checkVarnames(SCIP *scip, SCIP_VAR **vars, int nvars)
Definition: reader_pip.c:2863
#define SCIP_CALL(x)
Definition: def.h:266
SCIP_Longint * SCIPgetWeightsKnapsack(SCIP *scip, SCIP_CONS *cons)
enum SCIP_Varstatus SCIP_VARSTATUS
Definition: type_var.h:48
#define READER_DESC
Definition: reader_pip.c:47
#define READER_NAME
Definition: reader_pip.c:46
SCIP_RETCODE SCIPchgVarObj(SCIP *scip, SCIP_VAR *var, SCIP_Real newobj)
Definition: scip.c:19590
SCIP_VAR ** SCIPgetLinearVarsNonlinear(SCIP *scip, SCIP_CONS *cons)
PipSection
Definition: reader_pip.c:64
SCIP_EXPRTREE * SCIPgetExprtreeBivariate(SCIP *scip, SCIP_CONS *cons)
#define SCIPdebugMessage
Definition: pub_message.h:77
static SCIP_Bool isValueChar(char c, char nextc, SCIP_Bool firstchar, SCIP_Bool *hasdot, PIPEXPTYPE *exptype)
Definition: reader_pip.c:183
static SCIP_RETCODE readBounds(SCIP *scip, PIPINPUT *pipinput)
Definition: reader_pip.c:1639
#define BMSclearMemoryArray(ptr, num)
Definition: memory.h:85
Constraint handler for "and" constraints, .
SCIP_Real SCIPvarGetObj(SCIP_VAR *var)
Definition: var.c:16905
int SCIPgetNLinearVarsNonlinear(SCIP *scip, SCIP_CONS *cons)
struct PipInput PIPINPUT
Definition: reader_pip.c:114
SCIP_Real SCIPgetRhsNonlinear(SCIP *scip, SCIP_CONS *cons)
void * SCIPhashmapGetImage(SCIP_HASHMAP *hashmap, void *origin)
Definition: misc.c:2116
#define READER_EXTENSION
Definition: reader_pip.c:48
SCIP_RETCODE SCIPexprtreeCreate(BMS_BLKMEM *blkmem, SCIP_EXPRTREE **tree, SCIP_EXPR *root, int nvars, int nparams, SCIP_Real *params)
Definition: expr.c:8611
SCIP_RETCODE SCIPprintCons(SCIP *scip, SCIP_CONS *cons, FILE *file)
Definition: scip.c:26237
Constraint handler for the set partitioning / packing / covering constraints .
SCIP_RETCODE SCIPreleaseCons(SCIP *scip, SCIP_CONS **cons)
Definition: scip.c:24949
SCIP_VAR ** SCIPgetVarsKnapsack(SCIP *scip, SCIP_CONS *cons)
#define PIP_PRINTLEN
Definition: reader_pip.c:61
#define PIP_MAX_PRINTLEN
Definition: reader_pip.c:59
static SCIP_Bool hasError(PIPINPUT *pipinput)
Definition: reader_pip.c:154
SCIP_Real SCIPgetLhsNonlinear(SCIP *scip, SCIP_CONS *cons)
SCIP_EXPRDATA_MONOMIAL ** SCIPexprGetMonomials(SCIP_EXPR *expr)
Definition: expr.c:5744
SCIP_RETCODE SCIPhashtableCreate(SCIP_HASHTABLE **hashtable, BMS_BLKMEM *blkmem, int tablesize, SCIP_DECL_HASHGETKEY((*hashgetkey)), SCIP_DECL_HASHKEYEQ((*hashkeyeq)), SCIP_DECL_HASHKEYVAL((*hashkeyval)), void *userptr)
Definition: misc.c:1480
int SCIPexprGetMonomialNFactors(SCIP_EXPRDATA_MONOMIAL *monomial)
Definition: expr.c:5790
int SCIPexprGetIntPowerExponent(SCIP_EXPR *expr)
Definition: expr.c:5647
static void appendLine(SCIP *scip, FILE *file, char *linebuffer, int *linecnt, const char *extension)
Definition: reader_pip.c:2060
SCIP_Real * SCIPgetExprtreeCoefsNonlinear(SCIP *scip, SCIP_CONS *cons)
SCIP_VARSTATUS SCIPvarGetStatus(SCIP_VAR *var)
Definition: var.c:16562
SCIP_Bool SCIPhashmapExists(SCIP_HASHMAP *hashmap, void *origin)
Definition: misc.c:2159
static SCIP_RETCODE getVariable(SCIP *scip, char *name, SCIP_Bool dynamiccols, SCIP_VAR **var, SCIP_Bool *created)
Definition: reader_pip.c:642
SCIP_RETCODE SCIPsetReaderCopy(SCIP *scip, SCIP_READER *reader, SCIP_DECL_READERCOPY((*readercopy)))
Definition: scip.c:4601
SCIP_VAR * SCIPgetLinearVarAbspower(SCIP *scip, SCIP_CONS *cons)
SCIP_RETCODE SCIPcreateConsQuadratic(SCIP *scip, SCIP_CONS **cons, const char *name, int nlinvars, SCIP_VAR **linvars, SCIP_Real *lincoefs, int nquadterms, SCIP_VAR **quadvars1, SCIP_VAR **quadvars2, SCIP_Real *quadcoefs, SCIP_Real lhs, SCIP_Real rhs, SCIP_Bool initial, SCIP_Bool separate, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool propagate, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool dynamic, SCIP_Bool removable)
SCIP_FILE * SCIPfopen(const char *path, const char *mode)
Definition: fileio.c:140
enum PipSection PIPSECTION
Definition: reader_pip.c:74
SCIP_Real coef
Definition: type_expr.h:102
static const char delimchars[]
Definition: reader_pip.c:116
Constraint handler for knapsack constraints of the form , x binary and .
SCIP_Real SCIPgetLinearCoefBivariate(SCIP *scip, SCIP_CONS *cons)
static const char tokenchars[]
Definition: reader_pip.c:117
SCIP_VAR ** SCIPgetVarsAnd(SCIP *scip, SCIP_CONS *cons)
Definition: cons_and.c:5075
SCIP_Real * SCIPgetLinearCoefsNonlinear(SCIP *scip, SCIP_CONS *cons)
SCIP_Bool SCIPisNegative(SCIP *scip, SCIP_Real val)
Definition: scip.c:41709
SCIP_Real SCIPgetLhsBivariate(SCIP *scip, SCIP_CONS *cons)
int SCIPgetNLinearVarsQuadratic(SCIP *scip, SCIP_CONS *cons)
#define SCIPerrorMessage
Definition: pub_message.h:45
#define SCIPdebugPrintf
Definition: pub_message.h:80
int SCIPgetNVarsLogicor(SCIP *scip, SCIP_CONS *cons)
SCIP_Real * SCIPexprGetQuadLinearCoefs(SCIP_EXPR *expr)
Definition: expr.c:5720
Constraint handler for logicor constraints (equivalent to set covering, but algorithms are suited fo...
const char * SCIPconshdlrGetName(SCIP_CONSHDLR *conshdlr)
Definition: cons.c:3897
int SCIPcalcHashtableSize(int minsize)
Definition: misc.c:1157
#define SCIP_CALL_TERMINATE(retcode, x, TERM)
Definition: def.h:287
SCIP_VAR ** SCIPgetVarsSetppc(SCIP *scip, SCIP_CONS *cons)
Definition: cons_setppc.c:9107
BMS_BLKMEM * SCIPblkmem(SCIP *scip)
Definition: scip.c:41353
struct SCIP_File SCIP_FILE
Definition: pub_fileio.h:34
char * SCIPfgets(char *s, int size, SCIP_FILE *stream)
Definition: fileio.c:187
const char * SCIPconsGetName(SCIP_CONS *cons)
Definition: cons.c:7620
#define SCIPdebugPrintCons(x, y, z)
Definition: pub_message.h:83
SCIPInterval sign(const SCIPInterval &x)
#define PIP_MAX_LINELEN
Definition: reader_pip.c:54
SCIP_Real SCIPexprGetQuadConstant(SCIP_EXPR *expr)
Definition: expr.c:5707
void SCIPhashmapFree(SCIP_HASHMAP **hashmap)
Definition: misc.c:2075
constraint handler for quadratic constraints
SCIP_Real SCIPgetRhsLinear(SCIP *scip, SCIP_CONS *cons)
static void checkConsnames(SCIP *scip, SCIP_CONS **conss, int nconss, SCIP_Bool transformed)
Definition: reader_pip.c:2888
static SCIP_Bool isValue(SCIP *scip, PIPINPUT *pipinput, SCIP_Real *value)
Definition: reader_pip.c:579
SCIP_VAR * SCIPgetResultantAnd(SCIP *scip, SCIP_CONS *cons)
Definition: cons_and.c:5100
file reader for polynomial mixed-integer programs in PIP format
int SCIPexprtreeGetNVars(SCIP_EXPRTREE *tree)
Definition: expr.c:8452
SCIP_RETCODE SCIPaddLinearVarQuadratic(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *var, SCIP_Real coef)
SCIP_RETCODE SCIPcreateProb(SCIP *scip, const char *name, SCIP_DECL_PROBDELORIG((*probdelorig)), SCIP_DECL_PROBTRANS((*probtrans)), SCIP_DECL_PROBDELTRANS((*probdeltrans)), SCIP_DECL_PROBINITSOL((*probinitsol)), SCIP_DECL_PROBEXITSOL((*probexitsol)), SCIP_DECL_PROBCOPY((*probcopy)), SCIP_PROBDATA *probdata)
Definition: scip.c:9019
SCIP_Real SCIPinfinity(SCIP *scip)
Definition: scip.c:41637
SCIP_Real SCIPgetRhsVarbound(SCIP *scip, SCIP_CONS *cons)
SCIP_RETCODE SCIPexprCreatePolynomial(BMS_BLKMEM *blkmem, SCIP_EXPR **expr, int nchildren, SCIP_EXPR **children, int nmonomials, SCIP_EXPRDATA_MONOMIAL **monomials, SCIP_Real constant, SCIP_Bool copymonomials)
Definition: expr.c:6510
static SCIP_DECL_READERWRITE(readerWritePip)
Definition: reader_pip.c:3720
static void swapPointers(char **pointer1, char **pointer2)
Definition: reader_pip.c:271
SCIP_VAR ** SCIPgetLinearVarsQuadratic(SCIP *scip, SCIP_CONS *cons)
SCIP_Real SCIPgetVbdcoefVarbound(SCIP *scip, SCIP_CONS *cons)
static SCIP_Bool isSense(PIPINPUT *pipinput, PIPSENSE *sense)
Definition: reader_pip.c:611
SCIP_RETCODE SCIPsetReaderRead(SCIP *scip, SCIP_READER *reader, SCIP_DECL_READERREAD((*readerread)))
Definition: scip.c:4649
SCIP_RETCODE SCIPreleaseVar(SCIP *scip, SCIP_VAR **var)
Definition: scip.c:16884
SCIP_EXPR * SCIPexprtreeGetRoot(SCIP_EXPRTREE *tree)
Definition: expr.c:8442
static SCIP_Bool isDelimChar(char c)
Definition: reader_pip.c:165
SCIP_RETCODE SCIPchgVarType(SCIP *scip, SCIP_VAR *var, SCIP_VARTYPE vartype, SCIP_Bool *infeasible)
Definition: scip.c:22681
SCIP_Real SCIPvarGetUbLocal(SCIP_VAR *var)
Definition: var.c:17123
struct SCIP_ReaderData SCIP_READERDATA
Definition: type_reader.h:37
static SCIP_Bool isNewSection(SCIP *scip, PIPINPUT *pipinput)
Definition: reader_pip.c:421
public data structures and miscellaneous methods
int SCIPgetNExprtreesNonlinear(SCIP *scip, SCIP_CONS *cons)
SCIP_RETCODE SCIPcreateConsNonlinear(SCIP *scip, SCIP_CONS **cons, const char *name, int nlinvars, SCIP_VAR **linvars, SCIP_Real *lincoefs, int nexprtrees, SCIP_EXPRTREE **exprtrees, SCIP_Real *nonlincoefs, SCIP_Real lhs, SCIP_Real rhs, SCIP_Bool initial, SCIP_Bool separate, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool propagate, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool dynamic, SCIP_Bool removable, SCIP_Bool stickingatnode)
SCIP_EXPR ** SCIPexprGetChildren(SCIP_EXPR *expr)
Definition: expr.c:5593
SCIP_RETCODE SCIPchgVarUb(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound)
Definition: scip.c:19828
int SCIPvarGetIndex(SCIP_VAR *var)
Definition: var.c:16740
static SCIP_DECL_HASHKEYVAL(hashKeyValVar)
Definition: reader_pip.c:1975
#define SCIP_Bool
Definition: def.h:53
SCIP_MESSAGEHDLR * SCIPgetMessagehdlr(SCIP *scip)
Definition: scip.c:1216
void SCIPprintSysError(const char *message)
Definition: misc.c:8110
enum PipSense PIPSENSE
Definition: reader_pip.c:91
enum SCIP_Objsense SCIP_OBJSENSE
Definition: type_prob.h:41
SCIP_Real SCIPgetRhsBivariate(SCIP *scip, SCIP_CONS *cons)
SCIP_RETCODE SCIPincludeReaderBasic(SCIP *scip, SCIP_READER **readerptr, const char *name, const char *desc, const char *extension, SCIP_READERDATA *readerdata)
Definition: scip.c:4563
enum PipExpType PIPEXPTYPE
Definition: reader_pip.c:82
constraint handler for nonlinear constraints
static void pushToken(PIPINPUT *pipinput)
Definition: reader_pip.c:384
int SCIPexprGetNChildren(SCIP_EXPR *expr)
Definition: expr.c:5583
static void pushBufferToken(PIPINPUT *pipinput)
Definition: reader_pip.c:397
SCIP_RETCODE SCIPexprCreate(BMS_BLKMEM *blkmem, SCIP_EXPR **expr, SCIP_EXPROP op,...)
Definition: expr.c:5853
SCIP_Real * SCIPgetCoefsLinearVarsQuadratic(SCIP *scip, SCIP_CONS *cons)
SCIP_RETCODE SCIPexprtreeFree(SCIP_EXPRTREE **tree)
Definition: expr.c:8692
int SCIPgetNQuadVarTermsQuadratic(SCIP *scip, SCIP_CONS *cons)
static SCIP_Bool isSign(PIPINPUT *pipinput, int *sign)
Definition: reader_pip.c:554
static void swapTokenBuffer(PIPINPUT *pipinput)
Definition: reader_pip.c:410
SCIP_VAR * SCIPgetVbdvarVarbound(SCIP *scip, SCIP_CONS *cons)
constraint handler for bivariate nonlinear constraints
Constraint handler for linear constraints in their most general form, .
#define SCIP_EXPR_DEGREEINFINITY
Definition: type_expr.h:114
static SCIP_RETCODE readPIPFile(SCIP *scip, PIPINPUT *pipinput, const char *filename)
Definition: reader_pip.c:1889
SCIP_Real SCIPexprGetMonomialCoef(SCIP_EXPRDATA_MONOMIAL *monomial)
Definition: expr.c:5780
Constraint handler for absolute power constraints .
static SCIP_DECL_READERCOPY(readerCopyPip)
Definition: reader_pip.c:3694
void SCIPverbMessage(SCIP *scip, SCIP_VERBLEVEL msgverblevel, FILE *file, const char *formatstr,...)
Definition: scip.c:1298
#define PIP_INIT_VARSSIZE
Definition: reader_pip.c:56
void SCIPhashtableFree(SCIP_HASHTABLE **hashtable)
Definition: misc.c:1510
SCIP_RETCODE SCIPaddCons(SCIP *scip, SCIP_CONS *cons)
Definition: scip.c:11477
static SCIP_DECL_READERREAD(readerReadPip)
Definition: reader_pip.c:3709
SCIP_VARTYPE SCIPvarGetType(SCIP_VAR *var)
Definition: var.c:16608
PipExpType
Definition: reader_pip.c:76
#define SCIPallocBufferArray(scip, ptr, num)
Definition: scip.h:20585
static SCIP_RETCODE readBinaries(SCIP *scip, PIPINPUT *pipinput)
Definition: reader_pip.c:1845
SCIP_Real SCIPvarGetLbGlobal(SCIP_VAR *var)
Definition: var.c:17057
SCIP_Real SCIPgetLhsAbspower(SCIP *scip, SCIP_CONS *cons)
SCIP_RETCODE SCIPsetObjsense(SCIP *scip, SCIP_OBJSENSE objsense)
Definition: scip.c:10014
SCIP_Real * SCIPexprGetLinearCoefs(SCIP_EXPR *expr)
Definition: expr.c:5669
SCIP_RETCODE SCIPsetReaderWrite(SCIP *scip, SCIP_READER *reader, SCIP_DECL_READERWRITE((*readerwrite)))
Definition: scip.c:4673
SCIP_EXPRTREE ** SCIPgetExprtreesNonlinear(SCIP *scip, SCIP_CONS *cons)
static const SCIP_Real scalars[]
Definition: lp.c:5506
SCIP_Real SCIPexprGetOpReal(SCIP_EXPR *expr)
Definition: expr.c:5614
void SCIPinfoMessage(SCIP *scip, FILE *file, const char *formatstr,...)
Definition: scip.c:1281
static SCIP_RETCODE readGenerals(SCIP *scip, PIPINPUT *pipinput)
Definition: reader_pip.c:1810
SCIP_VAR ** SCIPgetVarsLogicor(SCIP *scip, SCIP_CONS *cons)
static SCIP_RETCODE readStart(SCIP *scip, PIPINPUT *pipinput)
Definition: reader_pip.c:681
int SCIPgetNVarsKnapsack(SCIP *scip, SCIP_CONS *cons)
SCIP_Real SCIPvarGetLbOriginal(SCIP_VAR *var)
Definition: var.c:17003
int SCIPgetNBilinTermsQuadratic(SCIP *scip, SCIP_CONS *cons)
SCIP_RETCODE SCIPcreateConsLinear(SCIP *scip, SCIP_CONS **cons, const char *name, int nvars, SCIP_VAR **vars, SCIP_Real *vals, SCIP_Real lhs, SCIP_Real rhs, SCIP_Bool initial, SCIP_Bool separate, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool propagate, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool dynamic, SCIP_Bool removable, SCIP_Bool stickingatnode)
SCIP_Bool SCIPisIntegral(SCIP *scip, SCIP_Real val)
Definition: scip.c:41721
SCIP_QUADELEM * SCIPexprGetQuadElements(SCIP_EXPR *expr)
Definition: expr.c:5695
SCIP_RETCODE SCIPincludeReaderPip(SCIP *scip)
Definition: reader_pip.c:3734
#define SCIPduplicateBufferArray(scip, ptr, source, num)
Definition: scip.h:20593
static void clearLine(char *linebuffer, int *linecnt)
Definition: reader_pip.c:2024
static SCIP_DECL_HASHKEYEQ(hashKeyEqVar)
Definition: reader_pip.c:1966
int SCIPexprGetNMonomials(SCIP_EXPR *expr)
Definition: expr.c:5756
static SCIP_RETCODE printQuadraticCons(SCIP *scip, FILE *file, const char *rowname, SCIP_VAR **linvars, SCIP_Real *linvals, int nlinvars, SCIP_QUADVARTERM *quadvarterms, int nquadvarterms, SCIP_BILINTERM *bilinterms, int nbilinterms, SCIP_Real lhs, SCIP_Real rhs, SCIP_Bool transformed)
Definition: reader_pip.c:2576
#define SCIP_Real
Definition: def.h:127
SCIP_Real SCIPgetOffsetAbspower(SCIP *scip, SCIP_CONS *cons)
static void printRowNl(SCIP *scip, FILE *file, const char *rowname, const char *rownameextension, const char *type, SCIP_VAR **linvars, SCIP_Real *linvals, int nlinvars, SCIP_EXPRTREE **exprtrees, SCIP_Real *exprtreecoefs, int nexprtrees, SCIP_Real rhs)
Definition: reader_pip.c:2222
SCIP_VAR * SCIPfindVar(SCIP *scip, const char *name)
Definition: scip.c:11392
static SCIP_Bool isTokenChar(char c)
Definition: reader_pip.c:174
SCIP_Real SCIPgetLhsLinear(SCIP *scip, SCIP_CONS *cons)
SCIP_Real * SCIPexprGetMonomialExponents(SCIP_EXPRDATA_MONOMIAL *monomial)
Definition: expr.c:5810
SCIP_VAR * SCIPgetNonlinearVarAbspower(SCIP *scip, SCIP_CONS *cons)
static SCIP_Bool getNextLine(SCIP *scip, PIPINPUT *pipinput)
Definition: reader_pip.c:227
SCIP_RETCODE SCIPexprtreePrintWithNames(SCIP_EXPRTREE *tree, SCIP_MESSAGEHDLR *messagehdlr, FILE *file)
Definition: nlp.c:172
#define SCIP_Longint
Definition: def.h:112
SCIP_Bool SCIPhashtableExists(SCIP_HASHTABLE *hashtable, void *element)
Definition: misc.c:1692
SCIP_RETCODE SCIPwritePip(SCIP *scip, FILE *file, const char *name, SCIP_Bool transformed, SCIP_OBJSENSE objsense, SCIP_Real objscale, SCIP_Real objoffset, SCIP_VAR **vars, int nvars, int nbinvars, int nintvars, int nimplvars, int ncontvars, SCIP_CONS **conss, int nconss, SCIP_RESULT *result)
Definition: reader_pip.c:2942
SCIP_Real SCIPgetRhsAbspower(SCIP *scip, SCIP_CONS *cons)
SCIP_Real SCIPround(SCIP *scip, SCIP_Real val)
Definition: scip.c:41782
SCIP_Real SCIPvarGetUbOriginal(SCIP_VAR *var)
Definition: var.c:17023
static SCIP_RETCODE getVariableIndex(SCIP *scip, SCIP_VAR ***vars, int *varssize, int *nvars, SCIP_HASHMAP *varhash, SCIP_VAR *var, int *varidx)
Definition: reader_pip.c:776
#define SCIPfreeBufferArray(scip, ptr)
Definition: scip.h:20597
SCIP_SETPPCTYPE SCIPgetTypeSetppc(SCIP *scip, SCIP_CONS *cons)
Definition: cons_setppc.c:9128
#define SCIPdebug(x)
Definition: pub_message.h:74
SCIP_VAR ** SCIPgetVarsLinear(SCIP *scip, SCIP_CONS *cons)
static const char commentchars[]
Definition: reader_pip.c:118
int SCIPcalcMemGrowSize(SCIP *scip, int num)
Definition: scip.c:41422
SCIP_RETCODE SCIPhashmapInsert(SCIP_HASHMAP *hashmap, void *origin, void *image)
Definition: misc.c:2094
static void syntaxError(SCIP *scip, PIPINPUT *pipinput, const char *msg)
Definition: reader_pip.c:127
SCIP_Real SCIPgetLhsQuadratic(SCIP *scip, SCIP_CONS *cons)
int SCIPfclose(SCIP_FILE *fp)
Definition: fileio.c:219
SCIP_Bool SCIPisPositive(SCIP *scip, SCIP_Real val)
Definition: scip.c:41697
SCIP_VAR * SCIPgetVarVarbound(SCIP *scip, SCIP_CONS *cons)
SCIP_Bool SCIPconsIsEnabled(SCIP_CONS *cons)
Definition: cons.c:7707
static SCIP_RETCODE readPolynomial(SCIP *scip, PIPINPUT *pipinput, char *name, SCIP_EXPRTREE **exprtree, int *degree, SCIP_Bool *newsection)
Definition: reader_pip.c:834
SCIP_Real SCIPexprGetLinearConstant(SCIP_EXPR *expr)
Definition: expr.c:5682
static SCIP_RETCODE collectAggregatedVars(SCIP *scip, int nvars, SCIP_VAR **vars, int *nAggregatedVars, SCIP_VAR ***aggregatedVars, SCIP_HASHTABLE **varAggregated)
Definition: reader_pip.c:2769
SCIP_VAR * SCIPgetLinearVarBivariate(SCIP *scip, SCIP_CONS *cons)
int SCIPexprGetNQuadElements(SCIP_EXPR *expr)
Definition: expr.c:5732
SCIP_RETCODE SCIPgetBoolParam(SCIP *scip, const char *name, SCIP_Bool *value)
Definition: scip.c:3740
static SCIP_Bool getNextToken(SCIP *scip, PIPINPUT *pipinput)
Definition: reader_pip.c:285
SCIP_Real SCIPgetRhsQuadratic(SCIP *scip, SCIP_CONS *cons)
SCIP_RETCODE SCIPreadPip(SCIP *scip, SCIP_READER *reader, const char *filename, SCIP_RESULT *result)
Definition: reader_pip.c:3757
SCIP_Real * SCIPgetValsLinear(SCIP *scip, SCIP_CONS *cons)
static SCIP_RETCODE getActiveVariables(SCIP *scip, SCIP_VAR **vars, SCIP_Real *scalars, int *nvars, SCIP_Real *constant, SCIP_Bool transformed)
Definition: reader_pip.c:1983
SCIP_Real SCIPgetCoefLinearAbspower(SCIP *scip, SCIP_CONS *cons)
SCIP_VAR ** SCIPexprtreeGetVars(SCIP_EXPRTREE *tree)
Definition: nlp.c:101
int SCIPgetNVarsAnd(SCIP *scip, SCIP_CONS *cons)
Definition: cons_and.c:5051