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