Scippy

SCIP

Solving Constraint Integer Programs

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