Scippy

SCIP

Solving Constraint Integer Programs

reader_pip.c
Go to the documentation of this file.
1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2 /* */
3 /* This file is part of the program and library */
4 /* SCIP --- Solving Constraint Integer Programs */
5 /* */
6 /* Copyright (c) 2002-2024 Zuse Institute Berlin (ZIB) */
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, /**< pointer to vars array to get active variables for */
1745  SCIP_Real** scalars, /**< pointer to 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(*vars != NULL || *nvars == 0);
1759  assert(*scalars != NULL || *nvars == 0);
1760  assert(constant != NULL);
1761 
1762  if( transformed )
1763  {
1764  SCIP_CALL( SCIPgetProbvarLinearSum(scip, *vars, *scalars, nvars, *nvars, constant, &requiredsize, TRUE) );
1765 
1766  if( requiredsize > *nvars )
1767  {
1768  SCIP_CALL( SCIPreallocBufferArray(scip, vars, requiredsize) );
1769  SCIP_CALL( SCIPreallocBufferArray(scip, scalars, requiredsize) );
1770 
1771  SCIP_CALL( SCIPgetProbvarLinearSum(scip, *vars, *scalars, nvars, requiredsize, constant, &requiredsize, TRUE) );
1772  assert( requiredsize <= *nvars );
1773  }
1774  }
1775  else
1776  {
1777  if( *nvars > 0 && ( *vars == NULL || *scalars == NULL ) ) /*lint !e774 !e845*/
1778  {
1779  SCIPerrorMessage("Null pointer in PIP reader\n"); /* should not happen */
1780  SCIPABORT();
1781  return SCIP_INVALIDDATA; /*lint !e527*/
1782  }
1783 
1784  for( v = 0; v < *nvars; ++v )
1785  {
1786  SCIP_CALL( SCIPvarGetOrigvarSum(&(*vars)[v], &(*scalars)[v], constant) );
1787 
1788  /* negated variables with an original counterpart may also be returned by SCIPvarGetOrigvarSum();
1789  * make sure we get the original variable in that case
1790  */
1791  if( SCIPvarGetStatus((*vars)[v]) == SCIP_VARSTATUS_NEGATED )
1792  {
1793  (*vars)[v] = SCIPvarGetNegatedVar((*vars)[v]);
1794  *constant += (*scalars)[v];
1795  (*scalars)[v] *= -1.0;
1796  }
1797  }
1798  }
1799  return SCIP_OKAY;
1800 }
1801 
1802 /** checks whether a given expression is a signomial
1803  *
1804  * assumes simplified expression
1805  */
1806 static
1808  SCIP* scip, /**< SCIP data structure */
1809  SCIP_EXPR* expr /**< expression */
1810  )
1811 {
1812  assert(scip != NULL);
1813  assert(expr != NULL);
1814 
1815  if( SCIPisExprVar(scip, expr) || SCIPisExprValue(scip, expr) )
1816  return TRUE;
1817 
1818  if( SCIPisExprPower(scip, expr) && SCIPisExprVar(scip, SCIPexprGetChildren(expr)[0]) )
1819  return TRUE;
1820 
1821  if( SCIPisExprProduct(scip, expr) )
1822  {
1823  SCIP_EXPR* child;
1824  int c;
1825 
1826  for( c = 0; c < SCIPexprGetNChildren(expr); ++c )
1827  {
1828  child = SCIPexprGetChildren(expr)[c];
1829 
1830  if( SCIPisExprVar(scip, child) )
1831  continue;
1832 
1833  if( SCIPisExprPower(scip, child) && SCIPisExprVar(scip, SCIPexprGetChildren(child)[0]) )
1834  continue;
1835 
1836  /* the pip format does not allow constants here */
1837 
1838  return FALSE;
1839  }
1840 
1841  return TRUE;
1842  }
1843 
1844  return FALSE;
1845 }
1846 
1847 /** checks whether a given expression is a sum of signomials (i.e., like a polynomial, but negative and fractional exponents allowed)
1848  *
1849  * assumes simplified expression;
1850  * does not check whether variables in powers with fractional exponent are nonnegative;
1851  * does not check whether variables in powers with negative exponent are bounded away from zero (the format specification does not require that, too)
1852  */
1853 static
1855  SCIP* scip, /**< SCIP data structure */
1856  SCIP_EXPR* expr /**< expression */
1857  )
1858 {
1859  int c;
1860 
1861  assert(scip != NULL);
1862  assert(expr != NULL);
1863 
1864  if( !SCIPisExprSum(scip, expr) )
1865  return isExprSignomial(scip, expr);
1866 
1867  /* check whether every term of sum is signomial */
1868  for( c = 0; c < SCIPexprGetNChildren(expr); ++c )
1869  if( !isExprSignomial(scip, SCIPexprGetChildren(expr)[c]) )
1870  return FALSE;
1871 
1872  return TRUE;
1873 }
1874 
1875 /** clears the given line buffer */
1876 static
1878  char* linebuffer, /**< line */
1879  int* linecnt /**< number of characters in line */
1880  )
1881 {
1882  assert( linebuffer != NULL );
1883  assert( linecnt != NULL );
1884 
1885  (*linecnt) = 0;
1886  linebuffer[0] = '\0';
1887 }
1888 
1889 /** ends the given line with '\\0' and prints it to the given file stream */
1890 static
1891 void endLine(
1892  SCIP* scip, /**< SCIP data structure */
1893  FILE* file, /**< output file (or NULL for standard output) */
1894  char* linebuffer, /**< line */
1895  int* linecnt /**< number of characters in line */
1896  )
1897 {
1898  assert( scip != NULL );
1899  assert( linebuffer != NULL );
1900  assert( linecnt != NULL );
1901  assert( 0 <= *linecnt && *linecnt < PIP_MAX_PRINTLEN );
1902 
1903  if( (*linecnt) > 0 )
1904  {
1905  linebuffer[(*linecnt)] = '\0';
1906  SCIPinfoMessage(scip, file, "%s\n", linebuffer);
1907  clearLine(linebuffer, linecnt);
1908  }
1909 }
1910 
1911 /** appends extension to line and prints it to the give file stream if the
1912  * line exceeded the length given in the define PIP_PRINTLEN */
1913 static
1915  SCIP* scip, /**< SCIP data structure */
1916  FILE* file, /**< output file (or NULL for standard output) */
1917  char* linebuffer, /**< line */
1918  int* linecnt, /**< number of characters in line */
1919  const char* extension /**< string to extent the line */
1920  )
1921 {
1922  assert( scip != NULL );
1923  assert( linebuffer != NULL );
1924  assert( linecnt != NULL );
1925  assert( extension != NULL );
1926  assert( strlen(linebuffer) + strlen(extension) < PIP_MAX_PRINTLEN );
1927 
1928  /* NOTE: avoid
1929  * sprintf(linebuffer, "%s%s", linebuffer, extension);
1930  * because of overlapping memory areas in memcpy used in sprintf.
1931  */
1932  (void) strncat(linebuffer, extension, PIP_MAX_PRINTLEN - strlen(linebuffer));
1933 
1934  (*linecnt) += (int) strlen(extension);
1935 
1936  SCIPdebugMsg(scip, "linebuffer <%s>, length = %lu\n", linebuffer, (unsigned long)strlen(linebuffer));
1937 
1938  if( (*linecnt) > PIP_PRINTLEN )
1939  endLine(scip, file, linebuffer, linecnt);
1940 }
1941 
1942 
1943 /** print linear or quadratic row in PIP format to file stream */
1944 static
1946  SCIP* scip, /**< SCIP data structure */
1947  FILE* file, /**< output file (or NULL for standard output) */
1948  const char* rowname, /**< row name */
1949  const char* rownameextension, /**< row name extension */
1950  const char* type, /**< row type ("=", "<=", or ">=") */
1951  SCIP_VAR** linvars, /**< array of linear variables */
1952  SCIP_Real* linvals, /**< array of linear coefficient values */
1953  int nlinvars, /**< number of linear variables */
1954  SCIP_EXPR* quadexpr, /**< quadratic expression */
1955  SCIP_Real rhs, /**< right hand side */
1956  SCIP_Bool transformed /**< transformed constraint? */
1957  )
1958 {
1959  int v;
1960  char linebuffer[PIP_MAX_PRINTLEN+1] = { '\0' };
1961  int linecnt;
1962 
1963  char varname[PIP_MAX_NAMELEN];
1964  char varname2[PIP_MAX_NAMELEN];
1965  char consname[PIP_MAX_NAMELEN + 1]; /* an extra character for ':' */
1966  char buffer[PIP_MAX_PRINTLEN];
1967 
1968  assert( scip != NULL );
1969  assert( strcmp(type, "=") == 0 || strcmp(type, "<=") == 0 || strcmp(type, ">=") == 0 );
1970  assert( nlinvars == 0 || (linvars != NULL && linvals != NULL) );
1971 
1972  clearLine(linebuffer, &linecnt);
1973 
1974  /* start each line with a space */
1975  appendLine(scip, file, linebuffer, &linecnt, " ");
1976 
1977  /* print row name */
1978  if ( strlen(rowname) > 0 || strlen(rownameextension) > 0 )
1979  {
1980  (void) SCIPsnprintf(consname, PIP_MAX_NAMELEN + 1, "%s%s:", rowname, rownameextension);
1981  appendLine(scip, file, linebuffer, &linecnt, consname);
1982  }
1983 
1984  /* print coefficients */
1985  for( v = 0; v < nlinvars; ++v )
1986  {
1987  SCIP_VAR* var;
1988 
1989  assert(linvars != NULL); /* for lint */
1990  assert(linvals != NULL);
1991 
1992  var = linvars[v];
1993  assert( var != NULL );
1994 
1995  /* we start a new line; therefore we tab this line */
1996  if ( linecnt == 0 )
1997  appendLine(scip, file, linebuffer, &linecnt, " ");
1998 
1999  (void) SCIPsnprintf(varname, PIP_MAX_NAMELEN, "%s", SCIPvarGetName(var));
2000  (void) SCIPsnprintf(buffer, PIP_MAX_PRINTLEN, " %+.15g %s", linvals[v], varname);
2001 
2002  appendLine(scip, file, linebuffer, &linecnt, buffer);
2003  }
2004 
2005  /* print quadratic part */
2006  if( quadexpr != NULL )
2007  {
2008  SCIP_EXPR** linexprs;
2009  SCIP_VAR** activevars;
2010  SCIP_Real* activevals;
2011  SCIP_Real* lincoefs;
2012  SCIP_Real constant;
2013  SCIP_Real activeconstant = 0.0;
2014  int nbilinexprterms;
2015  int nactivevars;
2016  int nquadexprs;
2017  int nlinexprs;
2018 
2019  /* get data from the quadratic expression */
2020  SCIPexprGetQuadraticData(quadexpr, &constant, &nlinexprs, &linexprs, &lincoefs, &nquadexprs, &nbilinexprterms,
2021  NULL, NULL);
2022 
2023  /* allocate memory to store active linear variables */
2024  SCIP_CALL( SCIPallocBufferArray(scip, &activevars, nlinexprs) );
2025  SCIP_CALL( SCIPduplicateBufferArray(scip, &activevals, lincoefs, nlinexprs) );
2026  nactivevars = nlinexprs;
2027 
2028  for( v = 0; v < nlinexprs; ++v )
2029  {
2030  assert(linexprs != NULL && linexprs[v] != NULL);
2031  assert(SCIPisExprVar(scip, linexprs[v]));
2032 
2033  activevars[v] = SCIPgetVarExprVar(linexprs[v]);
2034  assert(activevars[v] != NULL);
2035  }
2036 
2037  /* get active variables */
2038  SCIP_CALL( getActiveVariables(scip, &activevars, &activevals, &nactivevars, &activeconstant, transformed) );
2039  constant += activeconstant;
2040 
2041  /* print linear coefficients of linear variables */
2042  for( v = 0; v < nactivevars; ++v )
2043  {
2044  SCIP_VAR* var;
2045 
2046  assert(activevars != NULL); /* for lint */
2047  assert(activevals != NULL);
2048 
2049  var = activevars[v];
2050  assert( var != NULL );
2051 
2052  /* we start a new line; therefore we tab this line */
2053  if( linecnt == 0 )
2054  appendLine(scip, file, linebuffer, &linecnt, " ");
2055 
2056  (void) SCIPsnprintf(varname, PIP_MAX_NAMELEN, "%s", SCIPvarGetName(var));
2057  (void) SCIPsnprintf(buffer, PIP_MAX_PRINTLEN, " %+.15g %s", activevals[v], varname);
2058 
2059  appendLine(scip, file, linebuffer, &linecnt, buffer);
2060  }
2061 
2062  /* free memory for active linear variables */
2063  SCIPfreeBufferArray(scip, &activevals);
2064  SCIPfreeBufferArray(scip, &activevars);
2065 
2066  /* adjust rhs if there is a constant */
2067  if( constant != 0.0 && !SCIPisInfinity(scip, rhs) )
2068  rhs -= constant;
2069 
2070  /* print linear coefficients of quadratic variables */
2071  for( v = 0; v < nquadexprs; ++v )
2072  {
2073  SCIP_EXPR* expr;
2074  SCIP_VAR* var;
2075  SCIP_Real lincoef;
2076 
2077  /* get linear coefficient and variable of quadratic term */
2078  SCIPexprGetQuadraticQuadTerm(quadexpr, v, &expr, &lincoef, NULL, NULL, NULL, NULL);
2079  assert(expr != NULL);
2080  assert(SCIPisExprVar(scip, expr));
2081 
2082  var = SCIPgetVarExprVar(expr);
2083  assert(var != NULL);
2084 
2085  if( lincoef == 0.0 )
2086  continue;
2087 
2088  /* we start a new line; therefore we tab this line */
2089  if( linecnt == 0 )
2090  appendLine(scip, file, linebuffer, &linecnt, " ");
2091 
2092  (void) SCIPsnprintf(varname, PIP_MAX_NAMELEN, "%s", SCIPvarGetName(var));
2093  (void) SCIPsnprintf(buffer, PIP_MAX_PRINTLEN, " %+.15g %s", lincoef, varname);
2094 
2095  appendLine(scip, file, linebuffer, &linecnt, buffer);
2096  }
2097 
2098  /* print square terms */
2099  for( v = 0; v < nquadexprs; ++v )
2100  {
2101  SCIP_EXPR* expr;
2102  SCIP_VAR* var;
2103  SCIP_Real sqrcoef;
2104 
2105  /* get square coefficient and variable of quadratic term */
2106  SCIPexprGetQuadraticQuadTerm(quadexpr, v, &expr, NULL, &sqrcoef, NULL, NULL, NULL);
2107  assert(expr != NULL);
2108  assert(SCIPisExprVar(scip, expr));
2109 
2110  var = SCIPgetVarExprVar(expr);
2111  assert(var != NULL);
2112 
2113  if( sqrcoef == 0.0 )
2114  continue;
2115 
2116  /* we start a new line; therefore we tab this line */
2117  if( linecnt == 0 )
2118  appendLine(scip, file, linebuffer, &linecnt, " ");
2119 
2120  (void) SCIPsnprintf(varname, PIP_MAX_NAMELEN, "%s", SCIPvarGetName(var));
2121  (void) SCIPsnprintf(buffer, PIP_MAX_PRINTLEN, " %+.15g %s^2", sqrcoef, varname);
2122 
2123  appendLine(scip, file, linebuffer, &linecnt, buffer);
2124  }
2125 
2126  /* print bilinear terms */
2127  for( v = 0; v < nbilinexprterms; ++v )
2128  {
2129  SCIP_EXPR* expr1;
2130  SCIP_EXPR* expr2;
2131  SCIP_VAR* var1;
2132  SCIP_VAR* var2;
2133  SCIP_Real bilincoef;
2134 
2135  /* get coefficient and variables of bilinear */
2136  SCIPexprGetQuadraticBilinTerm(quadexpr, v, &expr1, &expr2, &bilincoef, NULL, NULL);
2137  assert(expr1 != NULL);
2138  assert(SCIPisExprVar(scip, expr1));
2139  assert(expr2 != NULL);
2140  assert(SCIPisExprVar(scip, expr2));
2141 
2142  var1 = SCIPgetVarExprVar(expr1);
2143  assert(var1 != NULL);
2144  var2 = SCIPgetVarExprVar(expr2);
2145  assert(var2 != NULL);
2146 
2147  /* we start a new line; therefore we tab this line */
2148  if( linecnt == 0 )
2149  appendLine(scip, file, linebuffer, &linecnt, " ");
2150 
2151  (void) SCIPsnprintf(varname, PIP_MAX_NAMELEN, "%s", SCIPvarGetName(var1));
2152  (void) SCIPsnprintf(varname2, PIP_MAX_NAMELEN, "%s", SCIPvarGetName(var2));
2153  (void) SCIPsnprintf(buffer, PIP_MAX_PRINTLEN, " %+.15g %s * %s", bilincoef, varname, varname2);
2154 
2155  appendLine(scip, file, linebuffer, &linecnt, buffer);
2156  }
2157  }
2158 
2159  /* print right hand side */
2160  if( SCIPisZero(scip, rhs) )
2161  rhs = 0.0;
2162 
2163  (void) SCIPsnprintf(buffer, PIP_MAX_PRINTLEN, " %s %+.15g", type, rhs);
2164 
2165  /* we start a new line; therefore we tab this line */
2166  if (linecnt == 0 )
2167  appendLine(scip, file, linebuffer, &linecnt, " ");
2168  appendLine(scip, file, linebuffer, &linecnt, buffer);
2169 
2170  endLine(scip, file, linebuffer, &linecnt);
2171 
2172  return SCIP_OKAY;
2173 }
2174 
2175 /** print signomial in PIP format to file stream */
2176 static
2178  SCIP* scip, /**< SCIP data structure */
2179  FILE* file, /**< output file (or NULL for standard output) */
2180  char* linebuffer, /**< line buffer to append to */
2181  int* linecnt, /**< count on line buffer use */
2182  SCIP_EXPR* expr, /**< sigomial expression */
2183  SCIP_Real coef, /**< coefficient */
2184  SCIP_Bool needsign /**< whether a sign needs to be ensured */
2185  )
2186 {
2187  char buffer[PIP_MAX_PRINTLEN];
2188  SCIP_EXPR* child;
2189  int c;
2190 
2191  assert(isExprSignomial(scip, expr));
2192 
2193  if( SCIPisExprProduct(scip, expr) )
2194  coef *= SCIPgetCoefExprProduct(expr);
2195 
2196  if( SCIPisExprValue(scip, expr) )
2197  coef *= SCIPgetValueExprValue(expr);
2198 
2199  if( REALABS(coef) != 1.0 )
2200  {
2201  (void) SCIPsnprintf(buffer, PIP_MAX_PRINTLEN, needsign ? " %+.15g " : " %.15g ", coef);
2202  appendLine(scip, file, linebuffer, linecnt, buffer);
2203  }
2204  else if( coef == 1.0 && needsign )
2205  {
2206  appendLine(scip, file, linebuffer, linecnt, " + ");
2207  }
2208  else if( coef == -1.0 )
2209  {
2210  appendLine(scip, file, linebuffer, linecnt, " - ");
2211  }
2212  else
2213  {
2214  appendLine(scip, file, linebuffer, linecnt, " ");
2215  }
2216 
2217  if( SCIPisExprVar(scip, expr) )
2218  {
2219  appendLine(scip, file, linebuffer, linecnt, SCIPvarGetName(SCIPgetVarExprVar(expr)));
2220  return;
2221  }
2222 
2223  if( SCIPisExprValue(scip, expr) )
2224  {
2225  if( REALABS(coef) == 1.0 )
2226  {
2227  /* in this case, we will have printed only a sign or space above, so print also a 1.0 */
2228  appendLine(scip, file, linebuffer, linecnt, "1.0");
2229  }
2230  return;
2231  }
2232 
2233  if( SCIPisExprPower(scip, expr) )
2234  {
2235  assert(SCIPisExprVar(scip, SCIPexprGetChildren(expr)[0]));
2236 
2238  appendLine(scip, file, linebuffer, linecnt, buffer);
2239 
2240  return;
2241  }
2242 
2243  assert(SCIPisExprProduct(scip, expr));
2244  for( c = 0; c < SCIPexprGetNChildren(expr); ++c )
2245  {
2246  child = SCIPexprGetChildren(expr)[c];
2247 
2248  if( c > 0 )
2249  appendLine(scip, file, linebuffer, linecnt, " ");
2250 
2251  if( SCIPisExprVar(scip, child) )
2252  {
2253  appendLine(scip, file, linebuffer, linecnt, SCIPvarGetName(SCIPgetVarExprVar(child)));
2254  continue;
2255  }
2256 
2257  assert(SCIPisExprPower(scip, child));
2258  assert(SCIPisExprVar(scip, SCIPexprGetChildren(child)[0]));
2259 
2261  appendLine(scip, file, linebuffer, linecnt, buffer);
2262  }
2263 }
2264 
2265 /** print polynomial row in PIP format to file stream */
2266 static
2268  SCIP* scip, /**< SCIP data structure */
2269  FILE* file, /**< output file (or NULL for standard output) */
2270  const char* rowname, /**< row name */
2271  const char* rownameextension, /**< row name extension */
2272  const char* type, /**< row type ("=", "<=", or ">=") */
2273  SCIP_EXPR* expr, /**< polynomial expression */
2274  SCIP_Real rhs /**< right hand side */
2275  )
2276 {
2277  char consname[PIP_MAX_NAMELEN + 1]; /* an extra character for ':' */
2278  char buffer[PIP_MAX_PRINTLEN];
2279  char linebuffer[PIP_MAX_PRINTLEN+1] = { '\0' };
2280  int linecnt;
2281 
2282  assert(scip != NULL);
2283  assert(strcmp(type, "=") == 0 || strcmp(type, "<=") == 0 || strcmp(type, ">=") == 0);
2284  assert(expr != NULL);
2285 
2286  clearLine(linebuffer, &linecnt);
2287 
2288  /* start each line with a space */
2289  appendLine(scip, file, linebuffer, &linecnt, " ");
2290 
2291  /* print row name */
2292  if( strlen(rowname) > 0 || strlen(rownameextension) > 0 )
2293  {
2294  (void) SCIPsnprintf(consname, PIP_MAX_NAMELEN + 1, "%s%s:", rowname, rownameextension);
2295  appendLine(scip, file, linebuffer, &linecnt, consname);
2296  }
2297 
2298  if( SCIPisExprSum(scip, expr) )
2299  {
2300  int c;
2301  SCIP_Bool needsign = FALSE;
2302 
2303  if( SCIPgetConstantExprSum(expr) != 0.0 )
2304  {
2305  (void) SCIPsnprintf(buffer, PIP_MAX_PRINTLEN, " %+.15g", SCIPgetConstantExprSum(expr));
2306  appendLine(scip, file, linebuffer, &linecnt, buffer);
2307 
2308  needsign = TRUE;
2309  }
2310 
2311  for( c = 0; c < SCIPexprGetNChildren(expr); ++c )
2312  {
2313  printSignomial(scip, file, linebuffer, &linecnt, SCIPexprGetChildren(expr)[c], SCIPgetCoefsExprSum(expr)[c], needsign);
2314  needsign = TRUE;
2315  }
2316  }
2317  else
2318  {
2319  printSignomial(scip, file, linebuffer, &linecnt, expr, 1.0, FALSE);
2320  }
2321 
2322  /* print right hand side */
2323  (void) SCIPsnprintf(buffer, PIP_MAX_PRINTLEN, " %s %+.15g", type, rhs);
2324 
2325  /* we start a new line; therefore we tab this line */
2326  if( linecnt == 0 )
2327  appendLine(scip, file, linebuffer, &linecnt, " ");
2328  appendLine(scip, file, linebuffer, &linecnt, buffer);
2329 
2330  endLine(scip, file, linebuffer, &linecnt);
2331 }
2332 
2333 /** print "and" constraint as row in PIP format to file stream */
2334 static
2336  SCIP* scip, /**< SCIP data structure */
2337  FILE* file, /**< output file (or NULL for standard output) */
2338  const char* rowname, /**< row name */
2339  SCIP_CONS* cons /**< "and" constraint */
2340  )
2341 {
2342  char linebuffer[PIP_MAX_PRINTLEN+1] = { '\0' };
2343  int linecnt;
2344  int i;
2345 
2346  assert(scip != NULL);
2347  assert(rowname != NULL);
2348  assert(cons != NULL);
2349 
2350  clearLine(linebuffer, &linecnt);
2351 
2352  /* start each line with a space */
2353  appendLine(scip, file, linebuffer, &linecnt, " ");
2354 
2355  /* print row name */
2356  if( strlen(rowname) > 0 )
2357  {
2358  appendLine(scip, file, linebuffer, &linecnt, rowname);
2359  appendLine(scip, file, linebuffer, &linecnt, ":");
2360  }
2361 
2362  for( i = 0; i < SCIPgetNVarsAnd(scip, cons); ++i )
2363  {
2364  appendLine(scip, file, linebuffer, &linecnt, " ");
2365  appendLine(scip, file, linebuffer, &linecnt, SCIPvarGetName(SCIPgetVarsAnd(scip, cons)[i]));
2366  }
2367 
2368  appendLine(scip, file, linebuffer, &linecnt, " - ");
2369  appendLine(scip, file, linebuffer, &linecnt, SCIPvarGetName(SCIPgetResultantAnd(scip, cons)));
2370 
2371  /* we start a new line; therefore we tab this line */
2372  if( linecnt == 0 )
2373  appendLine(scip, file, linebuffer, &linecnt, " ");
2374 
2375  /* print right hand side */
2376  appendLine(scip, file, linebuffer, &linecnt, " = 0");
2377 
2378  endLine(scip, file, linebuffer, &linecnt);
2379 }
2380 
2381 /** prints given (linear or) quadratic constraint information in LP format to file stream */
2382 static
2384  SCIP* scip, /**< SCIP data structure */
2385  FILE* file, /**< output file (or NULL for standard output) */
2386  const char* rowname, /**< name of the row */
2387  SCIP_VAR** linvars, /**< array of linear variables */
2388  SCIP_Real* linvals, /**< array of linear coefficients values (or NULL if all linear coefficient values are 1) */
2389  int nlinvars, /**< number of linear variables */
2390  SCIP_EXPR* quadexpr, /**< quadratic expression (or NULL if nlinvars > 0) */
2391  SCIP_Real lhs, /**< left hand side */
2392  SCIP_Real rhs, /**< right hand side */
2393  SCIP_Bool transformed /**< transformed constraint? */
2394  )
2395 {
2396  int v;
2397  SCIP_VAR** activevars = NULL;
2398  SCIP_Real* activevals = NULL;
2399  int nactivevars;
2400  SCIP_Real activeconstant = 0.0;
2401 
2402  assert( scip != NULL );
2403  assert( rowname != NULL );
2404 
2405  assert( nlinvars == 0 || linvars != NULL );
2406  assert( quadexpr == NULL || nlinvars == 0);
2407  assert( lhs <= rhs );
2408 
2409  if( SCIPisInfinity(scip, -lhs) && SCIPisInfinity(scip, rhs) )
2410  return SCIP_OKAY;
2411 
2412  nactivevars = nlinvars;
2413  if( nlinvars > 0 )
2414  {
2415  /* duplicate variable and value array */
2416  SCIP_CALL( SCIPduplicateBufferArray(scip, &activevars, linvars, nactivevars ) );
2417  if( linvals != NULL )
2418  {
2419  SCIP_CALL( SCIPduplicateBufferArray(scip, &activevals, linvals, nactivevars ) );
2420  }
2421  else
2422  {
2423  SCIP_CALL( SCIPallocBufferArray(scip, &activevals, nactivevars) );
2424 
2425  for( v = 0; v < nactivevars; ++v )
2426  activevals[v] = 1.0;
2427  }
2428 
2429  /* retransform given variables to active variables */
2430  SCIP_CALL( getActiveVariables(scip, &activevars, &activevals, &nactivevars, &activeconstant, transformed) );
2431  }
2432 
2433  /* print row(s) in LP format */
2434  if( SCIPisEQ(scip, lhs, rhs) )
2435  {
2436  assert( !SCIPisInfinity(scip, rhs) );
2437 
2438  /* equal constraint */
2439  SCIP_CALL( printRow(scip, file, rowname, "", "=", activevars, activevals, nactivevars, quadexpr,
2440  rhs - activeconstant, transformed) );
2441  }
2442  else
2443  {
2444  if( !SCIPisInfinity(scip, -lhs) )
2445  {
2446  /* print inequality ">=" */
2447  SCIP_CALL( printRow(scip, file, rowname, SCIPisInfinity(scip, rhs) ? "" : "_lhs", ">=", activevars,
2448  activevals, nactivevars, quadexpr, lhs - activeconstant, transformed) );
2449  }
2450  if( !SCIPisInfinity(scip, rhs) )
2451  {
2452  /* print inequality "<=" */
2453  SCIP_CALL( printRow(scip, file, rowname, SCIPisInfinity(scip, -lhs) ? "" : "_rhs", "<=", activevars,
2454  activevals, nactivevars, quadexpr, rhs - activeconstant, transformed) );
2455  }
2456  }
2457 
2458  if( nlinvars > 0 )
2459  {
2460  /* free buffer arrays */
2461  SCIPfreeBufferArray(scip, &activevars);
2462  SCIPfreeBufferArray(scip, &activevals);
2463  }
2464 
2465  return SCIP_OKAY;
2466 }
2467 
2468 /** prints given nonlinear constraint information in LP format to file stream */
2469 static
2471  SCIP* scip, /**< SCIP data structure */
2472  FILE* file, /**< output file (or NULL for standard output) */
2473  const char* rowname, /**< name of the row */
2474  SCIP_EXPR* expr, /**< polynomial expression */
2475  SCIP_Real lhs, /**< left hand side */
2476  SCIP_Real rhs /**< right hand side */
2477  )
2478 {
2479  assert(scip != NULL);
2480  assert(rowname != NULL);
2481  assert(expr != NULL);
2482  assert(lhs <= rhs);
2483 
2484  if( SCIPisInfinity(scip, -lhs) && SCIPisInfinity(scip, rhs) )
2485  return SCIP_OKAY;
2486 
2487  /* print row(s) in LP format */
2488  if( SCIPisEQ(scip, lhs, rhs) )
2489  {
2490  assert( !SCIPisInfinity(scip, rhs) );
2491 
2492  /* equal constraint */
2493  printRowNl(scip, file, rowname, "", "=", expr, rhs);
2494  }
2495  else
2496  {
2497  if( !SCIPisInfinity(scip, -lhs) )
2498  {
2499  /* print inequality ">=" */
2500  printRowNl(scip, file, rowname, SCIPisInfinity(scip, rhs) ? "" : "_lhs", ">=", expr, lhs);
2501  }
2502  if( !SCIPisInfinity(scip, rhs) )
2503  {
2504  /* print inequality "<=" */
2505  printRowNl(scip, file, rowname, SCIPisInfinity(scip, -lhs) ? "" : "_rhs", "<=", expr, rhs);
2506  }
2507  }
2508 
2509  return SCIP_OKAY;
2510 }
2511 
2512 /** check whether given variables are aggregated and put them into an array without duplication */
2513 static
2515  int nvars, /**< number of active variables in the problem */
2516  SCIP_VAR** vars, /**< variable array */
2517  int* nAggregatedVars, /**< number of aggregated variables on output */
2518  SCIP_VAR*** aggregatedVars, /**< array storing the aggregated variables on output */
2519  SCIP_HASHTABLE** varAggregated /**< hashtable for checking duplicates */
2520  )
2521 {
2522  int j;
2523 
2524  /* check variables */
2525  for (j = 0; j < nvars; ++j)
2526  {
2527  SCIP_VARSTATUS status;
2528  SCIP_VAR* var;
2529 
2530  var = vars[j];
2531  status = SCIPvarGetStatus(var);
2532 
2533  /* collect aggregated variables in a list */
2534  if( status >= SCIP_VARSTATUS_AGGREGATED )
2535  {
2536  assert( status == SCIP_VARSTATUS_AGGREGATED ||
2537  status == SCIP_VARSTATUS_MULTAGGR ||
2538  status == SCIP_VARSTATUS_NEGATED );
2539 
2540  if ( ! SCIPhashtableExists(*varAggregated, (void*) var) )
2541  {
2542  (*aggregatedVars)[(*nAggregatedVars)++] = var;
2543  SCIP_CALL( SCIPhashtableInsert(*varAggregated, (void*) var) );
2544  }
2545  }
2546  }
2547 
2548  return SCIP_OKAY;
2549 }
2550 
2551 
2552 /** print aggregated variable-constraints */
2553 static
2555  SCIP* scip, /**< SCIP data structure */
2556  FILE* file, /**< output file (or NULL for standard output) */
2557  SCIP_Bool transformed, /**< TRUE iff problem is the transformed problem */
2558  int nvars, /**< number of active variables in the problem */
2559  int nAggregatedVars, /**< number of aggregated variables */
2560  SCIP_VAR** aggregatedVars /**< array storing the aggregated variables */
2561  )
2562 {
2563  int j;
2564 
2565  SCIP_VAR** activevars;
2566  SCIP_Real* activevals;
2567  int nactivevars;
2568  SCIP_Real activeconstant = 0.0;
2569  char consname[PIP_MAX_NAMELEN];
2570 
2571  assert( scip != NULL );
2572 
2573  /* write aggregation constraints */
2574  SCIP_CALL( SCIPallocBufferArray(scip, &activevars, nvars) );
2575  SCIP_CALL( SCIPallocBufferArray(scip, &activevals, nvars) );
2576 
2577  for (j = 0; j < nAggregatedVars; ++j)
2578  {
2579  /* set up list to obtain substitution variables */
2580  nactivevars = 1;
2581 
2582  activevars[0] = aggregatedVars[j];
2583  activevals[0] = 1.0;
2584  activeconstant = 0.0;
2585 
2586  /* retransform given variables to active variables */
2587  SCIP_CALL( getActiveVariables(scip, &activevars, &activevals, &nactivevars, &activeconstant, transformed) );
2588 
2589  activevals[nactivevars] = -1.0;
2590  activevars[nactivevars] = aggregatedVars[j];
2591  ++nactivevars;
2592 
2593  /* output constraint */
2594  (void) SCIPsnprintf(consname, PIP_MAX_NAMELEN, "aggr_%s", SCIPvarGetName(aggregatedVars[j]));
2595  SCIP_CALL( printRow(scip, file, consname, "", "=", activevars, activevals, nactivevars, NULL, - activeconstant,
2596  transformed) );
2597  }
2598 
2599  /* free buffer arrays */
2600  SCIPfreeBufferArray(scip, &activevars);
2601  SCIPfreeBufferArray(scip, &activevals);
2602 
2603  return SCIP_OKAY;
2604 }
2605 
2606 /** returns whether name is valid according to PIP specification
2607  *
2608  * Checks these two conditions from http://polip.zib.de/pipformat.php:
2609  * - Names/labels can contain at most 255 characters.
2610  * - Name/labels have to consist of the following characters: a-z, A-Z, 0-9, "!", "#", "$", "%", "&", ";", "?", "@", "_". They cannot start with a number.
2611  *
2612  * In addition checks that the length is not zero.
2613  */
2614 static
2616  const char* name /**< name to check */
2617  )
2618 {
2619  size_t len;
2620  size_t i;
2621 
2622  assert(name != NULL);
2623 
2624  len = strlen(name); /*lint !e613*/
2625  if( len > (size_t) PIP_MAX_NAMELEN || len == 0 )
2626  return FALSE;
2627 
2628  /* names cannot start with a number */
2629  if( isdigit(name[0]) )
2630  return FALSE;
2631 
2632  for( i = 0; i < len; ++i )
2633  {
2634  /* a-z, A-Z, 0-9 are ok */
2635  if( isalnum(name[i]) )
2636  continue;
2637 
2638  /* characters in namechars are ok, too */
2639  if( strchr(namechars, name[i]) != NULL )
2640  continue;
2641 
2642  return FALSE;
2643  }
2644 
2645  return TRUE;
2646 }
2647 
2648 
2649 /** method check if the variable names are valid according to PIP specification */
2650 static
2652  SCIP* scip, /**< SCIP data structure */
2653  SCIP_VAR** vars, /**< array of variables */
2654  int nvars /**< number of variables */
2655  )
2656 {
2657  int v;
2658 
2659  assert(scip != NULL);
2660  assert(vars != NULL || nvars == 0);
2661 
2662  /* check if the variable names are not too long and have only characters allowed by PIP */
2663  for( v = 0; v < nvars; ++v )
2664  {
2665  if( !isNameValid(SCIPvarGetName(vars[v])) )
2666  {
2667  SCIPwarningMessage(scip, "variable name <%s> is not valid (too long or disallowed characters); PIP might be corrupted\n", SCIPvarGetName(vars[v]));
2668  return;
2669  }
2670  }
2671 }
2672 
2673 /** method check if the constraint names are valid according to PIP specification */
2674 static
2676  SCIP* scip, /**< SCIP data structure */
2677  SCIP_CONS** conss, /**< array of constraints */
2678  int nconss, /**< number of constraints */
2679  SCIP_Bool transformed /**< TRUE iff problem is the transformed problem */
2680  )
2681 {
2682  int c;
2683  SCIP_CONS* cons;
2684  SCIP_CONSHDLR* conshdlr;
2685  const char* conshdlrname;
2686 
2687  assert( scip != NULL );
2688  assert( conss != NULL || nconss == 0 );
2689 
2690  for( c = 0; c < nconss; ++c )
2691  {
2692  assert(conss != NULL); /* for lint */
2693  cons = conss[c];
2694  assert(cons != NULL );
2695 
2696  /* in case the transformed is written only constraints are posted which are enabled in the current node */
2697  assert(!transformed || SCIPconsIsEnabled(cons));
2698 
2699  conshdlr = SCIPconsGetHdlr(cons);
2700  assert( conshdlr != NULL );
2701 
2702  conshdlrname = SCIPconshdlrGetName(conshdlr);
2703  assert( transformed == SCIPconsIsTransformed(cons) );
2704 
2705  if( !isNameValid(SCIPconsGetName(cons)) )
2706  {
2707  SCIPwarningMessage(scip, "constraint name <%s> is not valid (too long or unallowed characters); PIP might be corrupted\n", SCIPconsGetName(cons));
2708  return;
2709  }
2710 
2711  if( strcmp(conshdlrname, "linear") == 0 )
2712  {
2713  SCIP_Real lhs = SCIPgetLhsLinear(scip, cons);
2714  SCIP_Real rhs = SCIPgetRhsLinear(scip, cons);
2715 
2716  /* for ranged constraints, we need to be able to append _lhs and _rhs to the constraint name, so need additional 4 characters */
2717  if( !SCIPisEQ(scip, lhs, rhs) && strlen(SCIPconsGetName(conss[c])) > (size_t) PIP_MAX_NAMELEN - 4 )
2718  {
2719  SCIPwarningMessage(scip, "name of ranged constraint <%s> has to be cut down to %d characters;\n", SCIPconsGetName(conss[c]),
2720  PIP_MAX_NAMELEN - 1);
2721  return;
2722  }
2723  }
2724  }
2725 }
2726 
2727 /** writes problem to file
2728  * @todo add writing cons_pseudoboolean
2729  */
2731  SCIP* scip, /**< SCIP data structure */
2732  FILE* file, /**< output file, or NULL if standard output should be used */
2733  const char* name, /**< problem name */
2734  SCIP_Bool transformed, /**< TRUE iff problem is the transformed problem */
2735  SCIP_OBJSENSE objsense, /**< objective sense */
2736  SCIP_Real objscale, /**< scalar applied to objective function; external objective value is
2737  * extobj = objsense * objscale * (intobj + objoffset) */
2738  SCIP_Real objoffset, /**< objective offset from bound shifting and fixing */
2739  SCIP_VAR** vars, /**< array with active variables ordered binary, integer, implicit, continuous */
2740  int nvars, /**< number of active variables in the problem */
2741  int nbinvars, /**< number of binary variables */
2742  int nintvars, /**< number of general integer variables */
2743  int nimplvars, /**< number of implicit integer variables */
2744  int ncontvars, /**< number of continuous variables */
2745  SCIP_CONS** conss, /**< array with constraints of the problem */
2746  int nconss, /**< number of constraints in the problem */
2747  SCIP_RESULT* result /**< pointer to store the result of the file writing call */
2748  )
2749 {
2750  int c;
2751  int v;
2752 
2753  int linecnt;
2754  char linebuffer[PIP_MAX_PRINTLEN+1];
2755 
2756  char varname[PIP_MAX_NAMELEN];
2757  char buffer[PIP_MAX_PRINTLEN];
2758 
2759  SCIP_CONSHDLR* conshdlr;
2760  const char* conshdlrname;
2761  SCIP_CONS* cons;
2762  SCIP_CONS** consNonlinear;
2763  int nConsNonlinear;
2764  SCIP_CONS** consAnd;
2765  int nConsAnd;
2766  char consname[PIP_MAX_NAMELEN];
2767 
2768  SCIP_VAR** aggregatedVars;
2769  int nAggregatedVars;
2770  SCIP_HASHTABLE* varAggregated;
2771 
2772  SCIP_VAR** tmpvars;
2773  int tmpvarssize;
2774 
2775  SCIP_VAR** consvars;
2776  SCIP_Real* consvals;
2777  int nconsvars;
2778 
2779  SCIP_VAR* var;
2780  SCIP_Real lb;
2781  SCIP_Real ub;
2782 
2783  assert( scip != NULL );
2784 
2785  nAggregatedVars = 0;
2786  nConsNonlinear = 0;
2787  nConsAnd = 0;
2788 
2789  /* check if the variable names are not to long */
2790  checkVarnames(scip, vars, nvars);
2791 
2792  /* check if the constraint names are to long */
2793  checkConsnames(scip, conss, nconss, transformed);
2794 
2795  /* print statistics as comment to file */
2796  SCIPinfoMessage(scip, file, "\\ SCIP STATISTICS\n");
2797  SCIPinfoMessage(scip, file, "\\ Problem name : %s\n", name);
2798  SCIPinfoMessage(scip, file, "\\ Variables : %d (%d binary, %d integer, %d implicit integer, %d continuous)\n",
2799  nvars, nbinvars, nintvars, nimplvars, ncontvars);
2800  SCIPinfoMessage(scip, file, "\\ Constraints : %d\n", nconss);
2801 
2802  /* print objective sense */
2803  SCIPinfoMessage(scip, file, "%s\n", objsense == SCIP_OBJSENSE_MINIMIZE ? "Minimize" : "Maximize");
2804 
2805  clearLine(linebuffer, &linecnt);
2806  appendLine(scip, file, linebuffer, &linecnt, " Obj:");
2807 
2808  for (v = 0; v < nvars; ++v)
2809  {
2810  var = vars[v];
2811 
2812 #ifndef NDEBUG
2813  /* in case the original problem has to be posted the variables have to be either "original" or "negated" */
2814  if ( !transformed )
2816 #endif
2817 
2818  if ( SCIPisZero(scip, SCIPvarGetObj(var)) )
2819  continue;
2820 
2821  /* we start a new line; therefore we tab this line */
2822  if ( linecnt == 0 )
2823  appendLine(scip, file, linebuffer, &linecnt, " ");
2824 
2825  (void) SCIPsnprintf(varname, PIP_MAX_NAMELEN, "%s", SCIPvarGetName(var));
2826  (void) SCIPsnprintf(buffer, PIP_MAX_PRINTLEN, " %+.15g %s", objscale * SCIPvarGetObj(var), varname );
2827 
2828  appendLine(scip, file, linebuffer, &linecnt, buffer);
2829  }
2830 
2831  if( ! SCIPisZero(scip, objoffset) )
2832  {
2833  (void) SCIPsnprintf(buffer, PIP_MAX_PRINTLEN, " %+.15g", objscale * objoffset);
2834  appendLine(scip, file, linebuffer, &linecnt, buffer);
2835  }
2836 
2837  endLine(scip, file, linebuffer, &linecnt);
2838 
2839  /* print "Subject to" section */
2840  SCIPinfoMessage(scip, file, "Subject to\n");
2841 
2842  /* collect quadratic, nonlinear, absolute power, and, and bivariate constraints in arrays */
2843  SCIP_CALL( SCIPallocBufferArray(scip, &consNonlinear, nconss) );
2844  SCIP_CALL( SCIPallocBufferArray(scip, &consAnd, nconss) );
2845 
2846  tmpvarssize = SCIPgetNTotalVars(scip);
2847  SCIP_CALL( SCIPallocBufferArray(scip, &tmpvars, tmpvarssize) );
2848 
2849  for (c = 0; c < nconss; ++c)
2850  {
2851  cons = conss[c];
2852  assert( cons != NULL);
2853 
2854  /* in case the transformed is written only constraints are posted which are enabled in the current node */
2855  assert(!transformed || SCIPconsIsEnabled(cons));
2856 
2857  conshdlr = SCIPconsGetHdlr(cons);
2858  assert( conshdlr != NULL );
2859 
2860  (void) SCIPsnprintf(consname, PIP_MAX_NAMELEN, "%s", SCIPconsGetName(cons));
2861  conshdlrname = SCIPconshdlrGetName(conshdlr);
2862  assert( transformed == SCIPconsIsTransformed(cons) );
2863 
2864  if( strcmp(conshdlrname, "linear") == 0 )
2865  {
2866  SCIP_CALL( printQuadraticCons(scip, file, consname,
2867  SCIPgetVarsLinear(scip, cons), SCIPgetValsLinear(scip, cons), SCIPgetNVarsLinear(scip, cons),
2868  NULL, SCIPgetLhsLinear(scip, cons), SCIPgetRhsLinear(scip, cons), transformed) );
2869  }
2870  else if( strcmp(conshdlrname, "setppc") == 0 )
2871  {
2872  consvars = SCIPgetVarsSetppc(scip, cons);
2873  nconsvars = SCIPgetNVarsSetppc(scip, cons);
2874 
2875  switch( SCIPgetTypeSetppc(scip, cons) )
2876  {
2878  SCIP_CALL( printQuadraticCons(scip, file, consname,
2879  consvars, NULL, nconsvars, NULL, 1.0, 1.0, transformed) );
2880  break;
2882  SCIP_CALL( printQuadraticCons(scip, file, consname,
2883  consvars, NULL, nconsvars, NULL, -SCIPinfinity(scip), 1.0, transformed) );
2884  break;
2886  SCIP_CALL( printQuadraticCons(scip, file, consname,
2887  consvars, NULL, nconsvars, NULL, 1.0, SCIPinfinity(scip), transformed) );
2888  break;
2889  }
2890  }
2891  else if ( strcmp(conshdlrname, "logicor") == 0 )
2892  {
2893  SCIP_CALL( printQuadraticCons(scip, file, consname,
2894  SCIPgetVarsLogicor(scip, cons), NULL, SCIPgetNVarsLogicor(scip, cons),
2895  NULL, 1.0, SCIPinfinity(scip), transformed) );
2896  }
2897  else if ( strcmp(conshdlrname, "knapsack") == 0 )
2898  {
2899  SCIP_Longint* weights;
2900 
2901  consvars = SCIPgetVarsKnapsack(scip, cons);
2902  nconsvars = SCIPgetNVarsKnapsack(scip, cons);
2903 
2904  /* copy Longint array to SCIP_Real array */
2905  weights = SCIPgetWeightsKnapsack(scip, cons);
2906  SCIP_CALL( SCIPallocBufferArray(scip, &consvals, nconsvars) );
2907  for( v = 0; v < nconsvars; ++v )
2908  consvals[v] = (SCIP_Real)weights[v];
2909 
2910  SCIP_CALL( printQuadraticCons(scip, file, consname, consvars, consvals, nconsvars,
2911  NULL, -SCIPinfinity(scip), (SCIP_Real) SCIPgetCapacityKnapsack(scip, cons), transformed) );
2912 
2913  SCIPfreeBufferArray(scip, &consvals);
2914  }
2915  else if ( strcmp(conshdlrname, "varbound") == 0 )
2916  {
2917  SCIP_CALL( SCIPallocBufferArray(scip, &consvars, 2) );
2918  SCIP_CALL( SCIPallocBufferArray(scip, &consvals, 2) );
2919 
2920  consvars[0] = SCIPgetVarVarbound(scip, cons);
2921  consvars[1] = SCIPgetVbdvarVarbound(scip, cons);
2922 
2923  consvals[0] = 1.0;
2924  consvals[1] = SCIPgetVbdcoefVarbound(scip, cons);
2925 
2926  SCIP_CALL( printQuadraticCons(scip, file, consname, consvars, consvals, 2, NULL,
2927  SCIPgetLhsVarbound(scip, cons), SCIPgetRhsVarbound(scip, cons), transformed) );
2928 
2929  SCIPfreeBufferArray(scip, &consvars);
2930  SCIPfreeBufferArray(scip, &consvals);
2931  }
2932  else if( strcmp(conshdlrname, "nonlinear") == 0 )
2933  {
2934  SCIP_Bool ispolynomial;
2935  SCIP_Bool isquadratic;
2936  SCIP_EXPR* simplifiedexpr = NULL;
2937 
2938  ispolynomial = isExprPolynomial(scip, SCIPgetExprNonlinear(cons));
2939  if( !ispolynomial )
2940  {
2941  /* simplify expression and check again if polynomial
2942  * simplifying the expr owned by the cons can have undesired sideffects onto the consdata (the varhashmap can get messed up), so we copy first
2943  */
2944  SCIP_EXPR* exprcopy;
2945  SCIP_Bool changed;
2946  SCIP_Bool infeasible;
2947 
2948  SCIP_CALL( SCIPduplicateExpr(scip, SCIPgetExprNonlinear(cons), &exprcopy, NULL, NULL, NULL, NULL) );
2949  SCIP_CALL( SCIPsimplifyExpr(scip, exprcopy, &simplifiedexpr, &changed, &infeasible, NULL, NULL) );
2950  SCIP_CALL( SCIPreleaseExpr(scip, &exprcopy) );
2951 
2952  ispolynomial = isExprPolynomial(scip, simplifiedexpr);
2953  }
2954 
2955  /* nonlinear constraints that are not polynomial cannot be printed as PIP */
2956  if( !ispolynomial )
2957  {
2958  SCIPwarningMessage(scip, "nonlinear constraint <%s> is not polynomial\n", SCIPconsGetName(cons));
2959  SCIPinfoMessage(scip, file, "\\ ");
2960  SCIP_CALL( SCIPprintCons(scip, cons, file) );
2961  SCIPinfoMessage(scip, file, ";\n");
2962 
2963  SCIP_CALL( SCIPreleaseExpr(scip, &simplifiedexpr) );
2964  return SCIP_OKAY;
2965  }
2966 
2967  /* check whether constraint is even quadratic
2968  * (we could also skip this and print as polynomial, but the code exists already)
2969  */
2970  SCIP_CALL( SCIPcheckExprQuadratic(scip, simplifiedexpr != NULL ? simplifiedexpr : SCIPgetExprNonlinear(cons), &isquadratic) );
2971  if( isquadratic )
2972  isquadratic = SCIPexprAreQuadraticExprsVariables(simplifiedexpr != NULL ? simplifiedexpr : SCIPgetExprNonlinear(cons));
2973 
2974  if( isquadratic )
2975  {
2976  SCIP_CALL( printQuadraticCons(scip, file, consname, NULL, NULL, 0, simplifiedexpr != NULL ? simplifiedexpr : SCIPgetExprNonlinear(cons),
2977  SCIPgetLhsNonlinear(cons), SCIPgetRhsNonlinear(cons), transformed) );
2978  }
2979  else
2980  {
2981  SCIP_CALL( printNonlinearCons(scip, file, consname, simplifiedexpr != NULL ? simplifiedexpr : SCIPgetExprNonlinear(cons), SCIPgetLhsNonlinear(cons), SCIPgetRhsNonlinear(cons)) );
2982  }
2983 
2984  consNonlinear[nConsNonlinear++] = cons;
2985 
2986  if( simplifiedexpr != NULL )
2987  {
2988  SCIP_CALL( SCIPreleaseExpr(scip, &simplifiedexpr) );
2989  }
2990  }
2991  else if( strcmp(conshdlrname, "and") == 0 )
2992  {
2993  printRowAnd(scip, file, consname, cons);
2994 
2995  consAnd[nConsAnd++] = cons;
2996  }
2997  else
2998  {
2999  SCIPwarningMessage(scip, "constraint handler <%s> cannot print requested format\n", conshdlrname );
3000  SCIPinfoMessage(scip, file, "\\ ");
3001  SCIP_CALL( SCIPprintCons(scip, cons, file) );
3002  SCIPinfoMessage(scip, file, ";\n");
3003  }
3004  }
3005 
3006  /* create hashtable for storing aggregated variables */
3007  SCIP_CALL( SCIPallocBufferArray(scip, &aggregatedVars, nvars) );
3008  SCIP_CALL( SCIPhashtableCreate(&varAggregated, SCIPblkmem(scip), nvars/10, hashGetKeyVar, hashKeyEqVar, hashKeyValVar, NULL) );
3009 
3010  /* check for aggregated variables in nonlinear constraints and output aggregations as linear constraints */
3011  for( c = 0; c < nConsNonlinear; ++c )
3012  {
3013  SCIP_Bool success;
3014  int ntmpvars;
3015 
3016  /* get variables of the nonlinear constraint */
3017  SCIP_CALL( SCIPgetConsNVars(scip, consNonlinear[c], &ntmpvars, &success) );
3018  assert(success);
3019  if( ntmpvars > tmpvarssize )
3020  {
3021  tmpvarssize = SCIPcalcMemGrowSize(scip, ntmpvars);
3022  SCIP_CALL( SCIPreallocBufferArray(scip, &tmpvars, tmpvarssize) );
3023  }
3024  SCIP_CALL( SCIPgetConsVars(scip, consNonlinear[c], tmpvars, tmpvarssize, &success) );
3025  assert(success);
3026 
3027  SCIP_CALL( collectAggregatedVars(ntmpvars, tmpvars, &nAggregatedVars, &aggregatedVars, &varAggregated) );
3028  }
3029 
3030  /* check for aggregated variables in and constraints and output aggregations as linear constraints */
3031  for (c = 0; c < nConsAnd; ++c)
3032  {
3033  SCIP_VAR* resultant;
3034 
3035  cons = consAnd[c];
3036 
3037  SCIP_CALL( collectAggregatedVars(SCIPgetNVarsAnd(scip, cons), SCIPgetVarsAnd(scip, cons), &nAggregatedVars, &aggregatedVars, &varAggregated) );
3038 
3039  resultant = SCIPgetResultantAnd(scip, cons);
3040  SCIP_CALL( collectAggregatedVars(1, &resultant, &nAggregatedVars, &aggregatedVars, &varAggregated) );
3041  }
3042 
3043  /* print aggregation constraints */
3044  SCIP_CALL( printAggregatedCons(scip, file, transformed, nvars, nAggregatedVars, aggregatedVars) );
3045 
3046  /* print "Bounds" section */
3047  SCIPinfoMessage(scip, file, "Bounds\n");
3048  for (v = 0; v < nvars; ++v)
3049  {
3050  var = vars[v];
3051  assert( var != NULL );
3052  (void) SCIPsnprintf(varname, PIP_MAX_NAMELEN, "%s", SCIPvarGetName(var) );
3053 
3054  if( transformed )
3055  {
3056  /* in case the transformed is written only local bounds are posted which are valid in the current node */
3057  lb = SCIPvarGetLbLocal(var);
3058  ub = SCIPvarGetUbLocal(var);
3059  }
3060  else
3061  {
3062  lb = SCIPvarGetLbOriginal(var);
3063  ub = SCIPvarGetUbOriginal(var);
3064  }
3065 
3066  if ( SCIPisInfinity(scip, -lb) && SCIPisInfinity(scip, ub) )
3067  SCIPinfoMessage(scip, file, " %s free\n", varname);
3068  else
3069  {
3070  /* print lower bound */
3071  if ( SCIPisInfinity(scip, -lb) )
3072  SCIPinfoMessage(scip, file, " -inf <= ");
3073  else
3074  {
3075  if ( SCIPisZero(scip, lb) )
3076  {
3077  /* variables are nonnegative by default - so we skip these variables */
3078  if ( SCIPisInfinity(scip, ub) )
3079  continue;
3080  lb = 0.0;
3081  }
3082 
3083  SCIPinfoMessage(scip, file, " %.15g <= ", lb);
3084  }
3085  /* print variable name */
3086  SCIPinfoMessage(scip, file, "%s", varname);
3087 
3088  /* print upper bound as far this one is not infinity */
3089  if( !SCIPisInfinity(scip, ub) )
3090  SCIPinfoMessage(scip, file, " <= %.15g", ub);
3091 
3092  SCIPinfoMessage(scip, file, "\n");
3093  }
3094  }
3095 
3096  /* output aggregated variables as 'free' */
3097  for (v = 0; v < nAggregatedVars; ++v)
3098  {
3099  var = aggregatedVars[v];
3100  assert( var != NULL );
3101  (void) SCIPsnprintf(varname, PIP_MAX_NAMELEN, "%s", SCIPvarGetName(var) );
3102 
3103  SCIPinfoMessage(scip, file, " %s free\n", varname);
3104  }
3105 
3106  /* free space */
3107  SCIPfreeBufferArray(scip, &aggregatedVars);
3108  SCIPhashtableFree(&varAggregated);
3109 
3110  /* print binaries section */
3111  if ( nbinvars > 0 )
3112  {
3113  SCIPinfoMessage(scip, file, "Binaries\n");
3114 
3115  clearLine(linebuffer, &linecnt);
3116 
3117  for (v = 0; v < nvars; ++v)
3118  {
3119  var = vars[v];
3120  assert( var != NULL );
3121 
3122  if ( SCIPvarGetType(var) == SCIP_VARTYPE_BINARY )
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 
3130  endLine(scip, file, linebuffer, &linecnt);
3131  }
3132 
3133  /* print generals section */
3134  if ( nintvars > 0 )
3135  {
3136  SCIPinfoMessage(scip, file, "Generals\n");
3137 
3138  for (v = 0; v < nvars; ++v)
3139  {
3140  var = vars[v];
3141  assert( var != NULL );
3142 
3143  if ( SCIPvarGetType(var) == SCIP_VARTYPE_INTEGER )
3144  {
3145  (void) SCIPsnprintf(varname, PIP_MAX_NAMELEN, "%s", SCIPvarGetName(var) );
3146  (void) SCIPsnprintf(buffer, PIP_MAX_PRINTLEN, " %s", varname);
3147  appendLine(scip, file, linebuffer, &linecnt, buffer);
3148  }
3149  }
3150  endLine(scip, file, linebuffer, &linecnt);
3151  }
3152 
3153  /* free space */
3154  SCIPfreeBufferArray(scip, &tmpvars);
3155  SCIPfreeBufferArray(scip, &consNonlinear);
3156  SCIPfreeBufferArray(scip, &consAnd);
3157 
3158  /* end of lp format */
3159  SCIPinfoMessage(scip, file, "%s\n", "End");
3160 
3161  *result = SCIP_SUCCESS;
3162 
3163  return SCIP_OKAY;
3164 }
3165 
3166 /*
3167  * Callback methods of reader
3168  */
3169 
3170 /** copy method for reader plugins (called when SCIP copies plugins) */
3171 static
3172 SCIP_DECL_READERCOPY(readerCopyPip)
3173 { /*lint --e{715}*/
3174  assert(scip != NULL);
3175  assert(reader != NULL);
3176  assert(strcmp(SCIPreaderGetName(reader), READER_NAME) == 0);
3177 
3178  /* call inclusion method of reader */
3180 
3181  return SCIP_OKAY;
3182 }
3183 
3184 
3185 /** problem reading method of reader */
3186 static
3187 SCIP_DECL_READERREAD(readerReadPip)
3188 { /*lint --e{715}*/
3189 
3190  SCIP_CALL( SCIPreadPip(scip, reader, filename, result) );
3191 
3192  return SCIP_OKAY;
3193 }
3194 
3195 
3196 /** problem writing method of reader */
3197 static
3198 SCIP_DECL_READERWRITE(readerWritePip)
3199 { /*lint --e{715}*/
3200  SCIP_CALL( SCIPwritePip(scip, file, name, transformed, objsense, objscale, objoffset, vars,
3201  nvars, nbinvars, nintvars, nimplvars, ncontvars, conss, nconss, result) );
3202 
3203  return SCIP_OKAY;
3204 }
3205 
3206 
3207 /*
3208  * reader specific interface methods
3209  */
3210 
3211 /** includes the pip file reader in SCIP */
3213  SCIP* scip /**< SCIP data structure */
3214  )
3215 {
3216  SCIP_READER* reader;
3217 
3218  /* include reader */
3220 
3221  /* set non fundamental callbacks via setter functions */
3222  SCIP_CALL( SCIPsetReaderCopy(scip, reader, readerCopyPip) );
3223  SCIP_CALL( SCIPsetReaderRead(scip, reader, readerReadPip) );
3224  SCIP_CALL( SCIPsetReaderWrite(scip, reader, readerWritePip) );
3225 
3226  return SCIP_OKAY;
3227 }
3228 
3229 
3230 /** reads problem from file */
3232  SCIP* scip, /**< SCIP data structure */
3233  SCIP_READER* reader, /**< the file reader itself */
3234  const char* filename, /**< full path and name of file to read, or NULL if stdin should be used */
3235  SCIP_RESULT* result /**< pointer to store the result of the file reading call */
3236  )
3237 { /*lint --e{715}*/
3238  PIPINPUT pipinput;
3239  SCIP_RETCODE retcode;
3240  int i;
3241 
3242  assert(scip != NULL); /* for lint */
3243  assert(reader != NULL);
3244 
3245  /* initialize PIP input data */
3246  pipinput.file = NULL;
3247  pipinput.linebuf[0] = '\0';
3248  pipinput.probname[0] = '\0';
3249  pipinput.objname[0] = '\0';
3250  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &pipinput.token, PIP_MAX_LINELEN) ); /*lint !e506*/
3251  pipinput.token[0] = '\0';
3252  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &pipinput.tokenbuf, PIP_MAX_LINELEN) ); /*lint !e506*/
3253  pipinput.tokenbuf[0] = '\0';
3254  for( i = 0; i < PIP_MAX_PUSHEDTOKENS; ++i )
3255  {
3256  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &((pipinput.pushedtokens)[i]), PIP_MAX_LINELEN) ); /*lint !e866 !e506*/
3257  }
3258 
3259  pipinput.npushedtokens = 0;
3260  pipinput.linenumber = 0;
3261  pipinput.linepos = 0;
3262  pipinput.section = PIP_START;
3263  pipinput.objsense = SCIP_OBJSENSE_MINIMIZE;
3264  pipinput.haserror = FALSE;
3265 
3266  SCIP_CALL( SCIPgetBoolParam(scip, "reading/initialconss", &(pipinput.initialconss)) );
3267  SCIP_CALL( SCIPgetBoolParam(scip, "reading/dynamicconss", &(pipinput.dynamicconss)) );
3268  SCIP_CALL( SCIPgetBoolParam(scip, "reading/dynamiccols", &(pipinput.dynamiccols)) );
3269  SCIP_CALL( SCIPgetBoolParam(scip, "reading/dynamicrows", &(pipinput.dynamicrows)) );
3270 
3271  /* read the file */
3272  retcode = readPIPFile(scip, &pipinput, filename);
3273 
3274  /* free dynamically allocated memory */
3275  for( i = PIP_MAX_PUSHEDTOKENS - 1; i >= 0 ; --i )
3276  {
3277  SCIPfreeBlockMemoryArray(scip, &pipinput.pushedtokens[i], PIP_MAX_LINELEN);
3278  }
3279  SCIPfreeBlockMemoryArray(scip, &pipinput.tokenbuf, PIP_MAX_LINELEN);
3280  SCIPfreeBlockMemoryArray(scip, &pipinput.token, PIP_MAX_LINELEN);
3281 
3282  if( retcode == SCIP_PLUGINNOTFOUND )
3283  retcode = SCIP_READERROR;
3284 
3285  /* evaluate the result */
3286  if( pipinput.haserror )
3287  retcode = SCIP_READERROR;
3288  else
3289  {
3290  /* set objective sense */
3291  SCIP_CALL( SCIPsetObjsense(scip, pipinput.objsense) );
3292  *result = SCIP_SUCCESS;
3293  }
3294 
3295  SCIP_CALL( retcode );
3296 
3297  return SCIP_OKAY;
3298 }
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:4113
static SCIP_DECL_HASHGETKEY(hashGetKeyVar)
Definition: reader_pip.c:1718
#define NULL
Definition: def.h:267
SCIP_Bool SCIPconsIsEnabled(SCIP_CONS *cons)
Definition: cons.c:8313
#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:1486
static void printSignomial(SCIP *scip, FILE *file, char *linebuffer, int *linecnt, SCIP_EXPR *expr, SCIP_Real coef, SCIP_Bool needsign)
Definition: reader_pip.c:2177
#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:2547
public methods for memory management
int SCIPexprGetNChildren(SCIP_EXPR *expr)
Definition: expr.c:3854
int SCIPgetNVarsSetppc(SCIP *scip, SCIP_CONS *cons)
Definition: cons_setppc.c:9553
#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:18079
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:3231
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:1945
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:2554
static SCIP_RETCODE readConstraints(SCIP *scip, PIPINPUT *pipinput)
Definition: reader_pip.c:1229
SCIP_Real SCIPvarGetLbLocal(SCIP_VAR *var)
Definition: var.c:18135
SCIP_Real SCIPgetConstantExprSum(SCIP_EXPR *expr)
Definition: expr_sum.c:1567
#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:1250
SCIP_RETCODE SCIPcheckExprQuadratic(SCIP *scip, SCIP_EXPR *expr, SCIP_Bool *isquadratic)
Definition: scip_expr.c:2377
static void endLine(SCIP *scip, FILE *file, char *linebuffer, int *linecnt)
Definition: reader_pip.c:1891
#define FALSE
Definition: def.h:94
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:1281
SCIP_Real SCIPinfinity(SCIP *scip)
int SCIPsnprintf(char *t, int len, const char *s,...)
Definition: misc.c:10877
SCIP_Real SCIPgetExponentExprPow(SCIP_EXPR *expr)
Definition: expr_pow.c:3457
#define TRUE
Definition: def.h:93
enum SCIP_Retcode SCIP_RETCODE
Definition: type_retcode.h:63
static void checkVarnames(SCIP *scip, SCIP_VAR **vars, int nvars)
Definition: reader_pip.c:2651
static SCIP_RETCODE printNonlinearCons(SCIP *scip, FILE *file, const char *rowname, SCIP_EXPR *expr, SCIP_Real lhs, SCIP_Real rhs)
Definition: reader_pip.c:2470
enum SCIP_Varstatus SCIP_VARSTATUS
Definition: type_var.h:57
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
#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:8525
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:2383
#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:4678
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:1151
#define PIP_PRINTLEN
Definition: reader_pip.c:85
SCIP_Bool SCIPexprAreQuadraticExprsVariables(SCIP_EXPR *expr)
Definition: expr.c:4234
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:1114
SCIP_Real SCIPgetRhsLinear(SCIP *scip, SCIP_CONS *cons)
int SCIPstrncpy(char *t, const char *s, int size)
Definition: misc.c:10919
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:1464
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:2296
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:1914
SCIP_VAR * SCIPvarGetNegatedVar(SCIP_VAR *var)
Definition: var.c:17895
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:2685
SCIP_RETCODE SCIPchgVarType(SCIP *scip, SCIP_VAR *var, SCIP_VARTYPE vartype, SCIP_Bool *infeasible)
Definition: scip_var.c:8178
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:3864
SCIP_Real SCIPvarGetUbGlobal(SCIP_VAR *var)
Definition: var.c:18089
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:1242
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:5230
SCIP_Real * SCIPgetCoefsExprSum(SCIP_EXPR *expr)
Definition: expr_sum.c:1552
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:4199
SCIP_RETCODE SCIPgetConsNVars(SCIP *scip, SCIP_CONS *cons, int *nvars, SCIP_Bool *success)
Definition: scip_cons.c:2622
SCIP_RETCODE SCIPaddCons(SCIP *scip, SCIP_CONS *cons)
Definition: scip_prob.c:2770
SCIP_Real SCIPvarGetLbOriginal(SCIP_VAR *var)
Definition: var.c:18025
SCIP_VAR * SCIPgetResultantAnd(SCIP *scip, SCIP_CONS *cons)
Definition: cons_and.c:5255
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:18045
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:1141
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:8216
SCIP_RETCODE SCIPchgVarUb(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound)
Definition: scip_var.c:4768
SCIP_Bool SCIPisExprValue(SCIP *scip, SCIP_EXPR *expr)
Definition: scip_expr.c:1442
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:2267
#define PIP_MAX_LINELEN
Definition: reader_pip.c:79
const char * SCIPvarGetName(SCIP_VAR *var)
Definition: var.c:17420
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:2675
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:4158
file reader for polynomial mixed-integer programs in PIP format
#define REALABS(x)
Definition: def.h:197
SCIP_Bool SCIPisExprSum(SCIP *scip, SCIP_EXPR *expr)
Definition: scip_expr.c:1453
#define SCIP_CALL(x)
Definition: def.h:380
int SCIPgetNTotalVars(SCIP *scip)
Definition: scip_prob.c:2569
SCIP_RETCODE SCIPgetProbvarLinearSum(SCIP *scip, SCIP_VAR **vars, SCIP_Real *scalars, int *nvars, int varssize, SCIP_Real *constant, int *requiredsize, SCIP_Bool mergemultiples)
Definition: scip_var.c:1740
static SCIP_DECL_READERWRITE(readerWritePip)
Definition: reader_pip.c:3198
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:2578
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:4515
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:91
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:10769
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:1417
SCIP_SETPPCTYPE SCIPgetTypeSetppc(SCIP *scip, SCIP_CONS *cons)
Definition: cons_setppc.c:9599
constraint handler for nonlinear constraints specified by algebraic expressions
SCIP_RETCODE SCIPprintCons(SCIP *scip, SCIP_CONS *cons, FILE *file)
Definition: scip_cons.c:2537
static void pushToken(PIPINPUT *pipinput)
Definition: reader_pip.c:410
SCIP_CONSHDLR * SCIPconsGetHdlr(SCIP_CONS *cons)
Definition: cons.c:8236
static void pushBufferToken(PIPINPUT *pipinput)
Definition: reader_pip.c:423
SCIP_Real SCIPvarGetObj(SCIP_VAR *var)
Definition: var.c:17927
static void printRowAnd(SCIP *scip, FILE *file, const char *rowname, SCIP_CONS *cons)
Definition: reader_pip.c:2335
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:3212
Constraint handler for linear constraints in their most general form, .
SCIP_Bool SCIPisExprPower(SCIP *scip, SCIP_EXPR *expr)
Definition: scip_expr.c:1475
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:12775
static SCIP_DECL_READERCOPY(readerCopyPip)
Definition: reader_pip.c:3172
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:1854
static SCIP_RETCODE collectAggregatedVars(int nvars, SCIP_VAR **vars, int *nAggregatedVars, SCIP_VAR ***aggregatedVars, SCIP_HASHTABLE **varAggregated)
Definition: reader_pip.c:2514
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:2730
SCIP_VAR ** SCIPgetVarsSetppc(SCIP *scip, SCIP_CONS *cons)
Definition: cons_setppc.c:9576
void SCIPhashtableFree(SCIP_HASHTABLE **hashtable)
Definition: misc.c:2346
static SCIP_DECL_READERREAD(readerReadPip)
Definition: reader_pip.c:3187
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:5743
SCIP_RETCODE SCIPaddVar(SCIP *scip, SCIP_VAR *var)
Definition: scip_prob.c:1668
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:1174
static void clearLine(char *linebuffer, int *linecnt)
Definition: reader_pip.c:1877
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:1431
void SCIPexprGetQuadraticBilinTerm(SCIP_EXPR *expr, int termidx, SCIP_EXPR **expr1, SCIP_EXPR **expr2, SCIP_Real *coef, int *pos2, SCIP_EXPR **prodexpr)
Definition: expr.c:4198
SCIP_VARSTATUS SCIPvarGetStatus(SCIP_VAR *var)
Definition: var.c:17539
#define SCIP_Real
Definition: def.h:173
public methods for input file readers
int SCIPgetNVarsAnd(SCIP *scip, SCIP_CONS *cons)
Definition: cons_and.c:5206
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:158
int SCIPvarGetIndex(SCIP_VAR *var)
Definition: var.c:17759
SCIP_VARTYPE SCIPvarGetType(SCIP_VAR *var)
Definition: var.c:17585
SCIP_Bool SCIPhashtableExists(SCIP_HASHTABLE *hashtable, void *element)
Definition: misc.c:2659
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:18145
static const char commentchars[]
Definition: reader_pip.c:142
#define BMSclearMemoryArray(ptr, num)
Definition: memory.h:130
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
#define SCIPABORT()
Definition: def.h:352
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:1807
SCIP_Real SCIPgetLhsLinear(SCIP *scip, SCIP_CONS *cons)
void SCIPsetConstantExprSum(SCIP_EXPR *expr, SCIP_Real constant)
Definition: expr_sum.c:1135
static SCIP_Bool isNameValid(const char *name)
Definition: reader_pip.c:2615
#define SCIPreallocBufferArray(scip, ptr, num)
Definition: scip_mem.h:128
memory allocation routines