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 2002-2022 Zuse Institute Berlin */
7 /* */
8 /* Licensed under the Apache License, Version 2.0 (the "License"); */
9 /* you may not use this file except in compliance with the License. */
10 /* You may obtain a copy of the License at */
11 /* */
12 /* http://www.apache.org/licenses/LICENSE-2.0 */
13 /* */
14 /* Unless required by applicable law or agreed to in writing, software */
15 /* distributed under the License is distributed on an "AS IS" BASIS, */
16 /* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */
17 /* See the License for the specific language governing permissions and */
18 /* limitations under the License. */
19 /* */
20 /* You should have received a copy of the Apache-2.0 license */
21 /* along with SCIP; see the file LICENSE. If not visit scipopt.org. */
22 /* */
23 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
24 
25 /**@file reader_pip.c
26  * @ingroup DEFPLUGINS_READER
27  * @brief file reader for polynomial mixed-integer programs in PIP format
28  * @author Stefan Vigerske
29  * @author Marc Pfetsch
30  */
31 
32 /*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
33 
34 #include <ctype.h>
35 
36 #include "blockmemshell/memory.h"
37 #include "scip/reader_pip.h"
38 #include "scip/cons_and.h"
39 #include "scip/cons_nonlinear.h"
40 #include "scip/cons_knapsack.h"
41 #include "scip/cons_linear.h"
42 #include "scip/cons_logicor.h"
43 #include "scip/cons_setppc.h"
44 #include "scip/cons_varbound.h"
45 #include "scip/expr_sum.h"
46 #include "scip/expr_var.h"
47 #include "scip/pub_cons.h"
48 #include "scip/pub_expr.h"
49 #include "scip/pub_fileio.h"
50 #include "scip/pub_message.h"
51 #include "scip/pub_misc.h"
52 #include "scip/pub_nlp.h"
53 #include "scip/pub_reader.h"
54 #include "scip/pub_var.h"
55 #include "scip/scip_cons.h"
56 #include "scip/scip_mem.h"
57 #include "scip/scip_message.h"
58 #include "scip/scip_numerics.h"
59 #include "scip/scip_param.h"
60 #include "scip/scip_prob.h"
61 #include "scip/scip_reader.h"
62 #include "scip/scip_var.h"
63 #include <stdlib.h>
64 #include <string.h>
65 #include <ctype.h>
66 
67 #if !defined(_WIN32) && !defined(_WIN64)
68 #include <strings.h> /*lint --e{766}*/ /* needed for strncasecmp() */
69 #endif
70 
71 #define READER_NAME "pipreader"
72 #define READER_DESC "file reader for polynomial mixed-integer programs in PIP format"
73 #define READER_EXTENSION "pip"
74 
75 
76 /*
77  * Data structures
78  */
79 #define PIP_MAX_LINELEN 65536
80 #define PIP_MAX_PUSHEDTOKENS 2
81 #define PIP_INIT_MONOMIALSSIZE 128
82 #define PIP_INIT_FACTORSSIZE 16
83 #define PIP_MAX_PRINTLEN 561 /**< the maximum length of any line is 560 + '\\0' = 561*/
84 #define PIP_MAX_NAMELEN 256 /**< the maximum length for any name is 255 + '\\0' = 256 */
85 #define PIP_PRINTLEN 100
86 
87 /** Section in PIP File */
89 {
97 };
98 typedef enum PipSection PIPSECTION;
99 
101 {
105 };
106 typedef enum PipExpType PIPEXPTYPE;
107 
109 {
114 };
115 typedef enum PipSense PIPSENSE;
116 
117 /** PIP reading data */
118 struct PipInput
119 {
120  SCIP_FILE* file;
121  char linebuf[PIP_MAX_LINELEN+1];
122  char probname[PIP_MAX_LINELEN];
123  char objname[PIP_MAX_LINELEN];
124  char* token;
125  char* tokenbuf;
126  char* pushedtokens[PIP_MAX_PUSHEDTOKENS];
127  int npushedtokens;
128  int linenumber;
129  int linepos;
130  PIPSECTION section;
131  SCIP_OBJSENSE objsense;
132  SCIP_Bool initialconss; /**< should model constraints be marked as initial? */
133  SCIP_Bool dynamicconss; /**< should model constraints be subject to aging? */
134  SCIP_Bool dynamiccols; /**< should columns be added and removed dynamically to the LP? */
135  SCIP_Bool dynamicrows; /**< should rows be added and removed dynamically to the LP? */
136  SCIP_Bool haserror;
137 };
138 typedef struct PipInput PIPINPUT;
139 
140 static const char delimchars[] = " \f\n\r\t\v";
141 static const char tokenchars[] = "-+:<>=*^";
142 static const char commentchars[] = "\\";
143 static const char namechars[] = "!#$%&;?@_"; /* and characters and numbers */
144 
145 
146 /*
147  * Local methods (for reading)
148  */
149 
150 /** issues an error message and marks the PIP data to have errors */
151 static
153  SCIP* scip, /**< SCIP data structure */
154  PIPINPUT* pipinput, /**< PIP reading data */
155  const char* msg /**< error message */
156  )
157 {
158  char formatstr[256];
159 
160  assert(pipinput != NULL);
161 
162  SCIPerrorMessage("Syntax error in line %d: %s ('%s')\n", pipinput->linenumber, msg, pipinput->token);
163  if( pipinput->linebuf[strlen(pipinput->linebuf)-1] == '\n' )
164  {
165  SCIPverbMessage(scip, SCIP_VERBLEVEL_MINIMAL, NULL, " input: %s", pipinput->linebuf);
166  }
167  else
168  {
169  SCIPverbMessage(scip, SCIP_VERBLEVEL_MINIMAL, NULL, " input: %s\n", pipinput->linebuf);
170  }
171  (void) SCIPsnprintf(formatstr, 256, " %%%ds\n", pipinput->linepos);
172  SCIPverbMessage(scip, SCIP_VERBLEVEL_MINIMAL, NULL, formatstr, "^");
173  pipinput->section = PIP_END;
174  pipinput->haserror = TRUE;
175 }
176 
177 /** returns whether a syntax error was detected */
178 static
180  PIPINPUT* pipinput /**< PIP reading data */
181  )
182 {
183  assert(pipinput != NULL);
184 
185  return pipinput->haserror;
186 }
187 
188 /** returns whether the given character is a token delimiter */
189 static
191  char c /**< input character */
192  )
193 {
194  return (c == '\0') || (strchr(delimchars, c) != NULL);
195 }
196 
197 /** returns whether the given character is a single token */
198 static
200  char c /**< input character */
201  )
202 {
203  return (strchr(tokenchars, c) != NULL);
204 }
205 
206 /** returns whether the current character is member of a value string */
207 static
209  char c, /**< input character */
210  char nextc, /**< next input character */
211  SCIP_Bool firstchar, /**< is the given character the first char of the token? */
212  SCIP_Bool* hasdot, /**< pointer to update the dot flag */
213  PIPEXPTYPE* exptype /**< pointer to update the exponent type */
214  )
215 {
216  assert(hasdot != NULL);
217  assert(exptype != NULL);
218 
219  if( isdigit((unsigned char)c) )
220  return TRUE;
221  else if( (*exptype == PIP_EXP_NONE) && !(*hasdot) && (c == '.') && isdigit((unsigned char)nextc) )
222  {
223  *hasdot = TRUE;
224  return TRUE;
225  }
226  else if( !firstchar && (*exptype == PIP_EXP_NONE) && (c == 'e' || c == 'E') )
227  {
228  if( nextc == '+' || nextc == '-' )
229  {
230  *exptype = PIP_EXP_SIGNED;
231  return TRUE;
232  }
233  else if( isdigit((unsigned char)nextc) )
234  {
235  *exptype = PIP_EXP_UNSIGNED;
236  return TRUE;
237  }
238  }
239  else if( (*exptype == PIP_EXP_SIGNED) && (c == '+' || c == '-') )
240  {
241  *exptype = PIP_EXP_UNSIGNED;
242  return TRUE;
243  }
244 
245  return FALSE;
246 }
247 
248 /** reads the next line from the input file into the line buffer; skips comments;
249  * returns whether a line could be read
250  */
251 static
253  SCIP* scip, /**< SCIP data structure */
254  PIPINPUT* pipinput /**< PIP reading data */
255  )
256 {
257  int i;
258 
259  assert(scip != NULL); /* for lint */
260  assert(pipinput != NULL);
261 
262  /* clear the line */
263  BMSclearMemoryArray(pipinput->linebuf, PIP_MAX_LINELEN);
264 
265  /* read next line */
266  pipinput->linepos = 0;
267  pipinput->linebuf[PIP_MAX_LINELEN-2] = '\0';
268  if( SCIPfgets(pipinput->linebuf, (int) sizeof(pipinput->linebuf), pipinput->file) == NULL )
269  return FALSE;
270  pipinput->linenumber++;
271  if( pipinput->linebuf[PIP_MAX_LINELEN-2] != '\0' )
272  {
273  SCIPerrorMessage("Error: line %d exceeds %d characters\n", pipinput->linenumber, PIP_MAX_LINELEN-2);
274  pipinput->haserror = TRUE;
275  return FALSE;
276  }
277  pipinput->linebuf[PIP_MAX_LINELEN-1] = '\0'; /* we want to use lookahead of one char -> we need two \0 at the end */
278 
279  /* skip characters after comment symbol */
280  for( i = 0; commentchars[i] != '\0'; ++i )
281  {
282  char* commentstart;
283 
284  commentstart = strchr(pipinput->linebuf, commentchars[i]);
285  if( commentstart != NULL )
286  {
287  *commentstart = '\0';
288  *(commentstart+1) = '\0'; /* we want to use lookahead of one char -> we need two \0 at the end */
289  }
290  }
291 
292  return TRUE;
293 }
294 
295 /** swaps the addresses of two pointers */
296 static
298  char** pointer1, /**< first pointer */
299  char** pointer2 /**< second pointer */
300  )
301 {
302  char* tmp;
303 
304  tmp = *pointer1;
305  *pointer1 = *pointer2;
306  *pointer2 = tmp;
307 }
308 
309 /** reads the next token from the input file into the token buffer; returns whether a token was read */
310 static
312  SCIP* scip, /**< SCIP data structure */
313  PIPINPUT* pipinput /**< PIP reading data */
314  )
315 {
316  SCIP_Bool hasdot;
317  PIPEXPTYPE exptype;
318  char* buf;
319  int tokenlen;
320 
321  assert(pipinput != NULL);
322  assert(pipinput->linepos < PIP_MAX_LINELEN);
323 
324  /* check the token stack */
325  if( pipinput->npushedtokens > 0 )
326  {
327  swapPointers(&pipinput->token, &pipinput->pushedtokens[pipinput->npushedtokens-1]);
328  pipinput->npushedtokens--;
329  SCIPdebugMsg(scip, "(line %d) read token again: '%s'\n", pipinput->linenumber, pipinput->token);
330  return TRUE;
331  }
332 
333  /* skip delimiters */
334  buf = pipinput->linebuf;
335  while( isDelimChar(buf[pipinput->linepos]) )
336  {
337  if( buf[pipinput->linepos] == '\0' )
338  {
339  if( !getNextLine(scip, pipinput) )
340  {
341  pipinput->section = PIP_END;
342  SCIPdebugMsg(scip, "(line %d) end of file\n", pipinput->linenumber);
343  return FALSE;
344  }
345  assert(pipinput->linepos == 0);
346  }
347  else
348  pipinput->linepos++;
349  }
350  assert(pipinput->linepos < PIP_MAX_LINELEN);
351  assert(!isDelimChar(buf[pipinput->linepos]));
352 
353  /* check if the token is a value */
354  hasdot = FALSE;
355  exptype = PIP_EXP_NONE;
356  if( isValueChar(buf[pipinput->linepos], buf[pipinput->linepos+1], TRUE, &hasdot, &exptype) )
357  {
358  /* read value token */
359  tokenlen = 0;
360  do
361  {
362  assert(tokenlen < PIP_MAX_LINELEN);
363  assert(!isDelimChar(buf[pipinput->linepos]));
364  pipinput->token[tokenlen] = buf[pipinput->linepos];
365  tokenlen++;
366  pipinput->linepos++;
367  }
368  while( isValueChar(buf[pipinput->linepos], buf[pipinput->linepos+1], FALSE, &hasdot, &exptype) );
369  }
370  else
371  {
372  /* read non-value token */
373  tokenlen = 0;
374  do
375  {
376  assert(tokenlen < PIP_MAX_LINELEN);
377  pipinput->token[tokenlen] = buf[pipinput->linepos];
378  tokenlen++;
379  pipinput->linepos++;
380  if( tokenlen == 1 && isTokenChar(pipinput->token[0]) )
381  break;
382  }
383  while( !isDelimChar(buf[pipinput->linepos]) && !isTokenChar(buf[pipinput->linepos]) );
384 
385  /* if the token is an equation sense '<', '>', or '=', skip a following '='
386  * if the token is an equality token '=' and the next character is a '<' or '>', replace the token by the inequality sense
387  */
388  if( tokenlen >= 1
389  && (pipinput->token[tokenlen-1] == '<' || pipinput->token[tokenlen-1] == '>' || pipinput->token[tokenlen-1] == '=')
390  && buf[pipinput->linepos] == '=' )
391  {
392  pipinput->linepos++;
393  }
394  else if( pipinput->token[tokenlen-1] == '=' && (buf[pipinput->linepos] == '<' || buf[pipinput->linepos] == '>') )
395  {
396  pipinput->token[tokenlen-1] = buf[pipinput->linepos];
397  pipinput->linepos++;
398  }
399  }
400  assert(tokenlen < PIP_MAX_LINELEN);
401  pipinput->token[tokenlen] = '\0';
402 
403  SCIPdebugMsg(scip, "(line %d) read token: '%s'\n", pipinput->linenumber, pipinput->token);
404 
405  return TRUE;
406 }
407 
408 /** puts the current token on the token stack, such that it is read at the next call to getNextToken() */
409 static
411  PIPINPUT* pipinput /**< PIP reading data */
412  )
413 {
414  assert(pipinput != NULL);
415  assert(pipinput->npushedtokens < PIP_MAX_PUSHEDTOKENS);
416 
417  swapPointers(&pipinput->pushedtokens[pipinput->npushedtokens], &pipinput->token);
418  pipinput->npushedtokens++;
419 }
420 
421 /** puts the buffered token on the token stack, such that it is read at the next call to getNextToken() */
422 static
424  PIPINPUT* pipinput /**< PIP reading data */
425  )
426 {
427  assert(pipinput != NULL);
428  assert(pipinput->npushedtokens < PIP_MAX_PUSHEDTOKENS);
429 
430  swapPointers(&pipinput->pushedtokens[pipinput->npushedtokens], &pipinput->tokenbuf);
431  pipinput->npushedtokens++;
432 }
433 
434 /** swaps the current token with the token buffer */
435 static
437  PIPINPUT* pipinput /**< PIP reading data */
438  )
439 {
440  assert(pipinput != NULL);
441 
442  swapPointers(&pipinput->token, &pipinput->tokenbuf);
443 }
444 
445 /** checks whether the current token is a section identifier, and if yes, switches to the corresponding section */
446 static
448  SCIP* scip, /**< SCIP data structure */
449  PIPINPUT* pipinput /**< PIP reading data */
450  )
451 {
452  SCIP_Bool iscolon;
453 
454  assert(pipinput != NULL);
455 
456  /* remember first token by swapping the token buffer */
457  swapTokenBuffer(pipinput);
458 
459  /* look at next token: if this is a ':', the first token is a name and no section keyword */
460  iscolon = FALSE;
461  if( getNextToken(scip, pipinput) )
462  {
463  iscolon = (strcmp(pipinput->token, ":") == 0);
464  pushToken(pipinput);
465  }
466 
467  /* reinstall the previous token by swapping back the token buffer */
468  swapTokenBuffer(pipinput);
469 
470  /* check for ':' */
471  if( iscolon )
472  return FALSE;
473 
474  if( strcasecmp(pipinput->token, "MINIMIZE") == 0
475  || strcasecmp(pipinput->token, "MINIMUM") == 0
476  || strcasecmp(pipinput->token, "MIN") == 0 )
477  {
478  SCIPdebugMsg(scip, "(line %d) new section: OBJECTIVE\n", pipinput->linenumber);
479  pipinput->section = PIP_OBJECTIVE;
480  pipinput->objsense = SCIP_OBJSENSE_MINIMIZE;
481  return TRUE;
482  }
483 
484  if( strcasecmp(pipinput->token, "MAXIMIZE") == 0
485  || strcasecmp(pipinput->token, "MAXIMUM") == 0
486  || strcasecmp(pipinput->token, "MAX") == 0 )
487  {
488  SCIPdebugMsg(scip, "(line %d) new section: OBJECTIVE\n", pipinput->linenumber);
489  pipinput->section = PIP_OBJECTIVE;
490  pipinput->objsense = SCIP_OBJSENSE_MAXIMIZE;
491  return TRUE;
492  }
493 
494  if( strcasecmp(pipinput->token, "SUBJECT") == 0 )
495  {
496  /* check if the next token is 'TO' */
497  swapTokenBuffer(pipinput);
498  if( getNextToken(scip, pipinput) )
499  {
500  if( strcasecmp(pipinput->token, "TO") == 0 )
501  {
502  SCIPdebugMsg(scip, "(line %d) new section: CONSTRAINTS\n", pipinput->linenumber);
503  pipinput->section = PIP_CONSTRAINTS;
504  return TRUE;
505  }
506  else
507  pushToken(pipinput);
508  }
509  swapTokenBuffer(pipinput);
510  }
511 
512  if( strcasecmp(pipinput->token, "SUCH") == 0 )
513  {
514  /* check if the next token is 'THAT' */
515  swapTokenBuffer(pipinput);
516  if( getNextToken(scip, pipinput) )
517  {
518  if( strcasecmp(pipinput->token, "THAT") == 0 )
519  {
520  SCIPdebugMsg(scip, "(line %d) new section: CONSTRAINTS\n", pipinput->linenumber);
521  pipinput->section = PIP_CONSTRAINTS;
522  return TRUE;
523  }
524  else
525  pushToken(pipinput);
526  }
527  swapTokenBuffer(pipinput);
528  }
529 
530  if( strcasecmp(pipinput->token, "st") == 0
531  || strcasecmp(pipinput->token, "S.T.") == 0
532  || strcasecmp(pipinput->token, "ST.") == 0 )
533  {
534  SCIPdebugMsg(scip, "(line %d) new section: CONSTRAINTS\n", pipinput->linenumber);
535  pipinput->section = PIP_CONSTRAINTS;
536  return TRUE;
537  }
538 
539  if( strcasecmp(pipinput->token, "BOUNDS") == 0
540  || strcasecmp(pipinput->token, "BOUND") == 0 )
541  {
542  SCIPdebugMsg(scip, "(line %d) new section: BOUNDS\n", pipinput->linenumber);
543  pipinput->section = PIP_BOUNDS;
544  return TRUE;
545  }
546 
547  if( strcasecmp(pipinput->token, "GENERAL") == 0
548  || strcasecmp(pipinput->token, "GENERALS") == 0
549  || strcasecmp(pipinput->token, "GEN") == 0
550  || strcasecmp(pipinput->token, "INTEGER") == 0
551  || strcasecmp(pipinput->token, "INTEGERS") == 0
552  || strcasecmp(pipinput->token, "INT") == 0 )
553  {
554  SCIPdebugMsg(scip, "(line %d) new section: GENERALS\n", pipinput->linenumber);
555  pipinput->section = PIP_GENERALS;
556  return TRUE;
557  }
558 
559  if( strcasecmp(pipinput->token, "BINARY") == 0
560  || strcasecmp(pipinput->token, "BINARIES") == 0
561  || strcasecmp(pipinput->token, "BIN") == 0 )
562  {
563  SCIPdebugMsg(scip, "(line %d) new section: BINARIES\n", pipinput->linenumber);
564  pipinput->section = PIP_BINARIES;
565  return TRUE;
566  }
567 
568  if( strcasecmp(pipinput->token, "END") == 0 )
569  {
570  SCIPdebugMsg(scip, "(line %d) new section: END\n", pipinput->linenumber);
571  pipinput->section = PIP_END;
572  return TRUE;
573  }
574 
575  return FALSE;
576 }
577 
578 /** returns whether the current token is a sign */
579 static
581  PIPINPUT* pipinput, /**< PIP reading data */
582  int* sign /**< pointer to update the sign */
583  )
584 {
585  assert(pipinput != NULL);
586  assert(sign != NULL);
587  assert(*sign == +1 || *sign == -1);
588 
589  if( pipinput->token[1] == '\0' )
590  {
591  if( *pipinput->token == '+' )
592  return TRUE;
593  else if( *pipinput->token == '-' )
594  {
595  *sign *= -1;
596  return TRUE;
597  }
598  }
599 
600  return FALSE;
601 }
602 
603 /** returns whether the current token is a value */
604 static
606  SCIP* scip, /**< SCIP data structure */
607  PIPINPUT* pipinput, /**< PIP reading data */
608  SCIP_Real* value /**< pointer to store the value (unchanged, if token is no value) */
609  )
610 {
611  assert(pipinput != NULL);
612  assert(value != NULL);
613 
614  if( strcasecmp(pipinput->token, "INFINITY") == 0 || strcasecmp(pipinput->token, "INF") == 0 )
615  {
616  *value = SCIPinfinity(scip);
617  return TRUE;
618  }
619  else
620  {
621  double val;
622  char* endptr;
623 
624  val = strtod(pipinput->token, &endptr);
625  if( endptr != pipinput->token && *endptr == '\0' )
626  {
627  *value = val;
628  return TRUE;
629  }
630  }
631 
632  return FALSE;
633 }
634 
635 /** returns whether the current token is an equation sense */
636 static
638  PIPINPUT* pipinput, /**< PIP reading data */
639  PIPSENSE* sense /**< pointer to store the equation sense, or NULL */
640  )
641 {
642  assert(pipinput != NULL);
643 
644  if( strcmp(pipinput->token, "<") == 0 )
645  {
646  if( sense != NULL )
647  *sense = PIP_SENSE_LE;
648  return TRUE;
649  }
650  else if( strcmp(pipinput->token, ">") == 0 )
651  {
652  if( sense != NULL )
653  *sense = PIP_SENSE_GE;
654  return TRUE;
655  }
656  else if( strcmp(pipinput->token, "=") == 0 )
657  {
658  if( sense != NULL )
659  *sense = PIP_SENSE_EQ;
660  return TRUE;
661  }
662 
663  return FALSE;
664 }
665 
666 /** returns the variable with the given name, or creates a new variable if it does not exist */
667 static
669  SCIP* scip, /**< SCIP data structure */
670  char* name, /**< name of the variable */
671  SCIP_Bool dynamiccols, /**< should columns be added and removed dynamically to the LP? */
672  SCIP_VAR** var, /**< pointer to store the variable */
673  SCIP_Bool* created /**< pointer to store whether a new variable was created, or NULL */
674  )
675 {
676  assert(name != NULL);
677  assert(var != NULL);
678 
679  *var = SCIPfindVar(scip, name);
680  if( *var == NULL )
681  {
682  SCIP_VAR* newvar;
683 
684  /* create new variable of the given name */
685  SCIPdebugMsg(scip, "creating new variable: <%s>\n", name);
686  SCIP_CALL( SCIPcreateVar(scip, &newvar, name, 0.0, SCIPinfinity(scip), 0.0, SCIP_VARTYPE_CONTINUOUS,
687  !dynamiccols, dynamiccols, NULL, NULL, NULL, NULL, NULL) );
688  SCIP_CALL( SCIPaddVar(scip, newvar) );
689  *var = newvar;
690 
691  /* because the variable was added to the problem, it is captured by SCIP and we can safely release it right now
692  * without making the returned *var invalid
693  */
694  SCIP_CALL( SCIPreleaseVar(scip, &newvar) );
695 
696  if( created != NULL )
697  *created = TRUE;
698  }
699  else if( created != NULL )
700  *created = FALSE;
701 
702  return SCIP_OKAY;
703 }
704 
705 /** reads the header of the file */
706 static
708  SCIP* scip, /**< SCIP data structure */
709  PIPINPUT* pipinput /**< PIP reading data */
710  )
711 {
712  assert(pipinput != NULL);
713 
714  /* everything before first section is treated as comment */
715  do
716  {
717  /* get token */
718  if( !getNextToken(scip, pipinput) )
719  return SCIP_OKAY;
720  }
721  while( !isNewSection(scip, pipinput) );
722 
723  return SCIP_OKAY;
724 }
725 
726 /** ensure that an array of monomials can hold a minimum number of entries */
727 static
729  SCIP* scip, /**< SCIP data structure */
730  SCIP_EXPR*** monomials, /**< pointer to current array of monomials */
731  SCIP_Real** monomialscoef, /**< pointer to current array of monomial coefficients */
732  int* monomialssize, /**< current size of monomials array at input; new size at exit */
733  int minnmonomials /**< required minimal size of monomials array */
734  )
735 {
736  int newsize;
737 
738  assert(scip != NULL);
739  assert(monomials != NULL);
740  assert(monomialscoef != NULL);
741  assert(monomialssize != NULL);
742  assert(*monomials != NULL || *monomialssize == 0);
743 
744  if( minnmonomials <= *monomialssize )
745  return SCIP_OKAY;
746 
747  newsize = SCIPcalcMemGrowSize(scip, minnmonomials);
748 
749  if( *monomials != NULL )
750  {
751  SCIP_CALL( SCIPreallocBufferArray(scip, monomials, newsize) );
752  }
753  else
754  {
755  SCIP_CALL( SCIPallocBufferArray(scip, monomials, newsize) );
756  }
757  if( *monomialscoef != NULL )
758  {
759  SCIP_CALL( SCIPreallocBufferArray(scip, monomialscoef, newsize) );
760  }
761  else
762  {
763  SCIP_CALL( SCIPallocBufferArray(scip, monomialscoef, newsize) );
764  }
765  *monomialssize = newsize;
766 
767  return SCIP_OKAY;
768 }
769 
770 /** ensure that arrays of exponents and variable indices can hold a minimum number of entries */
771 static
773  SCIP* scip, /**< SCIP data structure */
774  SCIP_VAR*** vars, /**< pointer to current array of variables */
775  SCIP_Real** exponents, /**< pointer to current array of exponents */
776  int* factorssize, /**< current size of arrays at input; new size at exit */
777  int minnfactors /**< required minimal size of arrays */
778  )
779 {
780  int newsize;
781 
782  assert(scip != NULL);
783  assert(vars != NULL);
784  assert(exponents != NULL);
785  assert(factorssize != NULL);
786  assert(*exponents != NULL || *factorssize == 0);
787  assert(*vars != NULL || *factorssize == 0);
788 
789  if( minnfactors <= *factorssize )
790  return SCIP_OKAY;
791 
792  newsize = SCIPcalcMemGrowSize(scip, minnfactors);
793 
794  if( *exponents != NULL )
795  {
796  SCIP_CALL( SCIPreallocBufferArray(scip, exponents, newsize) );
797  SCIP_CALL( SCIPreallocBufferArray(scip, vars, newsize) );
798  }
799  else
800  {
801  SCIP_CALL( SCIPallocBufferArray(scip, exponents, newsize) );
802  SCIP_CALL( SCIPallocBufferArray(scip, vars, newsize) );
803  }
804  *factorssize = newsize;
805 
806  return SCIP_OKAY;
807 }
808 
809 /** reads an objective or constraint with name and coefficients */
810 static
812  SCIP* scip, /**< SCIP data structure */
813  PIPINPUT* pipinput, /**< PIP reading data */
814  char* name, /**< pointer to store the name of the line; must be at least of size
815  * PIP_MAX_LINELEN */
816  SCIP_EXPR** expr, /**< pointer to store the constraint function as expression */
817  SCIP_Bool* islinear, /**< pointer to store polynomial is linear */
818  SCIP_Bool* newsection /**< pointer to store whether a new section was encountered */
819  )
820 {
821  SCIP_Bool havesign;
822  SCIP_Bool havevalue;
823  SCIP_Real coef;
824  int coefsign;
825  int nextcoefsign;
826  int monomialdegree;
827  int i;
828 
829  SCIP_VAR** vars;
830  SCIP_Real constant;
831 
832  SCIP_EXPR** monomials;
833  SCIP_Real* monomialscoef;
834  int monomialssize;
835  int nmonomials;
836 
837  int nfactors;
838  int factorssize;
839  SCIP_Real* exponents;
840 
841  assert(scip != NULL);
842  assert(pipinput != NULL);
843  assert(name != NULL);
844  assert(expr != NULL);
845  assert(islinear != NULL);
846  assert(newsection != NULL);
847 
848  *name = '\0';
849  *expr = NULL;
850  *islinear = TRUE;
851  *newsection = FALSE;
852 
853  /* read the first token, which may be the name of the line */
854  if( getNextToken(scip, pipinput) )
855  {
856  /* check if we reached a new section */
857  if( isNewSection(scip, pipinput) )
858  {
859  *newsection = TRUE;
860  return SCIP_OKAY;
861  }
862 
863  /* remember the token in the token buffer */
864  swapTokenBuffer(pipinput);
865 
866  /* get the next token and check, whether it is a colon */
867  if( getNextToken(scip, pipinput) )
868  {
869  if( strcmp(pipinput->token, ":") == 0 )
870  {
871  /* the second token was a colon: the first token is the line name */
872  (void)SCIPstrncpy(name, pipinput->tokenbuf, PIP_MAX_LINELEN);
873  SCIPdebugMsg(scip, "(line %d) read constraint name: '%s'\n", pipinput->linenumber, name);
874  }
875  else
876  {
877  /* the second token was no colon: push the tokens back onto the token stack and parse them as coefficients */
878  pushToken(pipinput);
879  pushBufferToken(pipinput);
880  }
881  }
882  else
883  {
884  /* there was only one token left: push it back onto the token stack and parse it as coefficient */
885  pushBufferToken(pipinput);
886  }
887  }
888 
889  /* initialize buffer for storing the monomials */
890  monomialssize = PIP_INIT_MONOMIALSSIZE;
891  SCIP_CALL( SCIPallocBufferArray(scip, &monomials, monomialssize) );
892  SCIP_CALL( SCIPallocBufferArray(scip, &monomialscoef, monomialssize) );
893 
894  /* initialize buffer for storing the factors in a monomial */
895  factorssize = PIP_INIT_FACTORSSIZE;
896  SCIP_CALL( SCIPallocBufferArray(scip, &exponents, factorssize) );
897  SCIP_CALL( SCIPallocBufferArray(scip, &vars, factorssize) );
898 
899  /* read the coefficients */
900  coefsign = +1;
901  nextcoefsign = +1;
902  coef = 1.0;
903  havesign = FALSE;
904  havevalue = FALSE;
905  nmonomials = 0;
906  nfactors = 0;
907  monomialdegree = 0;
908  constant = 0.0;
909  while( getNextToken(scip, pipinput) )
910  {
911  SCIP_VAR* var;
912  SCIP_Bool issense;
913  SCIP_Bool issign;
914  SCIP_Bool isnewsection;
915  SCIP_Real exponent;
916 
917  issign = FALSE; /* fix compiler warning */
918  issense = FALSE; /* fix lint warning */
919  if( (isnewsection = isNewSection(scip, pipinput)) || /*lint !e820*/
920  (issense = isSense(pipinput, NULL)) || /*lint !e820*/
921  ((nfactors > 0 || havevalue) && (issign = isSign(pipinput, &nextcoefsign))) ) /*lint !e820*/
922  {
923  /* finish the current monomial */
924  if( nfactors > 0 )
925  {
926  if( coefsign * coef != 0.0 )
927  {
928  SCIP_CALL( ensureMonomialsSize(scip, &monomials, &monomialscoef, &monomialssize, nmonomials + 1) );
929  SCIP_CALL( SCIPcreateExprMonomial(scip, &monomials[nmonomials], nfactors, vars, exponents, NULL, NULL) );
930  monomialscoef[nmonomials] = coefsign * coef;
931  ++nmonomials;
932  }
933  }
934  else if( havevalue )
935  {
936  constant += coefsign * coef;
937  }
938 
939  if( monomialdegree > 1 )
940  *islinear = FALSE;
941 
942  /* reset variables */
943  nfactors = 0;
944  coef = 1.0;
945  coefsign = +1;
946  havesign = FALSE;
947  havevalue = FALSE;
948  monomialdegree = 0;
949 
950  if( isnewsection )
951  {
952  *newsection = TRUE;
953  break;
954  }
955 
956  if( issense )
957  {
958  /* put the sense back onto the token stack */
959  pushToken(pipinput);
960  break;
961  }
962 
963  if( issign )
964  {
965  coefsign = nextcoefsign;
966  SCIPdebugMsg(scip, "(line %d) read coefficient sign: %+d\n", pipinput->linenumber, coefsign);
967  havesign = TRUE;
968  nextcoefsign = +1;
969  continue;
970  }
971  }
972 
973  /* check if we read a sign */
974  if( isSign(pipinput, &coefsign) )
975  {
976  SCIPdebugMsg(scip, "(line %d) read coefficient sign: %+d\n", pipinput->linenumber, coefsign);
977 
978  if( nfactors > 0 || havevalue )
979  {
980  syntaxError(scip, pipinput, "sign can only be at beginning of monomial");
981  goto TERMINATE_READPOLYNOMIAL;
982  }
983 
984  havesign = TRUE;
985  continue;
986  }
987 
988  /* check if we are in between factors of a monomial */
989  if( strcmp(pipinput->token, "*") == 0 )
990  {
991  if( nfactors == 0 )
992  {
993  syntaxError(scip, pipinput, "cannot have '*' before first variable in monomial");
994  goto TERMINATE_READPOLYNOMIAL;
995  }
996 
997  continue;
998  }
999 
1000  /* all but the first monomial need a sign */
1001  if( nmonomials > 0 && !havesign )
1002  {
1003  syntaxError(scip, pipinput, "expected sign ('+' or '-') or sense ('<' or '>')");
1004  goto TERMINATE_READPOLYNOMIAL;
1005  }
1006 
1007  /* check if we are at an exponent for the last variable */
1008  if( strcmp(pipinput->token, "^") == 0 )
1009  {
1010  if( !getNextToken(scip, pipinput) || !isValue(scip, pipinput, &exponent) )
1011  {
1012  syntaxError(scip, pipinput, "expected exponent value after '^'");
1013  goto TERMINATE_READPOLYNOMIAL;
1014  }
1015  if( nfactors == 0 )
1016  {
1017  syntaxError(scip, pipinput, "cannot have '^' before first variable in monomial");
1018  goto TERMINATE_READPOLYNOMIAL;
1019  }
1020  exponents[nfactors-1] = exponent; /*lint !e530*/
1021  if( SCIPisIntegral(scip, exponent) && exponent > 0.0 ) /*lint !e530*/
1022  monomialdegree += (int)exponent - 1; /*lint !e530*//* -1, because we added +1 when we put the variable into varidxs */
1023  else
1024  *islinear = FALSE;
1025 
1026  SCIPdebugMsg(scip, "(line %d) read exponent value %g for variable %s\n", pipinput->linenumber, exponent,
1027  SCIPvarGetName(vars[nfactors-1]));
1028  continue;
1029  }
1030 
1031  /* check if we read a value */
1032  if( isValue(scip, pipinput, &coef) )
1033  {
1034  SCIPdebugMsg(scip, "(line %d) read coefficient value: %g with sign %+d\n", pipinput->linenumber, coef, coefsign);
1035 
1036  if( havevalue )
1037  {
1038  syntaxError(scip, pipinput, "two consecutive values");
1039  goto TERMINATE_READPOLYNOMIAL;
1040  }
1041 
1042  if( nfactors > 0 )
1043  {
1044  syntaxError(scip, pipinput, "coefficients can only be at the beginning of a monomial");
1045  goto TERMINATE_READPOLYNOMIAL;
1046  }
1047 
1048  havevalue = TRUE;
1049  continue;
1050  }
1051 
1052  /* the token is a variable name: get the corresponding variable (or create a new one) */
1053  SCIP_CALL( getVariable(scip, pipinput->token, pipinput->dynamiccols, &var, NULL) );
1054 
1055  /* ensure that there is enough memory to store all factors */
1056  SCIP_CALL( ensureFactorsSize(scip, &vars, &exponents, &factorssize, nfactors + 1) );
1057 
1058  /* create and store corresponding variable expression */
1059  vars[nfactors] = var;
1060  exponents[nfactors] = 1.0;
1061  ++nfactors;
1062  ++monomialdegree;
1063  }
1064 
1065  if( nfactors > 0 )
1066  {
1067  syntaxError(scip, pipinput, "string ended before monomial has finished");
1068  goto TERMINATE_READPOLYNOMIAL;
1069  }
1070 
1071  /* create sum expression consisting of all monomial expressions */
1072  SCIP_CALL( SCIPcreateExprSum(scip, expr, nmonomials, monomials, monomialscoef, constant, NULL, NULL) );
1073 
1074  /* release monomial expressions */
1075  for( i = 0; i < nmonomials; ++i )
1076  {
1077  assert(monomials[i] != NULL);
1078  SCIP_CALL( SCIPreleaseExpr(scip, &monomials[i]) );
1079  }
1080 
1081 #ifdef SCIP_DEBUG
1082  SCIPdebugMsg(scip, "read polynomial: ");
1083  SCIP_CALL( SCIPprintExpr(scip, *expr, NULL) );
1084  SCIPinfoMessage(scip, NULL, "\n");
1085 #endif
1086 
1087  TERMINATE_READPOLYNOMIAL:
1088  SCIPfreeBufferArray(scip, &vars);
1089  SCIPfreeBufferArray(scip, &exponents);
1090  SCIPfreeBufferArray(scip, &monomialscoef);
1091  SCIPfreeBufferArray(scip, &monomials);
1092 
1093  return SCIP_OKAY;
1094 }
1095 
1096 /** reads the objective section */
1097 static
1099  SCIP* scip, /**< SCIP data structure */
1100  PIPINPUT* pipinput /**< PIP reading data */
1101  )
1102 {
1103  char name[PIP_MAX_LINELEN];
1104  SCIP_EXPR* expr;
1105  SCIP_Bool linear;
1106  SCIP_Bool newsection;
1107  SCIP_Bool initial;
1108  SCIP_Bool separate;
1109  SCIP_Bool enforce;
1110  SCIP_Bool check;
1111  SCIP_Bool propagate;
1112  SCIP_Bool local;
1113  SCIP_Bool modifiable;
1114  SCIP_Bool dynamic;
1115  SCIP_Bool removable;
1116 
1117  assert(pipinput != NULL);
1118 
1119  /* determine settings; note that reading/{initialconss,dynamicconss,dynamicrows,dynamiccols} apply only to model
1120  * constraints and variables, not to an auxiliary objective constraint (otherwise it can happen that an auxiliary
1121  * objective variable is loose with infinite best bound, triggering the problem that an LP that is unbounded because
1122  * of loose variables with infinite best bound cannot be solved)
1123  */
1124  initial = TRUE;
1125  separate = TRUE;
1126  enforce = TRUE;
1127  check = TRUE;
1128  propagate = TRUE;
1129  local = FALSE;
1130  modifiable = FALSE;
1131  dynamic = FALSE;
1132  removable = FALSE;
1133 
1134  /* read the objective coefficients */
1135  SCIP_CALL( readPolynomial(scip, pipinput, name, &expr, &linear, &newsection) );
1136  if( !hasError(pipinput) && expr != NULL )
1137  {
1138  SCIP_Real constant = SCIPgetConstantExprSum(expr);
1139 
1140  /* always create a variable that represents the constant; otherwise, this might lead to numerical issues on
1141  * instances with a relatively large constant, e.g., popdynm* instances
1142  */
1143  if( constant != 0.0 )
1144  {
1145  SCIP_VAR* objconst;
1146  SCIP_CALL( SCIPcreateVarBasic(scip, &objconst, "objconst", 1.0, 1.0, constant, SCIP_VARTYPE_CONTINUOUS) );
1147  SCIP_CALL( SCIPaddVar(scip, objconst) );
1148  SCIP_CALL( SCIPreleaseVar(scip, &objconst) );
1149 
1150  /* remove the constant of the sum expression */
1151  SCIPsetConstantExprSum(expr, 0.0);
1152  }
1153 
1154  if( linear )
1155  {
1156  int i;
1157 
1158  /* set objective coefficients of variables */
1159  for( i = 0; i < SCIPexprGetNChildren(expr); ++i )
1160  {
1161  SCIP_EXPR* child;
1162  SCIP_VAR* var;
1163  SCIP_Real coef;
1164 
1165  child = SCIPexprGetChildren(expr)[i];
1166  assert(child != NULL);
1167  assert(SCIPisExprVar(scip, child));
1168 
1169  /* child has to be a variable expression, see SCIPcreateExprMonomial() */
1170  var = SCIPgetVarExprVar(child);
1171  assert(var != NULL);
1172  coef = SCIPgetCoefsExprSum(expr)[i];
1173 
1174  /* adjust the objective coefficient */
1175  SCIP_CALL( SCIPchgVarObj(scip, var, SCIPvarGetObj(var) + coef) );
1176  }
1177  }
1178  else /* insert dummy variable and constraint to represent the nonlinear objective */
1179  {
1180  SCIP_EXPR* nonlinobjvarexpr;
1181  SCIP_VAR* nonlinobjvar;
1182  SCIP_CONS* nonlinobjcons;
1183  SCIP_Real lhs;
1184  SCIP_Real rhs;
1185 
1186  SCIP_CALL( SCIPcreateVar(scip, &nonlinobjvar, "nonlinobjvar", -SCIPinfinity(scip), SCIPinfinity(scip), 1.0,
1188  SCIP_CALL( SCIPaddVar(scip, nonlinobjvar) );
1189 
1190  if ( pipinput->objsense == SCIP_OBJSENSE_MINIMIZE )
1191  {
1192  lhs = -SCIPinfinity(scip);
1193  rhs = 0.0;
1194  }
1195  else
1196  {
1197  lhs = 0.0;
1198  rhs = SCIPinfinity(scip);
1199  }
1200 
1201  /* add created objective variable */
1202  SCIP_CALL( SCIPcreateExprVar(scip, &nonlinobjvarexpr, nonlinobjvar, NULL, NULL) );
1203  SCIP_CALL( SCIPappendExprSumExpr(scip, expr, nonlinobjvarexpr, -1.0) );
1204  SCIP_CALL( SCIPreleaseExpr(scip, &nonlinobjvarexpr) );
1205 
1206  /* create nonlinear constraint */
1207  SCIP_CALL( SCIPcreateConsNonlinear(scip, &nonlinobjcons, "nonlinobj", expr, lhs, rhs, initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable) );
1208 
1209  SCIP_CALL( SCIPaddCons(scip, nonlinobjcons) );
1210  SCIPdebugMsg(scip, "(line %d) added constraint <%s> to represent nonlinear objective: ", pipinput->linenumber, SCIPconsGetName(nonlinobjcons));
1211  SCIPdebugPrintCons(scip, nonlinobjcons, NULL);
1212 
1213  SCIP_CALL( SCIPreleaseCons(scip, &nonlinobjcons) );
1214  SCIP_CALL( SCIPreleaseVar(scip, &nonlinobjvar) );
1215  }
1216  }
1217 
1218  /* release expression */
1219  if( expr != NULL )
1220  {
1221  SCIP_CALL( SCIPreleaseExpr(scip, &expr) );
1222  }
1223 
1224  return SCIP_OKAY;
1225 }
1226 
1227 /** reads the constraints section */
1228 static
1230  SCIP* scip, /**< SCIP data structure */
1231  PIPINPUT* pipinput /**< PIP reading data */
1232  )
1233 {
1234  char name[PIP_MAX_LINELEN];
1235  SCIP_EXPR* expr;
1236  SCIP_CONS* cons = NULL;
1237  SCIP_Bool linear;
1238 
1239  PIPSENSE sense;
1240  SCIP_Real sidevalue;
1241  SCIP_Real lhs;
1242  SCIP_Real rhs;
1243  SCIP_Bool newsection;
1244  SCIP_Bool initial;
1245  SCIP_Bool separate;
1246  SCIP_Bool enforce;
1247  SCIP_Bool check;
1248  SCIP_Bool propagate;
1249  SCIP_Bool local;
1250  SCIP_Bool modifiable;
1251  SCIP_Bool dynamic;
1252  SCIP_Bool removable;
1253  int sidesign;
1254 
1255  assert(pipinput != NULL);
1256 
1257  /* read polynomial */
1258  SCIP_CALL( readPolynomial(scip, pipinput, name, &expr, &linear, &newsection) );
1259  if ( hasError(pipinput) )
1260  return SCIP_READERROR;
1261  if ( newsection )
1262  {
1263  if ( expr != NULL )
1264  syntaxError(scip, pipinput, "expected constraint sense '<=', '=', or '>='");
1265  return SCIP_OKAY;
1266  }
1267 
1268  /* read the constraint sense */
1269  if ( !getNextToken(scip, pipinput) )
1270  {
1271  syntaxError(scip, pipinput, "expected constraint sense.");
1272  return SCIP_READERROR;
1273  }
1274  if ( !isSense(pipinput, &sense) )
1275  {
1276  syntaxError(scip, pipinput, "expected constraint sense '<=', '=', or '>='");
1277  return SCIP_READERROR;
1278  }
1279 
1280  /* read the right hand side */
1281  sidesign = +1;
1282  if ( !getNextToken(scip, pipinput) )
1283  {
1284  syntaxError(scip, pipinput, "missing right hand side");
1285  return SCIP_READERROR;
1286  }
1287  if ( isSign(pipinput, &sidesign) )
1288  {
1289  if( !getNextToken(scip, pipinput) )
1290  {
1291  syntaxError(scip, pipinput, "missing value of right hand side");
1292  return SCIP_READERROR;
1293  }
1294  }
1295  if ( !isValue(scip, pipinput, &sidevalue) )
1296  {
1297  syntaxError(scip, pipinput, "expected value as right hand side");
1298  return SCIP_READERROR;
1299  }
1300  sidevalue *= sidesign;
1301 
1302  /* determine settings */
1303  initial = pipinput->initialconss;
1304  separate = TRUE;
1305  enforce = TRUE;
1306  check = TRUE;
1307  propagate = TRUE;
1308  local = FALSE;
1309  modifiable = FALSE;
1310  dynamic = pipinput->dynamicconss;
1311  removable = pipinput->dynamicrows;
1312 
1313  /* assign the left and right hand side, depending on the constraint sense */
1314  switch ( sense ) /*lint !e530*/
1315  {
1316  case PIP_SENSE_GE:
1317  lhs = sidevalue;
1318  rhs = SCIPinfinity(scip);
1319  break;
1320  case PIP_SENSE_LE:
1321  lhs = -SCIPinfinity(scip);
1322  rhs = sidevalue;
1323  break;
1324  case PIP_SENSE_EQ:
1325  lhs = sidevalue;
1326  rhs = sidevalue;
1327  break;
1328  case PIP_SENSE_NOTHING:
1329  default:
1330  SCIPerrorMessage("invalid constraint sense <%d>\n", sense);
1331  return SCIP_INVALIDDATA;
1332  }
1333 
1334  /* linear constraint function */
1335  if( linear )
1336  {
1337  SCIP_VAR** vars;
1338  SCIP_Real* coefs;
1339  SCIP_Real constant;
1340  int nchildren;
1341  int i;
1342 
1343  nchildren = SCIPexprGetNChildren(expr);
1344  constant = SCIPgetConstantExprSum(expr);
1345  coefs = SCIPgetCoefsExprSum(expr);
1346 
1347  /* allocate memory to store variables */
1348  SCIP_CALL( SCIPallocBufferArray(scip, &vars, nchildren) );
1349 
1350  /* collect variables */
1351  for( i = 0; i < nchildren; ++i )
1352  {
1353  SCIP_EXPR* child = SCIPexprGetChildren(expr)[i];
1354  assert(child != NULL);
1355  assert(SCIPisExprVar(scip, child));
1356 
1357  vars[i] = SCIPgetVarExprVar(child);
1358  assert(vars[i] != NULL);
1359  }
1360 
1361  /* adjust lhs and rhs */
1362  if( !SCIPisInfinity(scip, -lhs) )
1363  lhs -= constant;
1364  if( !SCIPisInfinity(scip, rhs) )
1365  rhs -= constant;
1366 
1367  /* create linear constraint */
1368  SCIP_CALL( SCIPcreateConsLinear(scip, &cons, name, nchildren, vars, coefs, lhs, rhs, initial, separate, enforce,
1369  check, propagate, local, modifiable, dynamic, removable, FALSE) );
1370 
1371  /* free memory */
1372  SCIPfreeBufferArray(scip, &vars);
1373  }
1374  else /* nonlinear constraint function */
1375  {
1376  SCIP_CALL( SCIPcreateConsNonlinear(scip, &cons, name, expr, lhs, rhs, initial, separate, enforce, check, propagate,
1377  local, modifiable, dynamic, removable) );
1378  }
1379 
1380  /* add and release constraint */
1381  assert(cons != NULL);
1382  SCIP_CALL( SCIPaddCons(scip, cons) );
1383  SCIPdebugMsg(scip, "(line %d) created constraint: ", pipinput->linenumber);
1384  SCIPdebugPrintCons(scip, cons, NULL);
1385  SCIP_CALL( SCIPreleaseCons(scip, &cons) );
1386 
1387  /* release expression */
1388  if( expr != NULL )
1389  {
1390  SCIP_CALL( SCIPreleaseExpr(scip, &expr) );
1391  }
1392 
1393  return SCIP_OKAY;
1394 }
1395 
1396 /** reads the bounds section */
1397 static
1399  SCIP* scip, /**< SCIP data structure */
1400  PIPINPUT* pipinput /**< PIP reading data */
1401  )
1402 {
1403  assert(pipinput != NULL);
1404 
1405  while( getNextToken(scip, pipinput) )
1406  {
1407  SCIP_VAR* var;
1408  SCIP_Real value;
1409  SCIP_Real lb;
1410  SCIP_Real ub;
1411  int sign;
1412  SCIP_Bool hassign;
1413  PIPSENSE leftsense;
1414 
1415  /* check if we reached a new section */
1416  if( isNewSection(scip, pipinput) )
1417  return SCIP_OKAY;
1418 
1419  /* default bounds are [0,+inf] */
1420  lb = 0.0;
1421  ub = SCIPinfinity(scip);
1422  leftsense = PIP_SENSE_NOTHING;
1423 
1424  /* check if the first token is a sign */
1425  sign = +1;
1426  hassign = isSign(pipinput, &sign);
1427  if( hassign && !getNextToken(scip, pipinput) )
1428  {
1429  syntaxError(scip, pipinput, "expected value");
1430  return SCIP_OKAY;
1431  }
1432 
1433  /* the first token must be either a value or a variable name */
1434  if( isValue(scip, pipinput, &value) )
1435  {
1436  /* first token is a value: the second token must be a sense */
1437  if( !getNextToken(scip, pipinput) || !isSense(pipinput, &leftsense) )
1438  {
1439  syntaxError(scip, pipinput, "expected bound sense '<=', '=', or '>='");
1440  return SCIP_OKAY;
1441  }
1442 
1443  /* update the bound corresponding to the sense */
1444  switch( leftsense )
1445  {
1446  case PIP_SENSE_GE:
1447  ub = sign * value;
1448  break;
1449  case PIP_SENSE_LE:
1450  lb = sign * value;
1451  break;
1452  case PIP_SENSE_EQ:
1453  lb = sign * value;
1454  ub = sign * value;
1455  break;
1456  case PIP_SENSE_NOTHING:
1457  default:
1458  SCIPerrorMessage("invalid bound sense <%d>\n", leftsense);
1459  return SCIP_INVALIDDATA;
1460  }
1461  }
1462  else if( hassign )
1463  {
1464  syntaxError(scip, pipinput, "expected value");
1465  return SCIP_OKAY;
1466  }
1467  else
1468  pushToken(pipinput);
1469 
1470  /* the next token must be a variable name */
1471  if( !getNextToken(scip, pipinput) )
1472  {
1473  syntaxError(scip, pipinput, "expected variable name");
1474  return SCIP_OKAY;
1475  }
1476  SCIP_CALL( getVariable(scip, pipinput->token, pipinput->dynamiccols, &var, NULL) );
1477 
1478  /* the next token might be another sense, or the word "free" */
1479  if( getNextToken(scip, pipinput) )
1480  {
1481  PIPSENSE rightsense;
1482 
1483  if( isSense(pipinput, &rightsense) )
1484  {
1485  /* check, if the senses fit */
1486  if( leftsense == PIP_SENSE_NOTHING
1487  || (leftsense == PIP_SENSE_LE && rightsense == PIP_SENSE_LE)
1488  || (leftsense == PIP_SENSE_GE && rightsense == PIP_SENSE_GE) )
1489  {
1490  if( !getNextToken(scip, pipinput) )
1491  {
1492  syntaxError(scip, pipinput, "expected value or sign");
1493  return SCIP_OKAY;
1494  }
1495 
1496  /* check if the next token is a sign */
1497  sign = +1;
1498  hassign = isSign(pipinput, &sign);
1499  if( hassign && !getNextToken(scip, pipinput) )
1500  {
1501  syntaxError(scip, pipinput, "expected value");
1502  return SCIP_OKAY;
1503  }
1504 
1505  /* the next token must be a value */
1506  if( !isValue(scip, pipinput, &value) )
1507  {
1508  syntaxError(scip, pipinput, "expected value");
1509  return SCIP_OKAY;
1510  }
1511 
1512  /* update the bound corresponding to the sense */
1513  switch( rightsense )
1514  {
1515  case PIP_SENSE_GE:
1516  lb = sign * value;
1517  break;
1518  case PIP_SENSE_LE:
1519  ub = sign * value;
1520  break;
1521  case PIP_SENSE_EQ:
1522  lb = sign * value;
1523  ub = sign * value;
1524  break;
1525  case PIP_SENSE_NOTHING:
1526  default:
1527  SCIPerrorMessage("invalid bound sense <%d>\n", leftsense);
1528  return SCIP_INVALIDDATA;
1529  }
1530  }
1531  else
1532  {
1533  syntaxError(scip, pipinput, "the two bound senses do not fit");
1534  return SCIP_OKAY;
1535  }
1536  }
1537  else if( strcasecmp(pipinput->token, "FREE") == 0 )
1538  {
1539  if( leftsense != PIP_SENSE_NOTHING )
1540  {
1541  syntaxError(scip, pipinput, "variable with bound is marked as 'free'");
1542  return SCIP_OKAY;
1543  }
1544  lb = -SCIPinfinity(scip);
1545  ub = SCIPinfinity(scip);
1546  }
1547  else
1548  {
1549  /* the token was no sense: push it back to the token stack */
1550  pushToken(pipinput);
1551  }
1552  }
1553 
1554  /* change the bounds of the variable if bounds have been given (do not destroy earlier specification of bounds) */
1555  if ( lb != 0.0 )
1556  SCIP_CALL( SCIPchgVarLb(scip, var, lb) );
1557  /*lint --e{777}*/
1558  if ( ub != SCIPinfinity(scip) )
1559  SCIP_CALL( SCIPchgVarUb(scip, var, ub) );
1560  SCIPdebugMsg(scip, "(line %d) new bounds: <%s>[%g,%g]\n", pipinput->linenumber, SCIPvarGetName(var),
1562  }
1563 
1564  return SCIP_OKAY;
1565 }
1566 
1567 /** reads the generals section */
1568 static
1570  SCIP* scip, /**< SCIP data structure */
1571  PIPINPUT* pipinput /**< PIP reading data */
1572  )
1573 {
1574  assert(pipinput != NULL);
1575 
1576  while( getNextToken(scip, pipinput) )
1577  {
1578  SCIP_VAR* var;
1579  SCIP_Bool created;
1580  SCIP_Bool infeasible;
1581 
1582  /* check if we reached a new section */
1583  if( isNewSection(scip, pipinput) )
1584  return SCIP_OKAY;
1585 
1586  /* the token must be the name of an existing variable */
1587  SCIP_CALL( getVariable(scip, pipinput->token, pipinput->dynamiccols, &var, &created) );
1588  if( created )
1589  {
1590  syntaxError(scip, pipinput, "unknown variable in generals section");
1591  return SCIP_OKAY;
1592  }
1593 
1594  /* mark the variable to be integral */
1595  SCIP_CALL( SCIPchgVarType(scip, var, SCIP_VARTYPE_INTEGER, &infeasible) );
1596  /* don't assert feasibility here because the presolver will and should detect a infeasibility */
1597  }
1598 
1599  return SCIP_OKAY;
1600 }
1601 
1602 /** reads the binaries section */
1603 static
1605  SCIP* scip, /**< SCIP data structure */
1606  PIPINPUT* pipinput /**< PIP reading data */
1607  )
1608 {
1609  assert(pipinput != NULL);
1610 
1611  while( getNextToken(scip, pipinput) )
1612  {
1613  SCIP_VAR* var;
1614  SCIP_Bool created;
1615  SCIP_Bool infeasible;
1616 
1617  /* check if we reached a new section */
1618  if( isNewSection(scip, pipinput) )
1619  return SCIP_OKAY;
1620 
1621  /* the token must be the name of an existing variable */
1622  SCIP_CALL( getVariable(scip, pipinput->token, pipinput->dynamiccols, &var, &created) );
1623  if( created )
1624  {
1625  syntaxError(scip, pipinput, "unknown variable in binaries section");
1626  return SCIP_OKAY;
1627  }
1628 
1629  /* mark the variable to be binary and change its bounds appropriately */
1630  if( SCIPvarGetLbGlobal(var) < 0.0 )
1631  {
1632  SCIP_CALL( SCIPchgVarLb(scip, var, 0.0) );
1633  }
1634  if( SCIPvarGetUbGlobal(var) > 1.0 )
1635  {
1636  SCIP_CALL( SCIPchgVarUb(scip, var, 1.0) );
1637  }
1638  SCIP_CALL( SCIPchgVarType(scip, var, SCIP_VARTYPE_BINARY, &infeasible) );
1639  /* don't assert feasibility here because the presolver will and should detect a infeasibility */
1640  }
1641 
1642  return SCIP_OKAY;
1643 }
1644 
1645 /** reads a PIP file
1646  */
1647 static
1649  SCIP* scip, /**< SCIP data structure */
1650  PIPINPUT* pipinput, /**< PIP reading data */
1651  const char* filename /**< name of the input file */
1652  )
1653 {
1654  assert(pipinput != NULL);
1655 
1656  /* open file */
1657  pipinput->file = SCIPfopen(filename, "r");
1658  if( pipinput->file == NULL )
1659  {
1660  SCIPerrorMessage("cannot open file <%s> for reading\n", filename);
1661  SCIPprintSysError(filename);
1662  return SCIP_NOFILE;
1663  }
1664 
1665  /* create problem */
1666  SCIP_CALL( SCIPcreateProb(scip, filename, NULL, NULL, NULL, NULL, NULL, NULL, NULL) );
1667 
1668  /* parse the file */
1669  pipinput->section = PIP_START;
1670  while( pipinput->section != PIP_END && !hasError(pipinput) )
1671  {
1672  switch( pipinput->section )
1673  {
1674  case PIP_START:
1675  SCIP_CALL( readStart(scip, pipinput) );
1676  break;
1677 
1678  case PIP_OBJECTIVE:
1679  SCIP_CALL( readObjective(scip, pipinput) );
1680  break;
1681 
1682  case PIP_CONSTRAINTS:
1683  SCIP_CALL( readConstraints(scip, pipinput) );
1684  break;
1685 
1686  case PIP_BOUNDS:
1687  SCIP_CALL( readBounds(scip, pipinput) );
1688  break;
1689 
1690  case PIP_GENERALS:
1691  SCIP_CALL( readGenerals(scip, pipinput) );
1692  break;
1693 
1694  case PIP_BINARIES:
1695  SCIP_CALL( readBinaries(scip, pipinput) );
1696  break;
1697 
1698  case PIP_END: /* this is already handled in the while() loop */
1699  default:
1700  SCIPerrorMessage("invalid PIP file section <%d>\n", pipinput->section);
1701  return SCIP_INVALIDDATA;
1702  }
1703  }
1704 
1705  /* close file */
1706  SCIPfclose(pipinput->file);
1707 
1708  return SCIP_OKAY;
1709 }
1710 
1711 
1712 /*
1713  * Local methods (for writing)
1714  */
1715 
1716 /** hash key retrieval function for variables */
1717 static
1718 SCIP_DECL_HASHGETKEY(hashGetKeyVar)
1719 { /*lint --e{715}*/
1720  return elem;
1721 }
1722 
1723 /** returns TRUE iff the indices of both variables are equal */
1724 static
1725 SCIP_DECL_HASHKEYEQ(hashKeyEqVar)
1726 { /*lint --e{715}*/
1727  if ( key1 == key2 )
1728  return TRUE;
1729  return FALSE;
1730 }
1731 
1732 /** returns the hash value of the key */
1733 static
1734 SCIP_DECL_HASHKEYVAL(hashKeyValVar)
1735 { /*lint --e{715}*/
1736  assert( SCIPvarGetIndex((SCIP_VAR*) key) >= 0 );
1737  return (unsigned int) SCIPvarGetIndex((SCIP_VAR*) key);
1738 }
1739 
1740 /** transforms given variables, scalars, and constant to the corresponding active variables, scalars, and constant */
1741 static
1743  SCIP* scip, /**< SCIP data structure */
1744  SCIP_VAR** vars, /**< vars array to get active variables for */
1745  SCIP_Real* scalars, /**< scalars a_1, ..., a_n in linear sum a_1*x_1 + ... + a_n*x_n + c */
1746  int* nvars, /**< pointer to number of variables and values in vars and vals array */
1747  SCIP_Real* constant, /**< pointer to constant c in linear sum a_1*x_1 + ... + a_n*x_n + c */
1748  SCIP_Bool transformed /**< transformed constraint? */
1749  )
1750 {
1751  int requiredsize;
1752  int v;
1753 
1754  assert( scip != NULL );
1755  assert( vars != NULL );
1756  assert( scalars != NULL );
1757  assert( nvars != NULL );
1758  assert( constant != NULL );
1759 
1760  if( transformed )
1761  {
1762  SCIP_CALL( SCIPgetProbvarLinearSum(scip, vars, scalars, nvars, *nvars, constant, &requiredsize, TRUE) );
1763 
1764  if( requiredsize > *nvars )
1765  {
1766  SCIP_CALL( SCIPreallocBufferArray(scip, &vars, requiredsize) );
1767  SCIP_CALL( SCIPreallocBufferArray(scip, &scalars, requiredsize) );
1768 
1769  SCIP_CALL( SCIPgetProbvarLinearSum(scip, vars, scalars, nvars, requiredsize, constant, &requiredsize, TRUE) );
1770  assert( requiredsize <= *nvars );
1771  }
1772  }
1773  else
1774  {
1775  for( v = 0; v < *nvars; ++v )
1776  SCIP_CALL( SCIPvarGetOrigvarSum(&vars[v], &scalars[v], constant) );
1777  }
1778  return SCIP_OKAY;
1779 }
1780 
1781 /** checks whether a given expression is a signomial
1782  *
1783  * assumes simplified expression
1784  */
1785 static
1787  SCIP* scip, /**< SCIP data structure */
1788  SCIP_EXPR* expr /**< expression */
1789  )
1790 {
1791  assert(scip != NULL);
1792  assert(expr != NULL);
1793 
1794  if( SCIPisExprVar(scip, expr) || SCIPisExprValue(scip, expr) )
1795  return TRUE;
1796 
1797  if( SCIPisExprPower(scip, expr) && SCIPisExprVar(scip, SCIPexprGetChildren(expr)[0]) )
1798  return TRUE;
1799 
1800  if( SCIPisExprProduct(scip, expr) )
1801  {
1802  SCIP_EXPR* child;
1803  int c;
1804 
1805  for( c = 0; c < SCIPexprGetNChildren(expr); ++c )
1806  {
1807  child = SCIPexprGetChildren(expr)[c];
1808 
1809  if( SCIPisExprVar(scip, child) )
1810  continue;
1811 
1812  if( SCIPisExprPower(scip, child) && SCIPisExprVar(scip, SCIPexprGetChildren(child)[0]) )
1813  continue;
1814 
1815  /* the pip format does not allow constants here */
1816 
1817  return FALSE;
1818  }
1819 
1820  return TRUE;
1821  }
1822 
1823  return FALSE;
1824 }
1825 
1826 /** checks whether a given expression is a sum of signomials (i.e., like a polynomial, but negative and fractional exponents allowed)
1827  *
1828  * assumes simplified expression;
1829  * does not check whether variables in powers with fractional exponent are nonnegative;
1830  * does not check whether variables in powers with negative exponent are bounded away from zero (the format specification does not require that, too)
1831  */
1832 static
1834  SCIP* scip, /**< SCIP data structure */
1835  SCIP_EXPR* expr /**< expression */
1836  )
1837 {
1838  int c;
1839 
1840  assert(scip != NULL);
1841  assert(expr != NULL);
1842 
1843  if( !SCIPisExprSum(scip, expr) )
1844  return isExprSignomial(scip, expr);
1845 
1846  /* check whether every term of sum is signomial */
1847  for( c = 0; c < SCIPexprGetNChildren(expr); ++c )
1848  if( !isExprSignomial(scip, SCIPexprGetChildren(expr)[c]) )
1849  return FALSE;
1850 
1851  return TRUE;
1852 }
1853 
1854 /** clears the given line buffer */
1855 static
1857  char* linebuffer, /**< line */
1858  int* linecnt /**< number of characters in line */
1859  )
1860 {
1861  assert( linebuffer != NULL );
1862  assert( linecnt != NULL );
1863 
1864  (*linecnt) = 0;
1865  linebuffer[0] = '\0';
1866 }
1867 
1868 /** ends the given line with '\\0' and prints it to the given file stream */
1869 static
1870 void endLine(
1871  SCIP* scip, /**< SCIP data structure */
1872  FILE* file, /**< output file (or NULL for standard output) */
1873  char* linebuffer, /**< line */
1874  int* linecnt /**< number of characters in line */
1875  )
1876 {
1877  assert( scip != NULL );
1878  assert( linebuffer != NULL );
1879  assert( linecnt != NULL );
1880  assert( 0 <= *linecnt && *linecnt < PIP_MAX_PRINTLEN );
1881 
1882  if( (*linecnt) > 0 )
1883  {
1884  linebuffer[(*linecnt)] = '\0';
1885  SCIPinfoMessage(scip, file, "%s\n", linebuffer);
1886  clearLine(linebuffer, linecnt);
1887  }
1888 }
1889 
1890 /** appends extension to line and prints it to the give file stream if the
1891  * line exceeded the length given in the define PIP_PRINTLEN */
1892 static
1894  SCIP* scip, /**< SCIP data structure */
1895  FILE* file, /**< output file (or NULL for standard output) */
1896  char* linebuffer, /**< line */
1897  int* linecnt, /**< number of characters in line */
1898  const char* extension /**< string to extent the line */
1899  )
1900 {
1901  assert( scip != NULL );
1902  assert( linebuffer != NULL );
1903  assert( linecnt != NULL );
1904  assert( extension != NULL );
1905  assert( strlen(linebuffer) + strlen(extension) < PIP_MAX_PRINTLEN );
1906 
1907  /* NOTE: avoid
1908  * sprintf(linebuffer, "%s%s", linebuffer, extension);
1909  * because of overlapping memory areas in memcpy used in sprintf.
1910  */
1911  (void) strncat(linebuffer, extension, PIP_MAX_PRINTLEN - strlen(linebuffer));
1912 
1913  (*linecnt) += (int) strlen(extension);
1914 
1915  SCIPdebugMsg(scip, "linebuffer <%s>, length = %lu\n", linebuffer, (unsigned long)strlen(linebuffer));
1916 
1917  if( (*linecnt) > PIP_PRINTLEN )
1918  endLine(scip, file, linebuffer, linecnt);
1919 }
1920 
1921 
1922 /** print linear or quadratic row in PIP format to file stream */
1923 static
1925  SCIP* scip, /**< SCIP data structure */
1926  FILE* file, /**< output file (or NULL for standard output) */
1927  const char* rowname, /**< row name */
1928  const char* rownameextension, /**< row name extension */
1929  const char* type, /**< row type ("=", "<=", or ">=") */
1930  SCIP_VAR** linvars, /**< array of linear variables */
1931  SCIP_Real* linvals, /**< array of linear coefficient values */
1932  int nlinvars, /**< number of linear variables */
1933  SCIP_EXPR* quadexpr, /**< quadratic expression */
1934  SCIP_Real rhs, /**< right hand side */
1935  SCIP_Bool transformed /**< transformed constraint? */
1936  )
1937 {
1938  int v;
1939  char linebuffer[PIP_MAX_PRINTLEN+1] = { '\0' };
1940  int linecnt;
1941 
1942  char varname[PIP_MAX_NAMELEN];
1943  char varname2[PIP_MAX_NAMELEN];
1944  char consname[PIP_MAX_NAMELEN + 1]; /* an extra character for ':' */
1945  char buffer[PIP_MAX_PRINTLEN];
1946 
1947  assert( scip != NULL );
1948  assert( strcmp(type, "=") == 0 || strcmp(type, "<=") == 0 || strcmp(type, ">=") == 0 );
1949  assert( nlinvars == 0 || (linvars != NULL && linvals != NULL) );
1950 
1951  clearLine(linebuffer, &linecnt);
1952 
1953  /* start each line with a space */
1954  appendLine(scip, file, linebuffer, &linecnt, " ");
1955 
1956  /* print row name */
1957  if ( strlen(rowname) > 0 || strlen(rownameextension) > 0 )
1958  {
1959  (void) SCIPsnprintf(consname, PIP_MAX_NAMELEN + 1, "%s%s:", rowname, rownameextension);
1960  appendLine(scip, file, linebuffer, &linecnt, consname);
1961  }
1962 
1963  /* print coefficients */
1964  for( v = 0; v < nlinvars; ++v )
1965  {
1966  SCIP_VAR* var;
1967 
1968  assert(linvars != NULL); /* for lint */
1969  assert(linvals != NULL);
1970 
1971  var = linvars[v];
1972  assert( var != NULL );
1973 
1974  /* we start a new line; therefore we tab this line */
1975  if ( linecnt == 0 )
1976  appendLine(scip, file, linebuffer, &linecnt, " ");
1977 
1978  (void) SCIPsnprintf(varname, PIP_MAX_NAMELEN, "%s", SCIPvarGetName(var));
1979  (void) SCIPsnprintf(buffer, PIP_MAX_PRINTLEN, " %+.15g %s", linvals[v], varname);
1980 
1981  appendLine(scip, file, linebuffer, &linecnt, buffer);
1982  }
1983 
1984  /* print quadratic part */
1985  if( quadexpr != NULL )
1986  {
1987  SCIP_EXPR** linexprs;
1988  SCIP_VAR** activevars;
1989  SCIP_Real* activevals;
1990  SCIP_Real* lincoefs;
1991  SCIP_Real constant;
1992  SCIP_Real activeconstant = 0.0;
1993  int nbilinexprterms;
1994  int nactivevars;
1995  int nquadexprs;
1996  int nlinexprs;
1997 
1998  /* get data from the quadratic expression */
1999  SCIPexprGetQuadraticData(quadexpr, &constant, &nlinexprs, &linexprs, &lincoefs, &nquadexprs, &nbilinexprterms,
2000  NULL, NULL);
2001 
2002  /* allocate memory to store active linear variables */
2003  SCIP_CALL( SCIPallocBufferArray(scip, &activevars, nlinexprs) );
2004  SCIP_CALL( SCIPduplicateBufferArray(scip, &activevals, lincoefs, nlinexprs) );
2005  nactivevars = nlinexprs;
2006 
2007  for( v = 0; v < nlinexprs; ++v )
2008  {
2009  assert(linexprs != NULL && linexprs[v] != NULL);
2010  assert(SCIPisExprVar(scip, linexprs[v]));
2011 
2012  activevars[v] = SCIPgetVarExprVar(linexprs[v]);
2013  assert(activevars[v] != NULL);
2014  }
2015 
2016  /* get active variables */
2017  SCIP_CALL( getActiveVariables(scip, activevars, activevals, &nactivevars, &activeconstant, transformed) );
2018  constant += activeconstant;
2019 
2020  /* print linear coefficients of linear variables */
2021  for( v = 0; v < nactivevars; ++v )
2022  {
2023  SCIP_VAR* var;
2024 
2025  assert(activevars != NULL); /* for lint */
2026  assert(activevals != NULL);
2027 
2028  var = activevars[v];
2029  assert( var != NULL );
2030 
2031  /* we start a new line; therefore we tab this line */
2032  if( linecnt == 0 )
2033  appendLine(scip, file, linebuffer, &linecnt, " ");
2034 
2035  (void) SCIPsnprintf(varname, PIP_MAX_NAMELEN, "%s", SCIPvarGetName(var));
2036  (void) SCIPsnprintf(buffer, PIP_MAX_PRINTLEN, " %+.15g %s", activevals[v], varname);
2037 
2038  appendLine(scip, file, linebuffer, &linecnt, buffer);
2039  }
2040 
2041  /* free memory for active linear variables */
2042  SCIPfreeBufferArray(scip, &activevals);
2043  SCIPfreeBufferArray(scip, &activevars);
2044 
2045  /* adjust rhs if there is a constant */
2046  if( constant != 0.0 && !SCIPisInfinity(scip, rhs) )
2047  rhs -= constant;
2048 
2049  /* print linear coefficients of quadratic variables */
2050  for( v = 0; v < nquadexprs; ++v )
2051  {
2052  SCIP_EXPR* expr;
2053  SCIP_VAR* var;
2054  SCIP_Real lincoef;
2055 
2056  /* get linear coefficient and variable of quadratic term */
2057  SCIPexprGetQuadraticQuadTerm(quadexpr, v, &expr, &lincoef, NULL, NULL, NULL, NULL);
2058  assert(expr != NULL);
2059  assert(SCIPisExprVar(scip, expr));
2060 
2061  var = SCIPgetVarExprVar(expr);
2062  assert(var != NULL);
2063 
2064  if( lincoef == 0.0 )
2065  continue;
2066 
2067  /* we start a new line; therefore we tab this line */
2068  if( linecnt == 0 )
2069  appendLine(scip, file, linebuffer, &linecnt, " ");
2070 
2071  (void) SCIPsnprintf(varname, PIP_MAX_NAMELEN, "%s", SCIPvarGetName(var));
2072  (void) SCIPsnprintf(buffer, PIP_MAX_PRINTLEN, " %+.15g %s", lincoef, varname);
2073 
2074  appendLine(scip, file, linebuffer, &linecnt, buffer);
2075  }
2076 
2077  /* print square terms */
2078  for( v = 0; v < nquadexprs; ++v )
2079  {
2080  SCIP_EXPR* expr;
2081  SCIP_VAR* var;
2082  SCIP_Real sqrcoef;
2083 
2084  /* get square coefficient and variable of quadratic term */
2085  SCIPexprGetQuadraticQuadTerm(quadexpr, v, &expr, NULL, &sqrcoef, NULL, NULL, NULL);
2086  assert(expr != NULL);
2087  assert(SCIPisExprVar(scip, expr));
2088 
2089  var = SCIPgetVarExprVar(expr);
2090  assert(var != NULL);
2091 
2092  if( sqrcoef == 0.0 )
2093  continue;
2094 
2095  /* we start a new line; therefore we tab this line */
2096  if( linecnt == 0 )
2097  appendLine(scip, file, linebuffer, &linecnt, " ");
2098 
2099  (void) SCIPsnprintf(varname, PIP_MAX_NAMELEN, "%s", SCIPvarGetName(var));
2100  (void) SCIPsnprintf(buffer, PIP_MAX_PRINTLEN, " %+.15g %s^2", sqrcoef, varname);
2101 
2102  appendLine(scip, file, linebuffer, &linecnt, buffer);
2103  }
2104 
2105  /* print bilinear terms */
2106  for( v = 0; v < nbilinexprterms; ++v )
2107  {
2108  SCIP_EXPR* expr1;
2109  SCIP_EXPR* expr2;
2110  SCIP_VAR* var1;
2111  SCIP_VAR* var2;
2112  SCIP_Real bilincoef;
2113 
2114  /* get coefficient and variables of bilinear */
2115  SCIPexprGetQuadraticBilinTerm(quadexpr, v, &expr1, &expr2, &bilincoef, NULL, NULL);
2116  assert(expr1 != NULL);
2117  assert(SCIPisExprVar(scip, expr1));
2118  assert(expr2 != NULL);
2119  assert(SCIPisExprVar(scip, expr2));
2120 
2121  var1 = SCIPgetVarExprVar(expr1);
2122  assert(var1 != NULL);
2123  var2 = SCIPgetVarExprVar(expr2);
2124  assert(var2 != NULL);
2125 
2126  /* we start a new line; therefore we tab this line */
2127  if( linecnt == 0 )
2128  appendLine(scip, file, linebuffer, &linecnt, " ");
2129 
2130  (void) SCIPsnprintf(varname, PIP_MAX_NAMELEN, "%s", SCIPvarGetName(var1));
2131  (void) SCIPsnprintf(varname2, PIP_MAX_NAMELEN, "%s", SCIPvarGetName(var2));
2132  (void) SCIPsnprintf(buffer, PIP_MAX_PRINTLEN, " %+.15g %s * %s", bilincoef, varname, varname2);
2133 
2134  appendLine(scip, file, linebuffer, &linecnt, buffer);
2135  }
2136  }
2137 
2138  /* print right hand side */
2139  if( SCIPisZero(scip, rhs) )
2140  rhs = 0.0;
2141 
2142  (void) SCIPsnprintf(buffer, PIP_MAX_PRINTLEN, " %s %+.15g", type, rhs);
2143 
2144  /* we start a new line; therefore we tab this line */
2145  if (linecnt == 0 )
2146  appendLine(scip, file, linebuffer, &linecnt, " ");
2147  appendLine(scip, file, linebuffer, &linecnt, buffer);
2148 
2149  endLine(scip, file, linebuffer, &linecnt);
2150 
2151  return SCIP_OKAY;
2152 }
2153 
2154 /** print signomial in PIP format to file stream */
2155 static
2157  SCIP* scip, /**< SCIP data structure */
2158  FILE* file, /**< output file (or NULL for standard output) */
2159  char* linebuffer, /**< line buffer to append to */
2160  int* linecnt, /**< count on line buffer use */
2161  SCIP_EXPR* expr, /**< sigomial expression */
2162  SCIP_Real coef, /**< coefficient */
2163  SCIP_Bool needsign /**< whether a sign needs to be ensured */
2164  )
2165 {
2166  char buffer[PIP_MAX_PRINTLEN];
2167  SCIP_EXPR* child;
2168  int c;
2169 
2170  assert(isExprSignomial(scip, expr));
2171 
2172  if( SCIPisExprProduct(scip, expr) )
2173  coef *= SCIPgetCoefExprProduct(expr);
2174 
2175  if( SCIPisExprValue(scip, expr) )
2176  coef *= SCIPgetValueExprValue(expr);
2177 
2178  if( REALABS(coef) != 1.0 )
2179  {
2180  (void) SCIPsnprintf(buffer, PIP_MAX_PRINTLEN, needsign ? " %+.15g " : " %.15g ", coef);
2181  appendLine(scip, file, linebuffer, linecnt, buffer);
2182  }
2183  else if( coef == 1.0 && needsign )
2184  {
2185  appendLine(scip, file, linebuffer, linecnt, " + ");
2186  }
2187  else if( coef == -1.0 )
2188  {
2189  appendLine(scip, file, linebuffer, linecnt, " - ");
2190  }
2191  else
2192  {
2193  appendLine(scip, file, linebuffer, linecnt, " ");
2194  }
2195 
2196  if( SCIPisExprVar(scip, expr) )
2197  {
2198  appendLine(scip, file, linebuffer, linecnt, SCIPvarGetName(SCIPgetVarExprVar(expr)));
2199  return;
2200  }
2201 
2202  if( SCIPisExprValue(scip, expr) )
2203  {
2204  if( REALABS(coef) == 1.0 )
2205  {
2206  /* in this case, we will have printed only a sign or space above, so print also a 1.0 */
2207  appendLine(scip, file, linebuffer, linecnt, "1.0");
2208  }
2209  return;
2210  }
2211 
2212  if( SCIPisExprPower(scip, expr) )
2213  {
2214  assert(SCIPisExprVar(scip, SCIPexprGetChildren(expr)[0]));
2215 
2217  appendLine(scip, file, linebuffer, linecnt, buffer);
2218 
2219  return;
2220  }
2221 
2222  assert(SCIPisExprProduct(scip, expr));
2223  for( c = 0; c < SCIPexprGetNChildren(expr); ++c )
2224  {
2225  child = SCIPexprGetChildren(expr)[c];
2226 
2227  if( c > 0 )
2228  appendLine(scip, file, linebuffer, linecnt, " ");
2229 
2230  if( SCIPisExprVar(scip, child) )
2231  {
2232  appendLine(scip, file, linebuffer, linecnt, SCIPvarGetName(SCIPgetVarExprVar(child)));
2233  continue;
2234  }
2235 
2236  assert(SCIPisExprPower(scip, child));
2237  assert(SCIPisExprVar(scip, SCIPexprGetChildren(child)[0]));
2238 
2240  appendLine(scip, file, linebuffer, linecnt, buffer);
2241  }
2242 }
2243 
2244 /** print polynomial 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_EXPR* expr, /**< polynomial expression */
2253  SCIP_Real rhs /**< right hand side */
2254  )
2255 {
2256  char consname[PIP_MAX_NAMELEN + 1]; /* an extra character for ':' */
2257  char buffer[PIP_MAX_PRINTLEN];
2258  char linebuffer[PIP_MAX_PRINTLEN+1] = { '\0' };
2259  int linecnt;
2260 
2261  assert(scip != NULL);
2262  assert(strcmp(type, "=") == 0 || strcmp(type, "<=") == 0 || strcmp(type, ">=") == 0);
2263  assert(expr != NULL);
2264 
2265  clearLine(linebuffer, &linecnt);
2266 
2267  /* start each line with a space */
2268  appendLine(scip, file, linebuffer, &linecnt, " ");
2269 
2270  /* print row name */
2271  if( strlen(rowname) > 0 || strlen(rownameextension) > 0 )
2272  {
2273  (void) SCIPsnprintf(consname, PIP_MAX_NAMELEN + 1, "%s%s:", rowname, rownameextension);
2274  appendLine(scip, file, linebuffer, &linecnt, consname);
2275  }
2276 
2277  if( SCIPisExprSum(scip, expr) )
2278  {
2279  int c;
2280  SCIP_Bool needsign = FALSE;
2281 
2282  if( SCIPgetConstantExprSum(expr) != 0.0 )
2283  {
2284  (void) SCIPsnprintf(buffer, PIP_MAX_PRINTLEN, " %+.15g", SCIPgetConstantExprSum(expr));
2285  appendLine(scip, file, linebuffer, &linecnt, buffer);
2286 
2287  needsign = TRUE;
2288  }
2289 
2290  for( c = 0; c < SCIPexprGetNChildren(expr); ++c )
2291  {
2292  printSignomial(scip, file, linebuffer, &linecnt, SCIPexprGetChildren(expr)[c], SCIPgetCoefsExprSum(expr)[c], needsign);
2293  needsign = TRUE;
2294  }
2295  }
2296  else
2297  {
2298  printSignomial(scip, file, linebuffer, &linecnt, expr, 1.0, FALSE);
2299  }
2300 
2301  /* print right hand side */
2302  (void) SCIPsnprintf(buffer, PIP_MAX_PRINTLEN, " %s %+.15g", type, rhs);
2303 
2304  /* we start a new line; therefore we tab this line */
2305  if( linecnt == 0 )
2306  appendLine(scip, file, linebuffer, &linecnt, " ");
2307  appendLine(scip, file, linebuffer, &linecnt, buffer);
2308 
2309  endLine(scip, file, linebuffer, &linecnt);
2310 }
2311 
2312 /** print "and" constraint as row in PIP format to file stream */
2313 static
2315  SCIP* scip, /**< SCIP data structure */
2316  FILE* file, /**< output file (or NULL for standard output) */
2317  const char* rowname, /**< row name */
2318  SCIP_CONS* cons /**< "and" constraint */
2319  )
2320 {
2321  char linebuffer[PIP_MAX_PRINTLEN+1] = { '\0' };
2322  int linecnt;
2323  int i;
2324 
2325  assert(scip != NULL);
2326  assert(rowname != NULL);
2327  assert(cons != NULL);
2328 
2329  clearLine(linebuffer, &linecnt);
2330 
2331  /* start each line with a space */
2332  appendLine(scip, file, linebuffer, &linecnt, " ");
2333 
2334  /* print row name */
2335  if( strlen(rowname) > 0 )
2336  {
2337  appendLine(scip, file, linebuffer, &linecnt, rowname);
2338  appendLine(scip, file, linebuffer, &linecnt, ":");
2339  }
2340 
2341  for( i = 0; i < SCIPgetNVarsAnd(scip, cons); ++i )
2342  {
2343  appendLine(scip, file, linebuffer, &linecnt, " ");
2344  appendLine(scip, file, linebuffer, &linecnt, SCIPvarGetName(SCIPgetVarsAnd(scip, cons)[i]));
2345  }
2346 
2347  appendLine(scip, file, linebuffer, &linecnt, " - ");
2348  appendLine(scip, file, linebuffer, &linecnt, SCIPvarGetName(SCIPgetResultantAnd(scip, cons)));
2349 
2350  /* we start a new line; therefore we tab this line */
2351  if( linecnt == 0 )
2352  appendLine(scip, file, linebuffer, &linecnt, " ");
2353 
2354  /* print right hand side */
2355  appendLine(scip, file, linebuffer, &linecnt, " = 0");
2356 
2357  endLine(scip, file, linebuffer, &linecnt);
2358 }
2359 
2360 /** prints given (linear or) quadratic constraint information in LP format to file stream */
2361 static
2363  SCIP* scip, /**< SCIP data structure */
2364  FILE* file, /**< output file (or NULL for standard output) */
2365  const char* rowname, /**< name of the row */
2366  SCIP_VAR** linvars, /**< array of linear variables */
2367  SCIP_Real* linvals, /**< array of linear coefficients values (or NULL if all linear coefficient values are 1) */
2368  int nlinvars, /**< number of linear variables */
2369  SCIP_EXPR* quadexpr, /**< quadratic expression (or NULL if nlinvars > 0) */
2370  SCIP_Real lhs, /**< left hand side */
2371  SCIP_Real rhs, /**< right hand side */
2372  SCIP_Bool transformed /**< transformed constraint? */
2373  )
2374 {
2375  int v;
2376  SCIP_VAR** activevars = NULL;
2377  SCIP_Real* activevals = NULL;
2378  int nactivevars;
2379  SCIP_Real activeconstant = 0.0;
2380 
2381  assert( scip != NULL );
2382  assert( rowname != NULL );
2383 
2384  assert( nlinvars == 0 || linvars != NULL );
2385  assert( quadexpr == NULL || nlinvars == 0);
2386  assert( lhs <= rhs );
2387 
2388  if( SCIPisInfinity(scip, -lhs) && SCIPisInfinity(scip, rhs) )
2389  return SCIP_OKAY;
2390 
2391  nactivevars = nlinvars;
2392  if( nlinvars > 0 )
2393  {
2394  /* duplicate variable and value array */
2395  SCIP_CALL( SCIPduplicateBufferArray(scip, &activevars, linvars, nactivevars ) );
2396  if( linvals != NULL )
2397  {
2398  SCIP_CALL( SCIPduplicateBufferArray(scip, &activevals, linvals, nactivevars ) );
2399  }
2400  else
2401  {
2402  SCIP_CALL( SCIPallocBufferArray(scip, &activevals, nactivevars) );
2403 
2404  for( v = 0; v < nactivevars; ++v )
2405  activevals[v] = 1.0;
2406  }
2407 
2408  /* retransform given variables to active variables */
2409  SCIP_CALL( getActiveVariables(scip, activevars, activevals, &nactivevars, &activeconstant, transformed) );
2410  }
2411 
2412  /* print row(s) in LP format */
2413  if( SCIPisEQ(scip, lhs, rhs) )
2414  {
2415  assert( !SCIPisInfinity(scip, rhs) );
2416 
2417  /* equal constraint */
2418  SCIP_CALL( printRow(scip, file, rowname, "", "=", activevars, activevals, nactivevars, quadexpr,
2419  rhs - activeconstant, transformed) );
2420  }
2421  else
2422  {
2423  if( !SCIPisInfinity(scip, -lhs) )
2424  {
2425  /* print inequality ">=" */
2426  SCIP_CALL( printRow(scip, file, rowname, SCIPisInfinity(scip, rhs) ? "" : "_lhs", ">=", activevars,
2427  activevals, nactivevars, quadexpr, lhs - activeconstant, transformed) );
2428  }
2429  if( !SCIPisInfinity(scip, rhs) )
2430  {
2431  /* print inequality "<=" */
2432  SCIP_CALL( printRow(scip, file, rowname, SCIPisInfinity(scip, -lhs) ? "" : "_rhs", "<=", activevars,
2433  activevals, nactivevars, quadexpr, rhs - activeconstant, transformed) );
2434  }
2435  }
2436 
2437  if( nlinvars > 0 )
2438  {
2439  /* free buffer arrays */
2440  SCIPfreeBufferArray(scip, &activevars);
2441  SCIPfreeBufferArray(scip, &activevals);
2442  }
2443 
2444  return SCIP_OKAY;
2445 }
2446 
2447 /** prints given nonlinear constraint information in LP format to file stream */
2448 static
2450  SCIP* scip, /**< SCIP data structure */
2451  FILE* file, /**< output file (or NULL for standard output) */
2452  const char* rowname, /**< name of the row */
2453  SCIP_EXPR* expr, /**< polynomial expression */
2454  SCIP_Real lhs, /**< left hand side */
2455  SCIP_Real rhs /**< right hand side */
2456  )
2457 {
2458  assert(scip != NULL);
2459  assert(rowname != NULL);
2460  assert(expr != NULL);
2461  assert(lhs <= rhs);
2462 
2463  if( SCIPisInfinity(scip, -lhs) && SCIPisInfinity(scip, rhs) )
2464  return SCIP_OKAY;
2465 
2466  /* print row(s) in LP format */
2467  if( SCIPisEQ(scip, lhs, rhs) )
2468  {
2469  assert( !SCIPisInfinity(scip, rhs) );
2470 
2471  /* equal constraint */
2472  printRowNl(scip, file, rowname, "", "=", expr, rhs);
2473  }
2474  else
2475  {
2476  if( !SCIPisInfinity(scip, -lhs) )
2477  {
2478  /* print inequality ">=" */
2479  printRowNl(scip, file, rowname, SCIPisInfinity(scip, rhs) ? "" : "_lhs", ">=", expr, lhs);
2480  }
2481  if( !SCIPisInfinity(scip, rhs) )
2482  {
2483  /* print inequality "<=" */
2484  printRowNl(scip, file, rowname, SCIPisInfinity(scip, -lhs) ? "" : "_rhs", "<=", expr, rhs);
2485  }
2486  }
2487 
2488  return SCIP_OKAY;
2489 }
2490 
2491 /** check whether given variables are aggregated and put them into an array without duplication */
2492 static
2494  int nvars, /**< number of active variables in the problem */
2495  SCIP_VAR** vars, /**< variable array */
2496  int* nAggregatedVars, /**< number of aggregated variables on output */
2497  SCIP_VAR*** aggregatedVars, /**< array storing the aggregated variables on output */
2498  SCIP_HASHTABLE** varAggregated /**< hashtable for checking duplicates */
2499  )
2500 {
2501  int j;
2502 
2503  /* check variables */
2504  for (j = 0; j < nvars; ++j)
2505  {
2506  SCIP_VARSTATUS status;
2507  SCIP_VAR* var;
2508 
2509  var = vars[j];
2510  status = SCIPvarGetStatus(var);
2511 
2512  /* collect aggregated variables in a list */
2513  if( status >= SCIP_VARSTATUS_AGGREGATED )
2514  {
2515  assert( status == SCIP_VARSTATUS_AGGREGATED ||
2516  status == SCIP_VARSTATUS_MULTAGGR ||
2517  status == SCIP_VARSTATUS_NEGATED );
2518 
2519  if ( ! SCIPhashtableExists(*varAggregated, (void*) var) )
2520  {
2521  (*aggregatedVars)[(*nAggregatedVars)++] = var;
2522  SCIP_CALL( SCIPhashtableInsert(*varAggregated, (void*) var) );
2523  }
2524  }
2525  }
2526 
2527  return SCIP_OKAY;
2528 }
2529 
2530 
2531 /** print aggregated variable-constraints */
2532 static
2534  SCIP* scip, /**< SCIP data structure */
2535  FILE* file, /**< output file (or NULL for standard output) */
2536  SCIP_Bool transformed, /**< TRUE iff problem is the transformed problem */
2537  int nvars, /**< number of active variables in the problem */
2538  int nAggregatedVars, /**< number of aggregated variables */
2539  SCIP_VAR** aggregatedVars /**< array storing the aggregated variables */
2540  )
2541 {
2542  int j;
2543 
2544  SCIP_VAR** activevars;
2545  SCIP_Real* activevals;
2546  int nactivevars;
2547  SCIP_Real activeconstant = 0.0;
2548  char consname[PIP_MAX_NAMELEN];
2549 
2550  assert( scip != NULL );
2551 
2552  /* write aggregation constraints */
2553  SCIP_CALL( SCIPallocBufferArray(scip, &activevars, nvars) );
2554  SCIP_CALL( SCIPallocBufferArray(scip, &activevals, nvars) );
2555 
2556  for (j = 0; j < nAggregatedVars; ++j)
2557  {
2558  /* set up list to obtain substitution variables */
2559  nactivevars = 1;
2560 
2561  activevars[0] = aggregatedVars[j];
2562  activevals[0] = 1.0;
2563  activeconstant = 0.0;
2564 
2565  /* retransform given variables to active variables */
2566  SCIP_CALL( getActiveVariables(scip, activevars, activevals, &nactivevars, &activeconstant, transformed) );
2567 
2568  activevals[nactivevars] = -1.0;
2569  activevars[nactivevars] = aggregatedVars[j];
2570  ++nactivevars;
2571 
2572  /* output constraint */
2573  (void) SCIPsnprintf(consname, PIP_MAX_NAMELEN, "aggr_%s", SCIPvarGetName(aggregatedVars[j]));
2574  SCIP_CALL( printRow(scip, file, consname, "", "=", activevars, activevals, nactivevars, NULL, - activeconstant,
2575  transformed) );
2576  }
2577 
2578  /* free buffer arrays */
2579  SCIPfreeBufferArray(scip, &activevars);
2580  SCIPfreeBufferArray(scip, &activevals);
2581 
2582  return SCIP_OKAY;
2583 }
2584 
2585 /** returns whether name is valid according to PIP specification
2586  *
2587  * Checks these two conditions from http://polip.zib.de/pipformat.php:
2588  * - Names/labels can contain at most 255 characters.
2589  * - Name/labels have to consist of the following characters: a-z, A-Z, 0-9, "!", "#", "$", "%", "&", ";", "?", "@", "_". They cannot start with a number.
2590  *
2591  * In addition checks that the length is not zero.
2592  */
2593 static
2595  const char* name /**< name to check */
2596  )
2597 {
2598  size_t len;
2599  size_t i;
2600 
2601  assert(name != NULL);
2602 
2603  len = strlen(name); /*lint !e613*/
2604  if( len > (size_t) PIP_MAX_NAMELEN || len == 0 )
2605  return FALSE;
2606 
2607  /* names cannot start with a number */
2608  if( isdigit(name[0]) )
2609  return FALSE;
2610 
2611  for( i = 0; i < len; ++i )
2612  {
2613  /* a-z, A-Z, 0-9 are ok */
2614  if( isalnum(name[i]) )
2615  continue;
2616 
2617  /* characters in namechars are ok, too */
2618  if( strchr(namechars, name[i]) != NULL )
2619  continue;
2620 
2621  return FALSE;
2622  }
2623 
2624  return TRUE;
2625 }
2626 
2627 
2628 /** method check if the variable names are valid according to PIP specification */
2629 static
2631  SCIP* scip, /**< SCIP data structure */
2632  SCIP_VAR** vars, /**< array of variables */
2633  int nvars /**< number of variables */
2634  )
2635 {
2636  int v;
2637 
2638  assert(scip != NULL);
2639  assert(vars != NULL || nvars == 0);
2640 
2641  /* check if the variable names are not too long and have only characters allowed by PIP */
2642  for( v = 0; v < nvars; ++v )
2643  {
2644  if( !isNameValid(SCIPvarGetName(vars[v])) )
2645  {
2646  SCIPwarningMessage(scip, "variable name <%s> is not valid (too long or disallowed characters); PIP might be corrupted\n", SCIPvarGetName(vars[v]));
2647  return;
2648  }
2649  }
2650 }
2651 
2652 /** method check if the constraint names are valid according to PIP specification */
2653 static
2655  SCIP* scip, /**< SCIP data structure */
2656  SCIP_CONS** conss, /**< array of constraints */
2657  int nconss, /**< number of constraints */
2658  SCIP_Bool transformed /**< TRUE iff problem is the transformed problem */
2659  )
2660 {
2661  int c;
2662  SCIP_CONS* cons;
2663  SCIP_CONSHDLR* conshdlr;
2664  const char* conshdlrname;
2665 
2666  assert( scip != NULL );
2667  assert( conss != NULL || nconss == 0 );
2668 
2669  for( c = 0; c < nconss; ++c )
2670  {
2671  assert(conss != NULL); /* for lint */
2672  cons = conss[c];
2673  assert(cons != NULL );
2674 
2675  /* in case the transformed is written only constraints are posted which are enabled in the current node */
2676  assert(!transformed || SCIPconsIsEnabled(cons));
2677 
2678  conshdlr = SCIPconsGetHdlr(cons);
2679  assert( conshdlr != NULL );
2680 
2681  conshdlrname = SCIPconshdlrGetName(conshdlr);
2682  assert( transformed == SCIPconsIsTransformed(cons) );
2683 
2684  if( !isNameValid(SCIPconsGetName(cons)) )
2685  {
2686  SCIPwarningMessage(scip, "constraint name <%s> is not valid (too long or unallowed characters); PIP might be corrupted\n", SCIPconsGetName(cons));
2687  return;
2688  }
2689 
2690  if( strcmp(conshdlrname, "linear") == 0 )
2691  {
2692  SCIP_Real lhs = SCIPgetLhsLinear(scip, cons);
2693  SCIP_Real rhs = SCIPgetRhsLinear(scip, cons);
2694 
2695  /* for ranged constraints, we need to be able to append _lhs and _rhs to the constraint name, so need additional 4 characters */
2696  if( !SCIPisEQ(scip, lhs, rhs) && strlen(SCIPconsGetName(conss[c])) > (size_t) PIP_MAX_NAMELEN - 4 )
2697  {
2698  SCIPwarningMessage(scip, "name of ranged constraint <%s> has to be cut down to %d characters;\n", SCIPconsGetName(conss[c]),
2699  PIP_MAX_NAMELEN - 1);
2700  return;
2701  }
2702  }
2703  }
2704 }
2705 
2706 /** writes problem to file
2707  * @todo add writing cons_pseudoboolean
2708  */
2710  SCIP* scip, /**< SCIP data structure */
2711  FILE* file, /**< output file, or NULL if standard output should be used */
2712  const char* name, /**< problem name */
2713  SCIP_Bool transformed, /**< TRUE iff problem is the transformed problem */
2714  SCIP_OBJSENSE objsense, /**< objective sense */
2715  SCIP_Real objscale, /**< scalar applied to objective function; external objective value is
2716  * extobj = objsense * objscale * (intobj + objoffset) */
2717  SCIP_Real objoffset, /**< objective offset from bound shifting and fixing */
2718  SCIP_VAR** vars, /**< array with active variables ordered binary, integer, implicit, continuous */
2719  int nvars, /**< number of active variables in the problem */
2720  int nbinvars, /**< number of binary variables */
2721  int nintvars, /**< number of general integer variables */
2722  int nimplvars, /**< number of implicit integer variables */
2723  int ncontvars, /**< number of continuous variables */
2724  SCIP_CONS** conss, /**< array with constraints of the problem */
2725  int nconss, /**< number of constraints in the problem */
2726  SCIP_RESULT* result /**< pointer to store the result of the file writing call */
2727  )
2728 {
2729  int c;
2730  int v;
2731 
2732  int linecnt;
2733  char linebuffer[PIP_MAX_PRINTLEN+1];
2734 
2735  char varname[PIP_MAX_NAMELEN];
2736  char buffer[PIP_MAX_PRINTLEN];
2737 
2738  SCIP_CONSHDLR* conshdlr;
2739  const char* conshdlrname;
2740  SCIP_CONS* cons;
2741  SCIP_CONS** consNonlinear;
2742  int nConsNonlinear;
2743  SCIP_CONS** consAnd;
2744  int nConsAnd;
2745  char consname[PIP_MAX_NAMELEN];
2746 
2747  SCIP_VAR** aggregatedVars;
2748  int nAggregatedVars;
2749  SCIP_HASHTABLE* varAggregated;
2750 
2751  SCIP_VAR** tmpvars;
2752  int tmpvarssize;
2753 
2754  SCIP_VAR** consvars;
2755  SCIP_Real* consvals;
2756  int nconsvars;
2757 
2758  SCIP_VAR* var;
2759  SCIP_Real lb;
2760  SCIP_Real ub;
2761 
2762  assert( scip != NULL );
2763 
2764  nAggregatedVars = 0;
2765  nConsNonlinear = 0;
2766  nConsAnd = 0;
2767 
2768  /* check if the variable names are not to long */
2769  checkVarnames(scip, vars, nvars);
2770 
2771  /* check if the constraint names are to long */
2772  checkConsnames(scip, conss, nconss, transformed);
2773 
2774  /* print statistics as comment to file */
2775  SCIPinfoMessage(scip, file, "\\ SCIP STATISTICS\n");
2776  SCIPinfoMessage(scip, file, "\\ Problem name : %s\n", name);
2777  SCIPinfoMessage(scip, file, "\\ Variables : %d (%d binary, %d integer, %d implicit integer, %d continuous)\n",
2778  nvars, nbinvars, nintvars, nimplvars, ncontvars);
2779  SCIPinfoMessage(scip, file, "\\ Constraints : %d\n", nconss);
2780 
2781  /* print objective sense */
2782  SCIPinfoMessage(scip, file, "%s\n", objsense == SCIP_OBJSENSE_MINIMIZE ? "Minimize" : "Maximize");
2783 
2784  clearLine(linebuffer, &linecnt);
2785  appendLine(scip, file, linebuffer, &linecnt, " Obj:");
2786 
2787  for (v = 0; v < nvars; ++v)
2788  {
2789  var = vars[v];
2790 
2791 #ifndef NDEBUG
2792  /* in case the original problem has to be posted the variables have to be either "original" or "negated" */
2793  if ( !transformed )
2795 #endif
2796 
2797  if ( SCIPisZero(scip, SCIPvarGetObj(var)) )
2798  continue;
2799 
2800  /* we start a new line; therefore we tab this line */
2801  if ( linecnt == 0 )
2802  appendLine(scip, file, linebuffer, &linecnt, " ");
2803 
2804  (void) SCIPsnprintf(varname, PIP_MAX_NAMELEN, "%s", SCIPvarGetName(var));
2805  (void) SCIPsnprintf(buffer, PIP_MAX_PRINTLEN, " %+.15g %s", objscale * SCIPvarGetObj(var), varname );
2806 
2807  appendLine(scip, file, linebuffer, &linecnt, buffer);
2808  }
2809 
2810  if( ! SCIPisZero(scip, objoffset) )
2811  {
2812  (void) SCIPsnprintf(buffer, PIP_MAX_PRINTLEN, " %+.15g", objscale * objoffset);
2813  appendLine(scip, file, linebuffer, &linecnt, buffer);
2814  }
2815 
2816  endLine(scip, file, linebuffer, &linecnt);
2817 
2818  /* print "Subject to" section */
2819  SCIPinfoMessage(scip, file, "Subject to\n");
2820 
2821  /* collect quadratic, nonlinear, absolute power, and, and bivariate constraints in arrays */
2822  SCIP_CALL( SCIPallocBufferArray(scip, &consNonlinear, nconss) );
2823  SCIP_CALL( SCIPallocBufferArray(scip, &consAnd, nconss) );
2824 
2825  tmpvarssize = SCIPgetNTotalVars(scip);
2826  SCIP_CALL( SCIPallocBufferArray(scip, &tmpvars, tmpvarssize) );
2827 
2828  for (c = 0; c < nconss; ++c)
2829  {
2830  cons = conss[c];
2831  assert( cons != NULL);
2832 
2833  /* in case the transformed is written only constraints are posted which are enabled in the current node */
2834  assert(!transformed || SCIPconsIsEnabled(cons));
2835 
2836  conshdlr = SCIPconsGetHdlr(cons);
2837  assert( conshdlr != NULL );
2838 
2839  (void) SCIPsnprintf(consname, PIP_MAX_NAMELEN, "%s", SCIPconsGetName(cons));
2840  conshdlrname = SCIPconshdlrGetName(conshdlr);
2841  assert( transformed == SCIPconsIsTransformed(cons) );
2842 
2843  if( strcmp(conshdlrname, "linear") == 0 )
2844  {
2845  SCIP_CALL( printQuadraticCons(scip, file, consname,
2846  SCIPgetVarsLinear(scip, cons), SCIPgetValsLinear(scip, cons), SCIPgetNVarsLinear(scip, cons),
2847  NULL, SCIPgetLhsLinear(scip, cons), SCIPgetRhsLinear(scip, cons), transformed) );
2848  }
2849  else if( strcmp(conshdlrname, "setppc") == 0 )
2850  {
2851  consvars = SCIPgetVarsSetppc(scip, cons);
2852  nconsvars = SCIPgetNVarsSetppc(scip, cons);
2853 
2854  switch( SCIPgetTypeSetppc(scip, cons) )
2855  {
2857  SCIP_CALL( printQuadraticCons(scip, file, consname,
2858  consvars, NULL, nconsvars, NULL, 1.0, 1.0, transformed) );
2859  break;
2861  SCIP_CALL( printQuadraticCons(scip, file, consname,
2862  consvars, NULL, nconsvars, NULL, -SCIPinfinity(scip), 1.0, transformed) );
2863  break;
2865  SCIP_CALL( printQuadraticCons(scip, file, consname,
2866  consvars, NULL, nconsvars, NULL, 1.0, SCIPinfinity(scip), transformed) );
2867  break;
2868  }
2869  }
2870  else if ( strcmp(conshdlrname, "logicor") == 0 )
2871  {
2872  SCIP_CALL( printQuadraticCons(scip, file, consname,
2873  SCIPgetVarsLogicor(scip, cons), NULL, SCIPgetNVarsLogicor(scip, cons),
2874  NULL, 1.0, SCIPinfinity(scip), transformed) );
2875  }
2876  else if ( strcmp(conshdlrname, "knapsack") == 0 )
2877  {
2878  SCIP_Longint* weights;
2879 
2880  consvars = SCIPgetVarsKnapsack(scip, cons);
2881  nconsvars = SCIPgetNVarsKnapsack(scip, cons);
2882 
2883  /* copy Longint array to SCIP_Real array */
2884  weights = SCIPgetWeightsKnapsack(scip, cons);
2885  SCIP_CALL( SCIPallocBufferArray(scip, &consvals, nconsvars) );
2886  for( v = 0; v < nconsvars; ++v )
2887  consvals[v] = (SCIP_Real)weights[v];
2888 
2889  SCIP_CALL( printQuadraticCons(scip, file, consname, consvars, consvals, nconsvars,
2890  NULL, -SCIPinfinity(scip), (SCIP_Real) SCIPgetCapacityKnapsack(scip, cons), transformed) );
2891 
2892  SCIPfreeBufferArray(scip, &consvals);
2893  }
2894  else if ( strcmp(conshdlrname, "varbound") == 0 )
2895  {
2896  SCIP_CALL( SCIPallocBufferArray(scip, &consvars, 2) );
2897  SCIP_CALL( SCIPallocBufferArray(scip, &consvals, 2) );
2898 
2899  consvars[0] = SCIPgetVarVarbound(scip, cons);
2900  consvars[1] = SCIPgetVbdvarVarbound(scip, cons);
2901 
2902  consvals[0] = 1.0;
2903  consvals[1] = SCIPgetVbdcoefVarbound(scip, cons);
2904 
2905  SCIP_CALL( printQuadraticCons(scip, file, consname, consvars, consvals, 2, NULL,
2906  SCIPgetLhsVarbound(scip, cons), SCIPgetRhsVarbound(scip, cons), transformed) );
2907 
2908  SCIPfreeBufferArray(scip, &consvars);
2909  SCIPfreeBufferArray(scip, &consvals);
2910  }
2911  else if( strcmp(conshdlrname, "nonlinear") == 0 )
2912  {
2913  SCIP_Bool ispolynomial;
2914  SCIP_Bool isquadratic;
2915  SCIP_EXPR* simplifiedexpr = NULL;
2916 
2917  ispolynomial = isExprPolynomial(scip, SCIPgetExprNonlinear(cons));
2918  if( !ispolynomial )
2919  {
2920  /* simplify expression and check again if polynomial
2921  * simplifying the expr owned by the cons can have undesired sideffects onto the consdata (the varhashmap can get messed up), so we copy first
2922  */
2923  SCIP_EXPR* exprcopy;
2924  SCIP_Bool changed;
2925  SCIP_Bool infeasible;
2926 
2927  SCIP_CALL( SCIPduplicateExpr(scip, SCIPgetExprNonlinear(cons), &exprcopy, NULL, NULL, NULL, NULL) );
2928  SCIP_CALL( SCIPsimplifyExpr(scip, exprcopy, &simplifiedexpr, &changed, &infeasible, NULL, NULL) );
2929  SCIP_CALL( SCIPreleaseExpr(scip, &exprcopy) );
2930 
2931  ispolynomial = isExprPolynomial(scip, simplifiedexpr);
2932  }
2933 
2934  /* nonlinear constraints that are not polynomial cannot be printed as PIP */
2935  if( !ispolynomial )
2936  {
2937  SCIPwarningMessage(scip, "nonlinear constraint <%s> is not polynomial\n", SCIPconsGetName(cons));
2938  SCIPinfoMessage(scip, file, "\\ ");
2939  SCIP_CALL( SCIPprintCons(scip, cons, file) );
2940  SCIPinfoMessage(scip, file, ";\n");
2941 
2942  SCIP_CALL( SCIPreleaseExpr(scip, &simplifiedexpr) );
2943  return SCIP_OKAY;
2944  }
2945 
2946  /* check whether constraint is even quadratic
2947  * (we could also skip this and print as polynomial, but the code exists already)
2948  */
2949  SCIP_CALL( SCIPcheckExprQuadratic(scip, simplifiedexpr != NULL ? simplifiedexpr : SCIPgetExprNonlinear(cons), &isquadratic) );
2950  if( isquadratic )
2951  isquadratic = SCIPexprAreQuadraticExprsVariables(simplifiedexpr != NULL ? simplifiedexpr : SCIPgetExprNonlinear(cons));
2952 
2953  if( isquadratic )
2954  {
2955  SCIP_CALL( printQuadraticCons(scip, file, consname, NULL, NULL, 0, simplifiedexpr != NULL ? simplifiedexpr : SCIPgetExprNonlinear(cons),
2956  SCIPgetLhsNonlinear(cons), SCIPgetRhsNonlinear(cons), transformed) );
2957  }
2958  else
2959  {
2960  SCIP_CALL( printNonlinearCons(scip, file, consname, simplifiedexpr != NULL ? simplifiedexpr : SCIPgetExprNonlinear(cons), SCIPgetLhsNonlinear(cons), SCIPgetRhsNonlinear(cons)) );
2961  }
2962 
2963  consNonlinear[nConsNonlinear++] = cons;
2964 
2965  if( simplifiedexpr != NULL )
2966  {
2967  SCIP_CALL( SCIPreleaseExpr(scip, &simplifiedexpr) );
2968  }
2969  }
2970  else if( strcmp(conshdlrname, "and") == 0 )
2971  {
2972  printRowAnd(scip, file, consname, cons);
2973 
2974  consAnd[nConsAnd++] = cons;
2975  }
2976  else
2977  {
2978  SCIPwarningMessage(scip, "constraint handler <%s> cannot print requested format\n", conshdlrname );
2979  SCIPinfoMessage(scip, file, "\\ ");
2980  SCIP_CALL( SCIPprintCons(scip, cons, file) );
2981  SCIPinfoMessage(scip, file, ";\n");
2982  }
2983  }
2984 
2985  /* create hashtable for storing aggregated variables */
2986  SCIP_CALL( SCIPallocBufferArray(scip, &aggregatedVars, nvars) );
2987  SCIP_CALL( SCIPhashtableCreate(&varAggregated, SCIPblkmem(scip), nvars/10, hashGetKeyVar, hashKeyEqVar, hashKeyValVar, NULL) );
2988 
2989  /* check for aggregated variables in nonlinear constraints and output aggregations as linear constraints */
2990  for( c = 0; c < nConsNonlinear; ++c )
2991  {
2992  SCIP_Bool success;
2993  int ntmpvars;
2994 
2995  /* get variables of the nonlinear constraint */
2996  SCIP_CALL( SCIPgetConsNVars(scip, consNonlinear[c], &ntmpvars, &success) );
2997  assert(success);
2998  if( ntmpvars > tmpvarssize )
2999  {
3000  tmpvarssize = SCIPcalcMemGrowSize(scip, ntmpvars);
3001  SCIP_CALL( SCIPreallocBufferArray(scip, &tmpvars, tmpvarssize) );
3002  }
3003  SCIP_CALL( SCIPgetConsVars(scip, consNonlinear[c], tmpvars, tmpvarssize, &success) );
3004  assert(success);
3005 
3006  SCIP_CALL( collectAggregatedVars(ntmpvars, tmpvars, &nAggregatedVars, &aggregatedVars, &varAggregated) );
3007  }
3008 
3009  /* check for aggregated variables in and constraints and output aggregations as linear constraints */
3010  for (c = 0; c < nConsAnd; ++c)
3011  {
3012  SCIP_VAR* resultant;
3013 
3014  cons = consAnd[c];
3015 
3016  SCIP_CALL( collectAggregatedVars(SCIPgetNVarsAnd(scip, cons), SCIPgetVarsAnd(scip, cons), &nAggregatedVars, &aggregatedVars, &varAggregated) );
3017 
3018  resultant = SCIPgetResultantAnd(scip, cons);
3019  SCIP_CALL( collectAggregatedVars(1, &resultant, &nAggregatedVars, &aggregatedVars, &varAggregated) );
3020  }
3021 
3022  /* print aggregation constraints */
3023  SCIP_CALL( printAggregatedCons(scip, file, transformed, nvars, nAggregatedVars, aggregatedVars) );
3024 
3025  /* print "Bounds" section */
3026  SCIPinfoMessage(scip, file, "Bounds\n");
3027  for (v = 0; v < nvars; ++v)
3028  {
3029  var = vars[v];
3030  assert( var != NULL );
3031  (void) SCIPsnprintf(varname, PIP_MAX_NAMELEN, "%s", SCIPvarGetName(var) );
3032 
3033  if( transformed )
3034  {
3035  /* in case the transformed is written only local bounds are posted which are valid in the current node */
3036  lb = SCIPvarGetLbLocal(var);
3037  ub = SCIPvarGetUbLocal(var);
3038  }
3039  else
3040  {
3041  lb = SCIPvarGetLbOriginal(var);
3042  ub = SCIPvarGetUbOriginal(var);
3043  }
3044 
3045  if ( SCIPisInfinity(scip, -lb) && SCIPisInfinity(scip, ub) )
3046  SCIPinfoMessage(scip, file, " %s free\n", varname);
3047  else
3048  {
3049  /* print lower bound */
3050  if ( SCIPisInfinity(scip, -lb) )
3051  SCIPinfoMessage(scip, file, " -inf <= ");
3052  else
3053  {
3054  if ( SCIPisZero(scip, lb) )
3055  {
3056  /* variables are nonnegative by default - so we skip these variables */
3057  if ( SCIPisInfinity(scip, ub) )
3058  continue;
3059  lb = 0.0;
3060  }
3061 
3062  SCIPinfoMessage(scip, file, " %.15g <= ", lb);
3063  }
3064  /* print variable name */
3065  SCIPinfoMessage(scip, file, "%s", varname);
3066 
3067  /* print upper bound as far this one is not infinity */
3068  if( !SCIPisInfinity(scip, ub) )
3069  SCIPinfoMessage(scip, file, " <= %.15g", ub);
3070 
3071  SCIPinfoMessage(scip, file, "\n");
3072  }
3073  }
3074 
3075  /* output aggregated variables as 'free' */
3076  for (v = 0; v < nAggregatedVars; ++v)
3077  {
3078  var = aggregatedVars[v];
3079  assert( var != NULL );
3080  (void) SCIPsnprintf(varname, PIP_MAX_NAMELEN, "%s", SCIPvarGetName(var) );
3081 
3082  SCIPinfoMessage(scip, file, " %s free\n", varname);
3083  }
3084 
3085  /* free space */
3086  SCIPfreeBufferArray(scip, &aggregatedVars);
3087  SCIPhashtableFree(&varAggregated);
3088 
3089  /* print binaries section */
3090  if ( nbinvars > 0 )
3091  {
3092  SCIPinfoMessage(scip, file, "Binaries\n");
3093 
3094  clearLine(linebuffer, &linecnt);
3095 
3096  for (v = 0; v < nvars; ++v)
3097  {
3098  var = vars[v];
3099  assert( var != NULL );
3100 
3101  if ( SCIPvarGetType(var) == SCIP_VARTYPE_BINARY )
3102  {
3103  (void) SCIPsnprintf(varname, PIP_MAX_NAMELEN, "%s", SCIPvarGetName(var) );
3104  (void) SCIPsnprintf(buffer, PIP_MAX_PRINTLEN, " %s", varname);
3105  appendLine(scip, file, linebuffer, &linecnt, buffer);
3106  }
3107  }
3108 
3109  endLine(scip, file, linebuffer, &linecnt);
3110  }
3111 
3112  /* print generals section */
3113  if ( nintvars > 0 )
3114  {
3115  SCIPinfoMessage(scip, file, "Generals\n");
3116 
3117  for (v = 0; v < nvars; ++v)
3118  {
3119  var = vars[v];
3120  assert( var != NULL );
3121 
3122  if ( SCIPvarGetType(var) == SCIP_VARTYPE_INTEGER )
3123  {
3124  (void) SCIPsnprintf(varname, PIP_MAX_NAMELEN, "%s", SCIPvarGetName(var) );
3125  (void) SCIPsnprintf(buffer, PIP_MAX_PRINTLEN, " %s", varname);
3126  appendLine(scip, file, linebuffer, &linecnt, buffer);
3127  }
3128  }
3129  endLine(scip, file, linebuffer, &linecnt);
3130  }
3131 
3132  /* free space */
3133  SCIPfreeBufferArray(scip, &tmpvars);
3134  SCIPfreeBufferArray(scip, &consNonlinear);
3135  SCIPfreeBufferArray(scip, &consAnd);
3136 
3137  /* end of lp format */
3138  SCIPinfoMessage(scip, file, "%s\n", "End");
3139 
3140  *result = SCIP_SUCCESS;
3141 
3142  return SCIP_OKAY;
3143 }
3144 
3145 /*
3146  * Callback methods of reader
3147  */
3148 
3149 /** copy method for reader plugins (called when SCIP copies plugins) */
3150 static
3151 SCIP_DECL_READERCOPY(readerCopyPip)
3152 { /*lint --e{715}*/
3153  assert(scip != NULL);
3154  assert(reader != NULL);
3155  assert(strcmp(SCIPreaderGetName(reader), READER_NAME) == 0);
3156 
3157  /* call inclusion method of reader */
3159 
3160  return SCIP_OKAY;
3161 }
3162 
3163 
3164 /** problem reading method of reader */
3165 static
3166 SCIP_DECL_READERREAD(readerReadPip)
3167 { /*lint --e{715}*/
3168 
3169  SCIP_CALL( SCIPreadPip(scip, reader, filename, result) );
3170 
3171  return SCIP_OKAY;
3172 }
3173 
3174 
3175 /** problem writing method of reader */
3176 static
3177 SCIP_DECL_READERWRITE(readerWritePip)
3178 { /*lint --e{715}*/
3179  SCIP_CALL( SCIPwritePip(scip, file, name, transformed, objsense, objscale, objoffset, vars,
3180  nvars, nbinvars, nintvars, nimplvars, ncontvars, conss, nconss, result) );
3181 
3182  return SCIP_OKAY;
3183 }
3184 
3185 
3186 /*
3187  * reader specific interface methods
3188  */
3189 
3190 /** includes the pip file reader in SCIP */
3192  SCIP* scip /**< SCIP data structure */
3193  )
3194 {
3195  SCIP_READER* reader;
3196 
3197  /* include reader */
3199 
3200  /* set non fundamental callbacks via setter functions */
3201  SCIP_CALL( SCIPsetReaderCopy(scip, reader, readerCopyPip) );
3202  SCIP_CALL( SCIPsetReaderRead(scip, reader, readerReadPip) );
3203  SCIP_CALL( SCIPsetReaderWrite(scip, reader, readerWritePip) );
3204 
3205  return SCIP_OKAY;
3206 }
3207 
3208 
3209 /** reads problem from file */
3211  SCIP* scip, /**< SCIP data structure */
3212  SCIP_READER* reader, /**< the file reader itself */
3213  const char* filename, /**< full path and name of file to read, or NULL if stdin should be used */
3214  SCIP_RESULT* result /**< pointer to store the result of the file reading call */
3215  )
3216 { /*lint --e{715}*/
3217  PIPINPUT pipinput;
3218  SCIP_RETCODE retcode;
3219  int i;
3220 
3221  assert(scip != NULL); /* for lint */
3222  assert(reader != NULL);
3223 
3224  /* initialize PIP input data */
3225  pipinput.file = NULL;
3226  pipinput.linebuf[0] = '\0';
3227  pipinput.probname[0] = '\0';
3228  pipinput.objname[0] = '\0';
3229  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &pipinput.token, PIP_MAX_LINELEN) ); /*lint !e506*/
3230  pipinput.token[0] = '\0';
3231  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &pipinput.tokenbuf, PIP_MAX_LINELEN) ); /*lint !e506*/
3232  pipinput.tokenbuf[0] = '\0';
3233  for( i = 0; i < PIP_MAX_PUSHEDTOKENS; ++i )
3234  {
3235  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &((pipinput.pushedtokens)[i]), PIP_MAX_LINELEN) ); /*lint !e866 !e506*/
3236  }
3237 
3238  pipinput.npushedtokens = 0;
3239  pipinput.linenumber = 0;
3240  pipinput.linepos = 0;
3241  pipinput.section = PIP_START;
3242  pipinput.objsense = SCIP_OBJSENSE_MINIMIZE;
3243  pipinput.haserror = FALSE;
3244 
3245  SCIP_CALL( SCIPgetBoolParam(scip, "reading/initialconss", &(pipinput.initialconss)) );
3246  SCIP_CALL( SCIPgetBoolParam(scip, "reading/dynamicconss", &(pipinput.dynamicconss)) );
3247  SCIP_CALL( SCIPgetBoolParam(scip, "reading/dynamiccols", &(pipinput.dynamiccols)) );
3248  SCIP_CALL( SCIPgetBoolParam(scip, "reading/dynamicrows", &(pipinput.dynamicrows)) );
3249 
3250  /* read the file */
3251  retcode = readPIPFile(scip, &pipinput, filename);
3252 
3253  /* free dynamically allocated memory */
3254  for( i = PIP_MAX_PUSHEDTOKENS - 1; i >= 0 ; --i )
3255  {
3256  SCIPfreeBlockMemoryArray(scip, &pipinput.pushedtokens[i], PIP_MAX_LINELEN);
3257  }
3258  SCIPfreeBlockMemoryArray(scip, &pipinput.tokenbuf, PIP_MAX_LINELEN);
3259  SCIPfreeBlockMemoryArray(scip, &pipinput.token, PIP_MAX_LINELEN);
3260 
3261  if( retcode == SCIP_PLUGINNOTFOUND )
3262  retcode = SCIP_READERROR;
3263 
3264  /* evaluate the result */
3265  if( pipinput.haserror )
3266  retcode = SCIP_READERROR;
3267  else
3268  {
3269  /* set objective sense */
3270  SCIP_CALL( SCIPsetObjsense(scip, pipinput.objsense) );
3271  *result = SCIP_SUCCESS;
3272  }
3273 
3274  SCIP_CALL( retcode );
3275 
3276  return SCIP_OKAY;
3277 }
enum SCIP_Result SCIP_RESULT
Definition: type_result.h:61
#define SCIPfreeBlockMemoryArray(scip, ptr, num)
Definition: scip_mem.h:110
void SCIPexprGetQuadraticData(SCIP_EXPR *expr, SCIP_Real *constant, int *nlinexprs, SCIP_EXPR ***linexprs, SCIP_Real **lincoefs, int *nquadexprs, int *nbilinexprs, SCIP_Real **eigenvalues, SCIP_Real **eigenvectors)
Definition: expr.c:4067
static SCIP_DECL_HASHGETKEY(hashGetKeyVar)
Definition: reader_pip.c:1718
SCIP_Bool SCIPconsIsEnabled(SCIP_CONS *cons)
Definition: cons.c:8191
#define SCIPallocBlockMemoryArray(scip, ptr, num)
Definition: scip_mem.h:93
SCIP_RETCODE SCIPsimplifyExpr(SCIP *scip, SCIP_EXPR *rootexpr, SCIP_EXPR **simplified, SCIP_Bool *changed, SCIP_Bool *infeasible, SCIP_DECL_EXPR_OWNERCREATE((*ownercreate)), void *ownercreatedata)
Definition: scip_expr.c:1773
public methods for SCIP parameter handling
SCIP_RETCODE SCIPprintExpr(SCIP *scip, SCIP_EXPR *expr, FILE *file)
Definition: scip_expr.c:1485
static void printSignomial(SCIP *scip, FILE *file, char *linebuffer, int *linecnt, SCIP_EXPR *expr, SCIP_Real coef, SCIP_Bool needsign)
Definition: reader_pip.c:2156
#define PIP_INIT_MONOMIALSSIZE
Definition: reader_pip.c:81
Constraint handler for variable bound constraints .
#define PIP_INIT_FACTORSSIZE
Definition: reader_pip.c:82
SCIP_RETCODE SCIPhashtableInsert(SCIP_HASHTABLE *hashtable, void *element)
Definition: misc.c:2496
public methods for memory management
int SCIPexprGetNChildren(SCIP_EXPR *expr)
Definition: expr.c:3808
int SCIPgetNVarsSetppc(SCIP *scip, SCIP_CONS *cons)
Definition: cons_setppc.c:9408
#define PIP_MAX_NAMELEN
Definition: reader_pip.c:84
SCIP_Real SCIPgetLhsVarbound(SCIP *scip, SCIP_CONS *cons)
SCIP_Real SCIPvarGetLbGlobal(SCIP_VAR *var)
Definition: var.c:17919
int SCIPgetNVarsLogicor(SCIP *scip, SCIP_CONS *cons)
SCIP_RETCODE SCIPreadPip(SCIP *scip, SCIP_READER *reader, const char *filename, SCIP_RESULT *result)
Definition: reader_pip.c:3210
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:117
static SCIP_RETCODE printRow(SCIP *scip, FILE *file, const char *rowname, const char *rownameextension, const char *type, SCIP_VAR **linvars, SCIP_Real *linvals, int nlinvars, SCIP_EXPR *quadexpr, SCIP_Real rhs, SCIP_Bool transformed)
Definition: reader_pip.c:1924
PipSense
Definition: reader_pip.c:108
int SCIPcalcMemGrowSize(SCIP *scip, int num)
Definition: scip_mem.c:139
static SCIP_RETCODE printAggregatedCons(SCIP *scip, FILE *file, SCIP_Bool transformed, int nvars, int nAggregatedVars, SCIP_VAR **aggregatedVars)
Definition: reader_pip.c:2533
static SCIP_RETCODE readConstraints(SCIP *scip, PIPINPUT *pipinput)
Definition: reader_pip.c:1229
SCIP_Real SCIPvarGetLbLocal(SCIP_VAR *var)
Definition: var.c:17975
SCIP_Real SCIPgetConstantExprSum(SCIP_EXPR *expr)
Definition: expr_sum.c:1181
#define PIP_MAX_PUSHEDTOKENS
Definition: reader_pip.c:80
SCIP_Real SCIPgetRhsNonlinear(SCIP_CONS *cons)
static SCIP_RETCODE readObjective(SCIP *scip, PIPINPUT *pipinput)
Definition: reader_pip.c:1098
const char * SCIPreaderGetName(SCIP_READER *reader)
Definition: reader.c:557
SCIP_RETCODE SCIPreleaseVar(SCIP *scip, SCIP_VAR **var)
Definition: scip_var.c:1254
SCIP_RETCODE SCIPcheckExprQuadratic(SCIP *scip, SCIP_EXPR *expr, SCIP_Bool *isquadratic)
Definition: scip_expr.c:2351
static void endLine(SCIP *scip, FILE *file, char *linebuffer, int *linecnt)
Definition: reader_pip.c:1870
#define FALSE
Definition: def.h:96
SCIP_RETCODE SCIPduplicateExpr(SCIP *scip, SCIP_EXPR *expr, SCIP_EXPR **copyexpr, SCIP_DECL_EXPR_MAPEXPR((*mapexpr)), void *mapexprdata, SCIP_DECL_EXPR_OWNERCREATE((*ownercreate)), void *ownercreatedata)
Definition: scip_expr.c:1280
SCIP_Real SCIPinfinity(SCIP *scip)
int SCIPsnprintf(char *t, int len, const char *s,...)
Definition: misc.c:10764
SCIP_Real SCIPgetExponentExprPow(SCIP_EXPR *expr)
Definition: expr_pow.c:3352
#define TRUE
Definition: def.h:95
enum SCIP_Retcode SCIP_RETCODE
Definition: type_retcode.h:63
static void checkVarnames(SCIP *scip, SCIP_VAR **vars, int nvars)
Definition: reader_pip.c:2630
static SCIP_RETCODE printNonlinearCons(SCIP *scip, FILE *file, const char *rowname, SCIP_EXPR *expr, SCIP_Real lhs, SCIP_Real rhs)
Definition: reader_pip.c:2449
enum SCIP_Varstatus SCIP_VARSTATUS
Definition: type_var.h:57
#define READER_DESC
Definition: reader_pip.c:72
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:194
#define READER_NAME
Definition: reader_pip.c:71
SCIP_Bool SCIPconsIsTransformed(SCIP_CONS *cons)
Definition: cons.c:8403
public methods for problem variables
PipSection
Definition: reader_pip.c:88
SCIP_VAR ** SCIPgetVarsKnapsack(SCIP *scip, SCIP_CONS *cons)
static SCIP_Bool isValueChar(char c, char nextc, SCIP_Bool firstchar, SCIP_Bool *hasdot, PIPEXPTYPE *exptype)
Definition: reader_pip.c:208
static SCIP_RETCODE readBounds(SCIP *scip, PIPINPUT *pipinput)
Definition: reader_pip.c:1398
Constraint handler for AND constraints, .
static SCIP_RETCODE printQuadraticCons(SCIP *scip, FILE *file, const char *rowname, SCIP_VAR **linvars, SCIP_Real *linvals, int nlinvars, SCIP_EXPR *quadexpr, SCIP_Real lhs, SCIP_Real rhs, SCIP_Bool transformed)
Definition: reader_pip.c:2362
#define SCIPduplicateBufferArray(scip, ptr, source, num)
Definition: scip_mem.h:132
struct PipInput PIPINPUT
Definition: reader_pip.c:138
SCIP_RETCODE SCIPchgVarLb(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound)
Definition: scip_var.c:4682
SCIP_Bool SCIPisEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
#define READER_EXTENSION
Definition: reader_pip.c:73
SCIP_RETCODE SCIPcreateExprVar(SCIP *scip, SCIP_EXPR **expr, SCIP_VAR *var, SCIP_DECL_EXPR_OWNERCREATE((*ownercreate)), void *ownercreatedata)
Definition: expr_var.c:390
#define SCIPfreeBufferArray(scip, ptr)
Definition: scip_mem.h:136
SCIP_VAR * SCIPgetVarVarbound(SCIP *scip, SCIP_CONS *cons)
Constraint handler for the set partitioning / packing / covering constraints .
#define SCIPdebugPrintCons(x, y, z)
Definition: pub_message.h:102
variable expression handler
public methods for SCIP variables
SCIP_RETCODE SCIPappendExprSumExpr(SCIP *scip, SCIP_EXPR *expr, SCIP_EXPR *child, SCIP_Real childcoef)
Definition: expr_sum.c:1116
#define PIP_PRINTLEN
Definition: reader_pip.c:85
SCIP_Bool SCIPexprAreQuadraticExprsVariables(SCIP_EXPR *expr)
Definition: expr.c:4195
void SCIPwarningMessage(SCIP *scip, const char *formatstr,...)
Definition: scip_message.c:120
#define SCIPdebugMsg
Definition: scip_message.h:78
#define PIP_MAX_PRINTLEN
Definition: reader_pip.c:83
SCIP_RETCODE SCIPcreateExprSum(SCIP *scip, SCIP_EXPR **expr, int nchildren, SCIP_EXPR **children, SCIP_Real *coefficients, SCIP_Real constant, SCIP_DECL_EXPR_OWNERCREATE((*ownercreate)), void *ownercreatedata)
Definition: expr_sum.c:1079
SCIP_Real SCIPgetRhsLinear(SCIP *scip, SCIP_CONS *cons)
int SCIPstrncpy(char *t, const char *s, int size)
Definition: misc.c:10807
static SCIP_Bool hasError(PIPINPUT *pipinput)
Definition: reader_pip.c:179
void SCIPinfoMessage(SCIP *scip, FILE *file, const char *formatstr,...)
Definition: scip_message.c:208
SCIP_Bool SCIPisExprProduct(SCIP *scip, SCIP_EXPR *expr)
Definition: scip_expr.c:1463
public methods for numerical tolerances
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:2245
public functions to work with algebraic expressions
static void appendLine(SCIP *scip, FILE *file, char *linebuffer, int *linecnt, const char *extension)
Definition: reader_pip.c:1893
static SCIP_RETCODE getVariable(SCIP *scip, char *name, SCIP_Bool dynamiccols, SCIP_VAR **var, SCIP_Bool *created)
Definition: reader_pip.c:668
SCIP_VAR * SCIPfindVar(SCIP *scip, const char *name)
Definition: scip_prob.c:2693
SCIP_RETCODE SCIPchgVarType(SCIP *scip, SCIP_VAR *var, SCIP_VARTYPE vartype, SCIP_Bool *infeasible)
Definition: scip_var.c:8182
SCIP_FILE * SCIPfopen(const char *path, const char *mode)
Definition: fileio.c:153
enum PipSection PIPSECTION
Definition: reader_pip.c:98
SCIP_EXPR ** SCIPexprGetChildren(SCIP_EXPR *expr)
Definition: expr.c:3818
SCIP_Real SCIPvarGetUbGlobal(SCIP_VAR *var)
Definition: var.c:17929
static const char delimchars[]
Definition: reader_pip.c:140
public methods for managing constraints
SCIP_RETCODE SCIPsetObjsense(SCIP *scip, SCIP_OBJSENSE objsense)
Definition: scip_prob.c:1250
Constraint handler for knapsack constraints of the form , x binary and .
SCIP_Real SCIPgetRhsVarbound(SCIP *scip, SCIP_CONS *cons)
static const char tokenchars[]
Definition: reader_pip.c:141
SCIP_VAR ** SCIPgetVarsAnd(SCIP *scip, SCIP_CONS *cons)
Definition: cons_and.c:5181
SCIP_Real * SCIPgetCoefsExprSum(SCIP_EXPR *expr)
Definition: expr_sum.c:1166
static const char namechars[]
Definition: reader_pip.c:143
#define SCIPerrorMessage
Definition: pub_message.h:64
const char * SCIPconshdlrGetName(SCIP_CONSHDLR *conshdlr)
Definition: cons.c:4184
SCIP_RETCODE SCIPgetConsNVars(SCIP *scip, SCIP_CONS *cons, int *nvars, SCIP_Bool *success)
Definition: scip_cons.c:2567
SCIP_RETCODE SCIPaddCons(SCIP *scip, SCIP_CONS *cons)
Definition: scip_prob.c:2778
SCIP_Real SCIPvarGetLbOriginal(SCIP_VAR *var)
Definition: var.c:17865
SCIP_VAR * SCIPgetResultantAnd(SCIP *scip, SCIP_CONS *cons)
Definition: cons_and.c:5206
SCIP_VAR * SCIPgetVarExprVar(SCIP_EXPR *expr)
Definition: expr_var.c:416
Constraint handler for logicor constraints (equivalent to set covering, but algorithms are suited fo...
SCIP_Real SCIPvarGetUbOriginal(SCIP_VAR *var)
Definition: var.c:17885
SCIP_RETCODE SCIPcreateExprMonomial(SCIP *scip, SCIP_EXPR **expr, int nfactors, SCIP_VAR **vars, SCIP_Real *exponents, SCIP_DECL_EXPR_OWNERCREATE((*ownercreate)), void *ownercreatedata)
Definition: scip_expr.c:1140
BMS_BLKMEM * SCIPblkmem(SCIP *scip)
Definition: scip_mem.c:57
struct SCIP_File SCIP_FILE
Definition: pub_fileio.h:43
char * SCIPfgets(char *s, int size, SCIP_FILE *stream)
Definition: fileio.c:200
const char * SCIPconsGetName(SCIP_CONS *cons)
Definition: cons.c:8094
SCIP_RETCODE SCIPchgVarUb(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound)
Definition: scip_var.c:4772
SCIP_Bool SCIPisExprValue(SCIP *scip, SCIP_EXPR *expr)
Definition: scip_expr.c:1441
SCIP_VAR ** SCIPgetVarsLogicor(SCIP *scip, SCIP_CONS *cons)
static void printRowNl(SCIP *scip, FILE *file, const char *rowname, const char *rownameextension, const char *type, SCIP_EXPR *expr, SCIP_Real rhs)
Definition: reader_pip.c:2246
#define PIP_MAX_LINELEN
Definition: reader_pip.c:79
const char * SCIPvarGetName(SCIP_VAR *var)
Definition: var.c:17260
SCIP_RETCODE SCIPgetBoolParam(SCIP *scip, const char *name, SCIP_Bool *value)
Definition: scip_param.c:250
SCIP_EXPR * SCIPgetExprNonlinear(SCIP_CONS *cons)
static void checkConsnames(SCIP *scip, SCIP_CONS **conss, int nconss, SCIP_Bool transformed)
Definition: reader_pip.c:2654
static SCIP_Bool isValue(SCIP *scip, PIPINPUT *pipinput, SCIP_Real *value)
Definition: reader_pip.c:605
void SCIPexprGetQuadraticQuadTerm(SCIP_EXPR *quadexpr, int termidx, SCIP_EXPR **expr, SCIP_Real *lincoef, SCIP_Real *sqrcoef, int *nadjbilin, int **adjbilin, SCIP_EXPR **sqrexpr)
Definition: expr.c:4114
#define NULL
Definition: lpi_spx1.cpp:164
file reader for polynomial mixed-integer programs in PIP format
#define REALABS(x)
Definition: def.h:210
SCIP_Bool SCIPisExprSum(SCIP *scip, SCIP_EXPR *expr)
Definition: scip_expr.c:1452
#define SCIP_CALL(x)
Definition: def.h:393
int SCIPgetNTotalVars(SCIP *scip)
Definition: scip_prob.c:2577
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:1744
static SCIP_DECL_READERWRITE(readerWritePip)
Definition: reader_pip.c:3177
static void swapPointers(char **pointer1, char **pointer2)
Definition: reader_pip.c:297
void SCIPverbMessage(SCIP *scip, SCIP_VERBLEVEL msgverblevel, FILE *file, const char *formatstr,...)
Definition: scip_message.c:225
static SCIP_Bool isSense(PIPINPUT *pipinput, PIPSENSE *sense)
Definition: reader_pip.c:637
SCIP_RETCODE SCIPgetConsVars(SCIP *scip, SCIP_CONS *cons, SCIP_VAR **vars, int varssize, SCIP_Bool *success)
Definition: scip_cons.c:2523
public methods for constraint handler plugins and constraints
public methods for NLP management
SCIP_Real SCIPgetCoefExprProduct(SCIP_EXPR *expr)
SCIP_Longint SCIPgetCapacityKnapsack(SCIP *scip, SCIP_CONS *cons)
wrapper functions to map file i/o to standard or zlib file i/o
static SCIP_Bool isDelimChar(char c)
Definition: reader_pip.c:190
SCIP_RETCODE SCIPchgVarObj(SCIP *scip, SCIP_VAR *var, SCIP_Real newobj)
Definition: scip_var.c:4519
SCIP_VAR * SCIPgetVbdvarVarbound(SCIP *scip, SCIP_CONS *cons)
#define SCIPallocBufferArray(scip, ptr, num)
Definition: scip_mem.h:124
static SCIP_Bool isNewSection(SCIP *scip, PIPINPUT *pipinput)
Definition: reader_pip.c:447
public data structures and miscellaneous methods
static SCIP_DECL_HASHKEYVAL(hashKeyValVar)
Definition: reader_pip.c:1734
#define SCIP_Bool
Definition: def.h:93
SCIP_RETCODE SCIPincludeReaderBasic(SCIP *scip, SCIP_READER **readerptr, const char *name, const char *desc, const char *extension, SCIP_READERDATA *readerdata)
Definition: scip_reader.c:109
void SCIPprintSysError(const char *message)
Definition: misc.c:10673
enum PipSense PIPSENSE
Definition: reader_pip.c:115
enum SCIP_Objsense SCIP_OBJSENSE
Definition: type_prob.h:50
enum PipExpType PIPEXPTYPE
Definition: reader_pip.c:106
SCIP_RETCODE SCIPreleaseExpr(SCIP *scip, SCIP_EXPR **expr)
Definition: scip_expr.c:1416
SCIP_SETPPCTYPE SCIPgetTypeSetppc(SCIP *scip, SCIP_CONS *cons)
Definition: cons_setppc.c:9454
constraint handler for nonlinear constraints specified by algebraic expressions
SCIP_RETCODE SCIPprintCons(SCIP *scip, SCIP_CONS *cons, FILE *file)
Definition: scip_cons.c:2482
static void pushToken(PIPINPUT *pipinput)
Definition: reader_pip.c:410
SCIP_CONSHDLR * SCIPconsGetHdlr(SCIP_CONS *cons)
Definition: cons.c:8114
static void pushBufferToken(PIPINPUT *pipinput)
Definition: reader_pip.c:423
SCIP_Real SCIPvarGetObj(SCIP_VAR *var)
Definition: var.c:17767
static void printRowAnd(SCIP *scip, FILE *file, const char *rowname, SCIP_CONS *cons)
Definition: reader_pip.c:2314
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:114
static SCIP_Bool isSign(PIPINPUT *pipinput, int *sign)
Definition: reader_pip.c:580
SCIP_RETCODE SCIPsetReaderWrite(SCIP *scip, SCIP_READER *reader, SCIP_DECL_READERWRITE((*readerwrite)))
Definition: scip_reader.c:219
SCIP_Real SCIPgetVbdcoefVarbound(SCIP *scip, SCIP_CONS *cons)
static SCIP_RETCODE ensureFactorsSize(SCIP *scip, SCIP_VAR ***vars, SCIP_Real **exponents, int *factorssize, int minnfactors)
Definition: reader_pip.c:772
static void swapTokenBuffer(PIPINPUT *pipinput)
Definition: reader_pip.c:436
SCIP_RETCODE SCIPincludeReaderPip(SCIP *scip)
Definition: reader_pip.c:3191
Constraint handler for linear constraints in their most general form, .
SCIP_Bool SCIPisExprPower(SCIP *scip, SCIP_EXPR *expr)
Definition: scip_expr.c:1474
SCIP_Bool SCIPisInfinity(SCIP *scip, SCIP_Real val)
static SCIP_RETCODE readPIPFile(SCIP *scip, PIPINPUT *pipinput, const char *filename)
Definition: reader_pip.c:1648
SCIP_RETCODE SCIPvarGetOrigvarSum(SCIP_VAR **var, SCIP_Real *scalar, SCIP_Real *constant)
Definition: var.c:12782
static SCIP_DECL_READERCOPY(readerCopyPip)
Definition: reader_pip.c:3151
static SCIP_RETCODE ensureMonomialsSize(SCIP *scip, SCIP_EXPR ***monomials, SCIP_Real **monomialscoef, int *monomialssize, int minnmonomials)
Definition: reader_pip.c:728
SCIP_RETCODE SCIPsetReaderCopy(SCIP *scip, SCIP_READER *reader, SCIP_DECL_READERCOPY((*readercopy)))
Definition: scip_reader.c:147
static SCIP_Bool isExprPolynomial(SCIP *scip, SCIP_EXPR *expr)
Definition: reader_pip.c:1833
static SCIP_RETCODE collectAggregatedVars(int nvars, SCIP_VAR **vars, int *nAggregatedVars, SCIP_VAR ***aggregatedVars, SCIP_HASHTABLE **varAggregated)
Definition: reader_pip.c:2493
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:2709
SCIP_VAR ** SCIPgetVarsSetppc(SCIP *scip, SCIP_CONS *cons)
Definition: cons_setppc.c:9431
void SCIPhashtableFree(SCIP_HASHTABLE **hashtable)
Definition: misc.c:2295
static SCIP_DECL_READERREAD(readerReadPip)
Definition: reader_pip.c:3166
SCIP_RETCODE SCIPcreateConsLinear(SCIP *scip, SCIP_CONS **cons, const char *name, int nvars, SCIP_VAR **vars, SCIP_Real *vals, SCIP_Real lhs, SCIP_Real rhs, SCIP_Bool initial, SCIP_Bool separate, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool propagate, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool dynamic, SCIP_Bool removable, SCIP_Bool stickingatnode)
PipExpType
Definition: reader_pip.c:100
static SCIP_RETCODE readBinaries(SCIP *scip, PIPINPUT *pipinput)
Definition: reader_pip.c:1604
SCIP_Bool SCIPisIntegral(SCIP *scip, SCIP_Real val)
static const SCIP_Real scalars[]
Definition: lp.c:5747
SCIP_RETCODE SCIPaddVar(SCIP *scip, SCIP_VAR *var)
Definition: scip_prob.c:1676
SCIP_VAR ** SCIPgetVarsLinear(SCIP *scip, SCIP_CONS *cons)
static SCIP_RETCODE readGenerals(SCIP *scip, PIPINPUT *pipinput)
Definition: reader_pip.c:1569
static SCIP_RETCODE readStart(SCIP *scip, PIPINPUT *pipinput)
Definition: reader_pip.c:707
SCIP_RETCODE SCIPreleaseCons(SCIP *scip, SCIP_CONS **cons)
Definition: scip_cons.c:1119
static void clearLine(char *linebuffer, int *linecnt)
Definition: reader_pip.c:1856
static SCIP_DECL_HASHKEYEQ(hashKeyEqVar)
Definition: reader_pip.c:1725
public methods for message output
SCIP_Bool SCIPisExprVar(SCIP *scip, SCIP_EXPR *expr)
Definition: scip_expr.c:1430
void SCIPexprGetQuadraticBilinTerm(SCIP_EXPR *expr, int termidx, SCIP_EXPR **expr1, SCIP_EXPR **expr2, SCIP_Real *coef, int *pos2, SCIP_EXPR **prodexpr)
Definition: expr.c:4157
SCIP_VARSTATUS SCIPvarGetStatus(SCIP_VAR *var)
Definition: var.c:17379
#define SCIP_Real
Definition: def.h:186
public methods for input file readers
int SCIPgetNVarsAnd(SCIP *scip, SCIP_CONS *cons)
Definition: cons_and.c:5157
int SCIPgetNVarsKnapsack(SCIP *scip, SCIP_CONS *cons)
public methods for message handling
static SCIP_Bool isTokenChar(char c)
Definition: reader_pip.c:199
SCIP_Real SCIPgetValueExprValue(SCIP_EXPR *expr)
Definition: expr_value.c:294
SCIP_RETCODE SCIPsetReaderRead(SCIP *scip, SCIP_READER *reader, SCIP_DECL_READERREAD((*readerread)))
Definition: scip_reader.c:195
static SCIP_Bool getNextLine(SCIP *scip, PIPINPUT *pipinput)
Definition: reader_pip.c:252
SCIP_RETCODE SCIPcreateConsNonlinear(SCIP *scip, SCIP_CONS **cons, const char *name, SCIP_EXPR *expr, 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)
#define SCIP_Longint
Definition: def.h:171
int SCIPvarGetIndex(SCIP_VAR *var)
Definition: var.c:17599
SCIP_VARTYPE SCIPvarGetType(SCIP_VAR *var)
Definition: var.c:17425
SCIP_Bool SCIPhashtableExists(SCIP_HASHTABLE *hashtable, void *element)
Definition: misc.c:2608
SCIP_Bool SCIPisZero(SCIP *scip, SCIP_Real val)
sum expression handler
SCIP_Real * SCIPgetValsLinear(SCIP *scip, SCIP_CONS *cons)
SCIP_Real SCIPvarGetUbLocal(SCIP_VAR *var)
Definition: var.c:17985
static const char commentchars[]
Definition: reader_pip.c:142
#define BMSclearMemoryArray(ptr, num)
Definition: memory.h:132
static void syntaxError(SCIP *scip, PIPINPUT *pipinput, const char *msg)
Definition: reader_pip.c:152
int SCIPfclose(SCIP_FILE *fp)
Definition: fileio.c:232
SCIP_Longint * SCIPgetWeightsKnapsack(SCIP *scip, SCIP_CONS *cons)
public methods for reader plugins
public methods for global and local (sub)problems
static SCIP_RETCODE readPolynomial(SCIP *scip, PIPINPUT *pipinput, char *name, SCIP_EXPR **expr, SCIP_Bool *islinear, SCIP_Bool *newsection)
Definition: reader_pip.c:811
SCIP_Real SCIPgetLhsNonlinear(SCIP_CONS *cons)
int SCIPgetNVarsLinear(SCIP *scip, SCIP_CONS *cons)
static SCIP_Bool getNextToken(SCIP *scip, PIPINPUT *pipinput)
Definition: reader_pip.c:311
static SCIP_Bool isExprSignomial(SCIP *scip, SCIP_EXPR *expr)
Definition: reader_pip.c:1786
static SCIP_RETCODE getActiveVariables(SCIP *scip, SCIP_VAR **vars, SCIP_Real *scalars, int *nvars, SCIP_Real *constant, SCIP_Bool transformed)
Definition: reader_pip.c:1742
SCIP_Real SCIPgetLhsLinear(SCIP *scip, SCIP_CONS *cons)
void SCIPsetConstantExprSum(SCIP_EXPR *expr, SCIP_Real constant)
Definition: expr_sum.c:1100
static SCIP_Bool isNameValid(const char *name)
Definition: reader_pip.c:2594
#define SCIPreallocBufferArray(scip, ptr, num)
Definition: scip_mem.h:128
memory allocation routines