Scippy

SCIP

Solving Constraint Integer Programs

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