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-2020 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 256u /**< 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) || !isSense(pipinput, &sense) )
1512  {
1513  syntaxError(scip, pipinput, "expected constraint sense '<=', '=', or '>='");
1514  goto TERMINATE;
1515  }
1516 
1517  /* read the right hand side */
1518  sidesign = +1;
1519  if ( !getNextToken(scip, pipinput) )
1520  {
1521  syntaxError(scip, pipinput, "missing right hand side");
1522  goto TERMINATE;
1523  }
1524  if ( isSign(pipinput, &sidesign) )
1525  {
1526  if( !getNextToken(scip, pipinput) )
1527  {
1528  syntaxError(scip, pipinput, "missing value of right hand side");
1529  goto TERMINATE;
1530  }
1531  }
1532  if ( !isValue(scip, pipinput, &sidevalue) )
1533  {
1534  syntaxError(scip, pipinput, "expected value as right hand side");
1535  goto TERMINATE;
1536  }
1537  sidevalue *= sidesign;
1538 
1539  /* determine settings */
1540  initial = pipinput->initialconss;
1541  separate = TRUE;
1542  enforce = TRUE;
1543  check = TRUE;
1544  propagate = TRUE;
1545  local = FALSE;
1546  modifiable = FALSE;
1547  dynamic = pipinput->dynamicconss;
1548  removable = pipinput->dynamicrows;
1549 
1550  if( degree > 2 )
1551  {
1552  /* assign the left and right hand side, depending on the constraint sense */
1553  switch ( sense ) /*lint !e530*/
1554  {
1555  case PIP_SENSE_GE:
1556  lhs = sidevalue;
1557  rhs = SCIPinfinity(scip);
1558  break;
1559  case PIP_SENSE_LE:
1560  lhs = -SCIPinfinity(scip);
1561  rhs = sidevalue;
1562  break;
1563  case PIP_SENSE_EQ:
1564  lhs = sidevalue;
1565  rhs = sidevalue;
1566  break;
1567  case PIP_SENSE_NOTHING:
1568  default:
1569  SCIPerrorMessage("invalid constraint sense <%d>\n", sense);
1570  return SCIP_INVALIDDATA;
1571  }
1572 
1573  SCIP_CALL_TERMINATE( retcode, SCIPcreateConsNonlinear(scip, &cons, name, 0, NULL, NULL, 1, &exprtree, NULL, lhs, rhs,
1574  initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, FALSE), TERMINATE );
1575  }
1576  else
1577  {
1578  expr = SCIPexprtreeGetRoot(exprtree);
1579  assert(expr != NULL);
1580  assert(SCIPexprGetOperator(expr) == SCIP_EXPR_POLYNOMIAL);
1581  nmonomials = SCIPexprGetNMonomials(expr);
1582 
1583  SCIP_CALL( SCIPallocBufferArray(scip, &linvars, nmonomials) );
1584  SCIP_CALL( SCIPallocBufferArray(scip, &lincoefs, nmonomials) );
1585  SCIP_CALL( SCIPallocBufferArray(scip, &quadvars1, nmonomials) );
1586  SCIP_CALL( SCIPallocBufferArray(scip, &quadvars2, nmonomials) );
1587  SCIP_CALL( SCIPallocBufferArray(scip, &quadcoefs, nmonomials) );
1588 
1589  getLinearAndQuadraticCoefs(exprtree, &constant, &nlinvars, linvars, lincoefs, &nquadcoefs, quadvars1, quadvars2, quadcoefs);
1590 
1591  /* assign the left and right hand side, depending on the constraint sense */
1592  switch( sense ) /*lint !e530*/
1593  {
1594  case PIP_SENSE_GE:
1595  lhs = sidevalue - constant;
1596  rhs = SCIPinfinity(scip);
1597  break;
1598  case PIP_SENSE_LE:
1599  lhs = -SCIPinfinity(scip);
1600  rhs = sidevalue - constant;
1601  break;
1602  case PIP_SENSE_EQ:
1603  lhs = sidevalue - constant;
1604  rhs = sidevalue - constant;
1605  break;
1606  case PIP_SENSE_NOTHING:
1607  default:
1608  SCIPerrorMessage("invalid constraint sense <%d>\n", sense);
1609  return SCIP_INVALIDDATA;
1610  }
1611 
1612  if( nquadcoefs == 0 )
1613  {
1614  retcode = SCIPcreateConsLinear(scip, &cons, name, nlinvars, linvars, lincoefs, lhs, rhs,
1615  initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, FALSE);
1616  }
1617  else
1618  {
1619  retcode = SCIPcreateConsQuadratic(scip, &cons, name, nlinvars, linvars, lincoefs,
1620  nquadcoefs, quadvars1, quadvars2, quadcoefs, lhs, rhs,
1621  initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable);
1622  }
1623 
1624  /* free memory */
1625  SCIPfreeBufferArray(scip, &quadcoefs);
1626  SCIPfreeBufferArray(scip, &quadvars2);
1627  SCIPfreeBufferArray(scip, &quadvars1);
1628  SCIPfreeBufferArray(scip, &lincoefs);
1629  SCIPfreeBufferArray(scip, &linvars);
1630  }
1631 
1632  if( retcode == SCIP_OKAY )
1633  {
1634  SCIP_CALL( SCIPaddCons(scip, cons) );
1635  SCIPdebugMsg(scip, "(line %d) created constraint: ", pipinput->linenumber);
1636  SCIPdebugPrintCons(scip, cons, NULL);
1637  SCIP_CALL( SCIPreleaseCons(scip, &cons) );
1638  }
1639 
1640  TERMINATE:
1641  if( exprtree != NULL )
1642  {
1643  SCIP_CALL( SCIPexprtreeFree(&exprtree) );
1644  }
1645 
1646  if( hasError(pipinput) )
1647  retcode = SCIP_READERROR;
1648 
1649  SCIP_CALL( retcode );
1650 
1651  return SCIP_OKAY;
1652 }
1653 
1654 /** reads the bounds section */
1655 static
1657  SCIP* scip, /**< SCIP data structure */
1658  PIPINPUT* pipinput /**< PIP reading data */
1659  )
1660 {
1661  assert(pipinput != NULL);
1662 
1663  while( getNextToken(scip, pipinput) )
1664  {
1665  SCIP_VAR* var;
1666  SCIP_Real value;
1667  SCIP_Real lb;
1668  SCIP_Real ub;
1669  int sign;
1670  SCIP_Bool hassign;
1671  PIPSENSE leftsense;
1672 
1673  /* check if we reached a new section */
1674  if( isNewSection(scip, pipinput) )
1675  return SCIP_OKAY;
1676 
1677  /* default bounds are [0,+inf] */
1678  lb = 0.0;
1679  ub = SCIPinfinity(scip);
1680  leftsense = PIP_SENSE_NOTHING;
1681 
1682  /* check if the first token is a sign */
1683  sign = +1;
1684  hassign = isSign(pipinput, &sign);
1685  if( hassign && !getNextToken(scip, pipinput) )
1686  {
1687  syntaxError(scip, pipinput, "expected value");
1688  return SCIP_OKAY;
1689  }
1690 
1691  /* the first token must be either a value or a variable name */
1692  if( isValue(scip, pipinput, &value) )
1693  {
1694  /* first token is a value: the second token must be a sense */
1695  if( !getNextToken(scip, pipinput) || !isSense(pipinput, &leftsense) )
1696  {
1697  syntaxError(scip, pipinput, "expected bound sense '<=', '=', or '>='");
1698  return SCIP_OKAY;
1699  }
1700 
1701  /* update the bound corresponding to the sense */
1702  switch( leftsense )
1703  {
1704  case PIP_SENSE_GE:
1705  ub = sign * value;
1706  break;
1707  case PIP_SENSE_LE:
1708  lb = sign * value;
1709  break;
1710  case PIP_SENSE_EQ:
1711  lb = sign * value;
1712  ub = sign * value;
1713  break;
1714  case PIP_SENSE_NOTHING:
1715  default:
1716  SCIPerrorMessage("invalid bound sense <%d>\n", leftsense);
1717  return SCIP_INVALIDDATA;
1718  }
1719  }
1720  else if( hassign )
1721  {
1722  syntaxError(scip, pipinput, "expected value");
1723  return SCIP_OKAY;
1724  }
1725  else
1726  pushToken(pipinput);
1727 
1728  /* the next token must be a variable name */
1729  if( !getNextToken(scip, pipinput) )
1730  {
1731  syntaxError(scip, pipinput, "expected variable name");
1732  return SCIP_OKAY;
1733  }
1734  SCIP_CALL( getVariable(scip, pipinput->token, pipinput->dynamiccols, &var, NULL) );
1735 
1736  /* the next token might be another sense, or the word "free" */
1737  if( getNextToken(scip, pipinput) )
1738  {
1739  PIPSENSE rightsense;
1740 
1741  if( isSense(pipinput, &rightsense) )
1742  {
1743  /* check, if the senses fit */
1744  if( leftsense == PIP_SENSE_NOTHING
1745  || (leftsense == PIP_SENSE_LE && rightsense == PIP_SENSE_LE)
1746  || (leftsense == PIP_SENSE_GE && rightsense == PIP_SENSE_GE) )
1747  {
1748  if( !getNextToken(scip, pipinput) )
1749  {
1750  syntaxError(scip, pipinput, "expected value or sign");
1751  return SCIP_OKAY;
1752  }
1753 
1754  /* check if the next token is a sign */
1755  sign = +1;
1756  hassign = isSign(pipinput, &sign);
1757  if( hassign && !getNextToken(scip, pipinput) )
1758  {
1759  syntaxError(scip, pipinput, "expected value");
1760  return SCIP_OKAY;
1761  }
1762 
1763  /* the next token must be a value */
1764  if( !isValue(scip, pipinput, &value) )
1765  {
1766  syntaxError(scip, pipinput, "expected value");
1767  return SCIP_OKAY;
1768  }
1769 
1770  /* update the bound corresponding to the sense */
1771  switch( rightsense )
1772  {
1773  case PIP_SENSE_GE:
1774  lb = sign * value;
1775  break;
1776  case PIP_SENSE_LE:
1777  ub = sign * value;
1778  break;
1779  case PIP_SENSE_EQ:
1780  lb = sign * value;
1781  ub = sign * value;
1782  break;
1783  case PIP_SENSE_NOTHING:
1784  default:
1785  SCIPerrorMessage("invalid bound sense <%d>\n", leftsense);
1786  return SCIP_INVALIDDATA;
1787  }
1788  }
1789  else
1790  {
1791  syntaxError(scip, pipinput, "the two bound senses do not fit");
1792  return SCIP_OKAY;
1793  }
1794  }
1795  else if( strcasecmp(pipinput->token, "FREE") == 0 )
1796  {
1797  if( leftsense != PIP_SENSE_NOTHING )
1798  {
1799  syntaxError(scip, pipinput, "variable with bound is marked as 'free'");
1800  return SCIP_OKAY;
1801  }
1802  lb = -SCIPinfinity(scip);
1803  ub = SCIPinfinity(scip);
1804  }
1805  else
1806  {
1807  /* the token was no sense: push it back to the token stack */
1808  pushToken(pipinput);
1809  }
1810  }
1811 
1812  /* change the bounds of the variable if bounds have been given (do not destroy earlier specification of bounds) */
1813  if ( lb != 0.0 )
1814  SCIP_CALL( SCIPchgVarLb(scip, var, lb) );
1815  /*lint --e{777}*/
1816  if ( ub != SCIPinfinity(scip) )
1817  SCIP_CALL( SCIPchgVarUb(scip, var, ub) );
1818  SCIPdebugMsg(scip, "(line %d) new bounds: <%s>[%g,%g]\n", pipinput->linenumber, SCIPvarGetName(var),
1820  }
1821 
1822  return SCIP_OKAY;
1823 }
1824 
1825 /** reads the generals section */
1826 static
1828  SCIP* scip, /**< SCIP data structure */
1829  PIPINPUT* pipinput /**< PIP reading data */
1830  )
1831 {
1832  assert(pipinput != NULL);
1833 
1834  while( getNextToken(scip, pipinput) )
1835  {
1836  SCIP_VAR* var;
1837  SCIP_Bool created;
1838  SCIP_Bool infeasible;
1839 
1840  /* check if we reached a new section */
1841  if( isNewSection(scip, pipinput) )
1842  return SCIP_OKAY;
1843 
1844  /* the token must be the name of an existing variable */
1845  SCIP_CALL( getVariable(scip, pipinput->token, pipinput->dynamiccols, &var, &created) );
1846  if( created )
1847  {
1848  syntaxError(scip, pipinput, "unknown variable in generals section");
1849  return SCIP_OKAY;
1850  }
1851 
1852  /* mark the variable to be integral */
1853  SCIP_CALL( SCIPchgVarType(scip, var, SCIP_VARTYPE_INTEGER, &infeasible) );
1854  /* don't assert feasibility here because the presolver will and should detect a infeasibility */
1855  }
1856 
1857  return SCIP_OKAY;
1858 }
1859 
1860 /** reads the binaries section */
1861 static
1863  SCIP* scip, /**< SCIP data structure */
1864  PIPINPUT* pipinput /**< PIP reading data */
1865  )
1866 {
1867  assert(pipinput != NULL);
1868 
1869  while( getNextToken(scip, pipinput) )
1870  {
1871  SCIP_VAR* var;
1872  SCIP_Bool created;
1873  SCIP_Bool infeasible;
1874 
1875  /* check if we reached a new section */
1876  if( isNewSection(scip, pipinput) )
1877  return SCIP_OKAY;
1878 
1879  /* the token must be the name of an existing variable */
1880  SCIP_CALL( getVariable(scip, pipinput->token, pipinput->dynamiccols, &var, &created) );
1881  if( created )
1882  {
1883  syntaxError(scip, pipinput, "unknown variable in binaries section");
1884  return SCIP_OKAY;
1885  }
1886 
1887  /* mark the variable to be binary and change its bounds appropriately */
1888  if( SCIPvarGetLbGlobal(var) < 0.0 )
1889  {
1890  SCIP_CALL( SCIPchgVarLb(scip, var, 0.0) );
1891  }
1892  if( SCIPvarGetUbGlobal(var) > 1.0 )
1893  {
1894  SCIP_CALL( SCIPchgVarUb(scip, var, 1.0) );
1895  }
1896  SCIP_CALL( SCIPchgVarType(scip, var, SCIP_VARTYPE_BINARY, &infeasible) );
1897  /* don't assert feasibility here because the presolver will and should detect a infeasibility */
1898  }
1899 
1900  return SCIP_OKAY;
1901 }
1902 
1903 /** reads a PIP file
1904  */
1905 static
1907  SCIP* scip, /**< SCIP data structure */
1908  PIPINPUT* pipinput, /**< PIP reading data */
1909  const char* filename /**< name of the input file */
1910  )
1911 {
1912  assert(pipinput != NULL);
1913 
1914  /* open file */
1915  pipinput->file = SCIPfopen(filename, "r");
1916  if( pipinput->file == NULL )
1917  {
1918  SCIPerrorMessage("cannot open file <%s> for reading\n", filename);
1919  SCIPprintSysError(filename);
1920  return SCIP_NOFILE;
1921  }
1922 
1923  /* create problem */
1924  SCIP_CALL( SCIPcreateProb(scip, filename, NULL, NULL, NULL, NULL, NULL, NULL, NULL) );
1925 
1926  /* parse the file */
1927  pipinput->section = PIP_START;
1928  while( pipinput->section != PIP_END && !hasError(pipinput) )
1929  {
1930  switch( pipinput->section )
1931  {
1932  case PIP_START:
1933  SCIP_CALL( readStart(scip, pipinput) );
1934  break;
1935 
1936  case PIP_OBJECTIVE:
1937  SCIP_CALL( readObjective(scip, pipinput) );
1938  break;
1939 
1940  case PIP_CONSTRAINTS:
1941  SCIP_CALL( readConstraints(scip, pipinput) );
1942  break;
1943 
1944  case PIP_BOUNDS:
1945  SCIP_CALL( readBounds(scip, pipinput) );
1946  break;
1947 
1948  case PIP_GENERALS:
1949  SCIP_CALL( readGenerals(scip, pipinput) );
1950  break;
1951 
1952  case PIP_BINARIES:
1953  SCIP_CALL( readBinaries(scip, pipinput) );
1954  break;
1955 
1956  case PIP_END: /* this is already handled in the while() loop */
1957  default:
1958  SCIPerrorMessage("invalid PIP file section <%d>\n", pipinput->section);
1959  return SCIP_INVALIDDATA;
1960  }
1961  }
1962 
1963  /* close file */
1964  SCIPfclose(pipinput->file);
1965 
1966  return SCIP_OKAY;
1967 }
1968 
1969 
1970 /*
1971  * Local methods (for writing)
1972  */
1973 
1974 /** hash key retrieval function for variables */
1975 static
1976 SCIP_DECL_HASHGETKEY(hashGetKeyVar)
1977 { /*lint --e{715}*/
1978  return elem;
1979 }
1980 
1981 /** returns TRUE iff the indices of both variables are equal */
1982 static
1983 SCIP_DECL_HASHKEYEQ(hashKeyEqVar)
1984 { /*lint --e{715}*/
1985  if ( key1 == key2 )
1986  return TRUE;
1987  return FALSE;
1988 }
1989 
1990 /** returns the hash value of the key */
1991 static
1992 SCIP_DECL_HASHKEYVAL(hashKeyValVar)
1993 { /*lint --e{715}*/
1994  assert( SCIPvarGetIndex((SCIP_VAR*) key) >= 0 );
1995  return (unsigned int) SCIPvarGetIndex((SCIP_VAR*) key);
1996 }
1997 
1998 /** transforms given variables, scalars, and constant to the corresponding active variables, scalars, and constant */
1999 static
2001  SCIP* scip, /**< SCIP data structure */
2002  SCIP_VAR** vars, /**< vars array to get active variables for */
2003  SCIP_Real* scalars, /**< scalars a_1, ..., a_n in linear sum a_1*x_1 + ... + a_n*x_n + c */
2004  int* nvars, /**< pointer to number of variables and values in vars and vals array */
2005  SCIP_Real* constant, /**< pointer to constant c in linear sum a_1*x_1 + ... + a_n*x_n + c */
2006  SCIP_Bool transformed /**< transformed constraint? */
2007  )
2008 {
2009  int requiredsize;
2010  int v;
2011 
2012  assert( scip != NULL );
2013  assert( vars != NULL );
2014  assert( scalars != NULL );
2015  assert( nvars != NULL );
2016  assert( constant != NULL );
2017 
2018  if( transformed )
2019  {
2020  SCIP_CALL( SCIPgetProbvarLinearSum(scip, vars, scalars, nvars, *nvars, constant, &requiredsize, TRUE) );
2021 
2022  if( requiredsize > *nvars )
2023  {
2024  SCIP_CALL( SCIPreallocBufferArray(scip, &vars, requiredsize) );
2025  SCIP_CALL( SCIPreallocBufferArray(scip, &scalars, requiredsize) );
2026 
2027  SCIP_CALL( SCIPgetProbvarLinearSum(scip, vars, scalars, nvars, requiredsize, constant, &requiredsize, TRUE) );
2028  assert( requiredsize <= *nvars );
2029  }
2030  }
2031  else
2032  {
2033  for( v = 0; v < *nvars; ++v )
2034  SCIP_CALL( SCIPvarGetOrigvarSum(&vars[v], &scalars[v], constant) );
2035  }
2036  return SCIP_OKAY;
2037 }
2038 
2039 /** clears the given line buffer */
2040 static
2042  char* linebuffer, /**< line */
2043  int* linecnt /**< number of characters in line */
2044  )
2045 {
2046  assert( linebuffer != NULL );
2047  assert( linecnt != NULL );
2048 
2049  (*linecnt) = 0;
2050  linebuffer[0] = '\0';
2051 }
2052 
2053 /** ends the given line with '\\0' and prints it to the given file stream */
2054 static
2055 void endLine(
2056  SCIP* scip, /**< SCIP data structure */
2057  FILE* file, /**< output file (or NULL for standard output) */
2058  char* linebuffer, /**< line */
2059  int* linecnt /**< number of characters in line */
2060  )
2061 {
2062  assert( scip != NULL );
2063  assert( linebuffer != NULL );
2064  assert( linecnt != NULL );
2065  assert( 0 <= *linecnt && *linecnt < PIP_MAX_PRINTLEN );
2066 
2067  if( (*linecnt) > 0 )
2068  {
2069  linebuffer[(*linecnt)] = '\0';
2070  SCIPinfoMessage(scip, file, "%s\n", linebuffer);
2071  clearLine(linebuffer, linecnt);
2072  }
2073 }
2074 
2075 /** appends extension to line and prints it to the give file stream if the
2076  * line exceeded the length given in the define PIP_PRINTLEN */
2077 static
2079  SCIP* scip, /**< SCIP data structure */
2080  FILE* file, /**< output file (or NULL for standard output) */
2081  char* linebuffer, /**< line */
2082  int* linecnt, /**< number of characters in line */
2083  const char* extension /**< string to extent the line */
2084  )
2085 {
2086  assert( scip != NULL );
2087  assert( linebuffer != NULL );
2088  assert( linecnt != NULL );
2089  assert( extension != NULL );
2090  assert( strlen(linebuffer) + strlen(extension) < PIP_MAX_PRINTLEN );
2091 
2092  /* NOTE: avoid
2093  * sprintf(linebuffer, "%s%s", linebuffer, extension);
2094  * because of overlapping memory areas in memcpy used in sprintf.
2095  */
2096  (void) strncat(linebuffer, extension, PIP_MAX_PRINTLEN - strlen(linebuffer));
2097 
2098  (*linecnt) += (int) strlen(extension);
2099 
2100  SCIPdebugMsg(scip, "linebuffer <%s>, length = %lu\n", linebuffer, (unsigned long)strlen(linebuffer));
2101 
2102  if( (*linecnt) > PIP_PRINTLEN )
2103  endLine(scip, file, linebuffer, linecnt);
2104 }
2105 
2106 
2107 /* print row in PIP format to file stream */
2108 static
2110  SCIP* scip, /**< SCIP data structure */
2111  FILE* file, /**< output file (or NULL for standard output) */
2112  const char* rowname, /**< row name */
2113  const char* rownameextension, /**< row name extension */
2114  const char* type, /**< row type ("=", "<=", or ">=") */
2115  SCIP_VAR** linvars, /**< array of linear variables */
2116  SCIP_Real* linvals, /**< array of linear coefficient values */
2117  int nlinvars, /**< number of linear variables */
2118  SCIP_QUADVARTERM* quadvarterms, /**< quadratic variable terms */
2119  int nquadvarterms, /**< number of quadratic variable terms */
2120  SCIP_BILINTERM* bilinterms, /**< bilinear terms */
2121  int nbilinterms, /**< number of bilinear terms */
2122  SCIP_Real rhs /**< right hand side */
2123  )
2124 {
2125  int v;
2126  char linebuffer[PIP_MAX_PRINTLEN+1] = { '\0' };
2127  int linecnt;
2128 
2129  SCIP_VAR* var;
2130  char varname[PIP_MAX_NAMELEN];
2131  char varname2[PIP_MAX_NAMELEN];
2132  char consname[PIP_MAX_NAMELEN + 1]; /* an extra character for ':' */
2133  char buffer[PIP_MAX_PRINTLEN];
2134 
2135  assert( scip != NULL );
2136  assert( strcmp(type, "=") == 0 || strcmp(type, "<=") == 0 || strcmp(type, ">=") == 0 );
2137  assert( nlinvars == 0 || (linvars != NULL && linvals != NULL) );
2138  assert( nquadvarterms == 0 || quadvarterms != NULL );
2139 
2140  /* if there is a bilinear term, then there need to be at least two quadratic variables */
2141  assert( nbilinterms == 0 || (bilinterms != NULL && nquadvarterms >= 2) );
2142 
2143  clearLine(linebuffer, &linecnt);
2144 
2145  /* start each line with a space */
2146  appendLine(scip, file, linebuffer, &linecnt, " ");
2147 
2148  /* print row name */
2149  if ( strlen(rowname) > 0 || strlen(rownameextension) > 0 )
2150  {
2151  (void) SCIPsnprintf(consname, PIP_MAX_NAMELEN + 1, "%s%s:", rowname, rownameextension);
2152  appendLine(scip, file, linebuffer, &linecnt, consname);
2153  }
2154 
2155  /* print coefficients */
2156  for( v = 0; v < nlinvars; ++v )
2157  {
2158  assert(linvars != NULL); /* for lint */
2159  assert(linvals != NULL);
2160 
2161  var = linvars[v];
2162  assert( var != NULL );
2163 
2164  /* we start a new line; therefore we tab this line */
2165  if ( linecnt == 0 )
2166  appendLine(scip, file, linebuffer, &linecnt, " ");
2167 
2168  (void) SCIPsnprintf(varname, PIP_MAX_NAMELEN, "%s", SCIPvarGetName(var));
2169  (void) SCIPsnprintf(buffer, PIP_MAX_PRINTLEN, " %+.15g %s", linvals[v], varname);
2170 
2171  appendLine(scip, file, linebuffer, &linecnt, buffer);
2172  }
2173 
2174  /* print quadratic part */
2175  if( nquadvarterms > 0 )
2176  {
2177  /* print linear coefficients of quadratic variables */
2178  for( v = 0; v < nquadvarterms; ++v )
2179  {
2180  assert(quadvarterms != NULL); /* for lint */
2181 
2182  if( quadvarterms[v].lincoef == 0.0 )
2183  continue;
2184 
2185  /* we start a new line; therefore we tab this line */
2186  if (linecnt == 0 )
2187  appendLine(scip, file, linebuffer, &linecnt, " ");
2188 
2189  (void) SCIPsnprintf(varname, PIP_MAX_NAMELEN, "%s", SCIPvarGetName(quadvarterms[v].var));
2190  (void) SCIPsnprintf(buffer, PIP_MAX_PRINTLEN, " %+.15g %s", quadvarterms[v].lincoef, varname);
2191 
2192  appendLine(scip, file, linebuffer, &linecnt, buffer);
2193  }
2194 
2195  /* start quadratic part */
2196 
2197  /* print square terms */
2198  for( v = 0; v < nquadvarterms; ++v )
2199  {
2200  assert(quadvarterms != NULL); /* for lint */
2201  if( quadvarterms[v].sqrcoef == 0.0 )
2202  continue;
2203 
2204  /* we start a new line; therefore we tab this line */
2205  if (linecnt == 0 )
2206  appendLine(scip, file, linebuffer, &linecnt, " ");
2207 
2208  (void) SCIPsnprintf(varname, PIP_MAX_NAMELEN, "%s", SCIPvarGetName(quadvarterms[v].var));
2209  (void) SCIPsnprintf(buffer, PIP_MAX_PRINTLEN, " %+.15g %s^2", quadvarterms[v].sqrcoef, varname);
2210 
2211  appendLine(scip, file, linebuffer, &linecnt, buffer);
2212  }
2213 
2214  /* print bilinear terms */
2215  for( v = 0; v < nbilinterms; ++v )
2216  {
2217  /* we start a new line; therefore we tab this line */
2218  if (linecnt == 0 )
2219  appendLine(scip, file, linebuffer, &linecnt, " ");
2220 
2221  (void) SCIPsnprintf(varname, PIP_MAX_NAMELEN, "%s", SCIPvarGetName(bilinterms[v].var1));
2222  (void) SCIPsnprintf(varname2, PIP_MAX_NAMELEN, "%s", SCIPvarGetName(bilinterms[v].var2));
2223  (void) SCIPsnprintf(buffer, PIP_MAX_PRINTLEN, " %+.15g %s * %s", bilinterms[v].coef, varname, varname2);
2224 
2225  appendLine(scip, file, linebuffer, &linecnt, buffer);
2226  }
2227  }
2228 
2229  /* print right hand side */
2230  if( SCIPisZero(scip, rhs) )
2231  rhs = 0.0;
2232 
2233  (void) SCIPsnprintf(buffer, PIP_MAX_PRINTLEN, " %s %+.15g", type, rhs);
2234 
2235  /* we start a new line; therefore we tab this line */
2236  if (linecnt == 0 )
2237  appendLine(scip, file, linebuffer, &linecnt, " ");
2238  appendLine(scip, file, linebuffer, &linecnt, buffer);
2239 
2240  endLine(scip, file, linebuffer, &linecnt);
2241 }
2242 
2243 
2244 /* print row in PIP format to file stream */
2245 static
2247  SCIP* scip, /**< SCIP data structure */
2248  FILE* file, /**< output file (or NULL for standard output) */
2249  const char* rowname, /**< row name */
2250  const char* rownameextension, /**< row name extension */
2251  const char* type, /**< row type ("=", "<=", or ">=") */
2252  SCIP_VAR** linvars, /**< array of linear variables */
2253  SCIP_Real* linvals, /**< array of linear coefficient values */
2254  int nlinvars, /**< number of linear variables */
2255  SCIP_EXPRTREE** exprtrees, /**< expression trees */
2256  SCIP_Real* exprtreecoefs, /**< coefficients of expression trees */
2257  int nexprtrees, /**< number of expression trees */
2258  SCIP_Real rhs /**< right hand side */
2259  )
2260 {
2261  int v;
2262  int c;
2263  int e;
2264  char linebuffer[PIP_MAX_PRINTLEN+1] = { '\0' };
2265  int linecnt;
2266 
2267  SCIP_VAR* var;
2268  char varname[PIP_MAX_NAMELEN];
2269  char varname2[PIP_MAX_NAMELEN];
2270  char consname[PIP_MAX_NAMELEN + 1]; /* an extra character for ':' */
2271  char buffer[PIP_MAX_PRINTLEN];
2272 
2273  assert( scip != NULL );
2274  assert( strcmp(type, "=") == 0 || strcmp(type, "<=") == 0 || strcmp(type, ">=") == 0 );
2275  assert( nlinvars == 0 || (linvars != NULL && linvals != NULL) );
2276  assert( nexprtrees == 0 || exprtrees != NULL );
2277  assert( nexprtrees == 0 || exprtreecoefs != NULL );
2278 
2279  clearLine(linebuffer, &linecnt);
2280 
2281  /* start each line with a space */
2282  appendLine(scip, file, linebuffer, &linecnt, " ");
2283 
2284  /* print row name */
2285  if ( strlen(rowname) > 0 || strlen(rownameextension) > 0 )
2286  {
2287  (void) SCIPsnprintf(consname, PIP_MAX_NAMELEN + 1, "%s%s:", rowname, rownameextension);
2288  appendLine(scip, file, linebuffer, &linecnt, consname);
2289  }
2290 
2291  /* print coefficients */
2292  for( v = 0; v < nlinvars; ++v )
2293  {
2294  assert(linvars != NULL); /* for lint */
2295  assert(linvals != NULL);
2296 
2297  var = linvars[v];
2298  assert( var != NULL );
2299 
2300  /* we start a new line; therefore we tab this line */
2301  if ( linecnt == 0 )
2302  appendLine(scip, file, linebuffer, &linecnt, " ");
2303 
2304  (void) SCIPsnprintf(varname, PIP_MAX_NAMELEN, "%s", SCIPvarGetName(var));
2305  (void) SCIPsnprintf(buffer, PIP_MAX_PRINTLEN, " %+.15g %s", linvals[v], varname);
2306 
2307  appendLine(scip, file, linebuffer, &linecnt, buffer);
2308  }
2309 
2310  /* print nonlinear part */
2311  for( e = 0; e < nexprtrees; ++e )
2312  {
2313  SCIP_VAR** vars;
2314  SCIP_EXPR* expr;
2315  SCIP_EXPR** children;
2316  int nchildren;
2317 
2318  vars = SCIPexprtreeGetVars(exprtrees[e]);
2319  expr = SCIPexprtreeGetRoot(exprtrees[e]);
2320  children = SCIPexprGetChildren(expr);
2321  nchildren = SCIPexprGetNChildren(expr);
2322  assert(nchildren == 0 || children != NULL);
2323 
2324  /* we start a new line; therefore we tab this line */
2325  if( linecnt == 0 )
2326  appendLine(scip, file, linebuffer, &linecnt, " ");
2327 
2328  /* assert that all children of expr correspond to variables */
2329 #ifndef NDEBUG
2330  for( c = 0; c < nchildren; ++c )
2331  {
2332  assert(SCIPexprGetOperator(children[c]) == SCIP_EXPR_VARIDX);
2333  assert(SCIPexprGetOpIndex(children[c]) >= 0);
2334  assert(SCIPexprGetOpIndex(children[c]) < SCIPexprtreeGetNVars(exprtrees[e]));
2335  }
2336 #endif
2337 
2338  switch( SCIPexprGetOperator(expr) )
2339  {
2340  case SCIP_EXPR_CONST:
2341  {
2342  (void) SCIPsnprintf(buffer, PIP_MAX_PRINTLEN, " %+.15g", exprtreecoefs[e] * SCIPexprGetOpReal(expr));
2343  appendLine(scip, file, linebuffer, &linecnt, buffer);
2344 
2345  break;
2346  }
2347 
2348  case SCIP_EXPR_VARIDX:
2349  {
2350  assert(SCIPexprGetOpIndex(expr) >= 0);
2351  assert(SCIPexprGetOpIndex(expr) < SCIPexprtreeGetNVars(exprtrees[e]));
2352  (void) SCIPsnprintf(varname, PIP_MAX_NAMELEN, "%s", SCIPvarGetName(vars[SCIPexprGetOpIndex(expr)]));
2353  (void) SCIPsnprintf(buffer, PIP_MAX_PRINTLEN, " %+.15g %s", exprtreecoefs[e], varname);
2354 
2355  appendLine(scip, file, linebuffer, &linecnt, buffer);
2356  break;
2357  }
2358 
2359  case SCIP_EXPR_PLUS:
2360  {
2361  (void) SCIPsnprintf(varname, PIP_MAX_NAMELEN, "%s", SCIPvarGetName(vars[SCIPexprGetOpIndex(children[0])]));
2362  (void) SCIPsnprintf(varname2, PIP_MAX_NAMELEN, "%s", SCIPvarGetName(vars[SCIPexprGetOpIndex(children[1])]));
2363  (void) SCIPsnprintf(buffer, PIP_MAX_PRINTLEN, " %+.15g %s %+.15g %s", exprtreecoefs[e], varname, exprtreecoefs[e], varname2);
2364 
2365  appendLine(scip, file, linebuffer, &linecnt, buffer);
2366  break;
2367  }
2368 
2369  case SCIP_EXPR_MINUS:
2370  {
2371  (void) SCIPsnprintf(varname, PIP_MAX_NAMELEN, "%s", SCIPvarGetName(vars[SCIPexprGetOpIndex(children[0])]));
2372  (void) SCIPsnprintf(varname2, PIP_MAX_NAMELEN, "%s", SCIPvarGetName(vars[SCIPexprGetOpIndex(children[1])]));
2373  (void) SCIPsnprintf(buffer, PIP_MAX_PRINTLEN, " %+.15g %s %+.15g %s", exprtreecoefs[e], varname, -exprtreecoefs[e], varname2);
2374 
2375  appendLine(scip, file, linebuffer, &linecnt, buffer);
2376  break;
2377  }
2378 
2379  case SCIP_EXPR_MUL:
2380  {
2381  (void) SCIPsnprintf(varname, PIP_MAX_NAMELEN, "%s", SCIPvarGetName(vars[SCIPexprGetOpIndex(children[0])]));
2382  (void) SCIPsnprintf(varname2, PIP_MAX_NAMELEN, "%s", SCIPvarGetName(vars[SCIPexprGetOpIndex(children[1])]));
2383  (void) SCIPsnprintf(buffer, PIP_MAX_PRINTLEN, " %+.15g %s %s", exprtreecoefs[e], varname, varname2);
2384 
2385  appendLine(scip, file, linebuffer, &linecnt, buffer);
2386  break;
2387  }
2388 
2389  case SCIP_EXPR_SQUARE:
2390  {
2391  (void) SCIPsnprintf(varname, PIP_MAX_NAMELEN, "%s", SCIPvarGetName(vars[SCIPexprGetOpIndex(children[0])]));
2392  (void) SCIPsnprintf(buffer, PIP_MAX_PRINTLEN, " %+.15g %s^2", exprtreecoefs[e], varname);
2393 
2394  appendLine(scip, file, linebuffer, &linecnt, buffer);
2395  break;
2396  }
2397 
2398  case SCIP_EXPR_SQRT:
2399  {
2400  (void) SCIPsnprintf(varname, PIP_MAX_NAMELEN, "%s", SCIPvarGetName(vars[SCIPexprGetOpIndex(children[0])]));
2401  (void) SCIPsnprintf(buffer, PIP_MAX_PRINTLEN, " %+.15g %s^0.5", exprtreecoefs[e], varname);
2402 
2403  appendLine(scip, file, linebuffer, &linecnt, buffer);
2404  break;
2405  }
2406 
2407  case SCIP_EXPR_INTPOWER:
2408  {
2409  (void) SCIPsnprintf(varname, PIP_MAX_NAMELEN, "%s", SCIPvarGetName(vars[SCIPexprGetOpIndex(children[0])]));
2410  (void) SCIPsnprintf(buffer, PIP_MAX_PRINTLEN, " %+.15g %s^%d", exprtreecoefs[e], varname, SCIPexprGetIntPowerExponent(expr));
2411 
2412  appendLine(scip, file, linebuffer, &linecnt, buffer);
2413  break;
2414  }
2415 
2416  case SCIP_EXPR_REALPOWER:
2417  {
2418  (void) SCIPsnprintf(varname, PIP_MAX_NAMELEN, "%s", SCIPvarGetName(vars[SCIPexprGetOpIndex(children[0])]));
2419  (void) SCIPsnprintf(buffer, PIP_MAX_PRINTLEN, " %+.15g %s^%.15g", exprtreecoefs[e], varname, SCIPexprGetRealPowerExponent(expr));
2420 
2421  appendLine(scip, file, linebuffer, &linecnt, buffer);
2422  break;
2423  }
2424 
2425  case SCIP_EXPR_SUM:
2426  {
2427  for( c = 0; c < nchildren; ++c )
2428  {
2429  /* we start a new line; therefore we tab this line */
2430  if( linecnt == 0 )
2431  appendLine(scip, file, linebuffer, &linecnt, " ");
2432 
2433  (void) SCIPsnprintf(varname, PIP_MAX_NAMELEN, "%s", SCIPvarGetName(vars[SCIPexprGetOpIndex(children[c])]));
2434  (void) SCIPsnprintf(buffer, PIP_MAX_PRINTLEN, " %+.15g %s", exprtreecoefs[e], varname);
2435 
2436  appendLine(scip, file, linebuffer, &linecnt, buffer);
2437  }
2438 
2439  break;
2440  }
2441 
2442  case SCIP_EXPR_PRODUCT:
2443  {
2444  (void) SCIPsnprintf(buffer, PIP_MAX_PRINTLEN, " %+.15g", exprtreecoefs[e]);
2445  appendLine(scip, file, linebuffer, &linecnt, buffer);
2446 
2447  for( c = 0; c < nchildren; ++c )
2448  {
2449  /* we start a new line; therefore we tab this line */
2450  if( linecnt == 0 )
2451  appendLine(scip, file, linebuffer, &linecnt, " ");
2452 
2453  (void) SCIPsnprintf(varname, PIP_MAX_NAMELEN, " %s", SCIPvarGetName(vars[SCIPexprGetOpIndex(children[c])]));
2454  (void) SCIPsnprintf(buffer, PIP_MAX_PRINTLEN, varname);
2455 
2456  appendLine(scip, file, linebuffer, &linecnt, buffer);
2457  }
2458 
2459  break;
2460  }
2461 
2462  case SCIP_EXPR_LINEAR:
2463  {
2464  if( SCIPexprGetLinearConstant(expr) != 0.0 )
2465  {
2466  (void) SCIPsnprintf(buffer, PIP_MAX_PRINTLEN, " %+.15g ", exprtreecoefs[e] * SCIPexprGetLinearConstant(expr));
2467  appendLine(scip, file, linebuffer, &linecnt, buffer);
2468  }
2469 
2470  for( c = 0; c < nchildren; ++c )
2471  {
2472  /* we start a new line; therefore we tab this line */
2473  if( linecnt == 0 )
2474  appendLine(scip, file, linebuffer, &linecnt, " ");
2475 
2476  (void) SCIPsnprintf(varname, PIP_MAX_NAMELEN, "%s", SCIPvarGetName(vars[SCIPexprGetOpIndex(children[c])]));
2477  (void) SCIPsnprintf(buffer, PIP_MAX_PRINTLEN, " %+.15g %s", exprtreecoefs[e] * SCIPexprGetLinearCoefs(expr)[c], varname);
2478 
2479  appendLine(scip, file, linebuffer, &linecnt, buffer);
2480  }
2481 
2482  break;
2483  }
2484 
2485  case SCIP_EXPR_QUADRATIC:
2486  {
2487  int q;
2488 
2489  if( SCIPexprGetQuadConstant(expr) != 0.0 )
2490  {
2491  (void) SCIPsnprintf(buffer, PIP_MAX_PRINTLEN, " %+.15g ", exprtreecoefs[e] * SCIPexprGetQuadConstant(expr));
2492  appendLine(scip, file, linebuffer, &linecnt, buffer);
2493  }
2494 
2495  if( SCIPexprGetQuadLinearCoefs(expr) != NULL )
2496  {
2497  for( c = 0; c < nchildren; ++c )
2498  {
2499  if( SCIPexprGetQuadLinearCoefs(expr)[c] == 0.0 )
2500  continue;
2501 
2502  /* we start a new line; therefore we tab this line */
2503  if( linecnt == 0 )
2504  appendLine(scip, file, linebuffer, &linecnt, " ");
2505 
2506  (void) SCIPsnprintf(varname, PIP_MAX_NAMELEN, "%s", SCIPvarGetName(vars[SCIPexprGetOpIndex(children[c])]));
2507  (void) SCIPsnprintf(buffer, PIP_MAX_PRINTLEN, " %+.15g %s", exprtreecoefs[e] * SCIPexprGetQuadLinearCoefs(expr)[c], varname);
2508 
2509  appendLine(scip, file, linebuffer, &linecnt, buffer);
2510  }
2511  }
2512 
2513  for( q = 0; q < SCIPexprGetNQuadElements(expr); ++q )
2514  {
2515  /* we start a new line; therefore we tab this line */
2516  if( linecnt == 0 )
2517  appendLine(scip, file, linebuffer, &linecnt, " ");
2518 
2519  (void) SCIPsnprintf(varname, PIP_MAX_NAMELEN, "%s", SCIPvarGetName(vars[SCIPexprGetOpIndex(children[SCIPexprGetQuadElements(expr)[q].idx1])]));
2520 
2521  if( SCIPexprGetQuadElements(expr)[q].idx1 == SCIPexprGetQuadElements(expr)[q].idx2 )
2522  {
2523  /* square term */
2524  (void) SCIPsnprintf(buffer, PIP_MAX_PRINTLEN, " %+.15g %s^2", exprtreecoefs[e] * SCIPexprGetQuadElements(expr)[q].coef, varname);
2525  }
2526  else
2527  {
2528  /* bilinear term */
2529  (void) SCIPsnprintf(varname2, PIP_MAX_NAMELEN, "%s", SCIPvarGetName(vars[SCIPexprGetOpIndex(children[SCIPexprGetQuadElements(expr)[q].idx2])]));
2530  (void) SCIPsnprintf(buffer, PIP_MAX_PRINTLEN, " %+.15g %s %s", exprtreecoefs[e] * SCIPexprGetQuadElements(expr)[q].coef, varname, varname2);
2531  }
2532 
2533  appendLine(scip, file, linebuffer, &linecnt, buffer);
2534  }
2535 
2536  break;
2537  }
2538 
2539  case SCIP_EXPR_POLYNOMIAL:
2540  {
2541  SCIP_EXPRDATA_MONOMIAL* monomial;
2542  int m;
2543  int f;
2544 
2545  if( SCIPexprGetPolynomialConstant(expr) != 0.0 )
2546  {
2547  (void) SCIPsnprintf(buffer, PIP_MAX_PRINTLEN, " %+.15g ", exprtreecoefs[e] * SCIPexprGetPolynomialConstant(expr));
2548  appendLine(scip, file, linebuffer, &linecnt, buffer);
2549  }
2550 
2551  for( m = 0; m < SCIPexprGetNMonomials(expr); ++m )
2552  {
2553  monomial = SCIPexprGetMonomials(expr)[m];
2554  assert(monomial != NULL);
2555 
2556  (void) SCIPsnprintf(buffer, PIP_MAX_PRINTLEN, " %+.15g", exprtreecoefs[e] * SCIPexprGetMonomialCoef(monomial));
2557  appendLine(scip, file, linebuffer, &linecnt, buffer);
2558 
2559  for( f = 0; f < SCIPexprGetMonomialNFactors(monomial); ++f )
2560  {
2561  /* we start a new line; therefore we tab this line */
2562  if( linecnt == 0 )
2563  appendLine(scip, file, linebuffer, &linecnt, " ");
2564 
2565  (void) SCIPsnprintf(varname, PIP_MAX_NAMELEN, "%s", SCIPvarGetName(vars[SCIPexprGetOpIndex(children[SCIPexprGetMonomialChildIndices(monomial)[f]])]));
2566  if( SCIPexprGetMonomialExponents(monomial)[f] != 1.0 )
2567  (void) SCIPsnprintf(buffer, PIP_MAX_PRINTLEN, " %s^%.15g", varname, SCIPexprGetMonomialExponents(monomial)[f]);
2568  else
2569  (void) SCIPsnprintf(buffer, PIP_MAX_PRINTLEN, " %s", varname);
2570  appendLine(scip, file, linebuffer, &linecnt, buffer);
2571  }
2572  }
2573 
2574  break;
2575  }
2576 
2577  default:
2578  {
2579  /* this should have been caught in SCIPwritePip before */
2580  SCIPerrorMessage("unsupported operator <%s> in writing of polynomial nonlinear constraint\n", SCIPexpropGetName(SCIPexprGetOperator(expr)));
2581  return;
2582  } /*lint !e788*/
2583  } /*lint !e788*/
2584  }
2585 
2586  /* print right hand side */
2587  if( SCIPisZero(scip, rhs) )
2588  rhs = 0.0;
2589 
2590  (void) SCIPsnprintf(buffer, PIP_MAX_PRINTLEN, " %s %+.15g", type, rhs);
2591 
2592  /* we start a new line; therefore we tab this line */
2593  if (linecnt == 0 )
2594  appendLine(scip, file, linebuffer, &linecnt, " ");
2595  appendLine(scip, file, linebuffer, &linecnt, buffer);
2596 
2597  endLine(scip, file, linebuffer, &linecnt);
2598 }
2599 
2600 
2601 /** prints given (linear or) quadratic constraint information in LP format to file stream */
2602 static
2604  SCIP* scip, /**< SCIP data structure */
2605  FILE* file, /**< output file (or NULL for standard output) */
2606  const char* rowname, /**< name of the row */
2607  SCIP_VAR** linvars, /**< array of linear variables */
2608  SCIP_Real* linvals, /**< array of linear coefficients values (or NULL if all linear coefficient values are 1) */
2609  int nlinvars, /**< number of linear variables */
2610  SCIP_QUADVARTERM* quadvarterms, /**< quadratic variable terms */
2611  int nquadvarterms, /**< number of quadratic variable terms */
2612  SCIP_BILINTERM* bilinterms, /**< bilinear terms */
2613  int nbilinterms, /**< number of bilinear terms */
2614  SCIP_Real lhs, /**< left hand side */
2615  SCIP_Real rhs, /**< right hand side */
2616  SCIP_Bool transformed /**< transformed constraint? */
2617  )
2618 {
2619  int v;
2620  SCIP_VAR** activevars = NULL;
2621  SCIP_Real* activevals = NULL;
2622  int nactivevars;
2623  SCIP_Real activeconstant = 0.0;
2624 
2625  assert( scip != NULL );
2626  assert( rowname != NULL );
2627 
2628  assert( nlinvars == 0 || linvars != NULL );
2629  assert( nquadvarterms == 0 || quadvarterms != NULL );
2630  assert( nbilinterms == 0 || bilinterms != NULL );
2631 
2632  assert( lhs <= rhs );
2633 
2634  if( SCIPisInfinity(scip, -lhs) && SCIPisInfinity(scip, rhs) )
2635  return SCIP_OKAY;
2636 
2637  nactivevars = nlinvars;
2638  if( nlinvars > 0 )
2639  {
2640  /* duplicate variable and value array */
2641  SCIP_CALL( SCIPduplicateBufferArray(scip, &activevars, linvars, nactivevars ) );
2642  if( linvals != NULL )
2643  {
2644  SCIP_CALL( SCIPduplicateBufferArray(scip, &activevals, linvals, nactivevars ) );
2645  }
2646  else
2647  {
2648  SCIP_CALL( SCIPallocBufferArray(scip, &activevals, nactivevars) );
2649 
2650  for( v = 0; v < nactivevars; ++v )
2651  activevals[v] = 1.0;
2652  }
2653 
2654  /* retransform given variables to active variables */
2655  SCIP_CALL( getActiveVariables(scip, activevars, activevals, &nactivevars, &activeconstant, transformed) );
2656  }
2657 
2658  /* print row(s) in LP format */
2659  if( SCIPisEQ(scip, lhs, rhs) )
2660  {
2661  assert( !SCIPisInfinity(scip, rhs) );
2662 
2663  /* equal constraint */
2664  printRow(scip, file, rowname, "", "=", activevars, activevals, nactivevars,
2665  quadvarterms, nquadvarterms, bilinterms, nbilinterms,
2666  rhs - activeconstant);
2667  }
2668  else
2669  {
2670  if( !SCIPisInfinity(scip, -lhs) )
2671  {
2672  /* print inequality ">=" */
2673  printRow(scip, file, rowname, SCIPisInfinity(scip, rhs) ? "" : "_lhs", ">=",
2674  activevars, activevals, nactivevars,
2675  quadvarterms, nquadvarterms, bilinterms, nbilinterms,
2676  lhs - activeconstant);
2677  }
2678  if( !SCIPisInfinity(scip, rhs) )
2679  {
2680  /* print inequality "<=" */
2681  printRow(scip, file, rowname, SCIPisInfinity(scip, -lhs) ? "" : "_rhs", "<=",
2682  activevars, activevals, nactivevars,
2683  quadvarterms, nquadvarterms, bilinterms, nbilinterms,
2684  rhs - activeconstant);
2685  }
2686  }
2687 
2688  if( nlinvars > 0 )
2689  {
2690  /* free buffer arrays */
2691  SCIPfreeBufferArray(scip, &activevars);
2692  SCIPfreeBufferArray(scip, &activevals);
2693  }
2694 
2695  return SCIP_OKAY;
2696 }
2697 
2698 /** prints given nonlinear constraint information in LP format to file stream */
2699 static
2701  SCIP* scip, /**< SCIP data structure */
2702  FILE* file, /**< output file (or NULL for standard output) */
2703  const char* rowname, /**< name of the row */
2704  SCIP_VAR** linvars, /**< array of linear variables */
2705  SCIP_Real* linvals, /**< array of linear coefficients values (or NULL if all linear coefficient values are 1) */
2706  int nlinvars, /**< number of linear variables */
2707  SCIP_EXPRTREE** exprtrees, /**< expression trees */
2708  SCIP_Real* exprtreecoefs, /**< coefficients of expression trees */
2709  int nexprtrees, /**< number of expression trees */
2710  SCIP_Real lhs, /**< left hand side */
2711  SCIP_Real rhs, /**< right hand side */
2712  SCIP_Bool transformed /**< transformed constraint? */
2713  )
2714 {
2715  int v;
2716  SCIP_VAR** activevars = NULL;
2717  SCIP_Real* activevals = NULL;
2718  int nactivevars;
2719  SCIP_Real activeconstant = 0.0;
2720 
2721  assert( scip != NULL );
2722  assert( rowname != NULL );
2723 
2724  assert( nlinvars == 0 || linvars != NULL );
2725  assert( nexprtrees == 0 || exprtrees != NULL );
2726  assert( nexprtrees == 0 || exprtreecoefs != NULL );
2727 
2728  assert( lhs <= rhs );
2729 
2730  if( SCIPisInfinity(scip, -lhs) && SCIPisInfinity(scip, rhs) )
2731  return SCIP_OKAY;
2732 
2733  nactivevars = nlinvars;
2734  if( nlinvars > 0 )
2735  {
2736  /* duplicate variable and value array */
2737  SCIP_CALL( SCIPduplicateBufferArray(scip, &activevars, linvars, nactivevars ) );
2738  if( linvals != NULL )
2739  {
2740  SCIP_CALL( SCIPduplicateBufferArray(scip, &activevals, linvals, nactivevars ) );
2741  }
2742  else
2743  {
2744  SCIP_CALL( SCIPallocBufferArray(scip, &activevals, nactivevars) );
2745 
2746  for( v = 0; v < nactivevars; ++v )
2747  activevals[v] = 1.0;
2748  }
2749 
2750  /* retransform given variables to active variables */
2751  SCIP_CALL( getActiveVariables(scip, activevars, activevals, &nactivevars, &activeconstant, transformed) );
2752  }
2753 
2754  /* print row(s) in LP format */
2755  if( SCIPisEQ(scip, lhs, rhs) )
2756  {
2757  assert( !SCIPisInfinity(scip, rhs) );
2758 
2759  /* equal constraint */
2760  /* coverity[tainted_string_warning] */
2761  printRowNl(scip, file, rowname, "", "=", activevars, activevals, nactivevars,
2762  exprtrees, exprtreecoefs, nexprtrees,
2763  rhs - activeconstant);
2764  }
2765  else
2766  {
2767  if( !SCIPisInfinity(scip, -lhs) )
2768  {
2769  /* print inequality ">=" */
2770  /* coverity[tainted_string_warning] */
2771  printRowNl(scip, file, rowname, SCIPisInfinity(scip, rhs) ? "" : "_lhs", ">=",
2772  activevars, activevals, nactivevars,
2773  exprtrees, exprtreecoefs, nexprtrees,
2774  lhs - activeconstant);
2775  }
2776  if( !SCIPisInfinity(scip, rhs) )
2777  {
2778  /* print inequality "<=" */
2779  /* coverity[tainted_string_warning] */
2780  printRowNl(scip, file, rowname, SCIPisInfinity(scip, -lhs) ? "" : "_rhs", "<=",
2781  activevars, activevals, nactivevars,
2782  exprtrees, exprtreecoefs, nexprtrees,
2783  rhs - activeconstant);
2784  }
2785  }
2786 
2787  if( nlinvars > 0 )
2788  {
2789  /* free buffer arrays */
2790  SCIPfreeBufferArray(scip, &activevars);
2791  SCIPfreeBufferArray(scip, &activevals);
2792  }
2793 
2794  return SCIP_OKAY;
2795 }
2796 
2797 /** check whether given variables are aggregated and put them into an array without duplication */
2798 static
2800  int nvars, /**< number of active variables in the problem */
2801  SCIP_VAR** vars, /**< variable array */
2802  int* nAggregatedVars, /**< number of aggregated variables on output */
2803  SCIP_VAR*** aggregatedVars, /**< array storing the aggregated variables on output */
2804  SCIP_HASHTABLE** varAggregated /**< hashtable for checking duplicates */
2805  )
2806 {
2807  int j;
2808 
2809  /* check variables */
2810  for (j = 0; j < nvars; ++j)
2811  {
2812  SCIP_VARSTATUS status;
2813  SCIP_VAR* var;
2814 
2815  var = vars[j];
2816  status = SCIPvarGetStatus(var);
2817 
2818  /* collect aggregated variables in a list */
2819  if( status >= SCIP_VARSTATUS_AGGREGATED )
2820  {
2821  assert( status == SCIP_VARSTATUS_AGGREGATED ||
2822  status == SCIP_VARSTATUS_MULTAGGR ||
2823  status == SCIP_VARSTATUS_NEGATED );
2824 
2825  if ( ! SCIPhashtableExists(*varAggregated, (void*) var) )
2826  {
2827  (*aggregatedVars)[(*nAggregatedVars)++] = var;
2828  SCIP_CALL( SCIPhashtableInsert(*varAggregated, (void*) var) );
2829  }
2830  }
2831  }
2832 
2833  return SCIP_OKAY;
2834 }
2835 
2836 
2837 /** print aggregated variable-constraints */
2838 static
2840  SCIP* scip, /**< SCIP data structure */
2841  FILE* file, /**< output file (or NULL for standard output) */
2842  SCIP_Bool transformed, /**< TRUE iff problem is the transformed problem */
2843  int nvars, /**< number of active variables in the problem */
2844  int nAggregatedVars, /**< number of aggregated variables */
2845  SCIP_VAR** aggregatedVars /**< array storing the aggregated variables */
2846  )
2847 {
2848  int j;
2849 
2850  SCIP_VAR** activevars;
2851  SCIP_Real* activevals;
2852  int nactivevars;
2853  SCIP_Real activeconstant = 0.0;
2854  char consname[PIP_MAX_NAMELEN];
2855 
2856  assert( scip != NULL );
2857 
2858  /* write aggregation constraints */
2859  SCIP_CALL( SCIPallocBufferArray(scip, &activevars, nvars) );
2860  SCIP_CALL( SCIPallocBufferArray(scip, &activevals, nvars) );
2861 
2862  for (j = 0; j < nAggregatedVars; ++j)
2863  {
2864  /* set up list to obtain substitution variables */
2865  nactivevars = 1;
2866 
2867  activevars[0] = aggregatedVars[j];
2868  activevals[0] = 1.0;
2869  activeconstant = 0.0;
2870 
2871  /* retransform given variables to active variables */
2872  SCIP_CALL( getActiveVariables(scip, activevars, activevals, &nactivevars, &activeconstant, transformed) );
2873 
2874  activevals[nactivevars] = -1.0;
2875  activevars[nactivevars] = aggregatedVars[j];
2876  ++nactivevars;
2877 
2878  /* output constraint */
2879  (void) SCIPsnprintf(consname, PIP_MAX_NAMELEN, "aggr_%s", SCIPvarGetName(aggregatedVars[j]));
2880  printRow(scip, file, consname, "", "=", activevars, activevals, nactivevars, NULL, 0, NULL, 0, - activeconstant);
2881  }
2882 
2883  /* free buffer arrays */
2884  SCIPfreeBufferArray(scip, &activevars);
2885  SCIPfreeBufferArray(scip, &activevals);
2886 
2887  return SCIP_OKAY;
2888 }
2889 
2890 /** returns whether name is valid according to PIP specification
2891  *
2892  * Checks these two conditions from http://polip.zib.de/pipformat.php:
2893  * - Names/labels can contain at most 255 characters.
2894  * - Name/labels have to consist of the following characters: a-z, A-Z, 0-9, "!", "#", "$", "%", "&", ";", "?", "@", "_". They cannot start with a number.
2895  *
2896  * In addition checks that the length is not zero.
2897  */
2898 static
2900  const char* name /**< name to check */
2901  )
2902 {
2903  size_t len;
2904  size_t i;
2905 
2906  assert(name != NULL);
2907 
2908  len = strlen(name); /*lint !e613*/
2909  if( len > PIP_MAX_NAMELEN || len == 0 )
2910  return FALSE;
2911 
2912  /* names cannot start with a number */
2913  if( isdigit(name[0]) )
2914  return FALSE;
2915 
2916  for( i = 0; i < len; ++i )
2917  {
2918  /* a-z, A-Z, 0-9 are ok */
2919  if( isalnum(name[i]) )
2920  continue;
2921 
2922  /* characters in namechars are ok, too */
2923  if( strchr(namechars, name[i]) != NULL )
2924  continue;
2925 
2926  return FALSE;
2927  }
2928 
2929  return TRUE;
2930 }
2931 
2932 
2933 /** method check if the variable names are valid according to PIP specification */
2934 static
2936  SCIP* scip, /**< SCIP data structure */
2937  SCIP_VAR** vars, /**< array of variables */
2938  int nvars /**< number of variables */
2939  )
2940 {
2941  int v;
2942 
2943  assert(scip != NULL);
2944  assert(vars != NULL || nvars == 0);
2945 
2946  /* check if the variable names are not too long and have only characters allowed by PIP */
2947  for( v = 0; v < nvars; ++v )
2948  {
2949  if( !isNameValid(SCIPvarGetName(vars[v])) )
2950  {
2951  SCIPwarningMessage(scip, "variable name <%s> is not valid (too long or disallowed characters); PIP might be corrupted\n", SCIPvarGetName(vars[v]));
2952  return;
2953  }
2954  }
2955 }
2956 
2957 /** method check if the constraint names are valid according to PIP specification */
2958 static
2960  SCIP* scip, /**< SCIP data structure */
2961  SCIP_CONS** conss, /**< array of constraints */
2962  int nconss, /**< number of constraints */
2963  SCIP_Bool transformed /**< TRUE iff problem is the transformed problem */
2964  )
2965 {
2966  int c;
2967  SCIP_CONS* cons;
2968  SCIP_CONSHDLR* conshdlr;
2969  const char* conshdlrname;
2970 
2971  assert( scip != NULL );
2972  assert( conss != NULL || nconss == 0 );
2973 
2974  for( c = 0; c < nconss; ++c )
2975  {
2976  assert(conss != NULL); /* for lint */
2977  cons = conss[c];
2978  assert(cons != NULL );
2979 
2980  /* in case the transformed is written only constraints are posted which are enabled in the current node */
2981  assert(!transformed || SCIPconsIsEnabled(cons));
2982 
2983  conshdlr = SCIPconsGetHdlr(cons);
2984  assert( conshdlr != NULL );
2985 
2986  conshdlrname = SCIPconshdlrGetName(conshdlr);
2987  assert( transformed == SCIPconsIsTransformed(cons) );
2988 
2989  if( !isNameValid(SCIPconsGetName(cons)) )
2990  {
2991  SCIPwarningMessage(scip, "constraint name <%s> is not valid (too long or unallowed characters); PIP might be corrupted\n", SCIPconsGetName(cons));
2992  return;
2993  }
2994 
2995  if( strcmp(conshdlrname, "linear") == 0 )
2996  {
2997  SCIP_Real lhs = SCIPgetLhsLinear(scip, cons);
2998  SCIP_Real rhs = SCIPgetLhsLinear(scip, cons);
2999 
3000  /* for ranged constraints, we need to be able to append _lhs and _rhs to the constraint name, so need additional 4 characters */
3001  if( !SCIPisEQ(scip, lhs, rhs) && strlen(SCIPconsGetName(cons)) > PIP_MAX_NAMELEN - 4 )
3002  {
3003  SCIPwarningMessage(scip, "name of ranged constraint <%s> has to be cut down to %d characters;\n", SCIPconsGetName(conss[c]),
3004  PIP_MAX_NAMELEN - 1);
3005  return;
3006  }
3007  }
3008  }
3009 }
3010 
3011 /** writes problem to file
3012  * @todo add writing cons_pseudoboolean
3013  */
3015  SCIP* scip, /**< SCIP data structure */
3016  FILE* file, /**< output file, or NULL if standard output should be used */
3017  const char* name, /**< problem name */
3018  SCIP_Bool transformed, /**< TRUE iff problem is the transformed problem */
3019  SCIP_OBJSENSE objsense, /**< objective sense */
3020  SCIP_Real objscale, /**< scalar applied to objective function; external objective value is
3021  * extobj = objsense * objscale * (intobj + objoffset) */
3022  SCIP_Real objoffset, /**< objective offset from bound shifting and fixing */
3023  SCIP_VAR** vars, /**< array with active variables ordered binary, integer, implicit, continuous */
3024  int nvars, /**< number of active variables in the problem */
3025  int nbinvars, /**< number of binary variables */
3026  int nintvars, /**< number of general integer variables */
3027  int nimplvars, /**< number of implicit integer variables */
3028  int ncontvars, /**< number of continuous variables */
3029  SCIP_CONS** conss, /**< array with constraints of the problem */
3030  int nconss, /**< number of constraints in the problem */
3031  SCIP_RESULT* result /**< pointer to store the result of the file writing call */
3032  )
3033 {
3034  int c;
3035  int v;
3036  int e;
3037 
3038  int linecnt;
3039  char linebuffer[PIP_MAX_PRINTLEN+1];
3040 
3041  char varname[PIP_MAX_NAMELEN];
3042  char buffer[PIP_MAX_PRINTLEN];
3043 
3044  SCIP_CONSHDLR* conshdlr;
3045  const char* conshdlrname;
3046  SCIP_CONS* cons;
3047  SCIP_CONS** consQuadratic;
3048  int nConsQuadratic;
3049  SCIP_CONS** consNonlinear;
3050  int nConsNonlinear;
3051  SCIP_CONS** consAbspower;
3052  int nConsAbspower;
3053  SCIP_CONS** consAnd;
3054  int nConsAnd;
3055  SCIP_CONS** consBivariate;
3056  int nConsBivariate;
3057  char consname[PIP_MAX_NAMELEN];
3058 
3059  SCIP_VAR** aggregatedVars;
3060  int nAggregatedVars;
3061  SCIP_HASHTABLE* varAggregated;
3062 
3063  SCIP_VAR** consvars;
3064  SCIP_Real* consvals;
3065  int nconsvars;
3066 
3067  SCIP_VAR* var;
3068  SCIP_Real lb;
3069  SCIP_Real ub;
3070 
3071  SCIP_EXPRTREE* exprtree;
3072  SCIP_EXPR* expr;
3073 
3074  assert( scip != NULL );
3075 
3076  nAggregatedVars = 0;
3077  nConsQuadratic = 0;
3078  nConsNonlinear = 0;
3079  nConsAbspower = 0;
3080  nConsAnd = 0;
3081  nConsBivariate = 0;
3082 
3083  /* check if the variable names are not to long */
3084  checkVarnames(scip, vars, nvars);
3085 
3086  /* check if the constraint names are to long */
3087  checkConsnames(scip, conss, nconss, transformed);
3088 
3089  /* print statistics as comment to file */
3090  SCIPinfoMessage(scip, file, "\\ SCIP STATISTICS\n");
3091  SCIPinfoMessage(scip, file, "\\ Problem name : %s\n", name);
3092  SCIPinfoMessage(scip, file, "\\ Variables : %d (%d binary, %d integer, %d implicit integer, %d continuous)\n",
3093  nvars, nbinvars, nintvars, nimplvars, ncontvars);
3094  SCIPinfoMessage(scip, file, "\\ Constraints : %d\n", nconss);
3095 
3096  /* print objective sense */
3097  SCIPinfoMessage(scip, file, "%s\n", objsense == SCIP_OBJSENSE_MINIMIZE ? "Minimize" : "Maximize");
3098 
3099  clearLine(linebuffer, &linecnt);
3100  appendLine(scip, file, linebuffer, &linecnt, " Obj:");
3101 
3102  for (v = 0; v < nvars; ++v)
3103  {
3104  var = vars[v];
3105 
3106 #ifndef NDEBUG
3107  /* in case the original problem has to be posted the variables have to be either "original" or "negated" */
3108  if ( !transformed )
3110 #endif
3111 
3112  if ( SCIPisZero(scip, SCIPvarGetObj(var)) )
3113  continue;
3114 
3115  /* we start a new line; therefore we tab this line */
3116  if ( linecnt == 0 )
3117  appendLine(scip, file, linebuffer, &linecnt, " ");
3118 
3119  (void) SCIPsnprintf(varname, PIP_MAX_NAMELEN, "%s", SCIPvarGetName(var));
3120  (void) SCIPsnprintf(buffer, PIP_MAX_PRINTLEN, " %+.15g %s", objscale * SCIPvarGetObj(var), varname );
3121 
3122  appendLine(scip, file, linebuffer, &linecnt, buffer);
3123  }
3124 
3125  if( ! SCIPisZero(scip, objoffset) )
3126  {
3127  (void) SCIPsnprintf(buffer, PIP_MAX_PRINTLEN, " %+.15g", objscale * objoffset);
3128  appendLine(scip, file, linebuffer, &linecnt, buffer);
3129  }
3130 
3131  endLine(scip, file, linebuffer, &linecnt);
3132 
3133  /* print "Subject to" section */
3134  SCIPinfoMessage(scip, file, "Subject to\n");
3135 
3136  /* collect quadratic, nonlinear, absolute power, and, and bivariate constraints in arrays */
3137  SCIP_CALL( SCIPallocBufferArray(scip, &consQuadratic, nconss) );
3138  SCIP_CALL( SCIPallocBufferArray(scip, &consNonlinear, nconss) );
3139  SCIP_CALL( SCIPallocBufferArray(scip, &consAbspower, nconss) );
3140  SCIP_CALL( SCIPallocBufferArray(scip, &consAnd, nconss) );
3141  SCIP_CALL( SCIPallocBufferArray(scip, &consBivariate, nconss) );
3142 
3143  for (c = 0; c < nconss; ++c)
3144  {
3145  cons = conss[c];
3146  assert( cons != NULL);
3147 
3148  /* in case the transformed is written only constraints are posted which are enabled in the current node */
3149  assert(!transformed || SCIPconsIsEnabled(cons));
3150 
3151  conshdlr = SCIPconsGetHdlr(cons);
3152  assert( conshdlr != NULL );
3153 
3154  (void) SCIPsnprintf(consname, PIP_MAX_NAMELEN, "%s", SCIPconsGetName(cons));
3155  conshdlrname = SCIPconshdlrGetName(conshdlr);
3156  assert( transformed == SCIPconsIsTransformed(cons) );
3157 
3158  if( strcmp(conshdlrname, "linear") == 0 )
3159  {
3160  SCIP_CALL( printQuadraticCons(scip, file, consname,
3161  SCIPgetVarsLinear(scip, cons), SCIPgetValsLinear(scip, cons), SCIPgetNVarsLinear(scip, cons),
3162  NULL, 0, NULL, 0, SCIPgetLhsLinear(scip, cons), SCIPgetRhsLinear(scip, cons), transformed) );
3163  }
3164  else if( strcmp(conshdlrname, "setppc") == 0 )
3165  {
3166  consvars = SCIPgetVarsSetppc(scip, cons);
3167  nconsvars = SCIPgetNVarsSetppc(scip, cons);
3168 
3169  switch( SCIPgetTypeSetppc(scip, cons) )
3170  {
3172  SCIP_CALL( printQuadraticCons(scip, file, consname,
3173  consvars, NULL, nconsvars, NULL, 0, NULL, 0, 1.0, 1.0, transformed) );
3174  break;
3176  SCIP_CALL( printQuadraticCons(scip, file, consname,
3177  consvars, NULL, nconsvars, NULL, 0, NULL, 0, -SCIPinfinity(scip), 1.0, transformed) );
3178  break;
3180  SCIP_CALL( printQuadraticCons(scip, file, consname,
3181  consvars, NULL, nconsvars, NULL, 0, NULL, 0, 1.0, SCIPinfinity(scip), transformed) );
3182  break;
3183  }
3184  }
3185  else if ( strcmp(conshdlrname, "logicor") == 0 )
3186  {
3187  SCIP_CALL( printQuadraticCons(scip, file, consname,
3188  SCIPgetVarsLogicor(scip, cons), NULL, SCIPgetNVarsLogicor(scip, cons),
3189  NULL, 0, NULL, 0, 1.0, SCIPinfinity(scip), transformed) );
3190  }
3191  else if ( strcmp(conshdlrname, "knapsack") == 0 )
3192  {
3193  SCIP_Longint* weights;
3194 
3195  consvars = SCIPgetVarsKnapsack(scip, cons);
3196  nconsvars = SCIPgetNVarsKnapsack(scip, cons);
3197 
3198  /* copy Longint array to SCIP_Real array */
3199  weights = SCIPgetWeightsKnapsack(scip, cons);
3200  SCIP_CALL( SCIPallocBufferArray(scip, &consvals, nconsvars) );
3201  for( v = 0; v < nconsvars; ++v )
3202  consvals[v] = (SCIP_Real)weights[v];
3203 
3204  SCIP_CALL( printQuadraticCons(scip, file, consname, consvars, consvals, nconsvars,
3205  NULL, 0, NULL, 0, -SCIPinfinity(scip), (SCIP_Real) SCIPgetCapacityKnapsack(scip, cons), transformed) );
3206 
3207  SCIPfreeBufferArray(scip, &consvals);
3208  }
3209  else if ( strcmp(conshdlrname, "varbound") == 0 )
3210  {
3211  SCIP_CALL( SCIPallocBufferArray(scip, &consvars, 2) );
3212  SCIP_CALL( SCIPallocBufferArray(scip, &consvals, 2) );
3213 
3214  consvars[0] = SCIPgetVarVarbound(scip, cons);
3215  consvars[1] = SCIPgetVbdvarVarbound(scip, cons);
3216 
3217  consvals[0] = 1.0;
3218  consvals[1] = SCIPgetVbdcoefVarbound(scip, cons);
3219 
3220  SCIP_CALL( printQuadraticCons(scip, file, consname, consvars, consvals, 2, NULL, 0, NULL, 0,
3221  SCIPgetLhsVarbound(scip, cons), SCIPgetRhsVarbound(scip, cons), transformed) );
3222 
3223  SCIPfreeBufferArray(scip, &consvars);
3224  SCIPfreeBufferArray(scip, &consvals);
3225  }
3226  else if( strcmp(conshdlrname, "quadratic") == 0 )
3227  {
3228  SCIP_CALL( printQuadraticCons(scip, file, consname,
3232  SCIPgetNBilinTermsQuadratic(scip, cons), SCIPgetLhsQuadratic(scip, cons),
3233  SCIPgetRhsQuadratic(scip, cons), transformed) );
3234 
3235  consQuadratic[nConsQuadratic++] = cons;
3236  }
3237  else if( strcmp(conshdlrname, "nonlinear") == 0 )
3238  {
3239  SCIP_Bool ispolynomial;
3240  int nexprtrees = SCIPgetNExprtreesNonlinear(scip, cons);
3241 
3242  /* check whether expressions are polynomials (assumed simplified exprtrees) */
3243  ispolynomial = TRUE;
3244  for( e = 0; e < nexprtrees && ispolynomial; ++e )
3245  {
3246  exprtree = SCIPgetExprtreesNonlinear(scip, cons)[e];
3247  expr = SCIPexprtreeGetRoot(exprtree);
3248  assert(expr != NULL);
3249 
3250  /* check if operator is something polynomial */
3251  switch( SCIPexprGetOperator(expr) )
3252  {
3253  case SCIP_EXPR_CONST:
3254  case SCIP_EXPR_VARIDX:
3255  case SCIP_EXPR_PLUS:
3256  case SCIP_EXPR_MINUS:
3257  case SCIP_EXPR_MUL:
3258  case SCIP_EXPR_SQUARE:
3259  case SCIP_EXPR_SQRT:
3260  case SCIP_EXPR_SUM:
3261  case SCIP_EXPR_PRODUCT:
3262  case SCIP_EXPR_LINEAR:
3263  case SCIP_EXPR_QUADRATIC:
3264  break;
3265 
3266  case SCIP_EXPR_INTPOWER:
3267  {
3268  if( SCIPexprGetIntPowerExponent(expr) < 0 )
3269  {
3270  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));
3271  ispolynomial = FALSE;
3272  }
3273 
3274  break;
3275  }
3276 
3277  case SCIP_EXPR_REALPOWER:
3278  {
3279  if( SCIPexprGetRealPowerExponent(expr) < 0.0 )
3280  {
3281  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));
3282  ispolynomial = FALSE;
3283  }
3284 
3285  break;
3286  }
3287 
3288  case SCIP_EXPR_POLYNOMIAL:
3289  {
3290  SCIP_EXPRDATA_MONOMIAL* monomial;
3291  int m;
3292  int f;
3293 
3294  for( m = 0; m < SCIPexprGetNMonomials(expr) && ispolynomial; ++m )
3295  {
3296  monomial = SCIPexprGetMonomials(expr)[m];
3297  for( f = 0; f < SCIPexprGetMonomialNFactors(monomial); ++f )
3298  {
3299  if( SCIPexprGetMonomialExponents(monomial)[f] < 0.0 )
3300  {
3301  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));
3302  ispolynomial = FALSE;
3303  break;
3304  }
3305  }
3306  }
3307 
3308  break;
3309  }
3310 
3311  default:
3312  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));
3313  ispolynomial = FALSE;
3314  break;
3315  } /*lint !e788*/
3316 
3317  /* check if all children of root expression correspond to variables */
3318  for( v = 0; v < SCIPexprGetNChildren(expr) && ispolynomial; ++v )
3319  {
3321  {
3322  SCIPwarningMessage(scip, "%dth expression tree of constraint <%s> is not simplified, cannot write in pip format\n", e, SCIPconsGetName(cons));
3323  ispolynomial = FALSE;
3324  }
3325  }
3326  }
3327 
3328  if( ispolynomial )
3329  {
3330  /* coverity[tainted_string_warning] */
3331  SCIP_CALL( printNonlinearCons(scip, file, consname,
3333  SCIPgetNLinearVarsNonlinear(scip, cons), SCIPgetExprtreesNonlinear(scip, cons),
3335  SCIPgetLhsNonlinear(scip, cons), SCIPgetRhsNonlinear(scip, cons), transformed) );
3336 
3337  consNonlinear[nConsNonlinear++] = cons;
3338  }
3339  else
3340  {
3341  SCIPinfoMessage(scip, file, "\\ ");
3342  SCIP_CALL( SCIPprintCons(scip, cons, file) );
3343  SCIPinfoMessage(scip, file, ";\n");
3344  }
3345  }
3346  else if( strcmp(conshdlrname, "abspower") == 0 )
3347  {
3348  SCIP_VAR* x;
3349  SCIP_Real xoffset;
3350  SCIP_Real exponent;
3351  SCIP_Real treecoef;
3352 
3353  expr = NULL;
3354  treecoef = 1.0;
3355 
3356  x = SCIPgetNonlinearVarAbspower(scip, cons);
3357  xoffset = SCIPgetOffsetAbspower(scip, cons);
3358  exponent = SCIPgetExponentAbspower(scip, cons);
3359 
3360  /* see if we formulate signpower(x+offset,exponent) as usual polynomial */
3361  if( !SCIPisZero(scip, xoffset) )
3362  {
3363  SCIPwarningMessage(scip, "nonzero offset for nonlinear variable in constraint <%s>, cannot write in pip format\n", SCIPconsGetName(cons));
3364  }
3365  if( SCIPisIntegral(scip, exponent) && ((int)SCIPround(scip, exponent) % 2 == 1) )
3366  {
3367  /* exponent is odd integer, so signpower(x,exponent) = x^exponent */
3368  SCIP_CALL( SCIPexprCreate(SCIPblkmem(scip), &expr, SCIP_EXPR_VARIDX, 0) );
3369  SCIP_CALL( SCIPexprCreate(SCIPblkmem(scip), &expr, SCIP_EXPR_INTPOWER, expr, (int)SCIPround(scip, exponent)) );
3370  }
3371  else if( SCIPisIntegral(scip, exponent) && ((int)SCIPround(scip, exponent) % 2 == 0) && !SCIPisPositive(scip, SCIPvarGetUbGlobal(x)) )
3372  {
3373  /* exponent is even integer and x is negative, so signpower(x,exponent) = -x^exponent */
3374  SCIP_CALL( SCIPexprCreate(SCIPblkmem(scip), &expr, SCIP_EXPR_VARIDX, 0) );
3375  SCIP_CALL( SCIPexprCreate(SCIPblkmem(scip), &expr, SCIP_EXPR_INTPOWER, expr, (int)SCIPround(scip, exponent)) );
3376  treecoef = -1.0;
3377  }
3378  else if( !SCIPisNegative(scip, SCIPvarGetLbGlobal(x)) )
3379  {
3380  /* x is positive, so signpower(x,exponent) = x^exponent */
3381  SCIP_CALL( SCIPexprCreate(SCIPblkmem(scip), &expr, SCIP_EXPR_VARIDX, 0) );
3382  SCIP_CALL( SCIPexprCreate(SCIPblkmem(scip), &expr, SCIP_EXPR_REALPOWER, expr, exponent) );
3383  }
3384  else
3385  {
3386  SCIPwarningMessage(scip, "cannot formulate signpower(<%s>, %g) in constraint <%s> as polynomial, cannot write in pip format\n", SCIPvarGetName(x), exponent, SCIPconsGetName(cons));
3387  }
3388 
3389  if( expr != NULL )
3390  {
3391  SCIP_VAR* z;
3392  SCIP_Real zcoef;
3393 
3394  SCIP_CALL( SCIPexprtreeCreate(SCIPblkmem(scip), &exprtree, expr, 1, 0, NULL) );
3395  SCIP_CALL( SCIPexprtreeSetVars(exprtree, 1, &x) );
3396 
3397  z = SCIPgetLinearVarAbspower(scip, cons);
3398  zcoef = SCIPgetCoefLinearAbspower(scip, cons);
3399 
3400  SCIP_CALL( printNonlinearCons(scip, file, consname,
3401  &z, &zcoef, 1, &exprtree, &treecoef, 1,
3402  SCIPgetLhsAbspower(scip, cons), SCIPgetRhsAbspower(scip, cons), transformed) );
3403 
3404  SCIP_CALL( SCIPexprtreeFree(&exprtree) );
3405 
3406  consAbspower[nConsAbspower++] = cons;
3407  }
3408  else
3409  {
3410  SCIPinfoMessage(scip, file, "\\ ");
3411  SCIP_CALL( SCIPprintCons(scip, cons, file) );
3412  SCIPinfoMessage(scip, file, ";\n");
3413  }
3414  }
3415  else if( strcmp(conshdlrname, "bivariate") == 0 )
3416  {
3417  SCIP_Bool ispolynomial;
3418 
3419  /* check whether expression is polynomial (simplified exprtree assumed) */
3420  ispolynomial = TRUE;
3421  exprtree = SCIPgetExprtreeBivariate(scip, cons);
3422  expr = SCIPexprtreeGetRoot(exprtree);
3423  assert(expr != NULL);
3424 
3425  /* check if operator is something polynomial */
3426  switch( SCIPexprGetOperator(expr) )
3427  {
3428  case SCIP_EXPR_CONST:
3429  case SCIP_EXPR_VARIDX:
3430  case SCIP_EXPR_PLUS:
3431  case SCIP_EXPR_MINUS:
3432  case SCIP_EXPR_MUL:
3433  case SCIP_EXPR_SQUARE:
3434  case SCIP_EXPR_SQRT:
3435  case SCIP_EXPR_SUM:
3436  case SCIP_EXPR_PRODUCT:
3437  case SCIP_EXPR_LINEAR:
3438  case SCIP_EXPR_QUADRATIC:
3439  break;
3440 
3441  case SCIP_EXPR_INTPOWER:
3442  {
3443  if( SCIPexprGetIntPowerExponent(expr) < 0 )
3444  {
3445  SCIPwarningMessage(scip, "negative exponent %d in intpower of constraint <%s> cannot be written in pip format\n", SCIPexprGetIntPowerExponent(expr), SCIPconsGetName(cons));
3446  ispolynomial = FALSE;
3447  }
3448 
3449  break;
3450  }
3451 
3452  case SCIP_EXPR_REALPOWER:
3453  {
3454  if( SCIPexprGetRealPowerExponent(expr) < 0.0 )
3455  {
3456  SCIPwarningMessage(scip, "negative exponent %g in realpower of constraint <%s> cannot be written in pip format\n", SCIPexprGetRealPowerExponent(expr), SCIPconsGetName(cons));
3457  ispolynomial = FALSE;
3458  }
3459 
3460  break;
3461  }
3462 
3463  case SCIP_EXPR_POLYNOMIAL:
3464  {
3465  SCIP_EXPRDATA_MONOMIAL* monomial;
3466  int m;
3467  int f;
3468 
3469  for( m = 0; m < SCIPexprGetNMonomials(expr) && ispolynomial; ++m )
3470  {
3471  monomial = SCIPexprGetMonomials(expr)[m];
3472  for( f = 0; f < SCIPexprGetMonomialNFactors(monomial); ++f )
3473  {
3474  if( SCIPexprGetMonomialExponents(monomial)[f] < 0.0 )
3475  {
3476  SCIPwarningMessage(scip, "negative exponent %g in polynomial of constraint <%s> cannot be written in pip format\n", SCIPexprGetMonomialExponents(monomial)[f], SCIPconsGetName(cons));
3477  ispolynomial = FALSE;
3478  break;
3479  }
3480  }
3481  }
3482 
3483  break;
3484  }
3485 
3486  default:
3487  SCIPwarningMessage(scip, "expression operand <%s> in constraint <%s> cannot be written in pip format\n", SCIPexpropGetName(SCIPexprGetOperator(expr)), SCIPconsGetName(cons));
3488  ispolynomial = FALSE;
3489  break;
3490  } /*lint !e788*/
3491 
3492  if( ispolynomial )
3493  {
3494  /* check if all children of root expression correspond to variables */
3495  for( v = 0; v < SCIPexprGetNChildren(expr); ++v )
3496  {
3498  {
3499  SCIPwarningMessage(scip, "expression tree of constraint <%s> is not simplified, cannot write in pip format\n", SCIPconsGetName(cons));
3500  ispolynomial = FALSE;
3501  break;
3502  }
3503  }
3504  }
3505 
3506  if( ispolynomial )
3507  {
3508  SCIP_VAR* z;
3509  SCIP_Real zcoef;
3510  SCIP_Real one;
3511 
3512  z = SCIPgetLinearVarBivariate(scip, cons);
3513  zcoef = SCIPgetLinearCoefBivariate(scip, cons);
3514 
3515  one = 1.0;
3516  SCIP_CALL( printNonlinearCons(scip, file, consname,
3517  &z, &zcoef, z == NULL ? 0 : 1, &exprtree, &one, 1,
3518  SCIPgetLhsBivariate(scip, cons), SCIPgetRhsBivariate(scip, cons), transformed) );
3519 
3520  consBivariate[nConsBivariate++] = cons;
3521  }
3522  else
3523  {
3524  SCIPinfoMessage(scip, file, "\\ ");
3525  SCIP_CALL( SCIPprintCons(scip, cons, file) );
3526  SCIPinfoMessage(scip, file, ";\n");
3527  }
3528  }
3529  else if( strcmp(conshdlrname, "and") == 0 )
3530  {
3531  SCIP_EXPR** children;
3532  SCIP_VAR* resultant;
3533  SCIP_Real minusone;
3534  SCIP_Real one;
3535 
3536  /* create expression for product of binaries */
3537  SCIP_CALL( SCIPallocBufferArray(scip, &children, SCIPgetNVarsAnd(scip, cons)) );
3538  for( v = 0; v < SCIPgetNVarsAnd(scip, cons); ++v )
3539  {
3540  SCIP_CALL( SCIPexprCreate(SCIPblkmem(scip), &children[v], SCIP_EXPR_VARIDX, v) );
3541  }
3542  SCIP_CALL( SCIPexprCreate(SCIPblkmem(scip), &expr, SCIP_EXPR_PRODUCT, SCIPgetNVarsAnd(scip, cons), children) );
3543  SCIP_CALL( SCIPexprtreeCreate(SCIPblkmem(scip), &exprtree, expr, SCIPgetNVarsAnd(scip, cons), 0, NULL) );
3544  SCIP_CALL( SCIPexprtreeSetVars(exprtree, SCIPgetNVarsAnd(scip, cons), SCIPgetVarsAnd(scip, cons)) );
3545 
3546  resultant = SCIPgetResultantAnd(scip, cons);
3547  minusone = -1.0;
3548 
3549  one = 1.0;
3550  SCIP_CALL( printNonlinearCons(scip, file, consname, &resultant, &minusone, 1, &exprtree, &one, 1, 0.0, 0.0, transformed) );
3551 
3552  SCIP_CALL( SCIPexprtreeFree(&exprtree) );
3553  SCIPfreeBufferArray(scip, &children);
3554 
3555  consAnd[nConsAnd++] = cons;
3556  }
3557  else
3558  {
3559  SCIPwarningMessage(scip, "constraint handler <%s> cannot print requested format\n", conshdlrname );
3560  SCIPinfoMessage(scip, file, "\\ ");
3561  SCIP_CALL( SCIPprintCons(scip, cons, file) );
3562  SCIPinfoMessage(scip, file, ";\n");
3563  }
3564  }
3565 
3566  /* create hashtable for storing aggregated variables */
3567  SCIP_CALL( SCIPallocBufferArray(scip, &aggregatedVars, nvars) );
3568  SCIP_CALL( SCIPhashtableCreate(&varAggregated, SCIPblkmem(scip), nvars/10, hashGetKeyVar, hashKeyEqVar, hashKeyValVar, NULL) );
3569 
3570  /* check for aggregated variables in quadratic parts of quadratic constraints and output aggregations as linear constraints */
3571  for (c = 0; c < nConsQuadratic; ++c)
3572  {
3573  cons = consQuadratic[c];
3574  for( v = 0; v < SCIPgetNQuadVarTermsQuadratic(scip, cons); ++v )
3575  {
3577  &nAggregatedVars, &aggregatedVars, &varAggregated) );
3578  }
3579  }
3580 
3581  /* check for aggregated variables in expression trees of nonlinear constraints and output aggregations as linear constraints */
3582  for (c = 0; c < nConsNonlinear; ++c)
3583  {
3584  cons = consNonlinear[c];
3585  for( e = 0; e < SCIPgetNExprtreesNonlinear(scip, cons); ++e )
3586  {
3587  exprtree = SCIPgetExprtreesNonlinear(scip, cons)[e];
3588  assert(exprtree != NULL);
3589 
3590  for( v = 0; v < SCIPexprtreeGetNVars(exprtree); ++v )
3591  {
3593  &nAggregatedVars, &aggregatedVars, &varAggregated) );
3594  }
3595  }
3596  }
3597 
3598  /* check for aggregated variables in absolute power constraints and output aggregations as linear constraints */
3599  for (c = 0; c < nConsAbspower; ++c)
3600  {
3601  SCIP_VAR* spvars[2];
3602 
3603  cons = consAbspower[c];
3604 
3605  spvars[0] = SCIPgetNonlinearVarAbspower(scip, cons);
3606  spvars[1] = SCIPgetLinearVarAbspower(scip, cons);
3607  SCIP_CALL( collectAggregatedVars(2, spvars, &nAggregatedVars, &aggregatedVars, &varAggregated) );
3608  }
3609 
3610  /* check for aggregated variables in and constraints and output aggregations as linear constraints */
3611  for (c = 0; c < nConsAnd; ++c)
3612  {
3613  SCIP_VAR* resultant;
3614 
3615  cons = consAnd[c];
3616 
3617  SCIP_CALL( collectAggregatedVars(SCIPgetNVarsAnd(scip, cons), SCIPgetVarsAnd(scip, cons), &nAggregatedVars, &aggregatedVars, &varAggregated) );
3618 
3619  resultant = SCIPgetResultantAnd(scip, cons);
3620  SCIP_CALL( collectAggregatedVars(1, &resultant, &nAggregatedVars, &aggregatedVars, &varAggregated) );
3621  }
3622 
3623  /* check for aggregated variables in bivariate constraints and output aggregations as linear constraints */
3624  for (c = 0; c < nConsBivariate; ++c)
3625  {
3626  SCIP_VAR* z;
3627 
3628  cons = consBivariate[c];
3629 
3630  assert(SCIPexprtreeGetNVars(SCIPgetExprtreeBivariate(scip, cons)) == 2);
3631  SCIP_CALL( collectAggregatedVars(2, SCIPexprtreeGetVars(SCIPgetExprtreeBivariate(scip, cons)), &nAggregatedVars, &aggregatedVars, &varAggregated) );
3632 
3633  z = SCIPgetLinearVarBivariate(scip, cons);
3634  if( z != NULL )
3635  {
3636  SCIP_CALL( collectAggregatedVars(1, &z, &nAggregatedVars, &aggregatedVars, &varAggregated) );
3637  }
3638  }
3639 
3640  /* print aggregation constraints */
3641  SCIP_CALL( printAggregatedCons(scip, file, transformed, nvars, nAggregatedVars, aggregatedVars) );
3642 
3643  /* print "Bounds" section */
3644  SCIPinfoMessage(scip, file, "Bounds\n");
3645  for (v = 0; v < nvars; ++v)
3646  {
3647  var = vars[v];
3648  assert( var != NULL );
3649  (void) SCIPsnprintf(varname, PIP_MAX_NAMELEN, "%s", SCIPvarGetName(var) );
3650 
3651  if( transformed )
3652  {
3653  /* in case the transformed is written only local bounds are posted which are valid in the current node */
3654  lb = SCIPvarGetLbLocal(var);
3655  ub = SCIPvarGetUbLocal(var);
3656  }
3657  else
3658  {
3659  lb = SCIPvarGetLbOriginal(var);
3660  ub = SCIPvarGetUbOriginal(var);
3661  }
3662 
3663  if ( SCIPisInfinity(scip, -lb) && SCIPisInfinity(scip, ub) )
3664  SCIPinfoMessage(scip, file, " %s free\n", varname);
3665  else
3666  {
3667  /* print lower bound */
3668  if ( SCIPisInfinity(scip, -lb) )
3669  SCIPinfoMessage(scip, file, " -inf <= ");
3670  else
3671  {
3672  if ( SCIPisZero(scip, lb) )
3673  {
3674  /* variables are nonnegative by default - so we skip these variables */
3675  if ( SCIPisInfinity(scip, ub) )
3676  continue;
3677  lb = 0.0;
3678  }
3679 
3680  SCIPinfoMessage(scip, file, " %.15g <= ", lb);
3681  }
3682  /* print variable name */
3683  SCIPinfoMessage(scip, file, "%s", varname);
3684 
3685  /* print upper bound as far this one is not infinity */
3686  if( !SCIPisInfinity(scip, ub) )
3687  SCIPinfoMessage(scip, file, " <= %.15g", ub);
3688 
3689  SCIPinfoMessage(scip, file, "\n");
3690  }
3691  }
3692 
3693  /* output aggregated variables as 'free' */
3694  for (v = 0; v < nAggregatedVars; ++v)
3695  {
3696  var = aggregatedVars[v];
3697  assert( var != NULL );
3698  (void) SCIPsnprintf(varname, PIP_MAX_NAMELEN, "%s", SCIPvarGetName(var) );
3699 
3700  SCIPinfoMessage(scip, file, " %s free\n", varname);
3701  }
3702 
3703  /* free space */
3704  SCIPfreeBufferArray(scip, &aggregatedVars);
3705  SCIPhashtableFree(&varAggregated);
3706 
3707  /* print binaries section */
3708  if ( nbinvars > 0 )
3709  {
3710  SCIPinfoMessage(scip, file, "Binaries\n");
3711 
3712  clearLine(linebuffer, &linecnt);
3713 
3714  for (v = 0; v < nvars; ++v)
3715  {
3716  var = vars[v];
3717  assert( var != NULL );
3718 
3719  if ( SCIPvarGetType(var) == SCIP_VARTYPE_BINARY )
3720  {
3721  (void) SCIPsnprintf(varname, PIP_MAX_NAMELEN, "%s", SCIPvarGetName(var) );
3722  (void) SCIPsnprintf(buffer, PIP_MAX_PRINTLEN, " %s", varname);
3723  appendLine(scip, file, linebuffer, &linecnt, buffer);
3724  }
3725  }
3726 
3727  endLine(scip, file, linebuffer, &linecnt);
3728  }
3729 
3730  /* print generals section */
3731  if ( nintvars > 0 )
3732  {
3733  SCIPinfoMessage(scip, file, "Generals\n");
3734 
3735  for (v = 0; v < nvars; ++v)
3736  {
3737  var = vars[v];
3738  assert( var != NULL );
3739 
3740  if ( SCIPvarGetType(var) == SCIP_VARTYPE_INTEGER )
3741  {
3742  (void) SCIPsnprintf(varname, PIP_MAX_NAMELEN, "%s", SCIPvarGetName(var) );
3743  (void) SCIPsnprintf(buffer, PIP_MAX_PRINTLEN, " %s", varname);
3744  appendLine(scip, file, linebuffer, &linecnt, buffer);
3745  }
3746  }
3747  endLine(scip, file, linebuffer, &linecnt);
3748  }
3749 
3750  /* free space */
3751  SCIPfreeBufferArray(scip, &consQuadratic);
3752  SCIPfreeBufferArray(scip, &consNonlinear);
3753  SCIPfreeBufferArray(scip, &consAbspower);
3754  SCIPfreeBufferArray(scip, &consAnd);
3755  SCIPfreeBufferArray(scip, &consBivariate);
3756 
3757  /* end of lp format */
3758  SCIPinfoMessage(scip, file, "%s\n", "End");
3759 
3760  *result = SCIP_SUCCESS;
3761 
3762  return SCIP_OKAY;
3763 }
3764 
3765 /*
3766  * Callback methods of reader
3767  */
3768 
3769 /** copy method for reader plugins (called when SCIP copies plugins) */
3770 static
3771 SCIP_DECL_READERCOPY(readerCopyPip)
3772 { /*lint --e{715}*/
3773  assert(scip != NULL);
3774  assert(reader != NULL);
3775  assert(strcmp(SCIPreaderGetName(reader), READER_NAME) == 0);
3776 
3777  /* call inclusion method of reader */
3779 
3780  return SCIP_OKAY;
3781 }
3782 
3783 
3784 /** problem reading method of reader */
3785 static
3786 SCIP_DECL_READERREAD(readerReadPip)
3787 { /*lint --e{715}*/
3788 
3789  SCIP_CALL( SCIPreadPip(scip, reader, filename, result) );
3790 
3791  return SCIP_OKAY;
3792 }
3793 
3794 
3795 /** problem writing method of reader */
3796 static
3797 SCIP_DECL_READERWRITE(readerWritePip)
3798 { /*lint --e{715}*/
3799  SCIP_CALL( SCIPwritePip(scip, file, name, transformed, objsense, objscale, objoffset, vars,
3800  nvars, nbinvars, nintvars, nimplvars, ncontvars, conss, nconss, result) );
3801 
3802  return SCIP_OKAY;
3803 }
3804 
3805 
3806 /*
3807  * reader specific interface methods
3808  */
3809 
3810 /** includes the pip file reader in SCIP */
3812  SCIP* scip /**< SCIP data structure */
3813  )
3814 {
3815  SCIP_READER* reader;
3816 
3817  /* include reader */
3819 
3820  /* set non fundamental callbacks via setter functions */
3821  SCIP_CALL( SCIPsetReaderCopy(scip, reader, readerCopyPip) );
3822  SCIP_CALL( SCIPsetReaderRead(scip, reader, readerReadPip) );
3823  SCIP_CALL( SCIPsetReaderWrite(scip, reader, readerWritePip) );
3824 
3825  return SCIP_OKAY;
3826 }
3827 
3828 
3829 /** reads problem from file */
3831  SCIP* scip, /**< SCIP data structure */
3832  SCIP_READER* reader, /**< the file reader itself */
3833  const char* filename, /**< full path and name of file to read, or NULL if stdin should be used */
3834  SCIP_RESULT* result /**< pointer to store the result of the file reading call */
3835  )
3836 { /*lint --e{715}*/
3837  PIPINPUT pipinput;
3838  SCIP_RETCODE retcode;
3839  int i;
3840 
3841  assert(scip != NULL); /* for lint */
3842  assert(reader != NULL);
3843 
3844  /* initialize PIP input data */
3845  pipinput.file = NULL;
3846  pipinput.linebuf[0] = '\0';
3847  pipinput.probname[0] = '\0';
3848  pipinput.objname[0] = '\0';
3849  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &pipinput.token, PIP_MAX_LINELEN) ); /*lint !e506*/
3850  pipinput.token[0] = '\0';
3851  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &pipinput.tokenbuf, PIP_MAX_LINELEN) ); /*lint !e506*/
3852  pipinput.tokenbuf[0] = '\0';
3853  for( i = 0; i < PIP_MAX_PUSHEDTOKENS; ++i )
3854  {
3855  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &((pipinput.pushedtokens)[i]), PIP_MAX_LINELEN) ); /*lint !e866 !e506*/
3856  }
3857 
3858  pipinput.npushedtokens = 0;
3859  pipinput.linenumber = 0;
3860  pipinput.linepos = 0;
3861  pipinput.section = PIP_START;
3862  pipinput.objsense = SCIP_OBJSENSE_MINIMIZE;
3863  pipinput.haserror = FALSE;
3864 
3865  SCIP_CALL( SCIPgetBoolParam(scip, "reading/initialconss", &(pipinput.initialconss)) );
3866  SCIP_CALL( SCIPgetBoolParam(scip, "reading/dynamicconss", &(pipinput.dynamicconss)) );
3867  SCIP_CALL( SCIPgetBoolParam(scip, "reading/dynamiccols", &(pipinput.dynamiccols)) );
3868  SCIP_CALL( SCIPgetBoolParam(scip, "reading/dynamicrows", &(pipinput.dynamicrows)) );
3869 
3870  /* read the file */
3871  retcode = readPIPFile(scip, &pipinput, filename);
3872 
3873  /* free dynamically allocated memory */
3874  for( i = PIP_MAX_PUSHEDTOKENS - 1; i >= 0 ; --i )
3875  {
3876  SCIPfreeBlockMemoryArray(scip, &pipinput.pushedtokens[i], PIP_MAX_LINELEN);
3877  }
3878  SCIPfreeBlockMemoryArray(scip, &pipinput.tokenbuf, PIP_MAX_LINELEN);
3879  SCIPfreeBlockMemoryArray(scip, &pipinput.token, PIP_MAX_LINELEN);
3880 
3881  if( retcode == SCIP_PLUGINNOTFOUND )
3882  retcode = SCIP_READERROR;
3883 
3884  /* evaluate the result */
3885  if( pipinput.haserror )
3886  retcode = SCIP_READERROR;
3887  else
3888  {
3889  /* set objective sense */
3890  SCIP_CALL( SCIPsetObjsense(scip, pipinput.objsense) );
3891  *result = SCIP_SUCCESS;
3892  }
3893 
3894  SCIP_CALL( retcode );
3895 
3896  return SCIP_OKAY;
3897 }
enum SCIP_Result SCIP_RESULT
Definition: type_result.h:52
SCIP_RETCODE SCIPincludeReaderPip(SCIP *scip)
Definition: reader_pip.c:3811
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:2700
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:1976
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:3830
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:2839
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:2055
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:2109
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:2935
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:1656
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:8775
#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:2078
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:1742
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:4677
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:2959
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:8616
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:364
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:3797
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:8606
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:1992
#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:8856
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:1906
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:4767
static SCIP_DECL_READERCOPY(readerCopyPip)
Definition: reader_pip.c:3771
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:2799
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:3786
PipExpType
Definition: reader_pip.c:92
static SCIP_RETCODE readBinaries(SCIP *scip, PIPINPUT *pipinput)
Definition: reader_pip.c:1862
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:4514
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:1827
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:2041
int SCIPgetNBilinTermsQuadratic(SCIP *scip, SCIP_CONS *cons)
static SCIP_DECL_HASHKEYEQ(hashKeyEqVar)
Definition: reader_pip.c:1983
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:2603
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:1252
#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:3014
public methods for input file readers
#define SCIP_CALL_TERMINATE(retcode, x, TERM)
Definition: def.h:385
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:2246
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:8157
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:2000
static SCIP_Bool isNameValid(const char *name)
Definition: reader_pip.c:2899
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