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