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