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-2025 Zuse Institute Berlin (ZIB) */
7/* */
8/* Licensed under the Apache License, Version 2.0 (the "License"); */
9/* you may not use this file except in compliance with the License. */
10/* You may obtain a copy of the License at */
11/* */
12/* http://www.apache.org/licenses/LICENSE-2.0 */
13/* */
14/* Unless required by applicable law or agreed to in writing, software */
15/* distributed under the License is distributed on an "AS IS" BASIS, */
16/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */
17/* See the License for the specific language governing permissions and */
18/* limitations under the License. */
19/* */
20/* You should have received a copy of the Apache-2.0 license */
21/* along with SCIP; see the file LICENSE. If not visit scipopt.org. */
22/* */
23/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
24
25/**@file reader_lp.c
26 * @ingroup DEFPLUGINS_READER
27 * @brief LP file reader
28 * @author Tobias Achterberg
29 * @author Marc Pfetsch
30 * @author Stefan Heinz
31 * @author Stefan Vigerske
32 * @author Michael Winkler
33 * @author Lars Schewe
34 *
35 * @todo write fixed (non-active) variables, e.g., for transformed problem
36 */
37
38/*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
39
41#include <ctype.h>
42#include "scip/cons_and.h"
44#include "scip/cons_nonlinear.h"
45#include "scip/cons_indicator.h"
46#include "scip/cons_knapsack.h"
47#include "scip/cons_linear.h"
49#include "scip/cons_logicor.h"
50#include "scip/cons_setppc.h"
51#include "scip/cons_sos1.h"
52#include "scip/cons_sos2.h"
53#include "scip/cons_varbound.h"
54#include "scip/pub_cons.h"
55#include "scip/pub_fileio.h"
56#include "scip/pub_message.h"
57#include "scip/pub_misc.h"
58#include "scip/pub_reader.h"
59#include "scip/pub_var.h"
60#include "scip/rational.h"
61#include "scip/reader_lp.h"
62#include "scip/scip_cons.h"
63#include "scip/scip_exact.h"
64#include "scip/scip_mem.h"
65#include "scip/scip_message.h"
66#include "scip/scip_numerics.h"
67#include "scip/scip_param.h"
68#include "scip/scip_prob.h"
69#include "scip/scip_reader.h"
70#include "scip/scip_var.h"
71#include <stdlib.h>
72#include <string.h>
73
74#define READER_NAME "lpreader"
75#define READER_DESC "file reader for MIPs in IBM CPLEX's LP file format"
76#define READER_EXTENSION "lp"
77
78#define DEFAULT_LINEARIZE_ANDS TRUE /**< Should possible \"and\"-constraints be linearized when writing the lp file? */
79#define DEFAULT_AGGRLINEARIZATION_ANDS TRUE /**< Should an aggregated linearization for and constraints be used? */
80
81/*
82 * Data structures
83 */
84
85#define LP_MAX_LINELEN 65536
86#define LP_MAX_PUSHEDTOKENS 2
87#define LP_INIT_COEFSSIZE 8192
88#define LP_INIT_QUADCOEFSSIZE 16
89#define LP_MAX_PRINTLEN 561 /**< the maximum length of any line is 560 + '\\0' = 561*/
90#define LP_MAX_NAMELEN 256 /**< the maximum length for any name is 255 + '\\0' = 256 */
91#define LP_PRINTLEN 100
92
93
94/** LP reading data */
95struct SCIP_ReaderData
96{
97 SCIP_Bool linearizeands;
98 SCIP_Bool aggrlinearizationands;
99};
100
101
102/** Section in LP File */
104{
107typedef enum LpSection LPSECTION;
108
110{
113typedef enum LpExpType LPEXPTYPE;
114
116{
119typedef enum LpSense LPSENSE;
120
121/** LP reading data */
122struct LpInput
123{
124 SCIP_FILE* file;
125 char* linebuf;
126 char probname[LP_MAX_LINELEN];
127 char objname[LP_MAX_LINELEN];
128 char* token;
129 char* tokenbuf;
130 char* pushedtokens[LP_MAX_PUSHEDTOKENS];
131 int npushedtokens;
132 int linenumber;
133 int linepos;
134 int linebufsize;
135 LPSECTION section;
136 SCIP_OBJSENSE objsense;
137 SCIP_Bool inlazyconstraints; /**< whether we are currently reading the section for lazy constraints */
138 SCIP_Bool inusercuts; /**< whether we are currently reading the section for user cuts */
139 SCIP_Bool initialconss; /**< should model constraints be marked as initial? */
140 SCIP_Bool dynamicconss; /**< should model constraints be subject to aging? */
141 SCIP_Bool dynamiccols; /**< should columns be added and removed dynamically to the LP? */
142 SCIP_Bool dynamicrows; /**< should rows be added and removed dynamically to the LP? */
143 SCIP_Bool haserror;
144};
145typedef struct LpInput LPINPUT;
146
147static const char commentchars[] = "\\";
148
149
150/*
151 * Local methods (for reading)
152 */
153
154/** issues an error message and marks the LP data to have errors */
155static
157 SCIP* scip, /**< SCIP data structure */
158 LPINPUT* lpinput, /**< LP reading data */
159 const char* msg /**< error message */
160 )
161{
162 char formatstr[256];
163
164 assert(lpinput != NULL);
165
166 SCIPerrorMessage("Syntax error in line %d ('%s'): %s \n", lpinput->linenumber, lpinput->token, msg);
167 if( lpinput->linebuf[lpinput->linebufsize - 1] == '\n' )
168 {
169 SCIPverbMessage(scip, SCIP_VERBLEVEL_MINIMAL, NULL, " input: %s", lpinput->linebuf);
170 }
171 else
172 {
173 SCIPverbMessage(scip, SCIP_VERBLEVEL_MINIMAL, NULL, " input: %s\n", lpinput->linebuf);
174 }
175 (void) SCIPsnprintf(formatstr, 256, " %%%ds\n", lpinput->linepos);
176 SCIPverbMessage(scip, SCIP_VERBLEVEL_MINIMAL, NULL, (const char*)formatstr, "^");
177 lpinput->section = LP_END;
178 lpinput->haserror = TRUE;
179}
180
181/** returns whether a syntax error was detected */
182static
184 LPINPUT* lpinput /**< LP reading data */
185 )
186{
187 assert(lpinput != NULL);
188
189 return lpinput->haserror;
190}
191
192/** returns whether the given character is a token delimiter */
193static
195 char c /**< input character */
196 )
197{
198 switch (c)
199 {
200 case ' ':
201 case '\f':
202 case '\n':
203 case '\r':
204 case '\t':
205 case '\v':
206 case '\0':
207 return TRUE;
208 default:
209 return FALSE;
210 }
211}
212
213/** returns whether the given character is a single token */
214static
216 char c /**< input character */
217 )
218{
219 switch (c)
220 {
221 case '-':
222 case '+':
223 case ':':
224 case '<':
225 case '>':
226 case '=':
227 case '[':
228 case ']':
229 case '*':
230 case '^':
231 return TRUE;
232 default:
233 return FALSE;
234 }
235}
236
237/** returns whether the current character is member of a value string */
238static
240 char c, /**< input character */
241 char nextc, /**< next input character */
242 SCIP_Bool firstchar, /**< is the given character the first char of the token? */
243 SCIP_Bool* hasdot, /**< pointer to update the dot flag */
244 LPEXPTYPE* exptype /**< pointer to update the exponent type */
245 )
246{
247 assert(hasdot != NULL);
248 assert(exptype != NULL);
249
250 if( isdigit((unsigned char)c) )
251 return TRUE;
252 else if( (*exptype == LP_EXP_NONE) && !(*hasdot) && (c == '.') && ( isdigit((unsigned char)nextc) || isspace((unsigned char)nextc) || nextc == 'e' || nextc == 'E') )
253 { /* note: we allow for numbers like "24311." for which the next character should be a space or exponent sign */
254 *hasdot = TRUE;
255 return TRUE;
256 }
257 else if( !firstchar && (*exptype == LP_EXP_NONE) && (c == 'e' || c == 'E') )
258 {
259 if( nextc == '+' || nextc == '-' )
260 {
261 *exptype = LP_EXP_SIGNED;
262 return TRUE;
263 }
264 else if( isdigit((unsigned char)nextc) )
265 {
266 *exptype = LP_EXP_UNSIGNED;
267 return TRUE;
268 }
269 }
270 else if( (*exptype == LP_EXP_SIGNED) && (c == '+' || c == '-') )
271 {
272 *exptype = LP_EXP_UNSIGNED;
273 return TRUE;
274 }
275 else if( c == '/' && isdigit((unsigned char)nextc) )
276 {
277 return TRUE;
278 }
279 else if( (*exptype == LP_EXP_UNSIGNED) && isdigit((unsigned char)c) )
280 {
281 return TRUE;
282 }
283 else
284 return FALSE;
285
286 return FALSE;
287}
288
289/** reads the next line from the input file into the line buffer; skips comments;
290 * returns whether a line could be read
291 */
292static
294 SCIP* scip, /**< SCIP data structure */
295 LPINPUT* lpinput /**< LP reading data */
296 )
297{
298 int i;
299
300 assert(lpinput != NULL);
301
302 /* read next line */
303 lpinput->linepos = 0;
304 lpinput->linebuf[lpinput->linebufsize - 2] = '\0';
305
306 if( SCIPfgets(lpinput->linebuf, lpinput->linebufsize, lpinput->file) == NULL )
307 {
308 /* clear the line, this is really necessary here! */
309 BMSclearMemoryArray(lpinput->linebuf, lpinput->linebufsize);
310
311 return FALSE;
312 }
313
314 lpinput->linenumber++;
315
316 /* if line is too long for our buffer reallocate buffer */
317 while( lpinput->linebuf[lpinput->linebufsize - 2] != '\0' )
318 {
319 int newsize;
320
321 newsize = SCIPcalcMemGrowSize(scip, lpinput->linebufsize + 1);
322 SCIP_CALL_ABORT( SCIPreallocBlockMemoryArray(scip, &lpinput->linebuf, lpinput->linebufsize, newsize) );
323
324 lpinput->linebuf[newsize-2] = '\0';
325 if ( SCIPfgets(lpinput->linebuf + lpinput->linebufsize - 1, newsize - lpinput->linebufsize + 1, lpinput->file) == NULL )
326 return FALSE;
327 lpinput->linebufsize = newsize;
328 }
329 lpinput->linebuf[lpinput->linebufsize - 1] = '\0'; /* we want to use lookahead of one char -> we need two \0 at the end */
330
331 /* skip characters after comment symbol */
332 for( i = 0; commentchars[i] != '\0'; ++i )
333 {
334 char* commentstart;
335
336 commentstart = strchr(lpinput->linebuf, commentchars[i]);
337 if( commentstart != NULL )
338 {
339 *commentstart = '\0';
340 *(commentstart+1) = '\0'; /* we want to use lookahead of one char -> we need two \0 at the end */
341
342 break;
343 }
344 }
345
346 return TRUE;
347}
348
349/** swaps the addresses of two pointers */
350static
352 char** pointer1, /**< first pointer */
353 char** pointer2 /**< second pointer */
354 )
355{
356 char* tmp;
357
358 tmp = *pointer1;
359 *pointer1 = *pointer2;
360 *pointer2 = tmp;
361}
362
363/** reads the next token from the input file into the token buffer; returns whether a token was read */
364static
366 SCIP* scip, /**< SCIP data structure */
367 LPINPUT* lpinput /**< LP reading data */
368 )
369{
370 SCIP_Bool hasdot;
371 LPEXPTYPE exptype;
372 char* buf;
373 int tokenlen;
374
375 assert(lpinput != NULL);
376 assert(lpinput->linepos < lpinput->linebufsize);
377
378 /* check the token stack */
379 if( lpinput->npushedtokens > 0 )
380 {
381 swapPointers(&lpinput->token, &lpinput->pushedtokens[lpinput->npushedtokens-1]);
382 lpinput->npushedtokens--;
383
384 SCIPdebugMsg(scip, "(line %d) read token again: '%s'\n", lpinput->linenumber, lpinput->token);
385 return TRUE;
386 }
387
388 /* skip delimiters */
389 buf = lpinput->linebuf;
390 while( isDelimChar(buf[lpinput->linepos]) )
391 {
392 if( buf[lpinput->linepos] == '\0' )
393 {
394 if( !getNextLine(scip, lpinput) )
395 {
396 lpinput->section = LP_END;
397 SCIPdebugMsg(scip, "(line %d) end of file\n", lpinput->linenumber);
398 return FALSE;
399 }
400 assert(lpinput->linepos == 0);
401 /* update buf, because the linebuffer may have been reallocated */
402 buf = lpinput->linebuf;
403 }
404 else
405 lpinput->linepos++;
406 }
407 assert(lpinput->linepos < lpinput->linebufsize);
408 assert(!isDelimChar(buf[lpinput->linepos]));
409
410 /* check if the token is a value */
411 hasdot = FALSE;
412 exptype = LP_EXP_NONE;
413 if( isValueChar(buf[lpinput->linepos], buf[lpinput->linepos+1], TRUE, &hasdot, &exptype) )
414 {
415 /* read value token */
416 tokenlen = 0;
417 do
418 {
419 assert(tokenlen < LP_MAX_LINELEN);
420 assert(!isDelimChar(buf[lpinput->linepos]));
421 lpinput->token[tokenlen] = buf[lpinput->linepos];
422 tokenlen++;
423 lpinput->linepos++;
424 }
425 while( isValueChar(buf[lpinput->linepos], buf[lpinput->linepos+1], FALSE, &hasdot, &exptype) );
426 }
427 else
428 {
429 /* read non-value token */
430 tokenlen = 0;
431 do
432 {
433 assert(tokenlen < LP_MAX_LINELEN);
434 lpinput->token[tokenlen] = buf[lpinput->linepos];
435 tokenlen++;
436 lpinput->linepos++;
437 if( tokenlen == 1 && isTokenChar(lpinput->token[0]) )
438 break;
439 }
440 while( !isDelimChar(buf[lpinput->linepos]) && !isTokenChar(buf[lpinput->linepos]) );
441
442 /* if the token is a power sign '^', skip a following '2'
443 * if the token is an equation sense '<', '>', or '=', skip a following '='
444 * if the token is an equality token '=' and the next character is a '<' or '>', replace the token by the inequality sense
445 */
446 if( tokenlen >= 1 && lpinput->token[tokenlen-1] == '^' && buf[lpinput->linepos] == '2' )
447 {
448 lpinput->linepos++;
449 }
450 if( tokenlen >= 1
451 && (lpinput->token[tokenlen-1] == '<' || lpinput->token[tokenlen-1] == '>' || lpinput->token[tokenlen-1] == '=')
452 && buf[lpinput->linepos] == '=' )
453 {
454 lpinput->linepos++;
455 }
456 else if( lpinput->token[tokenlen-1] == '=' && (buf[lpinput->linepos] == '<' || buf[lpinput->linepos] == '>') )
457 {
458 lpinput->token[tokenlen-1] = buf[lpinput->linepos];
459 lpinput->linepos++;
460 }
461 }
462 assert(tokenlen < LP_MAX_LINELEN);
463 lpinput->token[tokenlen] = '\0';
464
465 SCIPdebugMsg(scip, "(line %d) read token: '%s'\n", lpinput->linenumber, lpinput->token);
466
467 return TRUE;
468}
469
470/** puts the current token on the token stack, such that it is read at the next call to getNextToken() */
471static
473 LPINPUT* lpinput /**< LP reading data */
474 )
475{
476 assert(lpinput != NULL);
477 assert(lpinput->npushedtokens < LP_MAX_PUSHEDTOKENS);
478
479 swapPointers(&lpinput->pushedtokens[lpinput->npushedtokens], &lpinput->token);
480 lpinput->npushedtokens++;
481}
482
483/** puts the buffered token on the token stack, such that it is read at the next call to getNextToken() */
484static
486 LPINPUT* lpinput /**< LP reading data */
487 )
488{
489 assert(lpinput != NULL);
490 assert(lpinput->npushedtokens < LP_MAX_PUSHEDTOKENS);
491
492 swapPointers(&lpinput->pushedtokens[lpinput->npushedtokens], &lpinput->tokenbuf);
493 lpinput->npushedtokens++;
494}
495
496/** swaps the current token with the token buffer */
497static
499 LPINPUT* lpinput /**< LP reading data */
500 )
501{
502 assert(lpinput != NULL);
503
504 swapPointers(&lpinput->token, &lpinput->tokenbuf);
505}
506
507/** checks whether the current token is a section identifier, and if yes, switches to the corresponding section */
508static
510 SCIP* scip, /**< SCIP data structure */
511 LPINPUT* lpinput /**< LP reading data */
512 )
513{
514 SCIP_Bool iscolon;
515 size_t len;
516
517 assert(lpinput != NULL);
518
519 /* remember first token by swapping the token buffer */
520 swapTokenBuffer(lpinput);
521
522 /* look at next token: if this is a ':', the first token is a name and no section keyword */
523 iscolon = FALSE;
524 if( getNextToken(scip, lpinput) )
525 {
526 iscolon = (*lpinput->token == ':');
527 pushToken(lpinput);
528 }
529
530 /* reinstall the previous token by swapping back the token buffer */
531 swapTokenBuffer(lpinput);
532
533 /* check for ':' */
534 if( iscolon )
535 return FALSE;
536
537 len = strlen(lpinput->token);
538 assert(len < LP_MAX_LINELEN);
539
540 /* the section keywords are at least 2 characters up to 8 or exactly 15 characters long */
541 if( len > 1 && (len < 9 || len == 15) )
542 {
543 char token[16];
544 int c = 0;
545
546 while( lpinput->token[c] != '\0' )
547 {
548 token[c] = toupper((unsigned char)lpinput->token[c]); /*lint !e734*/
549 ++c;
550 assert(c < 16);
551 }
552 token[c] = '\0';
553
554 if( (len == 3 && strcmp(token, "MIN") == 0)
555 || (len == 7 && strcmp(token, "MINIMUM") == 0)
556 || (len == 8 && strcmp(token, "MINIMIZE") == 0) )
557 {
558 SCIPdebugMsg(scip, "(line %d) new section: OBJECTIVE\n", lpinput->linenumber);
559 lpinput->section = LP_OBJECTIVE;
560 lpinput->objsense = SCIP_OBJSENSE_MINIMIZE;
561 return TRUE;
562 }
563
564 if( (len == 3 && strcmp(token, "MAX") == 0)
565 || (len == 7 && strcmp(token, "MAXIMUM") == 0)
566 || (len == 8 && strcmp(token, "MAXIMIZE") == 0) )
567 {
568 SCIPdebugMsg(scip, "(line %d) new section: OBJECTIVE\n", lpinput->linenumber);
569 lpinput->section = LP_OBJECTIVE;
570 lpinput->objsense = SCIP_OBJSENSE_MAXIMIZE;
571 return TRUE;
572 }
573
574 if( len == 7 && strcmp(token, "SUBJECT") == 0 )
575 {
576 /* check if the next token is 'TO' */
577 swapTokenBuffer(lpinput);
578 if( getNextToken(scip, lpinput) )
579 {
580 if( SCIPstrcasecmp(lpinput->token, "TO") == 0 )
581 {
582 SCIPdebugMsg(scip, "(line %d) new section: CONSTRAINTS\n", lpinput->linenumber);
583 lpinput->section = LP_CONSTRAINTS;
584 lpinput->inlazyconstraints = FALSE;
585 lpinput->inusercuts = FALSE;
586 return TRUE;
587 }
588 else
589 pushToken(lpinput);
590 }
591 swapTokenBuffer(lpinput);
592 }
593
594 if( len == 4 && strcmp(token, "SUCH") == 0 )
595 {
596 /* check if the next token is 'THAT' */
597 swapTokenBuffer(lpinput);
598 if( getNextToken(scip, lpinput) )
599 {
600 if( SCIPstrcasecmp(lpinput->token, "THAT") == 0 )
601 {
602 SCIPdebugMsg(scip, "(line %d) new section: CONSTRAINTS\n", lpinput->linenumber);
603 lpinput->section = LP_CONSTRAINTS;
604 lpinput->inlazyconstraints = FALSE;
605 lpinput->inusercuts = FALSE;
606 return TRUE;
607 }
608 else
609 pushToken(lpinput);
610 }
611 swapTokenBuffer(lpinput);
612 }
613
614 if( (len == 2 && strcmp(token, "ST") == 0)
615 || (len == 3 && strcmp(token, "ST.") == 0)
616 || (len == 4 && strcmp(token, "S.T.") == 0) )
617 {
618 SCIPdebugMsg(scip, "(line %d) new section: CONSTRAINTS\n", lpinput->linenumber);
619 lpinput->section = LP_CONSTRAINTS;
620 lpinput->inlazyconstraints = FALSE;
621 lpinput->inusercuts = FALSE;
622 return TRUE;
623 }
624
625 if( len == 4 && strcmp(token, "LAZY") == 0 )
626 {
627 /* check if the next token is 'CONSTRAINTS' */
628 swapTokenBuffer(lpinput);
629 if( getNextToken(scip, lpinput) )
630 {
631 if( SCIPstrcasecmp(lpinput->token, "CONSTRAINTS") == 0 )
632 {
633 SCIPdebugMsg(scip, "(line %d) new section: CONSTRAINTS (lazy)\n", lpinput->linenumber);
634 lpinput->section = LP_CONSTRAINTS;
635 lpinput->inlazyconstraints = TRUE;
636 lpinput->inusercuts = FALSE;
637 return TRUE;
638 }
639 else
640 pushToken(lpinput);
641 }
642 swapTokenBuffer(lpinput);
643 }
644
645 if( len == 4 && strcmp(token, "USER") == 0 )
646 {
647 /* check if the next token is 'CUTS' */
648 swapTokenBuffer(lpinput);
649 if( getNextToken(scip, lpinput) )
650 {
651 if( SCIPstrcasecmp(lpinput->token, "CUTS") == 0 )
652 {
653 SCIPdebugMsg(scip, "(line %d) new section: CONSTRAINTS (user cuts)\n", lpinput->linenumber);
654 lpinput->section = LP_CONSTRAINTS;
655 lpinput->inlazyconstraints = FALSE;
656 lpinput->inusercuts = TRUE;
657 return TRUE;
658 }
659 else
660 pushToken(lpinput);
661 }
662 swapTokenBuffer(lpinput);
663 }
664
665 if( (len == 5 && strcmp(token, "BOUND") == 0)
666 || (len == 6 && strcmp(token, "BOUNDS") == 0) )
667 {
668 SCIPdebugMsg(scip, "(line %d) new section: BOUNDS\n", lpinput->linenumber);
669 lpinput->section = LP_BOUNDS;
670 return TRUE;
671 }
672
673 if( (len == 3 && (strcmp(token, "GEN") == 0 || strcmp(token, "INT") == 0))
674 || (len == 7 && (strcmp(token, "GENERAL") == 0 || strcmp(token, "INTEGER") == 0))
675 || (len == 8 && (strcmp(token, "GENERALS") == 0 || strcmp(token, "INTEGERS") == 0)) )
676 {
677 SCIPdebugMsg(scip, "(line %d) new section: GENERALS\n", lpinput->linenumber);
678 lpinput->section = LP_GENERALS;
679 return TRUE;
680 }
681
682 if( (len == 3 && strcmp(token, "BIN") == 0)
683 || (len == 6 && strcmp(token, "BINARY") == 0)
684 || (len == 8 && strcmp(token, "BINARIES") == 0) )
685 {
686 SCIPdebugMsg(scip, "(line %d) new section: BINARIES\n", lpinput->linenumber);
687 lpinput->section = LP_BINARIES;
688 return TRUE;
689 }
690
691 if( (len == 4 && strcmp(token, "SEMI") == 0)
692 || (len == 5 && strcmp(token, "SEMIS") == 0)
693 || (len == 15 && strcmp(token, "SEMI-CONTINUOUS") == 0) )
694 {
695 SCIPdebugMsg(scip, "(line %d) new section: SEMICONTINUOUS\n", lpinput->linenumber);
696 lpinput->section = LP_SEMICONTINUOUS;
697 return TRUE;
698 }
699
700 if( len == 3 && strcmp(token, "SOS") == 0 )
701 {
702 SCIPdebugMsg(scip, "(line %d) new section: SOS\n", lpinput->linenumber);
703 lpinput->section = LP_SOS;
704 return TRUE;
705 }
706
707 if( len == 3 && strcmp(token, "END") == 0 )
708 {
709 SCIPdebugMsg(scip, "(line %d) new section: END\n", lpinput->linenumber);
710 lpinput->section = LP_END;
711 return TRUE;
712 }
713 }
714
715 return FALSE;
716}
717
718/** returns whether the current token is a sign */
719static
721 LPINPUT* lpinput, /**< LP reading data */
722 int* sign /**< pointer to update the sign */
723 )
724{
725 assert(lpinput != NULL);
726 assert(sign != NULL);
727 assert(*sign == +1 || *sign == -1);
728
729 if( lpinput->token[1] == '\0' )
730 {
731 if( *lpinput->token == '+' )
732 return TRUE;
733 else if( *lpinput->token == '-' )
734 {
735 *sign *= -1;
736 return TRUE;
737 }
738 }
739
740 return FALSE;
741}
742
743/** returns whether the current token is a value */
744static
746 SCIP* scip, /**< SCIP data structure */
747 LPINPUT* lpinput, /**< LP reading data */
748 SCIP_Real* value /**< pointer to store the value (unchanged, if token is no value) */
749 )
750{
751 assert(lpinput != NULL);
752 assert(value != NULL);
753
754 if( SCIPstrcasecmp(lpinput->token, "INFINITY") == 0 || SCIPstrcasecmp(lpinput->token, "INF") == 0 )
755 {
756 *value = SCIPinfinity(scip);
757 return TRUE;
758 }
759 else
760 {
761 double val;
762 char* endptr;
763
764 val = strtod(lpinput->token, &endptr);
765 if( endptr != lpinput->token && *endptr == '\0' )
766 {
767 *value = val;
768 return TRUE;
769 }
770 }
771
772 return FALSE;
773}
774
775/** returns whether the current token is a value */
776static
778 SCIP* scip, /**< SCIP data structure */
779 LPINPUT* lpinput, /**< LP reading data */
780 SCIP_RATIONAL* value /**< pointer to store the value (unchanged, if token is no value) */
781 )
782{
783 assert(lpinput != NULL);
784 assert(value != NULL);
785
786 if( SCIPstrcasecmp(lpinput->token, "INFINITY") == 0 || SCIPstrcasecmp(lpinput->token, "INF") == 0 )
787 {
789 return TRUE;
790 }
791 else
792 {
793 double val;
794
795 if( isValue(scip, lpinput, &val) || SCIPrationalIsString(lpinput->token) )
796 {
797 SCIPrationalSetString(value, lpinput->token);
798 return TRUE;
799 }
800 }
801
802 return FALSE;
803}
804
805/** returns whether the current token is an equation sense */
806static
808 LPINPUT* lpinput, /**< LP reading data */
809 LPSENSE* sense /**< pointer to store the equation sense, or NULL */
810 )
811{
812 assert(lpinput != NULL);
813
814 if( strcmp(lpinput->token, "<") == 0 )
815 {
816 if( sense != NULL )
817 *sense = LP_SENSE_LE;
818 return TRUE;
819 }
820 else if( strcmp(lpinput->token, ">") == 0 )
821 {
822 if( sense != NULL )
823 *sense = LP_SENSE_GE;
824 return TRUE;
825 }
826 else if( strcmp(lpinput->token, "=") == 0 )
827 {
828 if( sense != NULL )
829 *sense = LP_SENSE_EQ;
830 return TRUE;
831 }
832
833 return FALSE;
834}
835
836/** returns the variable with the given name, or creates a new variable if it does not exist */
837static
839 SCIP* scip, /**< SCIP data structure */
840 char* name, /**< name of the variable */
841 SCIP_VAR** var, /**< pointer to store the variable */
842 SCIP_Bool* created /**< pointer to store whether a new variable was created, or NULL */
843 )
844{
845 assert(name != NULL);
846 assert(var != NULL);
847
848 *var = SCIPfindVar(scip, name);
849 if( *var == NULL )
850 {
851 SCIP_VAR* newvar;
852 SCIP_Bool dynamiccols;
853 SCIP_Bool initial;
854 SCIP_Bool removable;
855
856 SCIP_CALL( SCIPgetBoolParam(scip, "reading/dynamiccols", &dynamiccols) );
857 initial = !dynamiccols;
858 removable = dynamiccols;
859
860 /* create new variable of the given name */
861 SCIPdebugMsg(scip, "creating new variable: <%s>\n", name);
863 initial, removable, NULL, NULL, NULL, NULL, NULL) );
864 if( SCIPisExact(scip) )
865 {
867 }
868 SCIP_CALL( SCIPaddVar(scip, newvar) );
869 *var = newvar;
870
871 /* because the variable was added to the problem, it is captured by SCIP and we can safely release it right now
872 * without making the returned *var invalid
873 */
874 SCIP_CALL( SCIPreleaseVar(scip, &newvar) );
875
876 if( created != NULL )
877 *created = TRUE;
878 }
879 else if( created != NULL )
880 *created = FALSE;
881
882 return SCIP_OKAY;
883}
884
885/** reads the header of the file */
886static
888 SCIP* scip, /**< SCIP data structure */
889 LPINPUT* lpinput /**< LP reading data */
890 )
891{
892 assert(lpinput != NULL);
893
894 /* everything before first section is treated as comment */
895 do
896 {
897 /* get token */
898 if( !getNextToken(scip, lpinput) )
899 return SCIP_OKAY;
900 }
901 while( !isNewSection(scip, lpinput) );
902
903 return SCIP_OKAY;
904}
905
906/** reads an objective or constraint with name and coefficients */
907static
909 SCIP* scip, /**< SCIP data structure */
910 LPINPUT* lpinput, /**< LP reading data */
911 SCIP_Bool isobjective, /**< indicates whether we are currently reading the coefficients of the objective */
912 char* name, /**< pointer to store the name of the line; must be at least of size
913 * LP_MAX_LINELEN */
914 int* coefssize, /**< size of vars and coefs arrays */
915 SCIP_VAR*** vars, /**< pointer to store the array with variables (must be freed by caller) */
916 SCIP_Real** coefs, /**< pointer to store the array with coefficients (must be freed by caller) */
917 int* ncoefs, /**< pointer to store the number of coefficients */
918 int* quadcoefssize, /**< size of quadvars1, quadvars2, quadcoefs arrays */
919 SCIP_VAR*** quadvars1, /**< pointer to store the array with first variables in quadratic terms (must be freed by caller) */
920 SCIP_VAR*** quadvars2, /**< pointer to store the array with second variables in quadratic terms (must be freed by caller) */
921 SCIP_Real** quadcoefs, /**< pointer to store the array with coefficients in quadratic terms (must be freed by caller) */
922 int* nquadcoefs, /**< pointer to store the number of quadratic coefficients */
923 SCIP_Real* objoffset, /**< pointer to store an objective offset (or NULL if ! isobjective) */
924 SCIP_Bool* newsection /**< pointer to store whether a new section was encountered */
925 )
926{
927 SCIP_VAR* var = NULL;
928 SCIP_Bool havesign;
929 SCIP_Bool havevalue;
930 SCIP_Bool haveobjoffset = FALSE;
931 SCIP_Real coef;
932 int coefsign;
933 SCIP_Bool inquadpart;
934 SCIP_VAR* firstquadvar;
935
936 assert(lpinput != NULL);
937 assert(name != NULL);
938 assert(coefssize != NULL);
939 assert(vars != NULL);
940 assert(coefs != NULL);
941 assert(ncoefs != NULL);
942 assert(quadcoefssize != NULL);
943 assert(quadvars1 != NULL);
944 assert(quadvars2 != NULL);
945 assert(quadcoefs != NULL);
946 assert(nquadcoefs != NULL);
947 assert(!isobjective || objoffset != NULL);
948 assert(newsection != NULL);
949
950 *coefssize = 0;
951 *vars = NULL;
952 *coefs = NULL;
953 *quadvars1 = NULL;
954 *quadvars2 = NULL;
955 *quadcoefs = NULL;
956 *name = '\0';
957 *ncoefs = 0;
958 *quadcoefssize = 0;
959 *nquadcoefs = 0;
960 *newsection = FALSE;
961 inquadpart = FALSE;
962
963 if( isobjective )
964 {
965 assert(objoffset != NULL);
966 *objoffset = 0.0;
967 }
968
969 /* read the first token, which may be the name of the line */
970 if( getNextToken(scip, lpinput) )
971 {
972 /* check if we reached a new section */
973 if( isNewSection(scip, lpinput) )
974 {
975 *newsection = TRUE;
976 return SCIP_OKAY;
977 }
978
979 /* remember the token in the token buffer */
980 swapTokenBuffer(lpinput);
981
982 /* get the next token and check, whether it is a colon */
983 if( getNextToken(scip, lpinput) )
984 {
985 if( strcmp(lpinput->token, ":") == 0 )
986 {
987 /* the second token was a colon: the first token is the line name */
988 (void)SCIPmemccpy(name, lpinput->tokenbuf, '\0', LP_MAX_LINELEN);
989
990 name[LP_MAX_LINELEN - 1] = '\0';
991 SCIPdebugMsg(scip, "(line %d) read constraint name: '%s'\n", lpinput->linenumber, name);
992 }
993 else
994 {
995 /* the second token was no colon: push the tokens back onto the token stack and parse them as coefficients */
996 pushToken(lpinput);
997 pushBufferToken(lpinput);
998 }
999 }
1000 else
1001 {
1002 /* there was only one token left: push it back onto the token stack and parse it as coefficient */
1003 pushBufferToken(lpinput);
1004 }
1005 }
1006
1007 /* initialize buffers for storing the coefficients */
1008 *coefssize = LP_INIT_COEFSSIZE;
1009 SCIP_CALL( SCIPallocBlockMemoryArray(scip, vars, *coefssize) );
1010 SCIP_CALL( SCIPallocBlockMemoryArray(scip, coefs, *coefssize) );
1011
1012 *quadcoefssize = LP_INIT_QUADCOEFSSIZE;
1013 SCIP_CALL( SCIPallocBlockMemoryArray(scip, quadvars1, *quadcoefssize) );
1014 SCIP_CALL( SCIPallocBlockMemoryArray(scip, quadvars2, *quadcoefssize) );
1015 SCIP_CALL( SCIPallocBlockMemoryArray(scip, quadcoefs, *quadcoefssize) );
1016
1017 /* read the coefficients */
1018 coefsign = +1;
1019 coef = 1.0;
1020 havesign = FALSE;
1021 havevalue = FALSE;
1022 firstquadvar = NULL;
1023 *ncoefs = 0;
1024 *nquadcoefs = 0;
1025 while( getNextToken(scip, lpinput) )
1026 {
1027 /* check whether we reached a new sign token */
1028 if( lpinput->token[1] == '\0' && ( *lpinput->token == '+' || *lpinput->token == '-' ) )
1029 {
1030 /* check whether we found an objective offset */
1031 if( isobjective && havevalue && var == NULL )
1032 {
1033 assert( objoffset != NULL );
1034 if( haveobjoffset )
1035 {
1036 syntaxError(scip, lpinput, "two objective offsets.");
1037 return SCIP_OKAY;
1038 }
1039 SCIPdebugMsg(scip, "(line %d) read objective offset %g\n", lpinput->linenumber, coefsign * coef);
1040 haveobjoffset = TRUE;
1041 *objoffset = coefsign * coef;
1042 }
1043 }
1044
1045 /* check if we read a sign */
1046 if( isSign(lpinput, &coefsign) )
1047 {
1048 if( havevalue )
1049 {
1050 syntaxError(scip, lpinput, "sign after value without variable.");
1051 return SCIP_OKAY;
1052 }
1053
1054 SCIPdebugMsg(scip, "(line %d) read coefficient sign: %+d\n", lpinput->linenumber, coefsign);
1055 havesign = TRUE;
1056 continue;
1057 }
1058
1059 /* check if we read a value */
1060 if( isValue(scip, lpinput, &coef) )
1061 {
1062 SCIPdebugMsg(scip, "(line %d) read coefficient value: %g with sign %+d\n", lpinput->linenumber, coef, coefsign);
1063 if( havevalue )
1064 {
1065 syntaxError(scip, lpinput, "two consecutive values.");
1066 return SCIP_OKAY;
1067 }
1068 havevalue = TRUE;
1069 continue;
1070 }
1071
1072 /* check if we reached an equation sense */
1073 if( isSense(lpinput, NULL) )
1074 {
1075 if( isobjective )
1076 {
1077 syntaxError(scip, lpinput, "no sense allowed in objective");
1078 return SCIP_OKAY;
1079 }
1080
1081 if( havevalue )
1082 {
1083 syntaxError(scip, lpinput, "no constant values allowed for constraints in lp file format");
1084 return SCIP_OKAY;
1085 }
1086
1087 if( havesign )
1088 {
1089 syntaxError(scip, lpinput, "constaint has sign without a variable");
1090 return SCIP_OKAY;
1091 }
1092
1093 /* put the sense back onto the token stack */
1094 pushToken(lpinput);
1095 break;
1096 }
1097
1098 /* check if we reached a new section, that will be only allowed when having no current sign and value and if we
1099 * are not in the qudratic part
1100 */
1101 if( (isobjective || (!havevalue && !havesign)) && !inquadpart && isNewSection(scip, lpinput) )
1102 {
1103 if( havesign && !havevalue )
1104 {
1105 SCIPwarningMessage(scip, "skipped single sign %c without value or variable in objective\n", coefsign == 1 ? '+' : '-');
1106 }
1107 else if( isobjective && havevalue && !SCIPisZero(scip, coef) )
1108 {
1109 assert( objoffset != NULL );
1110 /* check whether we found an objective offset */
1111 if( haveobjoffset )
1112 {
1113 syntaxError(scip, lpinput, "two objective offsets.");
1114 return SCIP_OKAY;
1115 }
1116 SCIPdebugMsg(scip, "(line %d) read objective offset %g\n", lpinput->linenumber, coefsign * coef);
1117 *objoffset = coefsign * coef;
1118 }
1119
1120 *newsection = TRUE;
1121 return SCIP_OKAY;
1122 }
1123
1124 /* check if we start a quadratic part */
1125 if( *lpinput->token == '[' )
1126 {
1127 if( inquadpart )
1128 {
1129 syntaxError(scip, lpinput, "cannot start quadratic part while already in quadratic part.");
1130 return SCIP_OKAY;
1131 }
1132 if( havesign && coefsign != +1 )
1133 {
1134 syntaxError(scip, lpinput, "cannot have '-' in front of quadratic part.");
1135 return SCIP_OKAY;
1136 }
1137 if( havevalue )
1138 {
1139 syntaxError(scip, lpinput, "cannot have value in front of quadratic part.");
1140 return SCIP_OKAY;
1141 }
1142
1143 SCIPdebugMsg(scip, "(line %d) start quadratic part\n", lpinput->linenumber);
1144 inquadpart = TRUE;
1145 continue;
1146 }
1147
1148 /* check if we end a quadratic part */
1149 if( *lpinput->token == ']' )
1150 {
1151 if( !inquadpart )
1152 {
1153 syntaxError(scip, lpinput, "cannot end quadratic part before starting one.");
1154 return SCIP_OKAY;
1155 }
1156 if( havesign || havevalue || firstquadvar != NULL )
1157 {
1158 if( firstquadvar == NULL )
1159 {
1160 syntaxError(scip, lpinput, "expected value or first quadratic variable.");
1161 }
1162 else
1163 {
1164 syntaxError(scip, lpinput, "expected second quadratic variable.");
1165 }
1166 return SCIP_OKAY;
1167 }
1168
1169 SCIPdebugMsg(scip, "(line %d) end quadratic part\n", lpinput->linenumber);
1170 inquadpart = FALSE;
1171
1172 if( isobjective )
1173 {
1174 /* quadratic part in objective has to end with '/2' */
1175 if( !getNextToken(scip, lpinput) )
1176 {
1177 syntaxError(scip, lpinput, "expected '/2' or '/ 2' after end of quadratic part in objective.");
1178 return SCIP_OKAY;
1179 }
1180 if( strcmp(lpinput->token, "/2") == 0 )
1181 {
1182 SCIPdebugMsg(scip, "(line %d) saw '/2' or '/ 2' after quadratic part in objective\n", lpinput->linenumber);
1183 }
1184 else if( *lpinput->token == '/' )
1185 {
1186 /* maybe it says '/ 2' */
1187 if( !getNextToken(scip, lpinput) || *lpinput->token != '2' )
1188 {
1189 syntaxError(scip, lpinput, "expected '/2' or '/ 2' after end of quadratic part in objective.");
1190 return SCIP_OKAY;
1191 }
1192 SCIPdebugMsg(scip, "(line %d) saw '/ 2' after quadratic part in objective\n", lpinput->linenumber);
1193 }
1194 else
1195 {
1196 syntaxError(scip, lpinput, "expected '/2' or '/ 2' after end of quadratic part in objective.");
1197 return SCIP_OKAY;
1198 }
1199 }
1200
1201 continue;
1202 }
1203
1204 /* check if we are in between two quadratic variables */
1205 if( *lpinput->token == '*' )
1206 {
1207 if( !inquadpart )
1208 {
1209 syntaxError(scip, lpinput, "cannot have '*' outside of quadratic part.");
1210 return SCIP_OKAY;
1211 }
1212 if( firstquadvar == NULL )
1213 {
1214 syntaxError(scip, lpinput, "cannot have '*' before first variable in quadratic term.");
1215 return SCIP_OKAY;
1216 }
1217
1218 continue;
1219 }
1220
1221 /* all but the first coefficient need a sign */
1222 if( !inquadpart && *ncoefs > 0 && !havesign )
1223 {
1224 syntaxError(scip, lpinput, "expected sign ('+' or '-') or sense ('<' or '>').");
1225 return SCIP_OKAY;
1226 }
1227 if( inquadpart && *nquadcoefs > 0 && !havesign )
1228 {
1229 syntaxError(scip, lpinput, "expected sign ('+' or '-').");
1230 return SCIP_OKAY;
1231 }
1232
1233 /* check if the last variable should be squared */
1234 var = NULL;
1235 if( *lpinput->token == '^' )
1236 {
1237 if( !inquadpart )
1238 {
1239 syntaxError(scip, lpinput, "cannot have squares ('^2') outside of quadratic part.");
1240 return SCIP_OKAY;
1241 }
1242 if( firstquadvar == NULL )
1243 {
1244 syntaxError(scip, lpinput, "cannot have square '^2' before variable.");
1245 return SCIP_OKAY;
1246 }
1247
1248 var = firstquadvar;
1249 }
1250 else
1251 {
1252 /* the token is a variable name: get the corresponding variable (or create a new one) */
1253 SCIP_CALL( getVariable(scip, lpinput->token, &var, NULL) );
1254 }
1255
1256 if( !inquadpart )
1257 {
1258 /* insert the linear coefficient */
1259 SCIPdebugMsg(scip, "(line %d) read linear coefficient: %+g<%s>\n", lpinput->linenumber, coefsign * coef, SCIPvarGetName(var));
1260 if( !SCIPisZero(scip, coef) )
1261 {
1262 /* resize the vars and coefs array if needed */
1263 if( *ncoefs >= *coefssize )
1264 {
1265 int oldcoefssize;
1266 oldcoefssize = *coefssize;
1267 *coefssize *= 2;
1268 *coefssize = MAX(*coefssize, (*ncoefs)+1);
1269 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, vars, oldcoefssize, *coefssize) );
1270 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, coefs, oldcoefssize, *coefssize) );
1271 }
1272 assert(*ncoefs < *coefssize);
1273
1274 /* add coefficient */
1275 (*vars)[*ncoefs] = var;
1276 (*coefs)[*ncoefs] = coefsign * coef;
1277 (*ncoefs)++;
1278 }
1279 }
1280 else
1281 {
1282 if( firstquadvar == NULL )
1283 {
1284 /* if first quadratic variable read, store it and continue; expect second one in next round */
1285 firstquadvar = var;
1286 continue;
1287 }
1288
1289 /* insert the quadratic coefficient */
1290 SCIPdebugMsg(scip, "(line %d) read quadratic coefficient: %+g<%s><%s>\n", lpinput->linenumber, (isobjective ? 0.5 : 1) * coefsign * coef, SCIPvarGetName(firstquadvar), SCIPvarGetName(var));
1291 if( !SCIPisZero(scip, coef) )
1292 {
1293 /* resize the vars and coefs array if needed */
1294 if( *nquadcoefs >= *quadcoefssize )
1295 {
1296 int oldquadcoefssize;
1297 oldquadcoefssize = *quadcoefssize;
1298 *quadcoefssize *= 2;
1299 *quadcoefssize = MAX(*quadcoefssize, (*nquadcoefs)+1);
1300 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, quadcoefs, oldquadcoefssize, *quadcoefssize) );
1301 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, quadvars2, oldquadcoefssize, *quadcoefssize) );
1302 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, quadvars1, oldquadcoefssize, *quadcoefssize) );
1303 }
1304 assert(*nquadcoefs < *quadcoefssize);
1305
1306 /* add coefficient */
1307 (*quadvars1)[*nquadcoefs] = firstquadvar;
1308 (*quadvars2)[*nquadcoefs] = var;
1309 (*quadcoefs)[*nquadcoefs] = coefsign * coef;
1310 if( isobjective )
1311 (*quadcoefs)[*nquadcoefs] /= 2.0;
1312 (*nquadcoefs)++;
1313 }
1314 }
1315
1316 /* reset the flags and coefficient value for the next coefficient */
1317 coefsign = +1;
1318 coef = 1.0;
1319 havesign = FALSE;
1320 havevalue = FALSE;
1321 firstquadvar = NULL;
1322 }
1323
1324 return SCIP_OKAY;
1325}
1326
1327/** reads an objective or constraint with name and coefficients */
1328static
1330 SCIP* scip, /**< SCIP data structure */
1331 LPINPUT* lpinput, /**< LP reading data */
1332 SCIP_Bool isobjective, /**< indicates whether we are currently reading the coefficients of the objective */
1333 char* name, /**< pointer to store the name of the line; must be at least of size
1334 * LP_MAX_LINELEN */
1335 int* coefssize, /**< size of vars and coefs arrays */
1336 SCIP_VAR*** vars, /**< pointer to store the array with variables (must be freed by caller) */
1337 SCIP_RATIONAL*** coefs, /**< pointer to store the array with coefficients (must be freed by caller) */
1338 int* ncoefs, /**< pointer to store the number of coefficients */
1339 SCIP_RATIONAL* objoffset, /**< pointer to store an objective offset (or NULL if ! isobjective) */
1340 SCIP_Bool* newsection /**< pointer to store whether a new section was encountered */
1341 )
1342{
1343 SCIP_VAR* var = NULL;
1344 SCIP_Bool havesign;
1345 SCIP_Bool havevalue;
1346 SCIP_Bool haveobjoffset = FALSE;
1347 SCIP_RATIONAL* coef;
1348 int coefsign;
1349 SCIP_Bool inquadpart;
1350 SCIP_VAR* firstquadvar;
1351
1352 assert(lpinput != NULL);
1353 assert(name != NULL);
1354 assert(coefssize != NULL);
1355 assert(vars != NULL);
1356 assert(coefs != NULL);
1357 assert(ncoefs != NULL);
1358 assert(!isobjective || objoffset != NULL);
1359 assert(newsection != NULL);
1360
1361 *coefssize = 0;
1362 *vars = NULL;
1363 *coefs = NULL;
1364 *name = '\0';
1365 *ncoefs = 0;
1366 *newsection = FALSE;
1367 inquadpart = FALSE;
1368
1370
1371 if( isobjective )
1372 {
1373 assert(objoffset != NULL);
1374 SCIPrationalSetReal(objoffset, 0.0);
1375 }
1376
1377 /* read the first token, which may be the name of the line */
1378 if( getNextToken(scip, lpinput) )
1379 {
1380 /* check if we reached a new section */
1381 if( isNewSection(scip, lpinput) )
1382 {
1383 *newsection = TRUE;
1384 goto TERMINATE;
1385 }
1386
1387 /* remember the token in the token buffer */
1388 swapTokenBuffer(lpinput);
1389
1390 /* get the next token and check, whether it is a colon */
1391 if( getNextToken(scip, lpinput) )
1392 {
1393 if( strcmp(lpinput->token, ":") == 0 )
1394 {
1395 /* the second token was a colon: the first token is the line name */
1396 (void)SCIPmemccpy(name, lpinput->tokenbuf, '\0', LP_MAX_LINELEN);
1397
1398 name[LP_MAX_LINELEN - 1] = '\0';
1399 SCIPdebugMsg(scip, "(line %d) read constraint name: '%s'\n", lpinput->linenumber, name);
1400 }
1401 else
1402 {
1403 /* the second token was no colon: push the tokens back onto the token stack and parse them as coefficients */
1404 pushToken(lpinput);
1405 pushBufferToken(lpinput);
1406 }
1407 }
1408 else
1409 {
1410 /* there was only one token left: push it back onto the token stack and parse it as coefficient */
1411 pushBufferToken(lpinput);
1412 }
1413 }
1414
1415 /* initialize buffers for storing the coefficients */
1416 *coefssize = LP_INIT_COEFSSIZE;
1417
1418 SCIP_CALL( SCIPrationalCreateBlockArray(SCIPblkmem(scip), coefs, *coefssize) );
1419 SCIP_CALL( SCIPallocBlockMemoryArray(scip, vars, *coefssize) );
1420
1421 /* read the coefficients */
1422 coefsign = +1;
1423 SCIPrationalSetReal(coef, 1.0);
1424 havesign = FALSE;
1425 havevalue = FALSE;
1426 firstquadvar = NULL;
1427 *ncoefs = 0;
1428 while( getNextToken(scip, lpinput) )
1429 {
1430 /* check whether we reached a new sign token */
1431 if( lpinput->token[1] == '\0' && ( *lpinput->token == '+' || *lpinput->token == '-' ) )
1432 {
1433 /* check whether we found an objective offset */
1434 if( isobjective && havevalue && var == NULL )
1435 {
1436 assert( objoffset != NULL );
1437 if( haveobjoffset )
1438 {
1439 syntaxError(scip, lpinput, "two objective offsets.");
1440 goto TERMINATE;
1441 }
1442 SCIPdebugMsg(scip, "(line %d) read objective offset %g\n", lpinput->linenumber, coefsign * SCIPrationalGetReal(coef));
1443 haveobjoffset = TRUE;
1444 SCIPrationalMultReal(objoffset, coef, (double) coefsign);
1445 }
1446 }
1447
1448 /* check if we read a sign */
1449 if( isSign(lpinput, &coefsign) )
1450 {
1451 SCIPdebugMsg(scip, "(line %d) read coefficient sign: %+d\n", lpinput->linenumber, coefsign);
1452 havesign = TRUE;
1453 continue;
1454 }
1455
1456 /* check if we read a value */
1457 if( isValueRational(scip, lpinput, coef) )
1458 {
1459 SCIPdebugMsg(scip, "(line %d) read coefficient value: %g with sign %+d\n", lpinput->linenumber, SCIPrationalGetReal(coef), coefsign);
1460 if( havevalue )
1461 {
1462 syntaxError(scip, lpinput, "two consecutive values.");
1463 goto TERMINATE;
1464 }
1465 havevalue = TRUE;
1466 continue;
1467 }
1468
1469 /* check if we reached an equation sense */
1470 if( isSense(lpinput, NULL) )
1471 {
1472 if( isobjective )
1473 {
1474 syntaxError(scip, lpinput, "no sense allowed in objective");
1475 goto TERMINATE;
1476 }
1477
1478 /* put the sense back onto the token stack */
1479 pushToken(lpinput);
1480 break;
1481 }
1482
1483 /* check if we reached a new section, that will be only allowed when having no current sign and value and if we
1484 * are not in the qudratic part
1485 */
1486 if( (isobjective || (!havevalue && !havesign)) && !inquadpart && isNewSection(scip, lpinput) )
1487 {
1488 if( havesign && !havevalue )
1489 {
1490 SCIPwarningMessage(scip, "skipped single sign %c without value or variable in objective\n", coefsign == 1 ? '+' : '-');
1491 }
1492 else if( isobjective && havevalue && !SCIPrationalIsZero(coef) )
1493 {
1494 assert( objoffset != NULL );
1495 /* check whether we found an objective offset */
1496 if( haveobjoffset )
1497 {
1498 syntaxError(scip, lpinput, "two objective offsets.");
1499 goto TERMINATE;
1500 }
1501 SCIPdebugMsg(scip, "(line %d) read objective offset %g\n", lpinput->linenumber, coefsign * SCIPrationalGetReal(coef));
1502 SCIPrationalMultReal(objoffset, coef, (double) coefsign);
1503 }
1504
1505 *newsection = TRUE;
1506 goto TERMINATE;
1507 }
1508
1509 /* check if we start a quadratic part */
1510 if( *lpinput->token == '[' )
1511 {
1512 syntaxError(scip, lpinput, "cannot start quadratic part while in exact solving mode.");
1513 goto TERMINATE;
1514 }
1515
1516 /* check if we end a quadratic part */
1517 if( *lpinput->token == ']' )
1518 {
1519 syntaxError(scip, lpinput, "cannot end quadratic part while in exact solving mode.");
1520 goto TERMINATE;
1521 }
1522
1523 /* all but the first coefficient need a sign */
1524 if( !inquadpart && *ncoefs > 0 && !havesign )
1525 {
1526 syntaxError(scip, lpinput, "expected sign ('+' or '-') or sense ('<' or '>').");
1527 goto TERMINATE;
1528 }
1529
1530 /* check if the last variable should be squared */
1531 var = NULL;
1532 if( *lpinput->token == '^' )
1533 {
1534 if( !inquadpart )
1535 {
1536 syntaxError(scip, lpinput, "cannot have squares ('^2') outside of quadratic part.");
1537 goto TERMINATE;
1538 }
1539 if( firstquadvar == NULL )
1540 {
1541 syntaxError(scip, lpinput, "cannot have square '^2' before variable.");
1542 goto TERMINATE;
1543 }
1544
1545 var = firstquadvar;
1546 }
1547 else
1548 {
1549 /* the token is a variable name: get the corresponding variable (or create a new one) */
1550 SCIP_CALL( getVariable(scip, lpinput->token, &var, NULL) );
1551 }
1552
1553 if( !inquadpart )
1554 {
1555 /* insert the linear coefficient */
1556 SCIPdebugMsg(scip, "(line %d) read linear coefficient: %+g<%s>\n", lpinput->linenumber, coefsign * SCIPrationalGetReal(coef), SCIPvarGetName(var));
1557 if( !SCIPrationalIsZero(coef) )
1558 {
1559 /* resize the vars and coefs array if needed */
1560 if( *ncoefs >= *coefssize )
1561 {
1562 int oldcoefssize;
1563 oldcoefssize = *coefssize;
1564 *coefssize *= 2;
1565 *coefssize = MAX(*coefssize, (*ncoefs)+1);
1566 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, vars, oldcoefssize, *coefssize) );
1567 SCIP_CALL( SCIPrationalReallocBlockArray(SCIPblkmem(scip), coefs, oldcoefssize, *coefssize) );
1568 }
1569 assert(*ncoefs < *coefssize);
1570
1571 /* add coefficient */
1572 (*vars)[*ncoefs] = var;
1573 SCIPrationalMultReal((*coefs)[*ncoefs], coef, (double) coefsign);
1574 (*ncoefs)++;
1575 }
1576 }
1577
1578 /* reset the flags and coefficient value for the next coefficient */
1579 coefsign = +1;
1580 SCIPrationalSetReal(coef, 1.0);
1581 havesign = FALSE;
1582 havevalue = FALSE;
1583 firstquadvar = NULL;
1584 }
1585
1586TERMINATE:
1588
1589 return SCIP_OKAY;
1590}
1591
1592/** reads the objective section */
1593static
1595 SCIP* scip, /**< SCIP data structure */
1596 LPINPUT* lpinput /**< LP reading data */
1597 )
1598{
1599 char name[LP_MAX_LINELEN];
1600 SCIP_RETCODE retcode = SCIP_OKAY;
1601 SCIP_VAR** vars;
1602 SCIP_RATIONAL** coefs;
1603 SCIP_Bool newsection;
1604 SCIP_RATIONAL* objoffset;
1605 SCIP_RATIONAL* tmpval;
1606 int ncoefs;
1607 int coefssize;
1608
1609 assert(lpinput != NULL);
1610
1613
1614 /* read the objective coefficients */
1615 SCIP_CALL_TERMINATE( retcode, readCoefficientsRational(scip, lpinput, TRUE, name, &coefssize, &vars, &coefs, &ncoefs,
1616 objoffset, &newsection), TERMINATE );
1617
1618 if( !SCIPrationalIsZero(objoffset) )
1619 {
1620 SCIP_CALL_TERMINATE( retcode, SCIPaddOrigObjoffsetExact(scip, objoffset), TERMINATE );
1621 }
1622
1623 if( !hasError(lpinput) )
1624 {
1625 int i;
1626
1627 /* set the linear objective values */
1628 for( i = 0; i < ncoefs; ++i )
1629 {
1630 assert(vars != NULL); /* for lint */
1631 assert(coefs != NULL);
1632 SCIPrationalAdd(tmpval, SCIPvarGetObjExact(vars[i]), coefs[i]);
1633 SCIP_CALL_TERMINATE( retcode, SCIPchgVarObjExact(scip, vars[i], tmpval), TERMINATE );
1634 }
1635 }
1636
1637 TERMINATE:
1638 /* free memory */
1639 SCIPfreeBlockMemoryArrayNull(scip, &vars, coefssize);
1640 if( coefs != NULL )
1641 SCIPrationalFreeBlockArray(SCIPblkmem(scip), &coefs, coefssize);
1642
1645
1646 return retcode; /*lint !e438*/
1647}
1648
1649
1650/** reads the objective section */
1651static
1653 SCIP* scip, /**< SCIP data structure */
1654 LPINPUT* lpinput /**< LP reading data */
1655 )
1656{
1657 char name[LP_MAX_LINELEN];
1658 SCIP_VAR** vars;
1659 SCIP_Real* coefs;
1660 SCIP_VAR** quadvars1;
1661 SCIP_VAR** quadvars2;
1662 SCIP_Real* quadcoefs;
1663 SCIP_Bool newsection;
1664 SCIP_Real objoffset;
1665 int ncoefs;
1666 int coefssize;
1667 int quadcoefssize;
1668 int nquadcoefs;
1669
1670 assert(lpinput != NULL);
1671
1672 if( SCIPisExact(scip) )
1673 {
1675 return SCIP_OKAY;
1676 }
1677
1678 /* read the objective coefficients */
1679 SCIP_CALL( readCoefficients(scip, lpinput, TRUE, name, &coefssize, &vars, &coefs, &ncoefs,
1680 &quadcoefssize, &quadvars1, &quadvars2, &quadcoefs, &nquadcoefs, &objoffset, &newsection) );
1681
1682 if( ! SCIPisZero(scip, objoffset) )
1683 {
1684 SCIP_CALL( SCIPaddOrigObjoffset(scip, objoffset) );
1685 }
1686
1687 if( !hasError(lpinput) )
1688 {
1689 int i;
1690
1691 /* set the linear objective values */
1692 for( i = 0; i < ncoefs; ++i )
1693 {
1694 assert(vars != NULL); /* for lint */
1695 assert(coefs != NULL);
1696 SCIP_CALL( SCIPchgVarObj(scip, vars[i], SCIPvarGetObj(vars[i]) + coefs[i]) );
1697 }
1698
1699 /* insert dummy variable and constraint to represent quadratic part of objective; note that
1700 * reading/{initialconss,dynamicconss,dynamicrows,dynamiccols} apply only to model constraints and variables, not
1701 * to an auxiliary objective constraint (otherwise it can happen that an auxiliary objective variable is loose
1702 * with infinite best bound, triggering the problem that an LP that is unbounded because of loose variables with
1703 * infinite best bound cannot be solved)
1704 */
1705 if( nquadcoefs > 0 )
1706 {
1707 SCIP_VAR* quadobjvar;
1708 SCIP_CONS* quadobjcons;
1709 SCIP_Real lhs;
1710 SCIP_Real rhs;
1711 SCIP_Real minusone;
1712
1713 SCIP_CALL( SCIPcreateVar(scip, &quadobjvar, "quadobjvar", -SCIPinfinity(scip), SCIPinfinity(scip), 1.0,
1715 SCIP_CALL( SCIPaddVar(scip, quadobjvar) );
1716
1717 if( lpinput->objsense == SCIP_OBJSENSE_MINIMIZE )
1718 {
1719 lhs = -SCIPinfinity(scip);
1720 rhs = 0.0;
1721 }
1722 else
1723 {
1724 lhs = 0.0;
1725 rhs = SCIPinfinity(scip);
1726 }
1727
1728 minusone = -1.0;
1729 SCIP_CALL( SCIPcreateConsQuadraticNonlinear(scip, &quadobjcons, "quadobj", 1, &quadobjvar, &minusone, nquadcoefs, quadvars1, quadvars2, quadcoefs, lhs, rhs,
1731
1732 SCIP_CALL( SCIPaddCons(scip, quadobjcons) );
1733 SCIPdebugMsg(scip, "(line %d) added constraint <%s> to represent quadratic objective: ", lpinput->linenumber, SCIPconsGetName(quadobjcons));
1734 SCIPdebugPrintCons(scip, quadobjcons, NULL);
1735
1736 SCIP_CALL( SCIPreleaseCons(scip, &quadobjcons) );
1737 SCIP_CALL( SCIPreleaseVar(scip, &quadobjvar) );
1738 }
1739 }
1740
1741 /* free memory */
1742 SCIPfreeBlockMemoryArrayNull(scip, &quadcoefs, quadcoefssize);
1743 SCIPfreeBlockMemoryArrayNull(scip, &quadvars2, quadcoefssize);
1744 SCIPfreeBlockMemoryArrayNull(scip, &quadvars1, quadcoefssize);
1745 SCIPfreeBlockMemoryArrayNull(scip, &vars, coefssize);
1746 SCIPfreeBlockMemoryArrayNull(scip, &coefs, coefssize);
1747
1748 return SCIP_OKAY; /*lint !e438*/
1749}
1750
1751/** create indicator constraint */
1752static
1754 SCIP* scip, /**< SCIP data structure */
1755 LPINPUT* lpinput, /**< LP reading data */
1756 const char* name, /**< name of indicator constraint */
1757 SCIP_VAR* binvar, /**< binary indicator variable */
1758 SCIP_Real binvalue /**< value of indicator part (0/1) */
1759 )
1760{
1761 char name2[LP_MAX_LINELEN];
1762 SCIP_VAR** linvars;
1763 SCIP_Real* lincoefs;
1764 SCIP_VAR** quadvars1;
1765 SCIP_VAR** quadvars2;
1766 SCIP_Real* quadcoefs;
1767 SCIP_CONS* cons;
1768 SCIP_RETCODE retcode;
1769 LPSENSE linsense;
1770 SCIP_Real linsidevalue;
1771 SCIP_Real linrhs;
1772 SCIP_Bool newsection;
1773 SCIP_Bool linConsEQ;
1774 SCIP_Bool initial;
1776 SCIP_Bool enforce;
1777 SCIP_Bool check;
1778 SCIP_Bool propagate;
1779 SCIP_Bool local;
1780 SCIP_Bool dynamic;
1781 SCIP_Bool removable;
1782 int lincoefssize;
1783 int quadcoefssize;
1784 int nlincoefs;
1785 int nquadcoefs;
1786 int linsidesign;
1787 int j;
1788
1789 assert( lpinput != NULL );
1790 assert( binvar != NULL );
1791
1792 retcode = SCIP_OKAY;
1793
1794 /* check that binvalue is 0 or 1 */
1795 if( !SCIPisFeasEQ(scip, binvalue, 0.0) && !SCIPisFeasEQ(scip, binvalue, 1.0) )
1796 {
1797 syntaxError(scip, lpinput, "value for binary variable must be '0' or '1'.");
1798 return SCIP_OKAY;
1799 }
1800
1801 if( SCIPisFeasEQ(scip, binvalue, 0.0) )
1802 {
1803 SCIP_VAR* negbinvar;
1804 SCIP_Bool infeasible;
1805
1806 /* At this point we force the variable binvar to be binary, since we need the negated variable. We have to check
1807 * later whether the type of the variable specified in the file agrees with this specification.
1808 */
1809 /* check whether bounds are correct - might already been set if variable is used in another indicator constraint */
1810 if( SCIPvarGetLbGlobal(binvar) < 0.0 )
1811 SCIP_CALL( SCIPchgVarLb(scip, binvar, 0.0) );
1812 if( SCIPvarGetUbGlobal(binvar) > 1.0 )
1813 SCIP_CALL( SCIPchgVarUb(scip, binvar, 1.0) );
1814 SCIP_CALL( SCIPchgVarType(scip, binvar, SCIP_VARTYPE_BINARY, &infeasible) );
1815 /* don't assert feasibility here because the presolver will and should detect a infeasibility */
1816
1817 SCIP_CALL( SCIPgetNegatedVar(scip, binvar, &negbinvar) );
1818 binvar = negbinvar;
1819 assert( binvar != NULL );
1820 }
1821
1822 /* read linear constraint */
1823 SCIP_CALL( readCoefficients(scip, lpinput, FALSE, name2, &lincoefssize, &linvars, &lincoefs, &nlincoefs,
1824 &quadcoefssize, &quadvars1, &quadvars2, &quadcoefs, &nquadcoefs, NULL, &newsection) );
1825
1826 if( hasError(lpinput) )
1827 goto TERMINATE;
1828 if( newsection )
1829 {
1830 syntaxError(scip, lpinput, "expected constraint.");
1831 goto TERMINATE;
1832 }
1833 if( nquadcoefs > 0 )
1834 {
1835 /* @todo could introduce auxiliary variable and move quadratic part into quadratic constraint? */
1836 syntaxError(scip, lpinput, "quadratic indicator constraints not supported.");
1837 goto TERMINATE;
1838 }
1839 if( name2[0] != '\0' )
1840 {
1841 syntaxError(scip, lpinput, "did not expect name for linear constraint.");
1842 goto TERMINATE;
1843 }
1844
1845 /* read the constraint sense */
1846 if( !getNextToken(scip, lpinput) )
1847 {
1848 syntaxError(scip, lpinput, "missing constraint sense.");
1849 goto TERMINATE;
1850 }
1851 if( !isSense(lpinput, &linsense) )
1852 {
1853 syntaxError(scip, lpinput, "expected constraint sense '<=', '=', or '>='.");
1854 goto TERMINATE;
1855 }
1856 assert(linsense == LP_SENSE_GE || linsense == LP_SENSE_LE || linsense == LP_SENSE_EQ); /*lint !e530*/
1857
1858 /* read the right hand side */
1859 linsidesign = +1;
1860 if( !getNextToken(scip, lpinput) )
1861 {
1862 syntaxError(scip, lpinput, "missing right hand side.");
1863 goto TERMINATE;
1864 }
1865 if( isSign(lpinput, &linsidesign) )
1866 {
1867 if( !getNextToken(scip, lpinput) )
1868 {
1869 syntaxError(scip, lpinput, "missing value of right hand side.");
1870 goto TERMINATE;
1871 }
1872 }
1873 if( !isValue(scip, lpinput, &linsidevalue) )
1874 {
1875 syntaxError(scip, lpinput, "expected value for right hand side.");
1876 goto TERMINATE;
1877 }
1878 linsidevalue *= linsidesign;
1879
1880 /* assign the left and right hand side, depending on the constraint sense */
1881 linConsEQ = FALSE;
1882 switch( linsense ) /*lint !e530*/
1883 {
1884 case LP_SENSE_GE:
1885 linrhs = -linsidevalue;
1886 for( j = 0; j < nlincoefs; ++j )
1887 lincoefs[j] *= -1;
1888 break;
1889 case LP_SENSE_LE:
1890 linrhs = linsidevalue;
1891 break;
1892 case LP_SENSE_EQ:
1893 linConsEQ = TRUE;
1894 linrhs = linsidevalue;
1895 break;
1896 case LP_SENSE_NOTHING:
1897 default:
1898 /* this case cannot occur because it is caught by the syntax check method isSense() above */
1899 SCIPerrorMessage("invalid constraint sense <%d>\n", linsense);
1900 return SCIP_INVALIDDATA;
1901 }
1902 assert(lincoefs != NULL);
1903
1904 /* create and add the indicator constraint */
1905 initial = lpinput->initialconss && !lpinput->inlazyconstraints && !lpinput->inusercuts;
1906 separate = TRUE;
1907 enforce = !lpinput->inusercuts;
1908 check = !lpinput->inusercuts;
1909 propagate = TRUE;
1910 local = FALSE;
1911 dynamic = lpinput->dynamicconss;
1912 removable = lpinput->dynamicrows || lpinput->inusercuts;
1913
1914 retcode = SCIPcreateConsIndicator(scip, &cons, name, binvar, nlincoefs, linvars, lincoefs, linrhs,
1915 initial, separate, enforce, check, propagate, local, dynamic, removable, FALSE);
1916
1917 if( retcode != SCIP_OKAY )
1918 goto TERMINATE;
1919
1920 SCIP_CALL( SCIPaddCons(scip, cons) );
1921 SCIPdebugMsg(scip, "(line %d) created constraint%s: ", lpinput->linenumber,
1922 lpinput->inlazyconstraints ? " (lazy)" : (lpinput->inusercuts ? " (user cut)" : ""));
1924 SCIP_CALL( SCIPreleaseCons(scip, &cons) );
1925
1926 /* create second constraint if it was an equation */
1927 if( linConsEQ )
1928 {
1929 char newname[SCIP_MAXSTRLEN];
1930
1931 (void) SCIPsnprintf(newname, SCIP_MAXSTRLEN, "%s_eqneg", name);
1932
1933 for( j = 0; j < nlincoefs; ++j )
1934 lincoefs[j] *= -1;
1935 linrhs *= -1;
1936 retcode = SCIPcreateConsIndicator(scip, &cons, newname, binvar, nlincoefs, linvars, lincoefs, linrhs,
1937 initial, separate, enforce, check, propagate, local, dynamic, removable, FALSE);
1938
1939 if( retcode != SCIP_OKAY )
1940 goto TERMINATE;
1941
1942 SCIP_CALL( SCIPaddCons(scip, cons) );
1943 SCIPdebugMsg(scip, "(line %d) created constraint%s: ", lpinput->linenumber,
1944 lpinput->inlazyconstraints ? " (lazy)" : (lpinput->inusercuts ? " (user cut)" : ""));
1946 SCIP_CALL( SCIPreleaseCons(scip, &cons) );
1947 }
1948
1949 TERMINATE:
1950 /* free memory */
1951 SCIPfreeBlockMemoryArrayNull(scip, &quadvars1, quadcoefssize);
1952 SCIPfreeBlockMemoryArrayNull(scip, &quadvars2, quadcoefssize);
1953 SCIPfreeBlockMemoryArrayNull(scip, &quadcoefs, quadcoefssize);
1954 SCIPfreeBlockMemoryArrayNull(scip, &lincoefs, lincoefssize);
1955 SCIPfreeBlockMemoryArrayNull(scip, &linvars, lincoefssize);
1956
1957 SCIP_CALL( retcode );
1958
1959 return SCIP_OKAY;
1960}
1961
1962/** reads the constraints section
1963 *
1964 * Read linear and indicator constraints.
1965 *
1966 * The CPLEX manual says that indicator constraints are of the following form:
1967 *
1968 * [constraintname:] binaryvariable = value -> linear constraint
1969 *
1970 * We also accept "<->".
1971 */
1972static
1974 SCIP* scip, /**< SCIP data structure */
1975 LPINPUT* lpinput /**< LP reading data */
1976 )
1977{
1978 char name[LP_MAX_LINELEN];
1979 SCIP_CONS* cons;
1980 SCIP_VAR** vars;
1981 SCIP_RATIONAL** coefs;
1982 LPSENSE sense;
1983 SCIP_RETCODE retcode;
1984 SCIP_RATIONAL* sidevalue;
1985 SCIP_RATIONAL* lhs;
1986 SCIP_RATIONAL* rhs;
1987 SCIP_Bool newsection;
1988 SCIP_Bool initial;
1990 SCIP_Bool enforce;
1991 SCIP_Bool check;
1992 SCIP_Bool propagate;
1993 SCIP_Bool local;
1994 SCIP_Bool modifiable;
1995 SCIP_Bool dynamic;
1996 SCIP_Bool removable;
1997 SCIP_Bool isIndicatorCons;
1998 int ncoefs;
1999 int sidesign;
2000 int coefssize;
2001
2002 assert(lpinput != NULL);
2003
2004 retcode = SCIP_OKAY;
2005
2009
2010 /* read coefficients */
2011 SCIP_CALL( readCoefficientsRational(scip, lpinput, FALSE, name, &coefssize, &vars, &coefs, &ncoefs,
2012 NULL, &newsection) );
2013
2014 if( hasError(lpinput) )
2015 goto TERMINATE;
2016 if( newsection )
2017 {
2018 if( ncoefs > 0 )
2019 syntaxError(scip, lpinput, "expected constraint sense '<=', '=', or '>='.");
2020 goto TERMINATE;
2021 }
2022
2023 /* read the constraint sense */
2024 if( !getNextToken(scip, lpinput) )
2025 {
2026 syntaxError(scip, lpinput, "missing constraint sense.");
2027 goto TERMINATE;
2028 }
2029 if( !isSense(lpinput, &sense) )
2030 {
2031 syntaxError(scip, lpinput, "expected constraint sense '<=', '=', or '>='.");
2032 goto TERMINATE;
2033 }
2034 assert(sense == LP_SENSE_GE || sense == LP_SENSE_LE || sense == LP_SENSE_EQ); /*lint !e530*/
2035
2036 /* read the right hand side */
2037 sidesign = +1;
2038 if( !getNextToken(scip, lpinput) )
2039 {
2040 syntaxError(scip, lpinput, "missing right hand side.");
2041 goto TERMINATE;
2042 }
2043 if( isSign(lpinput, &sidesign) )
2044 {
2045 if( !getNextToken(scip, lpinput) )
2046 {
2047 syntaxError(scip, lpinput, "missing value of right hand side.");
2048 goto TERMINATE;
2049 }
2050 }
2051 if( !isValueRational(scip, lpinput, sidevalue) )
2052 {
2053 syntaxError(scip, lpinput, "expected value as right hand side.");
2054 goto TERMINATE;
2055 }
2056 SCIPrationalMultReal(sidevalue, sidevalue, (double) sidesign);
2057
2058 /* assign the left and right hand side, depending on the constraint sense */
2059 switch( sense ) /*lint !e530*/
2060 {
2061 case LP_SENSE_GE:
2062 SCIPrationalSetRational(lhs, sidevalue);
2064 break;
2065 case LP_SENSE_LE:
2067 SCIPrationalSetRational(rhs, sidevalue);
2068 break;
2069 case LP_SENSE_EQ:
2070 SCIPrationalSetRational(lhs, sidevalue);
2071 SCIPrationalSetRational(rhs, sidevalue);
2072 break;
2073 case LP_SENSE_NOTHING:
2074 default:
2075 /* this case cannot occur because it is caught by the syntax check method isSense() above */
2076 SCIPerrorMessage("invalid constraint sense <%d>.\n", sense);
2077 return SCIP_INVALIDDATA;
2078 }
2079
2080 /* check whether we read the first part of an indicator constraint */
2081 isIndicatorCons = FALSE;
2082 if ( getNextToken(scip, lpinput) && !isNewSection(scip, lpinput) )
2083 {
2084 /* check whether we have '<' from a "<->" string */
2085 if ( *lpinput->token == '<' )
2086 {
2087 int linepos = lpinput->linepos-1;
2088
2089 /* check next token - cannot be a new section */
2090 if ( getNextToken(scip, lpinput) )
2091 {
2092 /* check for "<-" */
2093 if ( *lpinput->token == '-' )
2094 {
2095 /* check next token - cannot be a new section */
2096 if ( getNextToken(scip, lpinput) )
2097 {
2098 /* check for "<->" */
2099 if ( *lpinput->token == '>' )
2100 {
2101 lpinput->linepos = linepos;
2102 (void) SCIPsnprintf(lpinput->token, 2, "<");
2103 syntaxError(scip, lpinput,
2104 "SCIP does not support equivalence (<->) indicator constraints; consider using the \"->\" form.");
2105 goto TERMINATE;
2106 }
2107 }
2108 }
2109 }
2110 /* reset the lpinput for further usage as we have no indicator constraint */
2111 lpinput->linepos = linepos;
2112 (void) SCIPsnprintf(lpinput->token, 2, "<");
2113 }
2114
2115 /* check for "->" */
2116 if ( *lpinput->token == '-' )
2117 {
2118 /* remember '-' in token buffer */
2119 swapTokenBuffer(lpinput);
2120
2121 /* check next token - cannot be a new section */
2122 if( getNextToken(scip, lpinput) )
2123 {
2124 /* check for "->" */
2125 if ( *lpinput->token == '>' )
2126 isIndicatorCons = TRUE;
2127 else
2128 {
2129 /* push back last token and '-' */
2130 pushToken(lpinput);
2131 pushBufferToken(lpinput);
2132 }
2133 }
2134 else
2135 pushBufferToken(lpinput);
2136 }
2137 else
2138 pushToken(lpinput);
2139 }
2140
2141 if( !isIndicatorCons )
2142 {
2143 /* create and add the linear constraint */
2144 initial = lpinput->initialconss && !lpinput->inlazyconstraints && !lpinput->inusercuts;
2145 separate = TRUE;
2146 enforce = !lpinput->inusercuts;
2147 check = !lpinput->inusercuts;
2148 propagate = TRUE;
2149 local = FALSE;
2150 modifiable = FALSE;
2151 dynamic = lpinput->dynamicconss;
2152 removable = lpinput->dynamicrows || lpinput->inusercuts;
2153
2154 retcode = SCIPcreateConsExactLinear(scip, &cons, name, ncoefs, vars, coefs, lhs, rhs,
2155 initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, FALSE);
2156
2157 if( retcode != SCIP_OKAY )
2158 goto TERMINATE;
2159
2160 SCIP_CALL( SCIPaddCons(scip, cons) );
2161 SCIPdebugMsg(scip, "(line %d) created constraint%s: ", lpinput->linenumber,
2162 lpinput->inlazyconstraints ? " (lazy)" : (lpinput->inusercuts ? " (user cut)" : ""));
2164 SCIP_CALL( SCIPreleaseCons(scip, &cons) );
2165 }
2166 else
2167 {
2168 /* now we should have an indicator constraint */
2169 if( ncoefs != 1 )
2170 {
2171 syntaxError(scip, lpinput, "Indicator part can only consist of one binary variable.");
2172 goto TERMINATE;
2173 }
2174 assert(coefs != NULL);
2175 if( !SCIPrationalIsEQReal(coefs[0], 1.0) )
2176 {
2177 syntaxError(scip, lpinput, "There cannot be a coefficient before the binary indicator variable.");
2178 goto TERMINATE;
2179 }
2180 if( sense != LP_SENSE_EQ )
2181 {
2182 syntaxError(scip, lpinput, "Indicator part cannot handle equations.");
2183 goto TERMINATE;
2184 }
2185 assert(vars != NULL);
2186 retcode = createIndicatorConstraint(scip, lpinput, name, vars[0], SCIPrationalGetReal(lhs));
2187 }
2188
2189 TERMINATE:
2190 /* free memory */
2191 SCIPrationalFreeBlockArray(SCIPblkmem(scip), &coefs, coefssize);
2192 SCIPfreeBlockMemoryArrayNull(scip, &vars, coefssize);
2193
2197
2198 SCIP_CALL( retcode );
2199
2200 return SCIP_OKAY;
2201}
2202
2203
2204/** reads the constraints section
2205 *
2206 * Read linear and indicator constraints.
2207 *
2208 * The CPLEX manual says that indicator constraints are of the following form:
2209 *
2210 * [constraintname:] binaryvariable = value -> linear constraint
2211 *
2212 * We also accept "<->".
2213 */
2214static
2216 SCIP* scip, /**< SCIP data structure */
2217 LPINPUT* lpinput /**< LP reading data */
2218 )
2219{
2220 char name[LP_MAX_LINELEN];
2221 SCIP_CONS* cons;
2222 SCIP_VAR** vars;
2223 SCIP_Real* coefs;
2224 SCIP_VAR** quadvars1;
2225 SCIP_VAR** quadvars2;
2226 SCIP_Real* quadcoefs;
2227 LPSENSE sense;
2228 SCIP_RETCODE retcode;
2229 SCIP_Real sidevalue;
2230 SCIP_Real lhs;
2231 SCIP_Real rhs;
2232 SCIP_Bool newsection;
2233 SCIP_Bool initial;
2235 SCIP_Bool enforce;
2236 SCIP_Bool check;
2237 SCIP_Bool propagate;
2238 SCIP_Bool local;
2239 SCIP_Bool modifiable;
2240 SCIP_Bool dynamic;
2241 SCIP_Bool removable;
2242 SCIP_Bool isIndicatorCons;
2243 int ncoefs;
2244 int sidesign;
2245 int nquadcoefs;
2246 int quadcoefssize;
2247 int coefssize;
2248
2249 assert(lpinput != NULL);
2250
2251 retcode = SCIP_OKAY;
2252
2253 if( SCIPisExact(scip) )
2254 {
2256 return SCIP_OKAY;
2257 }
2258
2259 /* read coefficients */
2260 SCIP_CALL( readCoefficients(scip, lpinput, FALSE, name, &coefssize, &vars, &coefs, &ncoefs,
2261 &quadcoefssize, &quadvars1, &quadvars2, &quadcoefs, &nquadcoefs, NULL, &newsection) );
2262
2263 if( hasError(lpinput) )
2264 goto TERMINATE;
2265 if( newsection )
2266 {
2267 if( ncoefs > 0 || nquadcoefs > 0 )
2268 syntaxError(scip, lpinput, "expected constraint sense '<=', '=', or '>='.");
2269 goto TERMINATE;
2270 }
2271
2272 /* read the constraint sense */
2273 if( !getNextToken(scip, lpinput) )
2274 {
2275 syntaxError(scip, lpinput, "missing constraint sense.");
2276 goto TERMINATE;
2277 }
2278 if( !isSense(lpinput, &sense) )
2279 {
2280 syntaxError(scip, lpinput, "expected constraint sense '<=', '=', or '>='.");
2281 goto TERMINATE;
2282 }
2283 assert(sense == LP_SENSE_GE || sense == LP_SENSE_LE || sense == LP_SENSE_EQ); /*lint !e530*/
2284
2285 /* read the right hand side */
2286 sidesign = +1;
2287 if( !getNextToken(scip, lpinput) )
2288 {
2289 syntaxError(scip, lpinput, "missing right hand side.");
2290 goto TERMINATE;
2291 }
2292 if( isSign(lpinput, &sidesign) )
2293 {
2294 if( !getNextToken(scip, lpinput) )
2295 {
2296 syntaxError(scip, lpinput, "missing value of right hand side.");
2297 goto TERMINATE;
2298 }
2299 }
2300 if( !isValue(scip, lpinput, &sidevalue) )
2301 {
2302 syntaxError(scip, lpinput, "expected value as right hand side.");
2303 goto TERMINATE;
2304 }
2305 sidevalue *= sidesign;
2306
2307 /* assign the left and right hand side, depending on the constraint sense */
2308 switch( sense ) /*lint !e530*/
2309 {
2310 case LP_SENSE_GE:
2311 lhs = sidevalue;
2312 rhs = SCIPinfinity(scip);
2313 break;
2314 case LP_SENSE_LE:
2315 lhs = -SCIPinfinity(scip);
2316 rhs = sidevalue;
2317 break;
2318 case LP_SENSE_EQ:
2319 lhs = sidevalue;
2320 rhs = sidevalue;
2321 break;
2322 case LP_SENSE_NOTHING:
2323 default:
2324 /* this case cannot occur because it is caught by the syntax check method isSense() above */
2325 SCIPerrorMessage("invalid constraint sense <%d>.\n", sense);
2326 return SCIP_INVALIDDATA;
2327 }
2328
2329 /* check whether we read the first part of an indicator constraint */
2330 isIndicatorCons = FALSE;
2331 if ( getNextToken(scip, lpinput) && !isNewSection(scip, lpinput) )
2332 {
2333 /* check whether we have '<' from a "<->" string */
2334 if ( *lpinput->token == '<' )
2335 {
2336 int linepos = lpinput->linepos-1;
2337
2338 /* check next token - cannot be a new section */
2339 if ( getNextToken(scip, lpinput) )
2340 {
2341 /* check for "<-" */
2342 if ( *lpinput->token == '-' )
2343 {
2344 /* check next token - cannot be a new section */
2345 if ( getNextToken(scip, lpinput) )
2346 {
2347 /* check for "<->" */
2348 if ( *lpinput->token == '>' )
2349 {
2350 lpinput->linepos = linepos;
2351 (void) SCIPsnprintf(lpinput->token, 2, "<");
2352 syntaxError(scip, lpinput,
2353 "SCIP does not support equivalence (<->) indicator constraints; consider using the \"->\" form.");
2354 goto TERMINATE;
2355 }
2356 }
2357 }
2358 }
2359 /* reset the lpinput for further usage as we have no indicator constraint */
2360 lpinput->linepos = linepos;
2361 (void) SCIPsnprintf(lpinput->token, 2, "<");
2362 }
2363
2364 /* check for "->" */
2365 if ( *lpinput->token == '-' )
2366 {
2367 /* remember '-' in token buffer */
2368 swapTokenBuffer(lpinput);
2369
2370 /* check next token - cannot be a new section */
2371 if( getNextToken(scip, lpinput) )
2372 {
2373 /* check for "->" */
2374 if ( *lpinput->token == '>' )
2375 isIndicatorCons = TRUE;
2376 else
2377 {
2378 /* push back last token and '-' */
2379 pushToken(lpinput);
2380 pushBufferToken(lpinput);
2381 }
2382 }
2383 else
2384 pushBufferToken(lpinput);
2385 }
2386 else
2387 pushToken(lpinput);
2388 }
2389
2390 if( !isIndicatorCons )
2391 {
2392 /* create and add the linear constraint */
2393 initial = lpinput->initialconss && !lpinput->inlazyconstraints && !lpinput->inusercuts;
2394 separate = TRUE;
2395 enforce = !lpinput->inusercuts;
2396 check = !lpinput->inusercuts;
2397 propagate = TRUE;
2398 local = FALSE;
2399 modifiable = FALSE;
2400 dynamic = lpinput->dynamicconss;
2401 removable = lpinput->dynamicrows || lpinput->inusercuts;
2402 if( nquadcoefs == 0 )
2403 {
2404 retcode = SCIPcreateConsLinear(scip, &cons, name, ncoefs, vars, coefs, lhs, rhs,
2405 initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, FALSE);
2406 }
2407 else
2408 {
2409 retcode = SCIPcreateConsQuadraticNonlinear(scip, &cons, name, ncoefs, vars, coefs,
2410 nquadcoefs, quadvars1, quadvars2, quadcoefs, lhs, rhs,
2411 initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable);
2412 }
2413
2414 if( retcode != SCIP_OKAY )
2415 goto TERMINATE;
2416
2417 SCIP_CALL( SCIPaddCons(scip, cons) );
2418 SCIPdebugMsg(scip, "(line %d) created constraint%s: ", lpinput->linenumber,
2419 lpinput->inlazyconstraints ? " (lazy)" : (lpinput->inusercuts ? " (user cut)" : ""));
2421 SCIP_CALL( SCIPreleaseCons(scip, &cons) );
2422 }
2423 else
2424 {
2425 /* now we should have an indicator constraint */
2426 if( ncoefs != 1 || nquadcoefs > 0 )
2427 {
2428 syntaxError(scip, lpinput, "Indicator part can only consist of one binary variable.");
2429 goto TERMINATE;
2430 }
2431 assert(coefs != NULL);
2432 if( !SCIPisEQ(scip, coefs[0], 1.0) )
2433 {
2434 syntaxError(scip, lpinput, "There cannot be a coefficient before the binary indicator variable.");
2435 goto TERMINATE;
2436 }
2437 if( sense != LP_SENSE_EQ )
2438 {
2439 syntaxError(scip, lpinput, "Indicator part cannot handle equations.");
2440 goto TERMINATE;
2441 }
2442 assert(vars != NULL);
2443 retcode = createIndicatorConstraint(scip, lpinput, name, vars[0], lhs);
2444 }
2445
2446 TERMINATE:
2447 /* free memory */
2448 SCIPfreeBlockMemoryArrayNull(scip, &quadcoefs, quadcoefssize);
2449 SCIPfreeBlockMemoryArrayNull(scip, &quadvars2, quadcoefssize);
2450 SCIPfreeBlockMemoryArrayNull(scip, &quadvars1, quadcoefssize);
2451 SCIPfreeBlockMemoryArrayNull(scip, &coefs, coefssize);
2452 SCIPfreeBlockMemoryArrayNull(scip, &vars, coefssize);
2453
2454 SCIP_CALL( retcode );
2455
2456 return SCIP_OKAY;
2457}
2458
2459/** reads the bounds section */
2460static
2462 SCIP* scip, /**< SCIP data structure */
2463 LPINPUT* lpinput /**< LP reading data */
2464 )
2465{
2466 SCIP_RATIONAL* value;
2467 SCIP_RATIONAL* lb;
2468 SCIP_RATIONAL* ub;
2469
2470 assert(lpinput != NULL);
2471
2475
2476 while( getNextToken(scip, lpinput) )
2477 {
2478 SCIP_VAR* var;
2479
2480 int sign;
2481 SCIP_Bool hassign;
2482 LPSENSE leftsense;
2483
2484 /* check if we reached a new section */
2485 if( isNewSection(scip, lpinput) )
2486 goto TERMINATE;
2487
2488 /* default bounds are [0,+inf] */
2489 SCIPrationalSetReal(lb, 0.0);
2491 leftsense = LP_SENSE_NOTHING;
2492
2493 /* check if the first token is a sign */
2494 sign = +1;
2495 hassign = isSign(lpinput, &sign);
2496 if( hassign && !getNextToken(scip, lpinput) )
2497 {
2498 syntaxError(scip, lpinput, "expected value.");
2499 goto TERMINATE;
2500 }
2501
2502 /* the first token must be either a value or a variable name */
2503 if( isValueRational(scip, lpinput, value) )
2504 {
2505 /* first token is a value: the second token must be a sense */
2506 if( !getNextToken(scip, lpinput) || !isSense(lpinput, &leftsense) )
2507 {
2508 syntaxError(scip, lpinput, "expected bound sense '<=', '=', or '>='.");
2509 goto TERMINATE;
2510 }
2511
2512 /* update the bound corresponding to the sense */
2513 switch( leftsense )
2514 {
2515 case LP_SENSE_GE:
2516 SCIPrationalMultReal(ub, value, (double) sign);
2517 break;
2518 case LP_SENSE_LE:
2519 SCIPrationalMultReal(lb, value, (double) sign);
2520 break;
2521 case LP_SENSE_EQ:
2522 SCIPrationalMultReal(lb, value, (double) sign);
2523 SCIPrationalMultReal(ub, value, (double) sign);
2524 break;
2525 case LP_SENSE_NOTHING:
2526 default:
2527 SCIPerrorMessage("invalid bound sense <%d>\n", leftsense);
2528 return SCIP_INVALIDDATA;
2529 }
2530 }
2531 else if( hassign )
2532 {
2533 syntaxError(scip, lpinput, "expected value.");
2534 goto TERMINATE;
2535 }
2536 else
2537 pushToken(lpinput);
2538
2539 /* the next token must be a variable name */
2540 if( !getNextToken(scip, lpinput) )
2541 {
2542 syntaxError(scip, lpinput, "expected variable name.");
2543 goto TERMINATE;
2544 }
2545 SCIP_CALL( getVariable(scip, lpinput->token, &var, NULL) );
2546
2547 /* the next token might be another sense, or the word "free" */
2548 if( getNextToken(scip, lpinput) )
2549 {
2550 LPSENSE rightsense;
2551
2552 if( isSense(lpinput, &rightsense) )
2553 {
2554 /* check, if the senses fit */
2555 if( leftsense == LP_SENSE_NOTHING
2556 || (leftsense == LP_SENSE_LE && rightsense == LP_SENSE_LE)
2557 || (leftsense == LP_SENSE_GE && rightsense == LP_SENSE_GE) )
2558 {
2559 if( !getNextToken(scip, lpinput) )
2560 {
2561 syntaxError(scip, lpinput, "expected value or sign.");
2562 goto TERMINATE;
2563 }
2564
2565 /* check if the next token is a sign */
2566 sign = +1;
2567 hassign = isSign(lpinput, &sign);
2568 if( hassign && !getNextToken(scip, lpinput) )
2569 {
2570 syntaxError(scip, lpinput, "expected value.");
2571 goto TERMINATE;
2572 }
2573
2574 /* the next token must be a value */
2575 if( !isValueRational(scip, lpinput, value) )
2576 {
2577 syntaxError(scip, lpinput, "expected value.");
2578 goto TERMINATE;
2579 }
2580
2581 /* update the bound corresponding to the sense */
2582 switch( rightsense )
2583 {
2584 case LP_SENSE_GE:
2585 SCIPrationalMultReal(lb, value, (double) sign);
2586 break;
2587 case LP_SENSE_LE:
2588 SCIPrationalMultReal(ub, value, (double) sign);
2589 break;
2590 case LP_SENSE_EQ:
2591 SCIPrationalMultReal(lb, value, (double) sign);
2592 SCIPrationalMultReal(ub, value, (double) sign);
2593 break;
2594 case LP_SENSE_NOTHING:
2595 default:
2596 SCIPerrorMessage("invalid bound sense <%d>\n", leftsense);
2597 return SCIP_INVALIDDATA;
2598 }
2599 }
2600 else
2601 {
2602 syntaxError(scip, lpinput, "the two bound senses do not fit.");
2603 goto TERMINATE;
2604 }
2605 }
2606 else if( SCIPstrcasecmp(lpinput->token, "FREE") == 0 )
2607 {
2608 if( leftsense != LP_SENSE_NOTHING )
2609 {
2610 syntaxError(scip, lpinput, "variable with bound is marked as 'free'.");
2611 goto TERMINATE;
2612 }
2615 }
2616 else
2617 {
2618 /* the token was no sense: push it back to the token stack */
2619 pushToken(lpinput);
2620 }
2621 }
2622
2623 /* change the bounds of the variable if bounds have been given (do not destroy earlier specification of bounds) */
2624 if( !SCIPrationalIsZero(lb) )
2625 SCIP_CALL( SCIPchgVarLbExact(scip, var, lb) );
2626 /*lint --e{777}*/
2627 if( !SCIPrationalIsInfinity(ub) )
2628 SCIP_CALL( SCIPchgVarUbExact(scip, var, ub) );
2629 SCIPdebugMsg(scip, "(line %d) new bounds: <%s>[%g,%g]\n", lpinput->linenumber, SCIPvarGetName(var),
2631 }
2632
2633TERMINATE:
2637
2638 return SCIP_OKAY;
2639}
2640
2641
2642/** reads the bounds section */
2643static
2645 SCIP* scip, /**< SCIP data structure */
2646 LPINPUT* lpinput /**< LP reading data */
2647 )
2648{
2649 assert(lpinput != NULL);
2650
2651 if( SCIPisExact(scip) )
2652 {
2653 SCIP_CALL( readBoundsRational(scip, lpinput) );
2654 return SCIP_OKAY;
2655 }
2656
2657 while( getNextToken(scip, lpinput) )
2658 {
2659 SCIP_VAR* var;
2660 SCIP_Real value;
2661 SCIP_Real lb;
2662 SCIP_Real ub;
2663 int sign;
2664 SCIP_Bool hassign;
2665 LPSENSE leftsense;
2666
2667 /* check if we reached a new section */
2668 if( isNewSection(scip, lpinput) )
2669 return SCIP_OKAY;
2670
2671 /* default bounds are [0,+inf] */
2672 lb = 0.0;
2673 ub = SCIPinfinity(scip);
2674 leftsense = LP_SENSE_NOTHING;
2675
2676 /* check if the first token is a sign */
2677 sign = +1;
2678 hassign = isSign(lpinput, &sign);
2679 if( hassign && !getNextToken(scip, lpinput) )
2680 {
2681 syntaxError(scip, lpinput, "expected value.");
2682 return SCIP_OKAY;
2683 }
2684
2685 /* the first token must be either a value or a variable name */
2686 if( isValue(scip, lpinput, &value) )
2687 {
2688 /* first token is a value: the second token must be a sense */
2689 if( !getNextToken(scip, lpinput) || !isSense(lpinput, &leftsense) )
2690 {
2691 syntaxError(scip, lpinput, "expected bound sense '<=', '=', or '>='.");
2692 return SCIP_OKAY;
2693 }
2694
2695 /* update the bound corresponding to the sense */
2696 switch( leftsense )
2697 {
2698 case LP_SENSE_GE:
2699 ub = sign * value;
2700 break;
2701 case LP_SENSE_LE:
2702 lb = sign * value;
2703 break;
2704 case LP_SENSE_EQ:
2705 lb = sign * value;
2706 ub = sign * value;
2707 break;
2708 case LP_SENSE_NOTHING:
2709 default:
2710 SCIPerrorMessage("invalid bound sense <%d>\n", leftsense);
2711 return SCIP_INVALIDDATA;
2712 }
2713 }
2714 else if( hassign )
2715 {
2716 syntaxError(scip, lpinput, "expected value.");
2717 return SCIP_OKAY;
2718 }
2719 else
2720 pushToken(lpinput);
2721
2722 /* the next token must be a variable name */
2723 if( !getNextToken(scip, lpinput) )
2724 {
2725 syntaxError(scip, lpinput, "expected variable name.");
2726 return SCIP_OKAY;
2727 }
2728 SCIP_CALL( getVariable(scip, lpinput->token, &var, NULL) );
2729
2730 /* the next token might be another sense, or the word "free" */
2731 if( getNextToken(scip, lpinput) )
2732 {
2733 LPSENSE rightsense;
2734
2735 if( isSense(lpinput, &rightsense) )
2736 {
2737 /* check, if the senses fit */
2738 if( leftsense == LP_SENSE_NOTHING
2739 || (leftsense == LP_SENSE_LE && rightsense == LP_SENSE_LE)
2740 || (leftsense == LP_SENSE_GE && rightsense == LP_SENSE_GE) )
2741 {
2742 if( !getNextToken(scip, lpinput) )
2743 {
2744 syntaxError(scip, lpinput, "expected value or sign.");
2745 return SCIP_OKAY;
2746 }
2747
2748 /* check if the next token is a sign */
2749 sign = +1;
2750 hassign = isSign(lpinput, &sign);
2751 if( hassign && !getNextToken(scip, lpinput) )
2752 {
2753 syntaxError(scip, lpinput, "expected value.");
2754 return SCIP_OKAY;
2755 }
2756
2757 /* the next token must be a value */
2758 if( !isValue(scip, lpinput, &value) )
2759 {
2760 syntaxError(scip, lpinput, "expected value.");
2761 return SCIP_OKAY;
2762 }
2763
2764 /* update the bound corresponding to the sense */
2765 switch( rightsense )
2766 {
2767 case LP_SENSE_GE:
2768 lb = sign * value;
2769 break;
2770 case LP_SENSE_LE:
2771 ub = sign * value;
2772 break;
2773 case LP_SENSE_EQ:
2774 lb = sign * value;
2775 ub = sign * value;
2776 break;
2777 case LP_SENSE_NOTHING:
2778 default:
2779 SCIPerrorMessage("invalid bound sense <%d>\n", leftsense);
2780 return SCIP_INVALIDDATA;
2781 }
2782 }
2783 else
2784 {
2785 syntaxError(scip, lpinput, "the two bound senses do not fit.");
2786 return SCIP_OKAY;
2787 }
2788 }
2789 else if( SCIPstrcasecmp(lpinput->token, "FREE") == 0 )
2790 {
2791 if( leftsense != LP_SENSE_NOTHING )
2792 {
2793 syntaxError(scip, lpinput, "variable with bound is marked as 'free'.");
2794 return SCIP_OKAY;
2795 }
2796 lb = -SCIPinfinity(scip);
2797 ub = SCIPinfinity(scip);
2798 }
2799 else
2800 {
2801 /* the token was no sense: push it back to the token stack */
2802 pushToken(lpinput);
2803 }
2804 }
2805
2806 /* change the bounds of the variable if bounds have been given (do not destroy earlier specification of bounds) */
2807 if( lb != 0.0 )
2808 SCIP_CALL( SCIPchgVarLb(scip, var, lb) );
2809 /*lint --e{777}*/
2810 if( ub != SCIPinfinity(scip) )
2811 SCIP_CALL( SCIPchgVarUb(scip, var, ub) );
2812 SCIPdebugMsg(scip, "(line %d) new bounds: <%s>[%g,%g]\n", lpinput->linenumber, SCIPvarGetName(var),
2814 }
2815
2816 return SCIP_OKAY;
2817}
2818
2819/** reads the generals section */
2820static
2822 SCIP* scip, /**< SCIP data structure */
2823 LPINPUT* lpinput /**< LP reading data */
2824 )
2825{
2826 assert(lpinput != NULL);
2827
2828 while( getNextToken(scip, lpinput) )
2829 {
2830 SCIP_VAR* var;
2831 SCIP_Real lb;
2832 SCIP_Real ub;
2833 SCIP_Bool created;
2834 SCIP_Bool infeasible;
2835
2836 /* check if we reached a new section */
2837 if( isNewSection(scip, lpinput) )
2838 return SCIP_OKAY;
2839
2840 /* the token must be the name of an existing variable */
2841 SCIP_CALL( getVariable(scip, lpinput->token, &var, &created) );
2842 if( created )
2843 {
2844 syntaxError(scip, lpinput, "unknown variable in generals section.");
2845 return SCIP_OKAY;
2846 }
2847
2848 lb = SCIPvarGetLbGlobal(var);
2849 ub = SCIPvarGetUbGlobal(var);
2850
2851 if( !SCIPisFeasIntegral(scip, lb) || !SCIPisFeasIntegral(scip, ub) )
2852 {
2853 SCIPwarningMessage(scip, "variable <%s> declared as integer has non-integral bounds[%.14g, %.14g] -> if feasible, bounds will be adjusted\n", SCIPvarGetName(var), lb, ub);
2854 }
2855
2856 /* mark the variable to be integral */
2857 SCIP_CALL( SCIPchgVarType(scip, var, SCIP_VARTYPE_INTEGER, &infeasible) );
2858 /* don't assert feasibility here because the presolver will and should detect a infeasibility */
2859 }
2860
2861 return SCIP_OKAY;
2862}
2863
2864/** reads the binaries section */
2865static
2867 SCIP* scip, /**< SCIP data structure */
2868 LPINPUT* lpinput /**< LP reading data */
2869 )
2870{
2871 assert(lpinput != NULL);
2872
2873 while( getNextToken(scip, lpinput) )
2874 {
2875 SCIP_VAR* var;
2876 SCIP_Real lb;
2877 SCIP_Real ub;
2878 SCIP_Bool created;
2879 SCIP_Bool infeasible;
2880
2881 /* check if we reached a new section */
2882 if( isNewSection(scip, lpinput) )
2883 return SCIP_OKAY;
2884
2885 /* the token must be the name of an existing variable */
2886 SCIP_CALL( getVariable(scip, lpinput->token, &var, &created) );
2887 if( created )
2888 {
2889 syntaxError(scip, lpinput, "unknown variable in binaries section.");
2890 return SCIP_OKAY;
2891 }
2892
2893 lb = SCIPvarGetLbGlobal(var);
2894 ub = SCIPvarGetUbGlobal(var);
2895
2896 if( (!SCIPisFeasZero(scip, lb) && !SCIPisFeasEQ(scip, lb, 1.0)) ||
2897 (!SCIPisFeasZero(scip, ub) && !SCIPisFeasEQ(scip, ub, 1.0) && !SCIPisInfinity(scip, ub)) )
2898 {
2899 SCIPwarningMessage(scip, "variable <%s> declared as binary has non-binary bounds[%.14g, %.14g] -> if feasible, bounds will be adjusted\n", SCIPvarGetName(var), lb, ub);
2900 }
2901
2902 /* mark the variable to be binary and change its bounds appropriately */
2903 if( SCIPvarGetLbGlobal(var) < 0.0 )
2904 {
2905 SCIP_CALL( SCIPchgVarLb(scip, var, 0.0) );
2906 if( SCIPisExact(scip) )
2907 {
2908 SCIP_RATIONAL* tmp;
2910 SCIPrationalSetReal(tmp, 0.0);
2911 SCIP_CALL( SCIPchgVarLbExact(scip, var, tmp) );
2913 }
2914 }
2915 if( SCIPvarGetUbGlobal(var) > 1.0 )
2916 {
2917 SCIP_CALL( SCIPchgVarUb(scip, var, 1.0) );
2918 if( SCIPisExact(scip) )
2919 {
2920 SCIP_RATIONAL* tmp;
2922 SCIPrationalSetReal(tmp, 1.0);
2923 SCIP_CALL( SCIPchgVarUbExact(scip, var, tmp) );
2925 }
2926 }
2927 SCIP_CALL( SCIPchgVarType(scip, var, SCIP_VARTYPE_BINARY, &infeasible) );
2928 /* don't assert feasibility here because the presolver will and should detect a infeasibility */
2929 }
2930
2931 return SCIP_OKAY;
2932}
2933
2934/** reads the semi-continuous section */
2935static
2937 SCIP* scip, /**< SCIP data structure */
2938 LPINPUT* lpinput /**< LP reading data */
2939 )
2940{
2941 SCIP_Real oldlb;
2942 char name[SCIP_MAXSTRLEN];
2943 SCIP_CONS* cons;
2944 SCIP_VAR* var;
2945 SCIP_Bool created;
2946
2947 SCIP_VAR* vars[2];
2948 SCIP_BOUNDTYPE boundtypes[2];
2949 SCIP_Real bounds[2];
2950
2951 assert(lpinput != NULL);
2952
2953 /* if section is titles "semi-continuous", then the parser breaks this into parts */
2954 if( SCIPstrcasecmp(lpinput->token, "SEMI") == 0 )
2955 {
2956 if( !getNextToken(scip, lpinput) )
2957 {
2958 syntaxError(scip, lpinput, "unexpected end.");
2959 return SCIP_OKAY;
2960 }
2961
2962 if( SCIPstrcasecmp(lpinput->token, "-") == 0 )
2963 {
2964 if( !getNextToken(scip, lpinput) || SCIPstrcasecmp(lpinput->token, "CONTINUOUS") != 0 )
2965 {
2966 syntaxError(scip, lpinput, "expected 'CONTINUOUS' after 'SEMI-'.");
2967 return SCIP_OKAY;
2968 }
2969 }
2970 else
2971 {
2972 pushToken(lpinput);
2973 }
2974 }
2975
2976 while( getNextToken(scip, lpinput) )
2977 {
2978 /* check if we reached a new section */
2979 if( isNewSection(scip, lpinput) )
2980 return SCIP_OKAY;
2981
2982 /* the token must be the name of an existing variable */
2983 SCIP_CALL( getVariable(scip, lpinput->token, &var, &created) );
2984 if( created )
2985 {
2986 syntaxError(scip, lpinput, "unknown variable in semi-continuous section.");
2987 return SCIP_OKAY;
2988 }
2989
2990 if( SCIPvarGetLbGlobal(var) <= 0.0 )
2991 {
2992 SCIPdebugMsg(scip, "ignore semi-continuity of variable <%s> with negative lower bound %g\n", SCIPvarGetName(var), SCIPvarGetLbGlobal(var));
2993 continue;
2994 }
2995
2996 oldlb = SCIPvarGetLbGlobal(var);
2997
2998 /* change the lower bound to 0.0 */
2999 SCIP_CALL( SCIPchgVarLb(scip, var, 0.0) );
3000
3001 /* add a bound disjunction constraint to say var <= 0.0 or var >= oldlb */
3002 (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "semicont_%s", SCIPvarGetName(var));
3003
3004 vars[0] = var;
3005 vars[1] = var;
3006 boundtypes[0] = SCIP_BOUNDTYPE_UPPER;
3007 boundtypes[1] = SCIP_BOUNDTYPE_LOWER;
3008 bounds[0] = 0.0;
3009 bounds[1] = oldlb;
3010
3011 SCIP_CALL( SCIPcreateConsBounddisjunction(scip, &cons, name, 2, vars, boundtypes, bounds,
3012 !(lpinput->dynamiccols), TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, lpinput->dynamicconss, lpinput->dynamiccols, FALSE) );
3013 SCIP_CALL( SCIPaddCons(scip, cons) );
3014
3015 SCIPdebugMsg(scip, "add bound disjunction constraint for semi-continuity of <%s>:\n\t", SCIPvarGetName(var));
3017
3018 SCIP_CALL( SCIPreleaseCons(scip, &cons) );
3019 }
3020
3021 return SCIP_OKAY;
3022}
3023
3024/** reads the sos section
3025 *
3026 * The format is as follows:
3027 *
3028 * SOS
3029 * <constraint name>: [S1|S2]:: {<variable name>:<weight>}
3030 * ...
3031 * <constraint name>: [S1|S2]:: {<variable name>:<weight>}
3032 * */
3033static
3035 SCIP* scip, /**< SCIP data structure */
3036 LPINPUT* lpinput /**< LP reading data */
3037 )
3038{
3039 SCIP_Bool initial, separate, enforce, check, propagate;
3040 SCIP_Bool local, dynamic, removable;
3041 char name[SCIP_MAXSTRLEN];
3042 int cnt = 0;
3043
3044 assert(lpinput != NULL);
3045
3046 /* standard settings for SOS constraints: */
3047 initial = lpinput->initialconss;
3048 separate = TRUE;
3049 enforce = TRUE;
3050 check = TRUE;
3051 propagate = TRUE;
3052 local = FALSE;
3053 dynamic = lpinput->dynamicconss;
3054 removable = lpinput->dynamicrows;
3055
3056 while( getNextToken(scip, lpinput) )
3057 {
3058 int type = -1;
3059 SCIP_CONS* cons;
3060
3061 /* check if we reached a new section */
3062 if( isNewSection(scip, lpinput) )
3063 return SCIP_OKAY;
3064
3065 /* check for an SOS constraint name */
3066 *name = '\0';
3067
3068 /* remember the token in the token buffer */
3069 swapTokenBuffer(lpinput);
3070
3071 /* get the next token and check, whether it is a colon */
3072 if( getNextToken(scip, lpinput) )
3073 {
3074 if( strcmp(lpinput->token, ":") == 0 )
3075 {
3076 /* the second token was a colon: the first token is the constraint name */
3077 (void)SCIPmemccpy(name, lpinput->tokenbuf, '\0', SCIP_MAXSTRLEN);
3078
3079 name[SCIP_MAXSTRLEN-1] = '\0';
3080 }
3081 else
3082 {
3083 /* the second token was no colon: push the tokens back onto the token stack and parse it next */
3084 pushToken(lpinput);
3085 pushBufferToken(lpinput);
3086 }
3087 }
3088 else
3089 {
3090 /* there was only one token left: push it back onto the token stack and parse it next */
3091 pushBufferToken(lpinput);
3092 }
3093
3094 /* get type */
3095 if( !getNextToken(scip, lpinput) )
3096 {
3097 syntaxError(scip, lpinput, "expected SOS type: 'S1::' or 'S2::'.");
3098 return SCIP_OKAY;
3099 }
3100 /* check whether constraint name was left out */
3101 if( strcmp(lpinput->token, ":") == 0 )
3102 {
3103 /* we have to push twice ':' and once the type: */
3104 pushToken(lpinput);
3105 lpinput->token[0] = ':';
3106 lpinput->token[1] = '\0';
3107 pushToken(lpinput);
3108 swapTokenBuffer(lpinput);
3109
3110 /* set artificial name */
3111 (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "SOS%d", ++cnt);
3112 }
3113
3114 /* check whether it is type 1 or type 2 */
3115 if( strcmp(lpinput->token, "S1") == 0 )
3116 {
3117 type = 1;
3118 SCIP_CALL( SCIPcreateConsSOS1(scip, &cons, name, 0, NULL, NULL, initial, separate, enforce, check, propagate,
3119 local, dynamic, removable, FALSE) );
3120 }
3121 else if( strcmp(lpinput->token, "S2") == 0 )
3122 {
3123 type = 2;
3124 SCIP_CALL( SCIPcreateConsSOS2(scip, &cons, name, 0, NULL, NULL, initial, separate, enforce, check, propagate,
3125 local, dynamic, removable, FALSE) );
3126 }
3127 else
3128 {
3129 syntaxError(scip, lpinput, "SOS constraint type other than 1 or 2 appeared.");
3130 return SCIP_OKAY;
3131 }
3132 assert( type == 1 || type == 2 );
3133
3134 SCIPdebugMsg(scip, "created SOS%d constraint <%s>\n", type, name);
3135
3136 /* make sure that a colons follows */
3137 if( !getNextToken(scip, lpinput) || strcmp(lpinput->token, ":") != 0 )
3138 {
3139 syntaxError(scip, lpinput, "SOS constraint type has to be followed by two colons.");
3140 return SCIP_OKAY;
3141 }
3142
3143 /* make sure that another colons follows */
3144 if( !getNextToken(scip, lpinput) || strcmp(lpinput->token, ":") != 0 )
3145 {
3146 syntaxError(scip, lpinput, "SOS constraint type has to be followed by two colons.");
3147 return SCIP_OKAY;
3148 }
3149
3150 /* parse elements of SOS constraint */
3151 while( getNextToken(scip, lpinput) )
3152 {
3153 SCIP_VAR* var;
3154 SCIP_Real weight;
3155
3156 /* check if we reached a new section */
3157 if( isNewSection(scip, lpinput) )
3158 break;
3159
3160 /* remember the token in the token buffer */
3161 swapTokenBuffer(lpinput);
3162
3163 /* get variable and colon */
3164 var = SCIPfindVar(scip, lpinput->tokenbuf);
3165
3166 /* if token is a variable name */
3167 if( var == NULL )
3168 {
3169 pushBufferToken(lpinput);
3170 break;
3171 }
3172 else
3173 {
3174 SCIPdebugMsg(scip, "found variable <%s>\n", SCIPvarGetName(var));
3175 if( !getNextToken(scip, lpinput) || strcmp(lpinput->token, ":") != 0 )
3176 {
3177 syntaxError(scip, lpinput, "expected colon and weight.");
3178 return SCIP_OKAY;
3179 }
3180 /* check next token */
3181 if( !getNextToken(scip, lpinput) )
3182 {
3183 /* push back token, since it could be the name of a new constraint */
3184 pushToken(lpinput);
3185 pushBufferToken(lpinput);
3186 break;
3187 }
3188 else
3189 {
3190 int sign = +1;
3191
3192 /* get sign */
3193 if( isSign(lpinput, &sign) )
3194 {
3195 (void) getNextToken(scip, lpinput);
3196 }
3197
3198 /* get weight */
3199 if( !isValue(scip, lpinput, &weight) )
3200 {
3201 /* push back token, since it could be the name of a new constraint */
3202 pushToken(lpinput);
3203 pushBufferToken(lpinput);
3204 break;
3205 }
3206 else
3207 {
3208 /* we now know that we have a variable/weight pair -> add variable*/
3209 switch( type )
3210 {
3211 case 1:
3212 SCIP_CALL( SCIPaddVarSOS1(scip, cons, var, sign * weight) );
3213 break;
3214 case 2:
3215 SCIP_CALL( SCIPaddVarSOS2(scip, cons, var, sign * weight) );
3216 break;
3217 default:
3218 SCIPerrorMessage("unknown SOS type: <%d>\n", type); /* should not happen */
3219 SCIPABORT();
3220 return SCIP_INVALIDDATA; /*lint !e527*/
3221 }
3222 SCIPdebugMsg(scip, "added variable <%s> with weight %g.\n", SCIPvarGetName(var), weight);
3223 }
3224 }
3225 }
3226 }
3227
3228 /* add the SOS constraint */
3229 SCIP_CALL( SCIPaddCons(scip, cons) );
3230 SCIPdebugMsg(scip, "(line %d) added constraint <%s>: ", lpinput->linenumber, SCIPconsGetName(cons));
3232 SCIP_CALL( SCIPreleaseCons(scip, &cons) );
3233 }
3234
3235 return SCIP_OKAY;
3236}
3237
3238/** reads an LP file
3239 *
3240 * @todo check whether variables forced to be binary for the creation of indicator constraints are
3241 * really specified to be binary (or general with 0/1 bounds) in the file.
3242 */
3243static
3245 SCIP* scip, /**< SCIP data structure */
3246 LPINPUT* lpinput, /**< LP reading data */
3247 const char* filename /**< name of the input file */
3248 )
3249{
3250 SCIP_RETCODE retcode = SCIP_OKAY;
3251
3252 assert(lpinput != NULL);
3253
3254 /* open file */
3255 lpinput->file = SCIPfopen(filename, "r");
3256 if( lpinput->file == NULL )
3257 {
3258 SCIPerrorMessage("cannot open file <%s> for reading\n", filename);
3259 SCIPprintSysError(filename);
3260 return SCIP_NOFILE;
3261 }
3262
3263 /* create problem */
3264 SCIP_CALL_TERMINATE( retcode, SCIPcreateProb(scip, filename, NULL, NULL, NULL, NULL, NULL, NULL, NULL), TERMINATE );
3265
3266 /* parse the file */
3267 lpinput->section = LP_START;
3268 while( lpinput->section != LP_END && !hasError(lpinput) )
3269 {
3270 switch( lpinput->section )
3271 {
3272 case LP_START:
3273 SCIP_CALL_TERMINATE( retcode, readStart(scip, lpinput), TERMINATE );
3274 break;
3275
3276 case LP_OBJECTIVE:
3277 SCIP_CALL_TERMINATE( retcode, readObjective(scip, lpinput), TERMINATE );
3278 break;
3279
3280 case LP_CONSTRAINTS:
3281 SCIP_CALL_TERMINATE( retcode, readConstraints(scip, lpinput), TERMINATE );
3282 break;
3283
3284 case LP_BOUNDS:
3285 SCIP_CALL_TERMINATE( retcode, readBounds(scip, lpinput), TERMINATE );
3286 break;
3287
3288 case LP_GENERALS:
3289 SCIP_CALL_TERMINATE( retcode, readGenerals(scip, lpinput), TERMINATE );
3290 break;
3291
3292 case LP_BINARIES:
3293 SCIP_CALL_TERMINATE( retcode, readBinaries(scip, lpinput), TERMINATE );
3294 break;
3295
3296 case LP_SEMICONTINUOUS:
3297 SCIP_CALL_TERMINATE( retcode, readSemicontinuous(scip, lpinput), TERMINATE );
3298 break;
3299
3300 case LP_SOS:
3301 SCIP_CALL_TERMINATE( retcode, readSos(scip, lpinput), TERMINATE );
3302 break;
3303
3304 case LP_END: /* this is already handled in the while() loop */
3305 default:
3306 SCIPerrorMessage("invalid LP file section <%d>\n", lpinput->section);
3307 retcode = SCIP_INVALIDDATA;
3308 goto TERMINATE;
3309 }
3310 }
3311
3312 TERMINATE:
3313 /* close file */
3314 SCIPfclose(lpinput->file);
3315
3316 return retcode;
3317}
3318
3319
3320/*
3321 * Local methods (for writing)
3322 */
3323
3324/** hash key retrieval function for variables */
3325static
3327{ /*lint --e{715}*/
3328 return elem;
3329}
3330
3331/** returns TRUE iff the indices of both variables are equal */
3332static
3334{ /*lint --e{715}*/
3335 if( key1 == key2 )
3336 return TRUE;
3337 return FALSE;
3338}
3339
3340/** returns the hash value of the key */
3341static
3343{ /*lint --e{715}*/
3344 assert( SCIPvarGetIndex((SCIP_VAR*) key) >= 0 );
3345 return (unsigned int) SCIPvarGetIndex((SCIP_VAR*) key);
3346}
3347
3348/** transforms given variables, scalars, and constant to the corresponding active variables, scalars, and constant */
3349static
3351 SCIP* scip, /**< SCIP data structure */
3352 SCIP_VAR*** vars, /**< pointer to vars array to get active variables for */
3353 SCIP_Real** scalars, /**< pointer to scalars a_1, ..., a_n in linear sum a_1*x_1 + ... + a_n*x_n + c */
3354 int* nvars, /**< pointer to number of variables and values in vars and vals array */
3355 SCIP_Real* constant, /**< pointer to constant c in linear sum a_1*x_1 + ... + a_n*x_n + c */
3356 SCIP_Bool transformed /**< transformed constraint? */
3357 )
3358{
3359 int requiredsize;
3360 int v;
3361
3362 assert(scip != NULL);
3363 assert(vars != NULL);
3364 assert(scalars != NULL);
3365 assert(nvars != NULL);
3366 assert(*vars != NULL || *nvars == 0);
3367 assert(*scalars != NULL || *nvars == 0);
3368 assert(constant != NULL);
3369
3370 if( transformed )
3371 {
3372 SCIP_CALL( SCIPgetProbvarLinearSum(scip, *vars, *scalars, nvars, *nvars, constant, &requiredsize) );
3373
3374 if( requiredsize > *nvars )
3375 {
3376 SCIP_CALL( SCIPreallocBufferArray(scip, vars, requiredsize) );
3377 SCIP_CALL( SCIPreallocBufferArray(scip, scalars, requiredsize) );
3378
3379 SCIP_CALL( SCIPgetProbvarLinearSum(scip, *vars, *scalars, nvars, requiredsize, constant, &requiredsize) );
3380 }
3381 assert( requiredsize == *nvars );
3382 }
3383 else
3384 {
3385 if( *nvars > 0 && ( *vars == NULL || *scalars == NULL ) ) /*lint !e774 !e845*/
3386 {
3387 SCIPerrorMessage("Null pointer in LP reader\n"); /* should not happen */
3388 SCIPABORT();
3389 return SCIP_INVALIDDATA; /*lint !e527*/
3390 }
3391
3392 for( v = 0; v < *nvars; ++v )
3393 {
3394 SCIP_CALL( SCIPvarGetOrigvarSum(&(*vars)[v], &(*scalars)[v], constant) );
3395
3396 /* negated variables with an original counterpart may also be returned by SCIPvarGetOrigvarSum();
3397 * make sure we get the original variable in that case
3398 */
3399 if( SCIPvarGetStatus((*vars)[v]) == SCIP_VARSTATUS_NEGATED )
3400 {
3401 (*vars)[v] = SCIPvarGetNegatedVar((*vars)[v]);
3402 *constant += (*scalars)[v];
3403 (*scalars)[v] *= -1.0;
3404 }
3405 }
3406 }
3407 return SCIP_OKAY;
3408}
3409
3410/** clears the given line buffer */
3411static
3413 char* linebuffer, /**< line */
3414 int* linecnt /**< number of characters in line */
3415 )
3416{
3417 assert( linebuffer != NULL );
3418 assert( linecnt != NULL );
3419
3420 (*linecnt) = 0;
3421 linebuffer[0] = '\0';
3422}
3423
3424/** ends the given line with '\\0' and prints it to the given file stream */
3425static
3427 SCIP* scip, /**< SCIP data structure */
3428 FILE* file, /**< output file (or NULL for standard output) */
3429 char* linebuffer, /**< line */
3430 int* linecnt /**< number of characters in line */
3431 )
3432{
3433 assert( scip != NULL );
3434 assert( linebuffer != NULL );
3435 assert( linecnt != NULL );
3436 assert( 0 <= *linecnt && *linecnt < LP_MAX_PRINTLEN );
3437
3438 if( (*linecnt) > 0 )
3439 {
3440 linebuffer[(*linecnt)] = '\0';
3441 SCIPinfoMessage(scip, file, "%s\n", linebuffer);
3442 clearLine(linebuffer, linecnt);
3443 }
3444}
3445
3446/** appends extension to line and prints it to the give file stream if the
3447 * line exceeded the length given in the define LP_PRINTLEN */
3448static
3450 SCIP* scip, /**< SCIP data structure */
3451 FILE* file, /**< output file (or NULL for standard output) */
3452 char* linebuffer, /**< line */
3453 int* linecnt, /**< number of characters in line */
3454 const char* extension /**< string to extent the line */
3455 )
3456{
3457 assert( scip != NULL );
3458 assert( linebuffer != NULL );
3459 assert( linecnt != NULL );
3460 assert( extension != NULL );
3461 assert( strlen(linebuffer) + strlen(extension) < LP_MAX_PRINTLEN );
3462
3463 /* NOTE: avoid
3464 * sprintf(linebuffer, "%s%s", linebuffer, extension);
3465 * because of overlapping memory areas in memcpy used in sprintf.
3466 */
3467 (void) strncat(linebuffer, extension, LP_MAX_PRINTLEN - strlen(linebuffer));
3468
3469 (*linecnt) += (int) strlen(extension);
3470
3471 SCIPdebugMsg(scip, "linebuffer <%s>, length = %lu\n", linebuffer, (unsigned long)strlen(linebuffer));
3472
3473 if( (*linecnt) > LP_PRINTLEN )
3474 endLine(scip, file, linebuffer, linecnt);
3475}
3476
3477/* print row in LP format to file stream */
3478static
3480 SCIP* scip, /**< SCIP data structure */
3481 FILE* file, /**< output file (or NULL for standard output) */
3482 const char* rowname, /**< row name */
3483 const char* rownameextension, /**< row name extension */
3484 const char* type, /**< row type ("=", "<=", or ">=") */
3485 SCIP_VAR** linvars, /**< array of linear variables */
3486 SCIP_Real* linvals, /**< array of linear coefficient values */
3487 int nlinvars, /**< number of linear variables */
3488 SCIP_EXPR* quadexpr, /**< quadratic expression */
3489 SCIP_Real rhs, /**< right hand side */
3490 SCIP_Bool transformed /**< transformed constraint? */
3491 )
3492{
3493 char linebuffer[LP_MAX_PRINTLEN + 1] = { '\0' };
3494 char varname[LP_MAX_NAMELEN];
3495 char varname2[LP_MAX_NAMELEN];
3496 char consname[LP_MAX_NAMELEN + 1]; /* an extra character for ':' */
3497 char buffer[LP_MAX_PRINTLEN];
3498 int linecnt;
3499 int written;
3500 int v;
3501
3502 assert(scip != NULL);
3503 assert(strcmp(type, "=") == 0 || strcmp(type, "<=") == 0 || strcmp(type, ">=") == 0);
3504 assert(nlinvars == 0 || (linvars != NULL && linvals != NULL));
3505
3506 clearLine(linebuffer, &linecnt);
3507
3508 /* start each line with a space */
3509 appendLine(scip, file, linebuffer, &linecnt, " ");
3510
3511 /* print row name */
3512 if( strlen(rowname) > 0 || strlen(rownameextension) > 0 )
3513 {
3514 written = SCIPsnprintf(consname, LP_MAX_NAMELEN + 1, "%s%s:", rowname, rownameextension);
3515 if( written > LP_MAX_NAMELEN )
3516 {
3517 SCIPerrorMessage("buffer length exceeded\n");
3518 return SCIP_INVALIDDATA;
3519 }
3520 appendLine(scip, file, linebuffer, &linecnt, consname);
3521 }
3522
3523 /* print coefficients */
3524 for( v = 0; v < nlinvars; ++v )
3525 {
3526 SCIP_VAR* var;
3527
3528 assert(linvars != NULL); /* for lint */
3529 assert(linvals != NULL);
3530
3531 var = linvars[v];
3532 assert(var != NULL);
3533
3534 /* we start a new line; therefore we tab this line */
3535 if( linecnt == 0 )
3536 appendLine(scip, file, linebuffer, &linecnt, " ");
3537
3538 written = SCIPsnprintf(varname, LP_MAX_NAMELEN, "%s", SCIPvarGetName(var));
3539 if( written >= LP_MAX_NAMELEN )
3540 {
3541 SCIPerrorMessage("buffer length exceeded\n");
3542 return SCIP_INVALIDDATA;
3543 }
3544 written = SCIPsnprintf(buffer, LP_MAX_PRINTLEN, " %+.15g %s", linvals[v], varname);
3545 if( written >= LP_MAX_PRINTLEN )
3546 {
3547 SCIPerrorMessage("buffer length exceeded\n");
3548 return SCIP_INVALIDDATA;
3549 }
3550 appendLine(scip, file, linebuffer, &linecnt, buffer);
3551 }
3552
3553 /* print quadratic part */
3554 if( quadexpr != NULL )
3555 {
3556 SCIP_EXPR** linexprs;
3557 SCIP_VAR** activevars;
3558 SCIP_Real* activevals;
3559 SCIP_Real* lincoefs;
3560 SCIP_Real constant;
3561 SCIP_Real activeconstant = 0.0;
3562 int nbilinexprterms;
3563 int nactivevars;
3564 int nquadexprs;
3565 int nlinexprs;
3566
3567 /* get data from the quadratic expression */
3568 SCIPexprGetQuadraticData(quadexpr, &constant, &nlinexprs, &linexprs, &lincoefs, &nquadexprs, &nbilinexprterms,
3569 NULL, NULL);
3570
3571 /* allocate memory to store active linear variables */
3572 SCIP_CALL( SCIPallocBufferArray(scip, &activevars, nlinexprs) );
3573 SCIP_CALL( SCIPduplicateBufferArray(scip, &activevals, lincoefs, nlinexprs) );
3574 nactivevars = nlinexprs;
3575
3576 for( v = 0; v < nlinexprs; ++v )
3577 {
3578 assert(linexprs != NULL && linexprs[v] != NULL);
3579 assert(SCIPisExprVar(scip, linexprs[v]));
3580
3581 activevars[v] = SCIPgetVarExprVar(linexprs[v]);
3582 assert(activevars[v] != NULL);
3583 }
3584
3585 /* get active variables */
3586 SCIP_CALL( getActiveVariables(scip, &activevars, &activevals, &nactivevars, &activeconstant, transformed) );
3587 constant += activeconstant;
3588
3589 /* print linear coefficients of linear variables */
3590 for( v = 0; v < nactivevars; ++v )
3591 {
3592 SCIP_VAR* var;
3593
3594 assert(activevars != NULL); /* for lint */
3595 assert(activevals != NULL);
3596
3597 var = activevars[v];
3598 assert(var != NULL);
3599
3600 /* we start a new line; therefore we tab this line */
3601 if( linecnt == 0 )
3602 appendLine(scip, file, linebuffer, &linecnt, " ");
3603
3604 written = SCIPsnprintf(varname, LP_MAX_NAMELEN, "%s", SCIPvarGetName(var));
3605 if( written >= LP_MAX_NAMELEN )
3606 {
3607 SCIPerrorMessage("buffer length exceeded\n");
3608 return SCIP_INVALIDDATA;
3609 }
3610 written = SCIPsnprintf(buffer, LP_MAX_PRINTLEN, " %+.15g %s", activevals[v], varname);
3611 if( written >= LP_MAX_PRINTLEN )
3612 {
3613 SCIPerrorMessage("buffer length exceeded\n");
3614 return SCIP_INVALIDDATA;
3615 }
3616 appendLine(scip, file, linebuffer, &linecnt, buffer);
3617 }
3618
3619 /* free memory for active linear variables */
3620 SCIPfreeBufferArray(scip, &activevals);
3621 SCIPfreeBufferArray(scip, &activevars);
3622
3623 /* adjust rhs if there is a constant */
3624 if( constant != 0.0 && !SCIPisInfinity(scip, rhs) )
3625 rhs -= constant;
3626
3627 /* print linear coefficients of quadratic variables */
3628 for( v = 0; v < nquadexprs; ++v )
3629 {
3630 SCIP_EXPR* expr;
3631 SCIP_VAR* var;
3632 SCIP_Real lincoef;
3633
3634 /* get linear coefficient and variable of quadratic term */
3635 SCIPexprGetQuadraticQuadTerm(quadexpr, v, &expr, &lincoef, NULL, NULL, NULL, NULL);
3636 assert(expr != NULL);
3637 assert(SCIPisExprVar(scip, expr));
3638
3639 var = SCIPgetVarExprVar(expr);
3640 assert(var != NULL);
3641
3642 if( lincoef == 0.0 )
3643 continue;
3644
3645 /* we start a new line; therefore we tab this line */
3646 if( linecnt == 0 )
3647 appendLine(scip, file, linebuffer, &linecnt, " ");
3648
3649 written = SCIPsnprintf(varname, LP_MAX_NAMELEN, "%s", SCIPvarGetName(var));
3650 if( written >= LP_MAX_NAMELEN )
3651 {
3652 SCIPerrorMessage("buffer length exceeded\n");
3653 return SCIP_INVALIDDATA;
3654 }
3655 written = SCIPsnprintf(buffer, LP_MAX_PRINTLEN, " %+.15g %s", lincoef, varname);
3656 if( written >= LP_MAX_PRINTLEN )
3657 {
3658 SCIPerrorMessage("buffer length exceeded\n");
3659 return SCIP_INVALIDDATA;
3660 }
3661 appendLine(scip, file, linebuffer, &linecnt, buffer);
3662 }
3663
3664 /* start quadratic part */
3665 appendLine(scip, file, linebuffer, &linecnt, " + [");
3666
3667 /* print square terms */
3668 for( v = 0; v < nquadexprs; ++v )
3669 {
3670 SCIP_EXPR* expr;
3671 SCIP_VAR* var;
3672 SCIP_Real sqrcoef;
3673
3674 /* get square coefficient and variable of quadratic term */
3675 SCIPexprGetQuadraticQuadTerm(quadexpr, v, &expr, NULL, &sqrcoef, NULL, NULL, NULL);
3676 assert(expr != NULL);
3677 assert(SCIPisExprVar(scip, expr));
3678
3679 var = SCIPgetVarExprVar(expr);
3680 assert(var != NULL);
3681
3682 if( sqrcoef == 0.0 )
3683 continue;
3684
3685 /* we start a new line; therefore we tab this line */
3686 if( linecnt == 0 )
3687 appendLine(scip, file, linebuffer, &linecnt, " ");
3688
3689 written = SCIPsnprintf(varname, LP_MAX_NAMELEN, "%s", SCIPvarGetName(var));
3690 if( written >= LP_MAX_NAMELEN )
3691 {
3692 SCIPerrorMessage("buffer length exceeded\n");
3693 return SCIP_INVALIDDATA;
3694 }
3695 written = SCIPsnprintf(buffer, LP_MAX_PRINTLEN, " %+.15g %s^2", sqrcoef, varname);
3696 if( written >= LP_MAX_PRINTLEN )
3697 {
3698 SCIPerrorMessage("buffer length exceeded\n");
3699 return SCIP_INVALIDDATA;
3700 }
3701 appendLine(scip, file, linebuffer, &linecnt, buffer);
3702 }
3703
3704 /* print bilinear terms */
3705 for( v = 0; v < nbilinexprterms; ++v )
3706 {
3707 SCIP_EXPR* expr1;
3708 SCIP_EXPR* expr2;
3709 SCIP_VAR* var1;
3710 SCIP_VAR* var2;
3711 SCIP_Real bilincoef;
3712
3713 /* get coefficient and variables of bilinear */
3714 SCIPexprGetQuadraticBilinTerm(quadexpr, v, &expr1, &expr2, &bilincoef, NULL, NULL);
3715 assert(expr1 != NULL);
3716 assert(SCIPisExprVar(scip, expr1));
3717 assert(expr2 != NULL);
3718 assert(SCIPisExprVar(scip, expr2));
3719
3720 var1 = SCIPgetVarExprVar(expr1);
3721 assert(var1 != NULL);
3722 var2 = SCIPgetVarExprVar(expr2);
3723 assert(var2 != NULL);
3724
3725 /* we start a new line; therefore we tab this line */
3726 if( linecnt == 0 )
3727 appendLine(scip, file, linebuffer, &linecnt, " ");
3728
3729 written = SCIPsnprintf(varname, LP_MAX_NAMELEN, "%s", SCIPvarGetName(var1));
3730 if( written >= LP_MAX_NAMELEN )
3731 {
3732 SCIPerrorMessage("buffer length exceeded\n");
3733 return SCIP_INVALIDDATA;
3734 }
3735 written = SCIPsnprintf(varname2, LP_MAX_NAMELEN, "%s", SCIPvarGetName(var2));
3736 if( written >= LP_MAX_NAMELEN )
3737 {
3738 SCIPerrorMessage("buffer length exceeded\n");
3739 return SCIP_INVALIDDATA;
3740 }
3741 written = SCIPsnprintf(buffer, LP_MAX_PRINTLEN, " %+.15g %s * %s", bilincoef, varname, varname2);
3742 if( written >= LP_MAX_PRINTLEN )
3743 {
3744 SCIPerrorMessage("buffer length exceeded\n");
3745 return SCIP_INVALIDDATA;
3746 }
3747 appendLine(scip, file, linebuffer, &linecnt, buffer);
3748 }
3749
3750 /* end quadratic part */
3751 appendLine(scip, file, linebuffer, &linecnt, " ]");
3752 }
3753
3754 /* print right hand side */
3755 written = SCIPsnprintf(buffer, LP_MAX_PRINTLEN, " %s %+.15g", type, rhs);
3756 if( written >= LP_MAX_PRINTLEN )
3757 {
3758 SCIPerrorMessage("buffer length exceeded\n");
3759 return SCIP_INVALIDDATA;
3760 }
3761
3762 /* we start a new line; therefore we tab this line */
3763 if( linecnt == 0 )
3764 appendLine(scip, file, linebuffer, &linecnt, " ");
3765 appendLine(scip, file, linebuffer, &linecnt, buffer);
3766
3767 endLine(scip, file, linebuffer, &linecnt);
3768
3769 return SCIP_OKAY;
3770}
3771
3772/* print exact row in LP format to file stream */
3773static
3775 SCIP* scip, /**< SCIP data structure */
3776 FILE* file, /**< output file (or NULL for standard output) */
3777 const char* rowname, /**< row name */
3778 const char* rownameextension, /**< row name extension */
3779 const char* type, /**< row type ("=", "<=", or ">=") */
3780 SCIP_VAR** linvars, /**< array of linear variables */
3781 SCIP_RATIONAL** linvals, /**< array of linear coefficient values */
3782 int nlinvars, /**< number of linear variables */
3783 SCIP_RATIONAL* rhs /**< right hand side */
3784 )
3785{
3786 char linebuffer[LP_MAX_PRINTLEN + 1] = { '\0' };
3787 char ratbuffer[LP_MAX_PRINTLEN] = { '\0' };
3788 char varname[LP_MAX_NAMELEN];
3789 char consname[LP_MAX_NAMELEN + 1]; /* an extra character for ':' */
3790 char buffer[LP_MAX_PRINTLEN];
3791 int linecnt;
3792 int written;
3793 int v;
3794
3795 assert(scip != NULL);
3796 assert(strcmp(type, "=") == 0 || strcmp(type, "<=") == 0 || strcmp(type, ">=") == 0);
3797 assert(nlinvars == 0 || (linvars != NULL && linvals != NULL));
3798
3799 clearLine(linebuffer, &linecnt);
3800
3801 /* start each line with a space */
3802 appendLine(scip, file, linebuffer, &linecnt, " ");
3803
3804 /* print row name */
3805 if( strlen(rowname) > 0 || strlen(rownameextension) > 0 )
3806 {
3807 written = SCIPsnprintf(consname, LP_MAX_NAMELEN + 1, "%s%s:", rowname, rownameextension);
3808 if( written > LP_MAX_NAMELEN )
3809 {
3810 SCIPerrorMessage("buffer length exceeded\n");
3811 return SCIP_INVALIDDATA;
3812 }
3813 appendLine(scip, file, linebuffer, &linecnt, consname);
3814 }
3815
3816 /* print coefficients */
3817 for( v = 0; v < nlinvars; ++v )
3818 {
3819 SCIP_VAR* var;
3820
3821 assert(linvars != NULL); /* for lint */
3822 assert(linvals != NULL);
3823
3824 var = linvars[v];
3825 assert(var != NULL);
3826
3827 /* we start a new line; therefore we tab this line */
3828 if( linecnt == 0 )
3829 appendLine(scip, file, linebuffer, &linecnt, " ");
3830
3831 written = SCIPsnprintf(varname, LP_MAX_NAMELEN, "%s", SCIPvarGetName(var));
3832 if( written >= LP_MAX_NAMELEN )
3833 {
3834 SCIPerrorMessage("buffer length exceeded\n");
3835 return SCIP_INVALIDDATA;
3836 }
3837 written = SCIPrationalToString(linvals[v], ratbuffer, LP_MAX_PRINTLEN);
3838 if( written >= LP_MAX_PRINTLEN )
3839 {
3840 SCIPerrorMessage("buffer length exceeded\n");
3841 return SCIP_INVALIDDATA;
3842 }
3843 if( !SCIPrationalIsNegative(linvals[v]) )
3844 written = SCIPsnprintf(buffer, LP_MAX_PRINTLEN, " +%s %s", ratbuffer, varname);
3845 else
3846 written = SCIPsnprintf(buffer, LP_MAX_PRINTLEN, " %s %s", ratbuffer, varname);
3847 if( written >= LP_MAX_PRINTLEN )
3848 {
3849 SCIPerrorMessage("buffer length exceeded\n");
3850 return SCIP_INVALIDDATA;
3851 }
3852 appendLine(scip, file, linebuffer, &linecnt, buffer);
3853 }
3854
3855 /* print right hand side */
3856 written = SCIPrationalToString(rhs, ratbuffer, LP_MAX_PRINTLEN);
3857 if( written >= LP_MAX_PRINTLEN )
3858 {
3859 SCIPerrorMessage("buffer length exceeded\n");
3860 return SCIP_INVALIDDATA;
3861 }
3862 if( !SCIPrationalIsNegative(rhs) )
3863 written = SCIPsnprintf(buffer, LP_MAX_PRINTLEN, " %s +%s", type, ratbuffer);
3864 else
3865 written = SCIPsnprintf(buffer, LP_MAX_PRINTLEN, " %s %s", type, ratbuffer);
3866 if( written >= LP_MAX_PRINTLEN )
3867 {
3868 SCIPerrorMessage("buffer length exceeded\n");
3869 return SCIP_INVALIDDATA;
3870 }
3871
3872 /* we start a new line; therefore we tab this line */
3873 if( linecnt == 0 )
3874 appendLine(scip, file, linebuffer, &linecnt, " ");
3875 appendLine(scip, file, linebuffer, &linecnt, buffer);
3876
3877 endLine(scip, file, linebuffer, &linecnt);
3878
3879 return SCIP_OKAY;
3880}
3881
3882/** prints given (linear or) quadratic constraint information in LP format to file stream */
3883static
3885 SCIP* scip, /**< SCIP data structure */
3886 FILE* file, /**< output file (or NULL for standard output) */
3887 const char* rowname, /**< name of the row */
3888 SCIP_VAR** linvars, /**< array of linear variables */
3889 SCIP_Real* linvals, /**< array of linear coefficients values (or NULL if all linear coefficient values are 1) */
3890 int nlinvars, /**< number of linear variables */
3891 SCIP_EXPR* quadexpr, /**< quadratic expression (or NULL if nlinvars > 0) */
3892 SCIP_Real lhs, /**< left hand side */
3893 SCIP_Real rhs, /**< right hand side */
3894 SCIP_Bool transformed /**< transformed constraint? */
3895 )
3896{
3897 int v;
3898 SCIP_VAR** activevars = NULL;
3899 SCIP_Real* activevals = NULL;
3900 int nactivevars;
3901 SCIP_Real activeconstant = 0.0;
3902
3903 assert( scip != NULL );
3904 assert( rowname != NULL );
3905 assert( quadexpr == NULL || nlinvars == 0);
3906
3907 /* The LP format does not forbid that the variable array is empty */
3908 assert( nlinvars == 0 || linvars != NULL );
3909 assert( lhs <= rhs );
3910
3911 if( SCIPisInfinity(scip, -lhs) && SCIPisInfinity(scip, rhs) )
3912 return SCIP_OKAY;
3913
3914 nactivevars = nlinvars;
3915 if( nlinvars > 0 )
3916 {
3917 /* duplicate variable and value array */
3918 SCIP_CALL( SCIPduplicateBufferArray(scip, &activevars, linvars, nactivevars ) );
3919 if( linvals != NULL )
3920 {
3921 SCIP_CALL( SCIPduplicateBufferArray(scip, &activevals, linvals, nactivevars ) );
3922 }
3923 else
3924 {
3925 SCIP_CALL( SCIPallocBufferArray(scip, &activevals, nactivevars) );
3926
3927 for( v = 0; v < nactivevars; ++v )
3928 activevals[v] = 1.0;
3929 }
3930
3931 /* retransform given variables to active variables */
3932 SCIP_CALL( getActiveVariables(scip, &activevars, &activevals, &nactivevars, &activeconstant, transformed) );
3933 }
3934
3935 /* print row(s) in LP format */
3936 if( SCIPisEQ(scip, lhs, rhs) )
3937 {
3938 assert( !SCIPisInfinity(scip, rhs) );
3939
3940 /* equal constraint */
3941 SCIP_CALL( printRow(scip, file, rowname, "", "=", activevars, activevals, nactivevars, quadexpr,
3942 rhs - activeconstant, transformed) );
3943 }
3944 else
3945 {
3946 if( !SCIPisInfinity(scip, -lhs) )
3947 {
3948 /* print inequality ">=" */
3949 SCIP_CALL( printRow(scip, file, rowname, SCIPisInfinity(scip, rhs) ? "" : "_lhs", ">=", activevars, activevals,
3950 nactivevars, quadexpr, lhs - activeconstant, transformed) );
3951 }
3952 if( !SCIPisInfinity(scip, rhs) )
3953 {
3954 /* print inequality "<=" */
3955 SCIP_CALL( printRow(scip, file, rowname, SCIPisInfinity(scip, -lhs) ? "" : "_rhs", "<=", activevars, activevals,
3956 nactivevars, quadexpr, rhs - activeconstant, transformed) );
3957 }
3958 }
3959
3960 if( nlinvars > 0 )
3961 {
3962 /* free buffer arrays */
3963 SCIPfreeBufferArray(scip, &activevals);
3964 SCIPfreeBufferArray(scip, &activevars);
3965 }
3966
3967 return SCIP_OKAY;
3968}
3969
3970/** prints given SOS constraint information in LP format to file stream */
3971static
3973 SCIP* scip, /**< SCIP data structure */
3974 FILE* file, /**< output file (or NULL for standard output) */
3975 const char* rowname, /**< name of the row */
3976 SCIP_VAR** vars, /**< array of variables */
3977 SCIP_Real* weights, /**< array of weight values (or NULL) */
3978 int nvars, /**< number of variables */
3979 int type /**< SOS type (SOS1 or SOS2) */
3980 )
3981{
3982 int v;
3983
3984 char linebuffer[LP_MAX_PRINTLEN+1];
3985 int linecnt;
3986 char buffer[LP_MAX_PRINTLEN];
3987 char varname[LP_MAX_NAMELEN];
3988
3989 assert( scip != NULL );
3990 assert( file != NULL );
3991 assert( type == 1 || type == 2 );
3992
3993 clearLine(linebuffer, &linecnt);
3994
3995 /* start each line with a space */
3996 appendLine(scip, file, linebuffer, &linecnt, " ");
3997 assert( strlen(rowname) < LP_MAX_NAMELEN );
3998
3999 if( strlen(rowname) > 0 )
4000 {
4001 (void) SCIPsnprintf(buffer, LP_MAX_PRINTLEN, "%s:", rowname);
4002 appendLine(scip, file, linebuffer, &linecnt, buffer);
4003 }
4004
4005 /* SOS type */
4006 (void) SCIPsnprintf(buffer, LP_MAX_PRINTLEN, " S%d::", type);
4007 appendLine(scip, file, linebuffer, &linecnt, buffer);
4008
4009 for( v = 0; v < nvars; ++v )
4010 {
4011 (void) SCIPsnprintf(varname, LP_MAX_NAMELEN, "%s", SCIPvarGetName(vars[v]));
4012
4013 if( weights != NULL )
4014 (void) SCIPsnprintf(buffer, LP_MAX_PRINTLEN, " %s:%.15g", varname, weights[v]);
4015 else
4016 (void) SCIPsnprintf(buffer, LP_MAX_PRINTLEN, " %s:%d", varname, v);
4017
4018 if(linecnt == 0 )
4019 {
4020 /* we start a new line; therefore we tab this line */
4021 appendLine(scip, file, linebuffer, &linecnt, " ");
4022 }
4023 appendLine(scip, file, linebuffer, &linecnt, buffer);
4024 }
4025
4026 endLine(scip, file, linebuffer, &linecnt);
4027}
4028
4029/** prints a linearization of an and-constraint into the given file */
4030static
4032 SCIP* scip, /**< SCIP data structure */
4033 FILE* file, /**< output file (or NULL for standard output) */
4034 const char* consname, /**< name of the constraint */
4035 SCIP_CONS* cons, /**< and constraint */
4036 SCIP_Bool aggrlinearizationands,/**< print weak or strong realaxation */
4037 SCIP_Bool transformed /**< transformed constraint? */
4038 )
4039{
4040 SCIP_VAR** vars;
4041 SCIP_VAR** operands;
4042 SCIP_VAR* resultant;
4043 SCIP_Real* vals;
4044 char rowname[LP_MAX_NAMELEN];
4045 int nvars;
4046 int v;
4047
4048 assert(scip != NULL);
4049 assert(consname != NULL);
4050 assert(cons != NULL);
4051
4052 nvars = SCIPgetNVarsAnd(scip, cons);
4053 operands = SCIPgetVarsAnd(scip, cons);
4054 resultant = SCIPgetResultantAnd(scip, cons);
4055
4056 /* allocate buffer array */
4057 SCIP_CALL( SCIPallocBufferArray(scip, &vars, nvars + 1) );
4058 SCIP_CALL( SCIPallocBufferArray(scip, &vals, nvars + 1) );
4059
4060 /* the tight relaxtion, number of and-constraint operands rows */
4061 if( !aggrlinearizationands )
4062 {
4063 vars[0] = resultant;
4064 vals[0] = 1.0;
4065 vals[1] = -1.0;
4066
4067 /* print operator rows */
4068 for( v = 0; v < nvars; ++v )
4069 {
4070 (void) SCIPsnprintf(rowname, LP_MAX_NAMELEN, "%s_%d", consname, v);
4071 vars[1] = operands[v];
4072
4073 /* print for each operator a row */
4074 SCIP_CALL( printQuadraticCons(scip, file, rowname, vars, vals, 2, NULL, -SCIPinfinity(scip), 0.0,
4075 transformed) );
4076 }
4077 }
4078
4079 /* prepare for next row */
4080 for( v = nvars - 1; v >= 0; --v )
4081 {
4082 vars[v] = operands[v];
4083 vals[v] = -1.0;
4084 }
4085
4086 vars[nvars] = resultant;
4087
4088 /* the weak relaxtion, only one constraint */
4089 if( aggrlinearizationands )
4090 {
4091 /* adjust rowname of constraint */
4092 (void) SCIPsnprintf(rowname, LP_MAX_NAMELEN, "%s_operators", consname);
4093
4094 vals[nvars] = (SCIP_Real) nvars;
4095
4096 /* print aggregated operator row */
4097 SCIP_CALL( printQuadraticCons(scip, file, rowname, vars, vals, nvars + 1, NULL, -SCIPinfinity(scip), 0.0,
4098 transformed) );
4099 }
4100
4101 /* create additional linear constraint */
4102 (void) SCIPsnprintf(rowname, LP_MAX_NAMELEN, "%s_add", consname);
4103
4104 vals[nvars] = 1.0;
4105
4106 SCIP_CALL( printQuadraticCons(scip, file, rowname, vars, vals, nvars + 1, NULL, -nvars + 1.0, SCIPinfinity(scip),
4107 transformed) );
4108
4109 /* free buffer array */
4110 SCIPfreeBufferArray(scip, &vals);
4111 SCIPfreeBufferArray(scip, &vars);
4112
4113 return SCIP_OKAY;
4114}
4115
4116/** check whether given variables are aggregated and put them into an array without duplication */
4117static
4119 SCIP* scip, /**< SCIP data structure */
4120 SCIP_VAR** vars, /**< variable array */
4121 int nvars, /**< number of active variables in the problem */
4122 SCIP_VAR*** aggvars, /**< pointer to array storing the aggregated variables on output */
4123 int* naggvars, /**< pointer to number of aggregated variables on output */
4124 int* saggvars, /**< pointer to number of slots in aggvars array */
4125 SCIP_HASHTABLE* varAggregated /**< hashtable for checking duplicates */
4126 )
4127{
4128 int v;
4129
4130 assert( scip != NULL );
4131 assert( aggvars != NULL );
4132 assert( naggvars != NULL );
4133 assert( saggvars != NULL );
4134
4135 /* check variables */
4136 for( v = 0; v < nvars; ++v )
4137 {
4138 SCIP_VARSTATUS status;
4139 SCIP_VAR* var;
4140
4141 var = vars[v];
4142 status = SCIPvarGetStatus(var);
4143
4144 /* collect aggregated variables in a list */
4145 if( status >= SCIP_VARSTATUS_AGGREGATED )
4146 {
4147 assert( status == SCIP_VARSTATUS_AGGREGATED || status == SCIP_VARSTATUS_MULTAGGR || status == SCIP_VARSTATUS_NEGATED );
4148 assert( varAggregated != NULL );
4149
4150 if( ! SCIPhashtableExists(varAggregated, (void*) var) )
4151 {
4152 /* possibly enlarge array */
4153 if ( *saggvars <= *naggvars )
4154 {
4155 int newsize;
4156 newsize = SCIPcalcMemGrowSize(scip, *naggvars + 1);
4157 assert( newsize > *saggvars );
4158 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &aggvars, *saggvars, newsize) );
4159 *saggvars = newsize;
4160 }
4161
4162 (*aggvars)[*naggvars] = var;
4163 (*naggvars)++;
4164 SCIP_CALL( SCIPhashtableInsert(varAggregated, (void*) var) );
4165 assert( *naggvars <= *saggvars );
4166 }
4167 }
4168 }
4169 return SCIP_OKAY;
4170}
4171
4172/** print aggregated variable-constraints */
4173static
4175 SCIP* scip, /**< SCIP data structure */
4176 FILE* file, /**< output file (or NULL for standard output) */
4177 SCIP_Bool transformed, /**< TRUE iff problem is the transformed problem */
4178 int nvars, /**< number of active variables in the problem */
4179 int nAggregatedVars, /**< number of aggregated variables */
4180 SCIP_VAR** aggregatedVars /**< array storing the aggregated variables */
4181 )
4182{
4183 int j;
4184
4185 SCIP_VAR** activevars;
4186 SCIP_Real* activevals;
4187 int nactivevars;
4188 SCIP_Real activeconstant;
4189 char consname[LP_MAX_NAMELEN];
4190
4191 assert( scip != NULL );
4192
4193 /* write aggregation constraints */
4194 SCIP_CALL( SCIPallocBufferArray(scip, &activevars, nvars) );
4195 SCIP_CALL( SCIPallocBufferArray(scip, &activevals, nvars) );
4196
4197 for( j = 0; j < nAggregatedVars; ++j )
4198 {
4199 /* set up list to obtain substitution variables */
4200 nactivevars = 1;
4201
4202 activevars[0] = aggregatedVars[j];
4203 activevals[0] = 1.0;
4204 activeconstant = 0.0;
4205
4206 /* retransform given variables to active variables */
4207 SCIP_CALL( getActiveVariables(scip, &activevars, &activevals, &nactivevars, &activeconstant, transformed) );
4208
4209 activevals[nactivevars] = -1.0;
4210 activevars[nactivevars] = aggregatedVars[j];
4211 ++nactivevars;
4212
4213 /* output constraint */
4214 (void) SCIPsnprintf(consname, LP_MAX_NAMELEN, "aggr_%s", SCIPvarGetName(aggregatedVars[j]));
4215 SCIP_CALL( printRow(scip, file, consname, "", "=", activevars, activevals, nactivevars, NULL, - activeconstant,
4216 transformed) );
4217 }
4218
4219 /* free buffer arrays */
4220 SCIPfreeBufferArray(scip, &activevals);
4221 SCIPfreeBufferArray(scip, &activevars);
4222
4223 return SCIP_OKAY;
4224}
4225
4226/** method check if the variable names are not longer than LP_MAX_NAMELEN */
4227static
4229 SCIP* scip, /**< SCIP data structure */
4230 SCIP_VAR** vars, /**< array of variables */
4231 int nvars /**< number of variables */
4232 )
4233{
4234 SCIP_Bool printwarning;
4235 int v;
4236
4237 assert(scip != NULL);
4238 assert(vars != NULL || nvars == 0);
4239
4240 printwarning = TRUE;
4241
4242 /* check if the variable names are not to long */
4243 for( v = 0; v < nvars; ++v )
4244 {
4245 if( strlen(SCIPvarGetName(vars[v])) > LP_MAX_NAMELEN ) /*lint !e613*/
4246 {
4247 SCIPwarningMessage(scip, "there is a variable name which has to be cut down to %d characters; LP might be corrupted\n",
4248 LP_MAX_NAMELEN - 1);
4249 return;
4250 }
4251
4252 /* check if variable name starts with a digit */
4253 if( printwarning && isdigit((unsigned char)SCIPvarGetName(vars[v])[0]) ) /*lint !e613*/
4254 {
4255 SCIPwarningMessage(scip, "violation of LP format - a variable name starts with a digit; " \
4256 "it is not possible to read the generated LP file with SCIP; " \
4257 "use write/genproblem or write/gentransproblem for generic variable names\n");
4258 printwarning = FALSE;
4259 }
4260 }
4261}
4262
4263/** method check if the constraint names are not longer than LP_MAX_NAMELEN */
4264static
4266 SCIP* scip, /**< SCIP data structure */
4267 SCIP_CONS** conss, /**< array of constraints */
4268 int nconss, /**< number of constraints */
4269 SCIP_Bool transformed /**< TRUE iff problem is the transformed problem */
4270 )
4271{
4272 int c;
4273 SCIP_CONS* cons;
4274 SCIP_CONSHDLR* conshdlr;
4275 const char* conshdlrname;
4276 SCIP_Bool printwarning = TRUE;
4277
4278 assert( scip != NULL );
4279 assert( conss != NULL || nconss == 0 );
4280
4281 for( c = 0; c < nconss; ++c )
4282 {
4283 int len;
4284
4285 assert(conss != NULL); /* for lint */
4286 cons = conss[c];
4287 assert(cons != NULL );
4288
4289 /* in case the transformed is written only constraints are posted which are enabled in the current node */
4290 assert(!transformed || SCIPconsIsEnabled(cons));
4291
4292 conshdlr = SCIPconsGetHdlr(cons);
4293 assert( conshdlr != NULL );
4294
4295 conshdlrname = SCIPconshdlrGetName(conshdlr);
4296 assert( transformed == SCIPconsIsTransformed(cons) );
4297
4298 len = (int) strlen(SCIPconsGetName(cons));
4299
4300 if( strcmp(conshdlrname, "linear") == 0 )
4301 {
4302 SCIP_Real lhs = SCIPgetLhsLinear(scip, cons);
4303 SCIP_Real rhs = SCIPgetRhsLinear(scip, cons);
4304
4305 if( (SCIPisEQ(scip, lhs, rhs) && len > LP_MAX_NAMELEN) || ( !SCIPisEQ(scip, lhs, rhs) && len > LP_MAX_NAMELEN - 4) )
4306 {
4307 SCIPwarningMessage(scip, "there is a constraint name which has to be cut down to %d characters;\n", LP_MAX_NAMELEN - 1);
4308 return;
4309 }
4310 }
4311 else if( len > LP_MAX_NAMELEN )
4312 {
4313 SCIPwarningMessage(scip, "there is a constraint name which has to be cut down to %d characters;\n", LP_MAX_NAMELEN - 1);
4314 return;
4315 }
4316
4317 /* check if constraint name starts with a digit */
4318 if( printwarning && isdigit((unsigned char)SCIPconsGetName(cons)[0]) )
4319 {
4320 SCIPwarningMessage(scip, "violation of LP format - a constraint name starts with a digit; " \
4321 "it is not possible to read the generated LP file with SCIP; " \
4322 "use write/genproblem or write/gentransproblem for generic variable names\n");
4323 printwarning = FALSE;
4324 }
4325 }
4326}
4327
4328/*
4329 * Callback methods of reader
4330 */
4331
4332/** copy method for reader plugins (called when SCIP copies plugins) */
4333static
4335{ /*lint --e{715}*/
4336 assert(scip != NULL);
4337 assert(reader != NULL);
4338 assert(strcmp(SCIPreaderGetName(reader), READER_NAME) == 0);
4339
4340 /* call inclusion method of reader */
4342
4343 return SCIP_OKAY;
4344}
4345
4346/** destructor of reader to free user data (called when SCIP is exiting) */
4347static
4349{
4350 SCIP_READERDATA* readerdata;
4351
4352 assert(strcmp(SCIPreaderGetName(reader), READER_NAME) == 0);
4353 readerdata = SCIPreaderGetData(reader);
4354 assert(readerdata != NULL);
4355 SCIPfreeBlockMemory(scip, &readerdata);
4356
4357 return SCIP_OKAY;
4358}
4359
4360/** problem reading method of reader */
4361static
4363{ /*lint --e{715}*/
4364
4365 SCIP_CALL( SCIPreadLp(scip, reader, filename, result) );
4366
4367 return SCIP_OKAY;
4368}
4369
4370
4371/** problem writing method of reader */
4372static
4374{ /*lint --e{715}*/
4375 assert(reader != NULL);
4376 assert(strcmp(SCIPreaderGetName(reader), READER_NAME) == 0);
4377
4378 SCIP_CALL( SCIPwriteLp(scip, file, name, transformed, objsense, objoffset, objscale, objoffsetexact, objscaleexact,
4379 vars, nvars, nbinvars, nintvars, nimplvars, ncontvars, conss, nconss, result) );
4380
4381 return SCIP_OKAY;
4382}
4383
4384
4385/*
4386 * reader specific interface methods
4387 */
4388
4389/** includes the lp file reader in SCIP */
4391 SCIP* scip /**< SCIP data structure */
4392 )
4393{
4394 SCIP_READERDATA* readerdata;
4395 SCIP_READER* reader;
4396
4397 /* create reader data */
4398 SCIP_CALL( SCIPallocBlockMemory(scip, &readerdata) );
4399
4400 /* include reader */
4402
4403 /* reader is safe to use in exact solving mode */
4404 SCIPreaderMarkExact(reader);
4405
4406 /* set non fundamental callbacks via setter functions */
4407 SCIP_CALL( SCIPsetReaderCopy(scip, reader, readerCopyLp) );
4408 SCIP_CALL( SCIPsetReaderFree(scip, reader, readerFreeLp) );
4409 SCIP_CALL( SCIPsetReaderRead(scip, reader, readerReadLp) );
4410 SCIP_CALL( SCIPsetReaderWrite(scip, reader, readerWriteLp) );
4411
4412 /* add lp-reader parameters */
4414 "reading/" READER_NAME "/linearize-and-constraints",
4415 "should possible \"and\" constraint be linearized when writing the lp file?",
4416 &readerdata->linearizeands, TRUE, DEFAULT_LINEARIZE_ANDS, NULL, NULL) );
4418 "reading/" READER_NAME "/aggrlinearization-ands",
4419 "should an aggregated linearization for and constraints be used?",
4420 &readerdata->aggrlinearizationands, TRUE, DEFAULT_AGGRLINEARIZATION_ANDS, NULL, NULL) );
4421
4422 return SCIP_OKAY;
4423}
4424
4425
4426/** reads problem from file */
4428 SCIP* scip, /**< SCIP data structure */
4429 SCIP_READER* reader, /**< the file reader itself */
4430 const char* filename, /**< full path and name of file to read, or NULL if stdin should be used */
4431 SCIP_RESULT* result /**< pointer to store the result of the file reading call */
4432 )
4433{ /*lint --e{715}*/
4434 SCIP_RETCODE retcode;
4435 LPINPUT lpinput;
4436 int i;
4437
4438 assert(scip != NULL);
4439 assert(reader != NULL);
4440
4441 /* initialize LP input data */
4442 lpinput.file = NULL;
4444 lpinput.linebuf[0] = '\0';
4445 lpinput.linebufsize = LP_MAX_LINELEN;
4446 lpinput.probname[0] = '\0';
4447 lpinput.objname[0] = '\0';
4448 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &lpinput.token, LP_MAX_LINELEN) ); /*lint !e506*/
4449 lpinput.token[0] = '\0';
4450 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &lpinput.tokenbuf, LP_MAX_LINELEN) ); /*lint !e506*/
4451 lpinput.tokenbuf[0] = '\0';
4452 for( i = 0; i < LP_MAX_PUSHEDTOKENS; ++i )
4453 {
4454 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &(lpinput.pushedtokens[i]), LP_MAX_LINELEN) ); /*lint !e866 !e506*/
4455 }
4456
4457 lpinput.npushedtokens = 0;
4458 lpinput.linenumber = 0;
4459 lpinput.linepos = 0;
4460 lpinput.section = LP_START;
4461 lpinput.objsense = SCIP_OBJSENSE_MINIMIZE;
4462 lpinput.inlazyconstraints = FALSE;
4463 lpinput.inusercuts = FALSE;
4464 lpinput.haserror = FALSE;
4465
4466 SCIP_CALL( SCIPgetBoolParam(scip, "reading/initialconss", &(lpinput.initialconss)) );
4467 SCIP_CALL( SCIPgetBoolParam(scip, "reading/dynamicconss", &(lpinput.dynamicconss)) );
4468 SCIP_CALL( SCIPgetBoolParam(scip, "reading/dynamiccols", &(lpinput.dynamiccols)) );
4469 SCIP_CALL( SCIPgetBoolParam(scip, "reading/dynamicrows", &(lpinput.dynamicrows)) );
4470
4471 /* read the file */
4472 retcode = readLPFile(scip, &lpinput, filename);
4473
4474 /* free dynamically allocated memory */
4475 for( i = 0; i < LP_MAX_PUSHEDTOKENS; ++i )
4476 {
4477 SCIPfreeBlockMemoryArray(scip, &lpinput.pushedtokens[i], LP_MAX_LINELEN);
4478 }
4479 SCIPfreeBlockMemoryArray(scip, &lpinput.tokenbuf, LP_MAX_LINELEN);
4481 SCIPfreeBlockMemoryArray(scip, &lpinput.linebuf, lpinput.linebufsize);
4482
4483 if( retcode == SCIP_PLUGINNOTFOUND || retcode == SCIP_INVALIDDATA )
4484 retcode = SCIP_READERROR;
4485
4486 /* check for correct return value */
4487 SCIP_CALL( retcode );
4488
4489 /* evaluate the result */
4490 if( lpinput.haserror )
4491 return SCIP_READERROR;
4492 else
4493 {
4494 /* set objective sense */
4495 SCIP_CALL( SCIPsetObjsense(scip, lpinput.objsense) );
4496 *result = SCIP_SUCCESS;
4497 }
4498
4499 return SCIP_OKAY;
4500}
4501
4502/** writes problem to file */
4504 SCIP* scip, /**< SCIP data structure */
4505 FILE* file, /**< output file, or NULL if standard output should be used */
4506 const char* name, /**< problem name */
4507 SCIP_Bool transformed, /**< TRUE iff problem is the transformed problem */
4508 SCIP_OBJSENSE objsense, /**< objective sense */
4509 SCIP_Real objoffset, /**< objective offset from bound shifting and fixing */
4510 SCIP_Real objscale, /**< scalar applied to objective function; external objective value is
4511 * extobj = objsense * objscale * (intobj + objoffset) */
4512 SCIP_RATIONAL* objoffsetexact, /**< exact objective offset from bound shifting and fixing */
4513 SCIP_RATIONAL* objscaleexact, /**< exact scalar applied to objective function; external objective value is
4514 * extobjexact = objsense * objscaleexact * (intobjexact + objoffsetexact) */
4515 SCIP_VAR** vars, /**< array with active variables ordered binary, integer, implicit, continuous */
4516 int nvars, /**< number of active variables in the problem */
4517 int nbinvars, /**< number of binary variables */
4518 int nintvars, /**< number of general integer variables */
4519 int nimplvars, /**< number of implicit integer variables */
4520 int ncontvars, /**< number of continuous variables */
4521 SCIP_CONS** conss, /**< array with constraints of the problem */
4522 int nconss, /**< number of constraints in the problem */
4523 SCIP_RESULT* result /**< pointer to store the result of the file writing call */
4524 )
4525{
4526 SCIP_READER* reader;
4527 SCIP_READERDATA* readerdata;
4528 SCIP_Bool linearizeands;
4529 SCIP_Bool aggrlinearizationands;
4530
4531 char linebuffer[LP_MAX_PRINTLEN + 1];
4532 char varname[LP_MAX_NAMELEN];
4533 char ratbuffer[LP_MAX_PRINTLEN];
4534 char buffer[LP_MAX_PRINTLEN];
4535 int linecnt;
4536 int written;
4537 int c;
4538 int v;
4539
4540 SCIP_CONSHDLR* conshdlr;
4541 SCIP_CONSHDLR* conshdlrInd;
4542 const char* conshdlrname;
4543 SCIP_CONS* cons;
4544 SCIP_CONS** consSOS1;
4545 SCIP_CONS** consSOS2;
4546 SCIP_CONS** consExpr;
4547 SCIP_CONS** consIndicator;
4548 int nConsSOS1 = 0;
4549 int nConsSOS2 = 0;
4550 int nConsExpr = 0;
4551 int nConsIndicator = 0;
4552 char consname[LP_MAX_NAMELEN];
4553
4554 SCIP_VAR** aggvars;
4555 SCIP_VAR** tmpvars;
4556 int tmpvarssize;
4557 int naggvars = 0;
4558 int saggvars;
4559 SCIP_HASHTABLE* varAggregated;
4560 SCIP_HASHMAP* consHidden;
4561
4562 SCIP_VAR** consvars;
4563 SCIP_Real* consvals;
4564 int nconsvars;
4565
4566 SCIP_VAR* var;
4567 SCIP_RATIONAL* objexact;
4568 SCIP_Real obj;
4569 SCIP_Real lb;
4570 SCIP_Real ub;
4571
4572 SCIP_Bool zeroobj;
4573 int implintlevel;
4574 int nintegers = nvars - ncontvars;
4575 assert(nintegers >= 0);
4576
4577 /* find indicator constraint handler */
4578 conshdlrInd = SCIPfindConshdlr(scip, "indicator");
4579 consHidden = NULL;
4580
4581 /* if indicator constraint handler is present */
4582 if( conshdlrInd != NULL )
4583 {
4584 /* create hashtable storing linear constraints that should not be output */
4585 SCIP_CALL( SCIPhashmapCreate(&consHidden, SCIPblkmem(scip), 500) );
4586
4587 /* loop through indicator constraints (works only in transformed problem) */
4588 if( transformed )
4589 {
4590 SCIP_CONS** consInd;
4591 int nConsInd;
4592
4593 consInd = SCIPconshdlrGetConss(conshdlrInd);
4594 nConsInd = SCIPconshdlrGetNConss(conshdlrInd);
4595 SCIPdebugMsg(scip, "Number of indicator constraints: %d\n", nConsInd);
4596
4597 for( c = 0; c < nConsInd; ++c )
4598 {
4599 assert( consInd[c] != NULL );
4600 cons = SCIPgetLinearConsIndicator(consInd[c]);
4601
4602 assert( !SCIPhashmapExists(consHidden, (void*) cons) );
4603 SCIP_CALL( SCIPhashmapSetImageInt(consHidden, (void*) cons, 1) );
4604 SCIPdebugMsg(scip, "Marked linear constraint <%s> as hidden.\n", SCIPconsGetName(cons));
4605 }
4606 }
4607 else
4608 {
4609 /* otherwise we have to pass through all constraints */
4610 for( c = 0; c < nconss; ++c )
4611 {
4612 cons = conss[c];
4613 assert( cons != NULL);
4614
4615 conshdlr = SCIPconsGetHdlr(cons);
4616 assert( conshdlr != NULL );
4617 conshdlrname = SCIPconshdlrGetName(conshdlr);
4618
4619 if( strcmp(conshdlrname, "indicator") == 0 )
4620 {
4621 SCIP_CONS* lincons;
4622
4623 lincons = SCIPgetLinearConsIndicator(cons);
4624 assert( lincons != NULL );
4625
4626 assert( !SCIPhashmapExists(consHidden, (void*) lincons) );
4627 SCIP_CALL( SCIPhashmapSetImageInt(consHidden, (void*) lincons, 1) );
4628 SCIPdebugMsg(scip, "Marked linear constraint <%s> as hidden.\n", SCIPconsGetName(lincons));
4629 }
4630 }
4631 }
4632 }
4633
4634 /* check if the variable names are not to long */
4635 checkVarnames(scip, vars, nvars);
4636 /* check if the constraint names are to long */
4637 checkConsnames(scip, conss, nconss, transformed);
4638
4639 /* adjust written integrality constraints on implied integral variables based on the implied integral level */
4640 SCIP_CALL( SCIPgetIntParam(scip, "write/implintlevel", &implintlevel) );
4641 assert(implintlevel >= -2);
4642 assert(implintlevel <= 2);
4643
4644 if( SCIPisExact(scip) )
4645 {
4647 }
4648 else
4649 objexact = NULL;
4650
4651 /* print statistics as comment to file */
4652 SCIPinfoMessage(scip, file, "\\ SCIP STATISTICS\n");
4653 SCIPinfoMessage(scip, file, "\\ Problem name : %s\n", name);
4654 SCIPinfoMessage(scip, file, "\\ Variables : %d (%d binary, %d integer, %d implicit integer, %d continuous)\n",
4655 nvars, nbinvars, nintvars, nimplvars, ncontvars);
4656 SCIPinfoMessage(scip, file, "\\ Constraints : %d\n", nconss);
4657
4658 /* print objective sense */
4659 SCIPinfoMessage(scip, file, "%s\n", objsense == SCIP_OBJSENSE_MINIMIZE ? "Minimize" : "Maximize");
4660
4661 clearLine(linebuffer, &linecnt);
4662 appendLine(scip, file, linebuffer, &linecnt, " Obj:");
4663
4664 zeroobj = TRUE;
4665 for( v = 0; v < nvars; ++v )
4666 {
4667 var = vars[v];
4668
4669#ifndef NDEBUG
4670 /* in case the original problem has to be written, the variables have to be either "original" or "negated" */
4671 if( ! transformed )
4673#endif
4674
4675 /* multiply exact objscale */
4676 if( objexact != NULL )
4677 {
4679
4680 if( SCIPrationalIsZero(objexact) )
4681 continue;
4682
4683 SCIPrationalMult(objexact, objexact, objscaleexact);
4684 zeroobj = FALSE;
4685
4686 /* we start a new line; therefore we tab this line */
4687 if( linecnt == 0 )
4688 appendLine(scip, file, linebuffer, &linecnt, " ");
4689
4690 written = SCIPsnprintf(varname, LP_MAX_NAMELEN, "%s", SCIPvarGetName(var));
4691 if( written >= LP_MAX_NAMELEN )
4692 {
4694 SCIPerrorMessage("buffer length exceeded\n");
4695 return SCIP_INVALIDDATA;
4696 }
4697 written = SCIPrationalToString(objexact, ratbuffer, LP_MAX_PRINTLEN);
4698 if( written >= LP_MAX_PRINTLEN )
4699 {
4701 SCIPerrorMessage("buffer length exceeded\n");
4702 return SCIP_INVALIDDATA;
4703 }
4704 if( !SCIPrationalIsNegative(objexact) )
4705 written = SCIPsnprintf(buffer, LP_MAX_PRINTLEN, " +%s %s", ratbuffer, varname);
4706 else
4707 written = SCIPsnprintf(buffer, LP_MAX_PRINTLEN, " %s %s", ratbuffer, varname);
4708 if( written >= LP_MAX_PRINTLEN )
4709 {
4711 SCIPerrorMessage("buffer length exceeded\n");
4712 return SCIP_INVALIDDATA;
4713 }
4714 }
4715 /* multiply real objscale */
4716 else
4717 {
4718 obj = SCIPvarGetObj(var);
4719
4720 if( obj == 0.0 ) /*lint !e777*/
4721 continue;
4722
4723 obj *= objscale;
4724 zeroobj = FALSE;
4725
4726 /* we start a new line; therefore we tab this line */
4727 if( linecnt == 0 )
4728 appendLine(scip, file, linebuffer, &linecnt, " ");
4729
4730 written = SCIPsnprintf(varname, LP_MAX_NAMELEN, "%s", SCIPvarGetName(var));
4731 if( written >= LP_MAX_NAMELEN )
4732 {
4733 SCIPerrorMessage("buffer length exceeded\n");
4734 return SCIP_INVALIDDATA;
4735 }
4736 written = SCIPsnprintf(buffer, LP_MAX_PRINTLEN, " %+.15g %s", obj, varname);
4737 if( written >= LP_MAX_PRINTLEN )
4738 {
4739 SCIPerrorMessage("buffer length exceeded\n");
4740 return SCIP_INVALIDDATA;
4741 }
4742 }
4743
4744 appendLine(scip, file, linebuffer, &linecnt, buffer);
4745 }
4746
4747 /* add exact objoffset */
4748 if( objexact != NULL )
4749 {
4750 if( zeroobj || !SCIPrationalIsZero(objoffsetexact) )
4751 {
4752 SCIPrationalMult(objexact, objoffsetexact, objscaleexact);
4753
4754 written = SCIPrationalToString(objexact, ratbuffer, LP_MAX_PRINTLEN);
4755 if( written >= LP_MAX_PRINTLEN )
4756 {
4758 SCIPerrorMessage("buffer length exceeded\n");
4759 return SCIP_INVALIDDATA;
4760 }
4761 if( !SCIPrationalIsNegative(objexact) )
4762 written = SCIPsnprintf(buffer, LP_MAX_PRINTLEN, " +%s", ratbuffer);
4763 else
4764 written = SCIPsnprintf(buffer, LP_MAX_PRINTLEN, " %s", ratbuffer);
4765 if( written >= LP_MAX_PRINTLEN )
4766 {
4768 SCIPerrorMessage("buffer length exceeded\n");
4769 return SCIP_INVALIDDATA;
4770 }
4771
4772 appendLine(scip, file, linebuffer, &linecnt, buffer);
4773 }
4774
4776 }
4777 /* add real objoffset */
4778 else
4779 {
4780 if( zeroobj || objoffset != 0.0 ) /*lint !e777*/
4781 {
4782 obj = objoffset * objscale;
4783
4784 written = SCIPsnprintf(buffer, LP_MAX_PRINTLEN, " %+.15g", obj);
4785 if( written >= LP_MAX_PRINTLEN )
4786 {
4787 SCIPerrorMessage("buffer length exceeded\n");
4788 return SCIP_INVALIDDATA;
4789 }
4790
4791 appendLine(scip, file, linebuffer, &linecnt, buffer);
4792 }
4793 }
4794
4795 endLine(scip, file, linebuffer, &linecnt);
4796
4797 /* print "Subject to" section */
4798 SCIPinfoMessage(scip, file, "Subject to\n");
4799
4800 reader = SCIPfindReader(scip, READER_NAME);
4801 if( reader != NULL )
4802 {
4803 readerdata = SCIPreaderGetData(reader);
4804 assert(readerdata != NULL);
4805
4806 linearizeands = readerdata->linearizeands;
4807 aggrlinearizationands = readerdata->aggrlinearizationands;
4808 }
4809 else
4810 {
4811 linearizeands = DEFAULT_LINEARIZE_ANDS;
4812 aggrlinearizationands = DEFAULT_AGGRLINEARIZATION_ANDS;
4813 }
4814
4815 /* collect SOS, quadratic, and SOC constraints in array for later output */
4816 SCIP_CALL( SCIPallocBufferArray(scip, &consSOS1, nconss) );
4817 SCIP_CALL( SCIPallocBufferArray(scip, &consSOS2, nconss) );
4818 SCIP_CALL( SCIPallocBufferArray(scip, &consExpr, nconss) );
4819 SCIP_CALL( SCIPallocBufferArray(scip, &consIndicator, nconss) );
4820
4821 tmpvarssize = SCIPgetNTotalVars(scip);
4822 SCIP_CALL( SCIPallocBufferArray(scip, &tmpvars, tmpvarssize) );
4823
4824 for( c = 0; c < nconss; ++c )
4825 {
4826 cons = conss[c];
4827 assert( cons != NULL);
4828
4829 /* in case the transformed is written only constraints are posted which are enabled in the current node */
4830 assert(!transformed || SCIPconsIsEnabled(cons));
4831
4832 /* skip marked constraints in connection with indicator constraints */
4833 if( conshdlrInd != NULL && SCIPhashmapExists(consHidden, (void*) cons) )
4834 {
4835 assert( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), "linear") == 0 );
4836 continue;
4837 }
4838
4839 conshdlr = SCIPconsGetHdlr(cons);
4840 assert( conshdlr != NULL );
4841
4842 (void) SCIPsnprintf(consname, LP_MAX_NAMELEN, "%s", SCIPconsGetName(cons));
4843 conshdlrname = SCIPconshdlrGetName(conshdlr);
4844 assert( transformed == SCIPconsIsTransformed(cons) );
4845
4846 if( strcmp(conshdlrname, "linear") == 0 )
4847 {
4848 SCIP_CALL( printQuadraticCons(scip, file, consname,
4850 NULL, SCIPgetLhsLinear(scip, cons), SCIPgetRhsLinear(scip, cons), transformed) );
4851 }
4852 else if( strcmp(conshdlrname, "setppc") == 0 )
4853 {
4854 consvars = SCIPgetVarsSetppc(scip, cons);
4855 nconsvars = SCIPgetNVarsSetppc(scip, cons);
4856
4857 switch( SCIPgetTypeSetppc(scip, cons) )
4858 {
4860 SCIP_CALL( printQuadraticCons(scip, file, consname,
4861 consvars, NULL, nconsvars, NULL, 1.0, 1.0, transformed) );
4862 break;
4864 SCIP_CALL( printQuadraticCons(scip, file, consname,
4865 consvars, NULL, nconsvars, NULL, -SCIPinfinity(scip), 1.0, transformed) );
4866 break;
4868 SCIP_CALL( printQuadraticCons(scip, file, consname,
4869 consvars, NULL, nconsvars, NULL, 1.0, SCIPinfinity(scip), transformed) );
4870 break;
4871 }
4872 }
4873 else if( strcmp(conshdlrname, "logicor") == 0 )
4874 {
4875 SCIP_CALL( printQuadraticCons(scip, file, consname,
4877 NULL, 1.0, SCIPinfinity(scip), transformed) );
4878 }
4879 else if( strcmp(conshdlrname, "knapsack") == 0 )
4880 {
4881 SCIP_Longint* weights;
4882
4883 consvars = SCIPgetVarsKnapsack(scip, cons);
4884 nconsvars = SCIPgetNVarsKnapsack(scip, cons);
4885
4886 /* copy Longint array to SCIP_Real array */
4887 weights = SCIPgetWeightsKnapsack(scip, cons);
4888 SCIP_CALL( SCIPallocBufferArray(scip, &consvals, nconsvars) );
4889 for( v = 0; v < nconsvars; ++v )
4890 consvals[v] = (SCIP_Real)weights[v];
4891
4892 SCIP_CALL( printQuadraticCons(scip, file, consname, consvars, consvals, nconsvars,
4893 NULL, -SCIPinfinity(scip), (SCIP_Real) SCIPgetCapacityKnapsack(scip, cons), transformed) );
4894
4895 SCIPfreeBufferArray(scip, &consvals);
4896 }
4897 else if( strcmp(conshdlrname, "varbound") == 0 )
4898 {
4899 SCIP_CALL( SCIPallocBufferArray(scip, &consvars, 2) );
4900 SCIP_CALL( SCIPallocBufferArray(scip, &consvals, 2) );
4901
4902 consvars[0] = SCIPgetVarVarbound(scip, cons);
4903 consvars[1] = SCIPgetVbdvarVarbound(scip, cons);
4904
4905 consvals[0] = 1.0;
4906 consvals[1] = SCIPgetVbdcoefVarbound(scip, cons);
4907
4908 SCIP_CALL( printQuadraticCons(scip, file, consname, consvars, consvals, 2, NULL,
4909 SCIPgetLhsVarbound(scip, cons), SCIPgetRhsVarbound(scip, cons), transformed) );
4910
4911 SCIPfreeBufferArray(scip, &consvals);
4912 SCIPfreeBufferArray(scip, &consvars);
4913 }
4914 else if( strcmp(conshdlrname, "SOS1") == 0 )
4915 {
4916 /* store constraint */
4917 consSOS1[nConsSOS1++] = cons;
4918 }
4919 else if( strcmp(conshdlrname, "SOS2") == 0 )
4920 {
4921 /* store constraint */
4922 consSOS2[nConsSOS2++] = cons;
4923 }
4924 else if( strcmp(conshdlrname, "indicator") == 0 )
4925 {
4926 SCIP_CONS* lincons;
4927 SCIP_VAR* binvar;
4928 SCIP_VAR* slackvar;
4929 SCIP_VAR** linvars;
4930 SCIP_Real* linvals;
4931 int nlinvars;
4932 int cnt;
4933 int rhs;
4934
4935 assert( conshdlrInd != NULL );
4936
4937 lincons = SCIPgetLinearConsIndicator(cons);
4938 binvar = SCIPgetBinaryVarIndicator(cons);
4939 slackvar = SCIPgetSlackVarIndicator(cons);
4940
4941 assert( lincons != NULL );
4942 assert( binvar != NULL );
4943 assert( slackvar != NULL );
4944
4945 rhs = 1;
4946 if ( SCIPvarIsNegated(binvar) )
4947 {
4948 rhs = 0;
4949 binvar = SCIPvarGetNegatedVar(binvar);
4950 }
4951
4952 /* collect linear constraint information (remove slack variable) */
4953 linvars = SCIPgetVarsLinear(scip, lincons);
4954 linvals = SCIPgetValsLinear(scip, lincons);
4955 nlinvars = SCIPgetNVarsLinear(scip, lincons);
4956 assert( linvars != NULL );
4957 assert( linvals != NULL );
4958
4959 /* linvars always contains slack variable, thus nlinvars >= 1 */
4960 if( nlinvars > 1 && !SCIPconsIsDeleted(lincons) )
4961 {
4962 (void) SCIPsnprintf(varname, LP_MAX_NAMELEN, "%s", SCIPvarGetName(binvar) );
4963 if( strlen(consname) > 0 )
4964 SCIPinfoMessage(scip, file, " %s: %s = %d ->", consname, varname, rhs);
4965 else
4966 SCIPinfoMessage(scip, file, " %s = %d ->", varname, rhs);
4967
4968 SCIP_CALL( SCIPallocBufferArray(scip, &consvars, nlinvars-1) );
4969 SCIP_CALL( SCIPallocBufferArray(scip, &consvals, nlinvars-1) );
4970
4971 cnt = 0;
4972 for( v = 0; v < nlinvars; ++v )
4973 {
4974 var = linvars[v];
4975 if( var != slackvar )
4976 {
4977 consvars[cnt] = var;
4978 consvals[cnt++] = linvals[v];
4979 }
4980 }
4981 /* if slackvariable is fixed, it might have been removed from constraint */
4982 assert( nlinvars == 0 || cnt == nlinvars-1 || SCIPisFeasEQ(scip, SCIPvarGetLbGlobal(slackvar), SCIPvarGetUbGlobal(slackvar)) );
4983
4984 SCIP_CALL( printQuadraticCons(scip, file, "", consvars, consvals, cnt, NULL,
4985 SCIPgetLhsLinear(scip, lincons), SCIPgetRhsLinear(scip, lincons), transformed) );
4986
4987 SCIPfreeBufferArray(scip, &consvals);
4988 SCIPfreeBufferArray(scip, &consvars);
4989 }
4990
4991 /* store constraint */
4992 consIndicator[nConsIndicator++] = cons;
4993 }
4994 else if( strcmp(conshdlrname, "nonlinear") == 0 )
4995 {
4996 SCIP_Bool isquadratic;
4997 SCIP_EXPR* expr;
4998
4999 /* check whether there is a quadratic representation of the nonlinear constraint */
5000 SCIP_CALL( SCIPcheckQuadraticNonlinear(scip, cons, &isquadratic) );
5001 if( !isquadratic )
5002 {
5003 /* simplify expr and check again whether there is a quadratic representation */
5004 SCIP_EXPR* exprcopy;
5005 SCIP_Bool changed;
5006 SCIP_Bool infeasible;
5007
5009 SCIP_CALL( SCIPsimplifyExpr(scip, exprcopy, &expr, &changed, &infeasible, NULL, NULL) );
5010 SCIP_CALL( SCIPreleaseExpr(scip, &exprcopy) );
5011 if( changed && !infeasible )
5012 {
5013 SCIP_CALL( SCIPcheckExprQuadratic(scip, expr, &isquadratic) );
5014 isquadratic &= SCIPexprAreQuadraticExprsVariables(expr);
5015 }
5016 }
5017 else
5018 {
5019 expr = SCIPgetExprNonlinear(cons);
5020 }
5021
5022 /* we cannot handle nonlinear constraint that are not quadratically representable */
5023 if( !isquadratic )
5024 {
5025 SCIPwarningMessage(scip, "nonlinear constraint <%s> not recognized as quadratic: cannot print as LP\n", SCIPconsGetName(cons));
5026 SCIPinfoMessage(scip, file, "\\ ");
5027 SCIP_CALL( SCIPprintCons(scip, cons, file) );
5028 SCIPinfoMessage(scip, file, ";\n");
5029 }
5030 else
5031 {
5032 SCIP_CALL( printQuadraticCons(scip, file, consname, NULL, NULL, 0, expr,
5033 SCIPgetLhsNonlinear(cons), SCIPgetRhsNonlinear(cons), transformed) );
5034
5035 consExpr[nConsExpr++] = cons;
5036 }
5037
5038 if( expr != SCIPgetExprNonlinear(cons) )
5039 {
5040 SCIP_CALL( SCIPreleaseExpr(scip, &expr) );
5041 }
5042 }
5043 else if( strcmp(conshdlrname, "and") == 0 )
5044 {
5045 if( linearizeands )
5046 {
5047 SCIP_CALL( printAndCons(scip, file, consname, cons, aggrlinearizationands, transformed) );
5048 }
5049 else
5050 {
5051 SCIPwarningMessage(scip, "change parameter \"reading/" READER_NAME "/linearize-and-constraints\" to TRUE to print and-constraints\n");
5052 SCIPinfoMessage(scip, file, "\\ ");
5053 SCIP_CALL( SCIPprintCons(scip, cons, file) );
5054 SCIPinfoMessage(scip, file, ";\n");
5055 }
5056 }
5057 else if(strcmp(conshdlrname, "exactlinear") == 0 )
5058 {
5060 {
5061 SCIP_CALL( printRowExact(scip, file, consname, "_", "=",
5064 }
5065 else
5066 {
5068 {
5069 SCIP_CALL( printRowExact(scip, file, consname, "_lhs", ">=",
5072 }
5074 {
5075 SCIP_CALL( printRowExact(scip, file, consname, "_rhs", "<=",
5078 }
5079 }
5080 }
5081 else
5082 {
5083 SCIPwarningMessage(scip, "constraint handler <%s> cannot print requested format\n", conshdlrname );
5084 SCIPinfoMessage(scip, file, "\\ ");
5085 SCIP_CALL( SCIPprintCons(scip, cons, file) );
5086 SCIPinfoMessage(scip, file, ";\n");
5087 }
5088 }
5089
5090 /* allocate array for storing aggregated and negated variables (dynamically adjusted) */
5091 saggvars = MAX(10, nvars);
5092 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &aggvars, saggvars) );
5093
5094 /* create hashtable for storing aggregated variables */
5095 SCIP_CALL( SCIPhashtableCreate(&varAggregated, SCIPblkmem(scip), saggvars, hashGetKeyVar, hashKeyEqVar, hashKeyValVar, NULL) );
5096
5097 /* check for aggregated variables in SOS1 constraints and output aggregations as linear constraints */
5098 for( c = 0; c < nConsSOS1; ++c )
5099 {
5100 cons = consSOS1[c];
5101 consvars = SCIPgetVarsSOS1(scip, cons);
5102 nconsvars = SCIPgetNVarsSOS1(scip, cons);
5103
5104 SCIP_CALL( collectAggregatedVars(scip, consvars, nconsvars, &aggvars, &naggvars, &saggvars, varAggregated) );
5105 }
5106
5107 /* check for aggregated variables in SOS2 constraints and output aggregations as linear constraints */
5108 for( c = 0; c < nConsSOS2; ++c )
5109 {
5110 cons = consSOS2[c];
5111 consvars = SCIPgetVarsSOS2(scip, cons);
5112 nconsvars = SCIPgetNVarsSOS2(scip, cons);
5113
5114 SCIP_CALL( collectAggregatedVars(scip, consvars, nconsvars, &aggvars, &naggvars, &saggvars, varAggregated) );
5115 }
5116
5117 /* check for aggregated variables in nonlinear constraints and output aggregations as linear constraints */
5118 for( c = 0; c < nConsExpr; ++c )
5119 {
5120 SCIP_Bool success;
5121 int ntmpvars;
5122
5123 /* get variables of the nonlinear constraint */
5124 SCIP_CALL( SCIPgetConsNVars(scip, consExpr[c], &ntmpvars, &success) );
5125 assert(success);
5126 if( ntmpvars > tmpvarssize )
5127 {
5128 tmpvarssize = SCIPcalcMemGrowSize(scip, ntmpvars);
5129 SCIP_CALL( SCIPreallocBufferArray(scip, &tmpvars, tmpvarssize) );
5130 }
5131 SCIP_CALL( SCIPgetConsVars(scip, consExpr[c], tmpvars, tmpvarssize, &success) );
5132 assert(success);
5133
5134 SCIP_CALL( collectAggregatedVars(scip, tmpvars, ntmpvars, &aggvars, &naggvars, &saggvars, varAggregated) );
5135 }
5136
5137 /* check for aggregated variables in indicator constraints and output aggregations as linear constraints */
5138 for( c = 0; c < nConsIndicator; ++c )
5139 {
5140 SCIP_VAR* binvar;
5141
5142 cons = consIndicator[c];
5143 binvar = SCIPgetBinaryVarIndicator(cons);
5144 if ( ! SCIPvarIsNegated(binvar) )
5145 {
5146 /* we take care of negated variables above, but not of aggregated variables */
5147 SCIP_CALL( collectAggregatedVars(scip, &binvar, 1, &aggvars, &naggvars, &saggvars, varAggregated) );
5148 }
5149 }
5150
5151 /* print aggregation constraints */
5152 SCIP_CALL( printAggregatedCons(scip, file, transformed, nvars, naggvars, aggvars) );
5153
5154 /* print "Bounds" section */
5155 SCIPinfoMessage(scip, file, "Bounds\n");
5156 for( v = 0; v < nvars; ++v )
5157 {
5158 var = vars[v];
5159 assert( var != NULL );
5160 (void) SCIPsnprintf(varname, LP_MAX_NAMELEN, "%s", SCIPvarGetName(var) );
5161
5162 if( transformed )
5163 {
5164 /* in case the transformed is written only local bounds are posted which are valid in the current node */
5165 lb = SCIPvarGetLbLocal(var);
5166 ub = SCIPvarGetUbLocal(var);
5167 }
5168 else
5169 {
5170 lb = SCIPvarGetLbOriginal(var);
5171 ub = SCIPvarGetUbOriginal(var);
5172 }
5173
5174 if( SCIPisInfinity(scip, -lb) && SCIPisInfinity(scip, ub) )
5175 SCIPinfoMessage(scip, file, " %s free\n", varname);
5176 else
5177 {
5178 /* print lower bound */
5179 if( SCIPisInfinity(scip, -lb) )
5180 SCIPinfoMessage(scip, file, " -inf <= ");
5181 else
5182 {
5183 if( SCIPisZero(scip, lb) )
5184 {
5185 /* variables are nonnegative by default - so we skip these variables */
5186 if( SCIPisInfinity(scip, ub) )
5187 continue;
5188 lb = 0.0;
5189 }
5190
5191 SCIPinfoMessage(scip, file, " %.15g <= ", lb);
5192 }
5193 /* print variable name */
5194 SCIPinfoMessage(scip, file, "%s", varname);
5195
5196 /* print upper bound as far this one is not infinity */
5197 if( !SCIPisInfinity(scip, ub) )
5198 SCIPinfoMessage(scip, file, " <= %.15g", ub);
5199
5200 SCIPinfoMessage(scip, file, "\n");
5201 }
5202 }
5203
5204 /* output aggregated variables as 'free' */
5205 for( v = 0; v < naggvars; ++v )
5206 {
5207 var = aggvars[v];
5208 assert( var != NULL );
5209 (void) SCIPsnprintf(varname, LP_MAX_NAMELEN, "%s", SCIPvarGetName(var) );
5210
5211 SCIPinfoMessage(scip, file, " %s free\n", varname);
5212 }
5213
5214 /* print binaries section */
5215 {
5216 SCIP_Bool initial = TRUE;
5217
5218 /* output active variables */
5219 for( v = 0; v < nintegers; ++v )
5220 {
5221 var = vars[v];
5222
5223 if( SCIPvarGetType(var) != SCIP_VARTYPE_BINARY || (int)SCIPvarGetImplType(var) > 2 + implintlevel )
5224 continue;
5225
5226 if( initial )
5227 {
5228 SCIPinfoMessage(scip, file, "Binaries\n");
5229 initial = FALSE;
5230 }
5231
5232 (void) SCIPsnprintf(varname, LP_MAX_NAMELEN, "%s", SCIPvarGetName(var) );
5233 (void) SCIPsnprintf(buffer, LP_MAX_PRINTLEN, " %s", varname);
5234 appendLine(scip, file, linebuffer, &linecnt, buffer);
5235 }
5236
5237 /* possibly output aggregated variables */
5238 for( v = 0; v < naggvars; ++v )
5239 {
5240 var = aggvars[v];
5241
5242 if( SCIPvarGetType(var) != SCIP_VARTYPE_BINARY || (int)SCIPvarGetImplType(var) > 2 + implintlevel )
5243 continue;
5244
5245 if( initial )
5246 {
5247 SCIPinfoMessage(scip, file, "Binaries\n");
5248 initial = FALSE;
5249 }
5250
5251 (void) SCIPsnprintf(varname, LP_MAX_NAMELEN, "%s", SCIPvarGetName(var) );
5252 (void) SCIPsnprintf(buffer, LP_MAX_PRINTLEN, " %s", varname);
5253 appendLine(scip, file, linebuffer, &linecnt, buffer);
5254 }
5255
5256 endLine(scip, file, linebuffer, &linecnt);
5257 }
5258
5259 /* print generals section */
5260 {
5261 SCIP_Bool initial = TRUE;
5262
5263 /* output active variables */
5264 for( v = nbinvars; v < nintegers; ++v )
5265 {
5266 var = vars[v];
5267
5268 switch( SCIPvarGetType(var) )
5269 {
5271 continue;
5273 if( (int)SCIPvarGetImplType(var) > 2 + implintlevel )
5274 continue;
5275 break;
5277 if( (int)SCIPvarGetImplType(var) <= 2 - implintlevel )
5278 continue;
5279 break;
5280 default:
5281 SCIPerrorMessage("unknown variable type\n");
5282 return SCIP_INVALIDDATA;
5283 } /*lint !e788*/
5284
5285 if( initial )
5286 {
5287 SCIPinfoMessage(scip, file, "Generals\n");
5288 initial = FALSE;
5289 }
5290
5291 (void) SCIPsnprintf(varname, LP_MAX_NAMELEN, "%s", SCIPvarGetName(var));
5292 (void) SCIPsnprintf(buffer, LP_MAX_PRINTLEN, " %s", varname);
5293 appendLine(scip, file, linebuffer, &linecnt, buffer);
5294 }
5295
5296 /* possibly output aggregated variables */
5297 for( v = 0; v < naggvars; ++v )
5298 {
5299 var = aggvars[v];
5300
5301 switch( SCIPvarGetType(var) )
5302 {
5304 continue;
5306 if( (int)SCIPvarGetImplType(var) > 2 + implintlevel )
5307 continue;
5308 break;
5310 if( (int)SCIPvarGetImplType(var) <= 2 - implintlevel )
5311 continue;
5312 break;
5313 default:
5314 SCIPerrorMessage("unknown variable type\n");
5315 return SCIP_INVALIDDATA;
5316 } /*lint !e788*/
5317
5318 if( initial )
5319 {
5320 SCIPinfoMessage(scip, file, "Generals\n");
5321 initial = FALSE;
5322 }
5323
5324 (void) SCIPsnprintf(varname, LP_MAX_NAMELEN, "%s", SCIPvarGetName(var));
5325 (void) SCIPsnprintf(buffer, LP_MAX_PRINTLEN, " %s", varname);
5326 appendLine(scip, file, linebuffer, &linecnt, buffer);
5327 }
5328
5329 endLine(scip, file, linebuffer, &linecnt);
5330 }
5331
5332 /* free space */
5333 SCIPfreeBlockMemoryArray(scip, &aggvars, saggvars);
5334 SCIPhashtableFree(&varAggregated);
5335 if( conshdlrInd != NULL )
5336 SCIPhashmapFree(&consHidden);
5337
5338 /* print SOS section */
5339 if( nConsSOS1 > 0 || nConsSOS2 > 0 )
5340 {
5341 SCIP_Real* weights;
5342 SCIPinfoMessage(scip, file, "SOS\n");
5343
5344 /* first output SOS1 constraints */
5345 for( c = 0; c < nConsSOS1; ++c )
5346 {
5347 cons = consSOS1[c];
5348 consvars = SCIPgetVarsSOS1(scip, cons);
5349 nconsvars = SCIPgetNVarsSOS1(scip, cons);
5350 weights = SCIPgetWeightsSOS1(scip, cons);
5351
5352 (void) SCIPsnprintf(consname, LP_MAX_NAMELEN, "%s", SCIPconsGetName(cons) );
5353 printSosCons(scip, file, consname, consvars, weights, nconsvars, 1);
5354 }
5355
5356 /* next output SOS2 constraints */
5357 for( c = 0; c < nConsSOS2; ++c )
5358 {
5359 cons = consSOS2[c];
5360 consvars = SCIPgetVarsSOS2(scip, cons);
5361 nconsvars = SCIPgetNVarsSOS2(scip, cons);
5362 weights = SCIPgetWeightsSOS2(scip, cons);
5363
5364 (void) SCIPsnprintf(consname, LP_MAX_NAMELEN, "%s", SCIPconsGetName(cons) );
5365 printSosCons(scip, file, consname, consvars, weights, nconsvars, 2);
5366 }
5367 }
5368
5369 /* free space */
5370 SCIPfreeBufferArray(scip, &tmpvars);
5371 SCIPfreeBufferArray(scip, &consIndicator);
5372 SCIPfreeBufferArray(scip, &consExpr);
5373 SCIPfreeBufferArray(scip, &consSOS2);
5374 SCIPfreeBufferArray(scip, &consSOS1);
5375
5376 /* end of lp format */
5377 SCIPinfoMessage(scip, file, "%s\n", "End");
5378
5379 *result = SCIP_SUCCESS;
5380
5381 return SCIP_OKAY;
5382}
Constraint handler for AND constraints, .
constraint handler for bound disjunction constraints
Constraint handler for linear constraints in their most general form, .
constraint handler for indicator constraints
Constraint handler for knapsack constraints of the form , x binary and .
Constraint handler for linear constraints in their most general form, .
Constraint handler for logicor constraints (equivalent to set covering, but algorithms are suited fo...
constraint handler for nonlinear constraints specified by algebraic expressions
Constraint handler for the set partitioning / packing / covering constraints .
constraint handler for SOS type 1 constraints
constraint handler for SOS type 2 constraints
Constraint handler for variable bound constraints .
#define NULL
Definition: def.h:248
#define SCIP_MAXSTRLEN
Definition: def.h:269
#define SCIP_Longint
Definition: def.h:141
#define SCIP_Bool
Definition: def.h:91
#define SCIP_Real
Definition: def.h:156
#define TRUE
Definition: def.h:93
#define FALSE
Definition: def.h:94
#define MAX(x, y)
Definition: def.h:220
#define SCIP_CALL_ABORT(x)
Definition: def.h:334
#define SCIP_CALL_TERMINATE(retcode, x, TERM)
Definition: def.h:376
#define SCIPABORT()
Definition: def.h:327
#define SCIP_CALL(x)
Definition: def.h:355
SCIP_FILE * SCIPfopen(const char *path, const char *mode)
Definition: fileio.c:153
int SCIPfclose(SCIP_FILE *fp)
Definition: fileio.c:232
char * SCIPfgets(char *s, int size, SCIP_FILE *stream)
Definition: fileio.c:200
SCIP_RETCODE SCIPcheckQuadraticNonlinear(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *isquadratic)
int SCIPgetNVarsKnapsack(SCIP *scip, SCIP_CONS *cons)
SCIP_Real SCIPgetVbdcoefVarbound(SCIP *scip, SCIP_CONS *cons)
SCIP_RATIONAL * SCIPgetLhsExactLinear(SCIP *scip, SCIP_CONS *cons)
int SCIPgetNVarsLogicor(SCIP *scip, SCIP_CONS *cons)
SCIP_Real SCIPgetRhsLinear(SCIP *scip, SCIP_CONS *cons)
SCIP_VAR ** SCIPgetVarsLinear(SCIP *scip, SCIP_CONS *cons)
SCIP_RATIONAL * SCIPgetRhsExactLinear(SCIP *scip, SCIP_CONS *cons)
SCIP_RETCODE SCIPcreateConsExactLinear(SCIP *scip, SCIP_CONS **cons, const char *name, int nvars, SCIP_VAR **vars, SCIP_RATIONAL **vals, SCIP_RATIONAL *lhs, SCIP_RATIONAL *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)
SCIP_Real * SCIPgetWeightsSOS2(SCIP *scip, SCIP_CONS *cons)
Definition: cons_sos2.c:2790
SCIP_VAR ** SCIPgetVarsSOS2(SCIP *scip, SCIP_CONS *cons)
Definition: cons_sos2.c:2765
SCIP_VAR ** SCIPgetVarsExactLinear(SCIP *scip, SCIP_CONS *cons)
SCIP_Real SCIPgetLhsLinear(SCIP *scip, SCIP_CONS *cons)
int SCIPgetNVarsLinear(SCIP *scip, SCIP_CONS *cons)
SCIP_VAR * SCIPgetResultantAnd(SCIP *scip, SCIP_CONS *cons)
Definition: cons_and.c:5248
SCIP_RETCODE SCIPaddVarSOS1(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *var, SCIP_Real weight)
Definition: cons_sos1.c:10725
SCIP_RETCODE SCIPcreateConsBounddisjunction(SCIP *scip, SCIP_CONS **cons, const char *name, int nvars, SCIP_VAR **vars, SCIP_BOUNDTYPE *boundtypes, SCIP_Real *bounds, SCIP_Bool initial, SCIP_Bool separate, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool propagate, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool dynamic, SCIP_Bool removable, SCIP_Bool stickingatnode)
SCIP_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)
int SCIPgetNVarsAnd(SCIP *scip, SCIP_CONS *cons)
Definition: cons_and.c:5199
int SCIPgetNVarsExactLinear(SCIP *scip, SCIP_CONS *cons)
SCIP_Real * SCIPgetValsLinear(SCIP *scip, SCIP_CONS *cons)
SCIP_RETCODE SCIPcreateConsSOS1(SCIP *scip, SCIP_CONS **cons, const char *name, int nvars, SCIP_VAR **vars, SCIP_Real *weights, SCIP_Bool initial, SCIP_Bool separate, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool propagate, SCIP_Bool local, SCIP_Bool dynamic, SCIP_Bool removable, SCIP_Bool stickingatnode)
Definition: cons_sos1.c:10579
SCIP_VAR * SCIPgetVbdvarVarbound(SCIP *scip, SCIP_CONS *cons)
int SCIPgetNVarsSetppc(SCIP *scip, SCIP_CONS *cons)
Definition: cons_setppc.c:9596
int SCIPgetNVarsSOS2(SCIP *scip, SCIP_CONS *cons)
Definition: cons_sos2.c:2740
SCIP_Real * SCIPgetWeightsSOS1(SCIP *scip, SCIP_CONS *cons)
Definition: cons_sos1.c:10844
SCIP_VAR ** SCIPgetVarsSetppc(SCIP *scip, SCIP_CONS *cons)
Definition: cons_setppc.c:9619
SCIP_EXPR * SCIPgetExprNonlinear(SCIP_CONS *cons)
SCIP_Real SCIPgetRhsNonlinear(SCIP_CONS *cons)
SCIP_VAR * SCIPgetBinaryVarIndicator(SCIP_CONS *cons)
SCIP_VAR * SCIPgetVarVarbound(SCIP *scip, SCIP_CONS *cons)
SCIP_Longint * SCIPgetWeightsKnapsack(SCIP *scip, SCIP_CONS *cons)
SCIP_VAR * SCIPgetSlackVarIndicator(SCIP_CONS *cons)
SCIP_Longint SCIPgetCapacityKnapsack(SCIP *scip, SCIP_CONS *cons)
SCIP_Real SCIPgetLhsVarbound(SCIP *scip, SCIP_CONS *cons)
SCIP_SETPPCTYPE SCIPgetTypeSetppc(SCIP *scip, SCIP_CONS *cons)
Definition: cons_setppc.c:9642
SCIP_CONS * SCIPgetLinearConsIndicator(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:2578
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)
SCIP_VAR ** SCIPgetVarsSOS1(SCIP *scip, SCIP_CONS *cons)
Definition: cons_sos1.c:10819
SCIP_VAR ** SCIPgetVarsLogicor(SCIP *scip, SCIP_CONS *cons)
SCIP_Real SCIPgetRhsVarbound(SCIP *scip, SCIP_CONS *cons)
SCIP_VAR ** SCIPgetVarsAnd(SCIP *scip, SCIP_CONS *cons)
Definition: cons_and.c:5223
SCIP_VAR ** SCIPgetVarsKnapsack(SCIP *scip, SCIP_CONS *cons)
SCIP_RETCODE SCIPcreateConsQuadraticNonlinear(SCIP *scip, SCIP_CONS **cons, const char *name, int nlinvars, SCIP_VAR **linvars, SCIP_Real *lincoefs, int nquadterms, SCIP_VAR **quadvars1, SCIP_VAR **quadvars2, SCIP_Real *quadcoefs, SCIP_Real lhs, SCIP_Real rhs, SCIP_Bool initial, SCIP_Bool separate, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool propagate, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool dynamic, SCIP_Bool removable)
int SCIPgetNVarsSOS1(SCIP *scip, SCIP_CONS *cons)
Definition: cons_sos1.c:10794
SCIP_Real SCIPgetLhsNonlinear(SCIP_CONS *cons)
SCIP_RATIONAL ** SCIPgetValsExactLinear(SCIP *scip, SCIP_CONS *cons)
SCIP_RETCODE SCIPaddVarSOS2(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *var, SCIP_Real weight)
Definition: cons_sos2.c:2687
@ SCIP_SETPPCTYPE_PARTITIONING
Definition: cons_setppc.h:87
@ SCIP_SETPPCTYPE_COVERING
Definition: cons_setppc.h:89
@ SCIP_SETPPCTYPE_PACKING
Definition: cons_setppc.h:88
SCIP_RETCODE SCIPreadLp(SCIP *scip, SCIP_READER *reader, const char *filename, SCIP_RESULT *result)
Definition: reader_lp.c:4427
SCIP_RETCODE SCIPwriteLp(SCIP *scip, FILE *file, const char *name, SCIP_Bool transformed, SCIP_OBJSENSE objsense, SCIP_Real objoffset, SCIP_Real objscale, SCIP_RATIONAL *objoffsetexact, SCIP_RATIONAL *objscaleexact, 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:4503
SCIP_RETCODE SCIPincludeReaderLp(SCIP *scip)
Definition: reader_lp.c:4390
SCIP_RETCODE SCIPaddVar(SCIP *scip, SCIP_VAR *var)
Definition: scip_prob.c:1907
SCIP_RETCODE SCIPaddCons(SCIP *scip, SCIP_CONS *cons)
Definition: scip_prob.c:3274
SCIP_RETCODE SCIPsetObjsense(SCIP *scip, SCIP_OBJSENSE objsense)
Definition: scip_prob.c:1417
SCIP_RETCODE SCIPaddOrigObjoffset(SCIP *scip, SCIP_Real addval)
Definition: scip_prob.c:1486
SCIP_RETCODE SCIPcreateProb(SCIP *scip, const char *name, SCIP_DECL_PROBDELORIG((*probdelorig)), SCIP_DECL_PROBTRANS((*probtrans)), SCIP_DECL_PROBDELTRANS((*probdeltrans)), SCIP_DECL_PROBINITSOL((*probinitsol)), SCIP_DECL_PROBEXITSOL((*probexitsol)), SCIP_DECL_PROBCOPY((*probcopy)), SCIP_PROBDATA *probdata)
Definition: scip_prob.c:119
int SCIPgetNTotalVars(SCIP *scip)
Definition: scip_prob.c:3064
SCIP_VAR * SCIPfindVar(SCIP *scip, const char *name)
Definition: scip_prob.c:3189
SCIP_RETCODE SCIPaddOrigObjoffsetExact(SCIP *scip, SCIP_RATIONAL *addval)
Definition: scip_prob.c:1465
void SCIPhashmapFree(SCIP_HASHMAP **hashmap)
Definition: misc.c:3095
SCIP_RETCODE SCIPhashmapCreate(SCIP_HASHMAP **hashmap, BMS_BLKMEM *blkmem, int mapsize)
Definition: misc.c:3061
SCIP_Bool SCIPhashmapExists(SCIP_HASHMAP *hashmap, void *origin)
Definition: misc.c:3466
SCIP_RETCODE SCIPhashmapSetImageInt(SCIP_HASHMAP *hashmap, void *origin, int image)
Definition: misc.c:3400
void SCIPhashtableFree(SCIP_HASHTABLE **hashtable)
Definition: misc.c:2348
SCIP_Bool SCIPhashtableExists(SCIP_HASHTABLE *hashtable, void *element)
Definition: misc.c:2647
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:2298
SCIP_RETCODE SCIPhashtableInsert(SCIP_HASHTABLE *hashtable, void *element)
Definition: misc.c:2535
void SCIPinfoMessage(SCIP *scip, FILE *file, const char *formatstr,...)
Definition: scip_message.c:208
void SCIPverbMessage(SCIP *scip, SCIP_VERBLEVEL msgverblevel, FILE *file, const char *formatstr,...)
Definition: scip_message.c:225
#define SCIPdebugMsg
Definition: scip_message.h:78
void SCIPwarningMessage(SCIP *scip, const char *formatstr,...)
Definition: scip_message.c:120
SCIP_RETCODE SCIPgetBoolParam(SCIP *scip, const char *name, SCIP_Bool *value)
Definition: scip_param.c:250
SCIP_RETCODE SCIPaddBoolParam(SCIP *scip, const char *name, const char *desc, SCIP_Bool *valueptr, SCIP_Bool isadvanced, SCIP_Bool defaultvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
Definition: scip_param.c:57
SCIP_RETCODE SCIPgetIntParam(SCIP *scip, const char *name, int *value)
Definition: scip_param.c:269
int SCIPconshdlrGetNConss(SCIP_CONSHDLR *conshdlr)
Definition: cons.c:4778
const char * SCIPconshdlrGetName(SCIP_CONSHDLR *conshdlr)
Definition: cons.c:4316
SCIP_CONSHDLR * SCIPfindConshdlr(SCIP *scip, const char *name)
Definition: scip_cons.c:940
SCIP_CONS ** SCIPconshdlrGetConss(SCIP_CONSHDLR *conshdlr)
Definition: cons.c:4735
SCIP_RETCODE SCIPgetConsNVars(SCIP *scip, SCIP_CONS *cons, int *nvars, SCIP_Bool *success)
Definition: scip_cons.c:2621
SCIP_CONSHDLR * SCIPconsGetHdlr(SCIP_CONS *cons)
Definition: cons.c:8409
SCIP_RETCODE SCIPprintCons(SCIP *scip, SCIP_CONS *cons, FILE *file)
Definition: scip_cons.c:2536
SCIP_Bool SCIPconsIsDeleted(SCIP_CONS *cons)
Definition: cons.c:8518
SCIP_Bool SCIPconsIsTransformed(SCIP_CONS *cons)
Definition: cons.c:8698
SCIP_RETCODE SCIPgetConsVars(SCIP *scip, SCIP_CONS *cons, SCIP_VAR **vars, int varssize, SCIP_Bool *success)
Definition: scip_cons.c:2577
SCIP_Bool SCIPconsIsEnabled(SCIP_CONS *cons)
Definition: cons.c:8486
const char * SCIPconsGetName(SCIP_CONS *cons)
Definition: cons.c:8389
SCIP_RETCODE SCIPreleaseCons(SCIP *scip, SCIP_CONS **cons)
Definition: scip_cons.c:1173
SCIP_Bool SCIPisExact(SCIP *scip)
Definition: scip_exact.c:193
void SCIPexprGetQuadraticBilinTerm(SCIP_EXPR *expr, int termidx, SCIP_EXPR **expr1, SCIP_EXPR **expr2, SCIP_Real *coef, int *pos2, SCIP_EXPR **prodexpr)
Definition: expr.c:4226
SCIP_Bool SCIPexprAreQuadraticExprsVariables(SCIP_EXPR *expr)
Definition: expr.c:4262
void SCIPexprGetQuadraticData(SCIP_EXPR *expr, SCIP_Real *constant, int *nlinexprs, SCIP_EXPR ***linexprs, SCIP_Real **lincoefs, int *nquadexprs, int *nbilinexprs, SCIP_Real **eigenvalues, SCIP_Real **eigenvectors)
Definition: expr.c:4141
SCIP_RETCODE SCIPreleaseExpr(SCIP *scip, SCIP_EXPR **expr)
Definition: scip_expr.c:1443
SCIP_Bool SCIPisExprVar(SCIP *scip, SCIP_EXPR *expr)
Definition: scip_expr.c:1457
SCIP_RETCODE SCIPcheckExprQuadratic(SCIP *scip, SCIP_EXPR *expr, SCIP_Bool *isquadratic)
Definition: scip_expr.c:2402
SCIP_VAR * SCIPgetVarExprVar(SCIP_EXPR *expr)
Definition: expr_var.c:424
void SCIPexprGetQuadraticQuadTerm(SCIP_EXPR *quadexpr, int termidx, SCIP_EXPR **expr, SCIP_Real *lincoef, SCIP_Real *sqrcoef, int *nadjbilin, int **adjbilin, SCIP_EXPR **sqrexpr)
Definition: expr.c:4186
SCIP_RETCODE SCIPduplicateExpr(SCIP *scip, SCIP_EXPR *expr, SCIP_EXPR **copyexpr, SCIP_DECL_EXPR_MAPEXPR((*mapexpr)), void *mapexprdata, SCIP_DECL_EXPR_OWNERCREATE((*ownercreate)), void *ownercreatedata)
Definition: scip_expr.c:1307
SCIP_RETCODE SCIPsimplifyExpr(SCIP *scip, SCIP_EXPR *rootexpr, SCIP_EXPR **simplified, SCIP_Bool *changed, SCIP_Bool *infeasible, SCIP_DECL_EXPR_OWNERCREATE((*ownercreate)), void *ownercreatedata)
Definition: scip_expr.c:1798
#define SCIPfreeBlockMemoryArray(scip, ptr, num)
Definition: scip_mem.h:110
BMS_BLKMEM * SCIPblkmem(SCIP *scip)
Definition: scip_mem.c:57
BMS_BUFMEM * SCIPbuffer(SCIP *scip)
Definition: scip_mem.c:72
int SCIPcalcMemGrowSize(SCIP *scip, int num)
Definition: scip_mem.c:139
#define SCIPallocBufferArray(scip, ptr, num)
Definition: scip_mem.h:124
#define SCIPreallocBufferArray(scip, ptr, num)
Definition: scip_mem.h:128
#define SCIPfreeBufferArray(scip, ptr)
Definition: scip_mem.h:136
#define SCIPduplicateBufferArray(scip, ptr, source, num)
Definition: scip_mem.h:132
#define SCIPallocBlockMemoryArray(scip, ptr, num)
Definition: scip_mem.h:93
#define SCIPreallocBlockMemoryArray(scip, ptr, oldnum, newnum)
Definition: scip_mem.h:99
#define SCIPfreeBlockMemory(scip, ptr)
Definition: scip_mem.h:108
#define SCIPfreeBlockMemoryArrayNull(scip, ptr, num)
Definition: scip_mem.h:111
#define SCIPallocBlockMemory(scip, ptr)
Definition: scip_mem.h:89
void SCIPrationalMult(SCIP_RATIONAL *res, SCIP_RATIONAL *op1, SCIP_RATIONAL *op2)
Definition: rational.cpp:1066
void SCIPrationalSetInfinity(SCIP_RATIONAL *res)
Definition: rational.cpp:618
void SCIPrationalAdd(SCIP_RATIONAL *res, SCIP_RATIONAL *op1, SCIP_RATIONAL *op2)
Definition: rational.cpp:935
SCIP_Real SCIPrationalGetReal(SCIP_RATIONAL *rational)
Definition: rational.cpp:2085
SCIP_Bool SCIPrationalIsString(const char *desc)
Definition: rational.cpp:652
int SCIPrationalToString(SCIP_RATIONAL *rational, char *str, int strlen)
Definition: rational.cpp:1743
SCIP_RETCODE SCIPrationalCreateBlockArray(BMS_BLKMEM *mem, SCIP_RATIONAL ***rational, int size)
Definition: rational.cpp:196
void SCIPrationalSetReal(SCIP_RATIONAL *res, SCIP_Real real)
Definition: rational.cpp:603
void SCIPrationalFreeBuffer(BMS_BUFMEM *bufmem, SCIP_RATIONAL **rational)
Definition: rational.cpp:473
SCIP_RETCODE SCIPrationalCreateBuffer(BMS_BUFMEM *bufmem, SCIP_RATIONAL **rational)
Definition: rational.cpp:123
SCIP_Bool SCIPrationalIsZero(SCIP_RATIONAL *rational)
Definition: rational.cpp:1624
void SCIPrationalSetRational(SCIP_RATIONAL *res, SCIP_RATIONAL *src)
Definition: rational.cpp:569
void SCIPrationalSetString(SCIP_RATIONAL *res, const char *desc)
Definition: rational.cpp:716
void SCIPrationalSetNegInfinity(SCIP_RATIONAL *res)
Definition: rational.cpp:630
SCIP_Bool SCIPrationalIsNegative(SCIP_RATIONAL *rational)
Definition: rational.cpp:1650
SCIP_Bool SCIPrationalIsInfinity(SCIP_RATIONAL *rational)
Definition: rational.cpp:1660
void SCIPrationalFreeBlockArray(BMS_BLKMEM *mem, SCIP_RATIONAL ***ratblockarray, int size)
Definition: rational.cpp:501
SCIP_Bool SCIPrationalIsEQReal(SCIP_RATIONAL *rat, SCIP_Real real)
Definition: rational.cpp:1437
SCIP_Bool SCIPrationalIsNegInfinity(SCIP_RATIONAL *rational)
Definition: rational.cpp:1670
SCIP_RETCODE SCIPrationalReallocBlockArray(BMS_BLKMEM *mem, SCIP_RATIONAL ***result, int oldlen, int newlen)
Definition: rational.cpp:344
SCIP_Bool SCIPrationalIsEQ(SCIP_RATIONAL *rat1, SCIP_RATIONAL *rat2)
Definition: rational.cpp:1404
void SCIPrationalMultReal(SCIP_RATIONAL *res, SCIP_RATIONAL *op1, SCIP_Real op2)
Definition: rational.cpp:1097
SCIP_RETCODE SCIPincludeReaderBasic(SCIP *scip, SCIP_READER **readerptr, const char *name, const char *desc, const char *extension, SCIP_READERDATA *readerdata)
Definition: scip_reader.c:109
SCIP_RETCODE SCIPsetReaderCopy(SCIP *scip, SCIP_READER *reader, SCIP_DECL_READERCOPY((*readercopy)))
Definition: scip_reader.c:147
SCIP_READERDATA * SCIPreaderGetData(SCIP_READER *reader)
Definition: reader.c:605
SCIP_READER * SCIPfindReader(SCIP *scip, const char *name)
Definition: scip_reader.c:235
SCIP_RETCODE SCIPsetReaderFree(SCIP *scip, SCIP_READER *reader, SCIP_DECL_READERFREE((*readerfree)))
Definition: scip_reader.c:171
const char * SCIPreaderGetName(SCIP_READER *reader)
Definition: reader.c:680
SCIP_RETCODE SCIPsetReaderRead(SCIP *scip, SCIP_READER *reader, SCIP_DECL_READERREAD((*readerread)))
Definition: scip_reader.c:195
void SCIPreaderMarkExact(SCIP_READER *reader)
Definition: reader.c:670
SCIP_RETCODE SCIPsetReaderWrite(SCIP *scip, SCIP_READER *reader, SCIP_DECL_READERWRITE((*readerwrite)))
Definition: scip_reader.c:219
SCIP_Real SCIPinfinity(SCIP *scip)
SCIP_Bool SCIPisFeasEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisFeasZero(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisInfinity(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisFeasIntegral(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisZero(SCIP *scip, SCIP_Real val)
SCIP_RETCODE SCIPvarGetOrigvarSum(SCIP_VAR **var, SCIP_Real *scalar, SCIP_Real *constant)
Definition: var.c:18320
SCIP_VAR * SCIPvarGetNegatedVar(SCIP_VAR *var)
Definition: var.c:23868
SCIP_RETCODE SCIPchgVarUbExact(SCIP *scip, SCIP_VAR *var, SCIP_RATIONAL *newbound)
Definition: scip_var.c:5964
SCIP_RETCODE SCIPchgVarLb(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound)
Definition: scip_var.c:5697
SCIP_VARSTATUS SCIPvarGetStatus(SCIP_VAR *var)
Definition: var.c:23386
SCIP_Real SCIPvarGetUbLocal(SCIP_VAR *var)
Definition: var.c:24268
SCIP_Real SCIPvarGetLbOriginal(SCIP_VAR *var)
Definition: var.c:24020
SCIP_RETCODE SCIPaddVarExactData(SCIP *scip, SCIP_VAR *var, SCIP_RATIONAL *lb, SCIP_RATIONAL *ub, SCIP_RATIONAL *obj)
Definition: scip_var.c:299
SCIP_RETCODE SCIPchgVarUb(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound)
Definition: scip_var.c:5875
SCIP_Real SCIPvarGetObj(SCIP_VAR *var)
Definition: var.c:23900
SCIP_VARTYPE SCIPvarGetType(SCIP_VAR *var)
Definition: var.c:23453
SCIP_Real SCIPvarGetUbGlobal(SCIP_VAR *var)
Definition: var.c:24142
int SCIPvarGetIndex(SCIP_VAR *var)
Definition: var.c:23652
const char * SCIPvarGetName(SCIP_VAR *var)
Definition: var.c:23267
SCIP_Real SCIPvarGetUbOriginal(SCIP_VAR *var)
Definition: var.c:24063
SCIP_RETCODE SCIPreleaseVar(SCIP *scip, SCIP_VAR **var)
Definition: scip_var.c:1887
SCIP_RETCODE SCIPgetProbvarLinearSum(SCIP *scip, SCIP_VAR **vars, SCIP_Real *scalars, int *nvars, int varssize, SCIP_Real *constant, int *requiredsize)
Definition: scip_var.c:2378
SCIP_RETCODE SCIPchgVarType(SCIP *scip, SCIP_VAR *var, SCIP_VARTYPE vartype, SCIP_Bool *infeasible)
Definition: scip_var.c:10113
SCIP_RETCODE SCIPgetNegatedVar(SCIP *scip, SCIP_VAR *var, SCIP_VAR **negvar)
Definition: scip_var.c:2166
SCIP_Real SCIPvarGetLbLocal(SCIP_VAR *var)
Definition: var.c:24234
SCIP_Bool SCIPvarIsNegated(SCIP_VAR *var)
Definition: var.c:23443
SCIP_RETCODE SCIPcreateVar(SCIP *scip, SCIP_VAR **var, const char *name, SCIP_Real lb, SCIP_Real ub, SCIP_Real obj, SCIP_VARTYPE vartype, SCIP_Bool initial, SCIP_Bool removable, SCIP_DECL_VARDELORIG((*vardelorig)), SCIP_DECL_VARTRANS((*vartrans)), SCIP_DECL_VARDELTRANS((*vardeltrans)), SCIP_DECL_VARCOPY((*varcopy)), SCIP_VARDATA *vardata)
Definition: scip_var.c:120
SCIP_Real SCIPvarGetLbGlobal(SCIP_VAR *var)
Definition: var.c:24120
SCIP_IMPLINTTYPE SCIPvarGetImplType(SCIP_VAR *var)
Definition: var.c:23463
SCIP_RETCODE SCIPchgVarObjExact(SCIP *scip, SCIP_VAR *var, SCIP_RATIONAL *newobj)
Definition: scip_var.c:5420
SCIP_RETCODE SCIPchgVarObj(SCIP *scip, SCIP_VAR *var, SCIP_Real newobj)
Definition: scip_var.c:5372
SCIP_RETCODE SCIPchgVarLbExact(SCIP *scip, SCIP_VAR *var, SCIP_RATIONAL *newbound)
Definition: scip_var.c:5786
SCIP_RATIONAL * SCIPvarGetObjExact(SCIP_VAR *var)
Definition: var.c:23910
int SCIPstrcasecmp(const char *s1, const char *s2)
Definition: misc.c:10863
int SCIPsnprintf(char *t, int len, const char *s,...)
Definition: misc.c:10827
void SCIPprintSysError(const char *message)
Definition: misc.c:10719
int SCIPmemccpy(char *dest, const char *src, char stop, unsigned int cnt)
Definition: misc.c:10694
static const SCIP_Real scalars[]
Definition: lp.c:5959
memory allocation routines
#define BMSclearMemoryArray(ptr, num)
Definition: memory.h:130
public methods for managing constraints
wrapper functions to map file i/o to standard or zlib file i/o
struct SCIP_File SCIP_FILE
Definition: pub_fileio.h:43
public methods for message output
#define SCIPerrorMessage
Definition: pub_message.h:64
#define SCIPdebugPrintCons(x, y, z)
Definition: pub_message.h:102
public data structures and miscellaneous methods
public methods for input file readers
public methods for problem variables
wrapper for rational number arithmetic
enum LpExpType LPEXPTYPE
Definition: reader_diff.c:83
struct LpInput LPINPUT
Definition: reader_diff.c:109
LpExpType
Definition: reader_diff.c:80
LpSection
Definition: reader_diff.c:74
enum LpSection LPSECTION
Definition: reader_diff.c:77
enum LpSense LPSENSE
Definition: reader_diff.c:89
LpSense
Definition: reader_diff.c:86
#define LP_MAX_NAMELEN
Definition: reader_lp.c:90
static SCIP_DECL_READERWRITE(readerWriteLp)
Definition: reader_lp.c:4373
static SCIP_RETCODE printAndCons(SCIP *scip, FILE *file, const char *consname, SCIP_CONS *cons, SCIP_Bool aggrlinearizationands, SCIP_Bool transformed)
Definition: reader_lp.c:4031
static SCIP_RETCODE getActiveVariables(SCIP *scip, SCIP_VAR ***vars, SCIP_Real **scalars, int *nvars, SCIP_Real *constant, SCIP_Bool transformed)
Definition: reader_lp.c:3350
#define LP_INIT_COEFSSIZE
Definition: reader_lp.c:87
static SCIP_DECL_READERCOPY(readerCopyLp)
Definition: reader_lp.c:4334
static SCIP_Bool isSign(LPINPUT *lpinput, int *sign)
Definition: reader_lp.c:720
static SCIP_Bool isNewSection(SCIP *scip, LPINPUT *lpinput)
Definition: reader_lp.c:509
#define LP_INIT_QUADCOEFSSIZE
Definition: reader_lp.c:88
static void clearLine(char *linebuffer, int *linecnt)
Definition: reader_lp.c:3412
static SCIP_Bool hasError(LPINPUT *lpinput)
Definition: reader_lp.c:183
static void pushToken(LPINPUT *lpinput)
Definition: reader_lp.c:472
static SCIP_Bool getNextLine(SCIP *scip, LPINPUT *lpinput)
Definition: reader_lp.c:293
static SCIP_DECL_READERREAD(readerReadLp)
Definition: reader_lp.c:4362
static void swapTokenBuffer(LPINPUT *lpinput)
Definition: reader_lp.c:498
static SCIP_DECL_HASHGETKEY(hashGetKeyVar)
Definition: reader_lp.c:3326
enum LpExpType LPEXPTYPE
Definition: reader_lp.c:113
static SCIP_RETCODE readConstraints(SCIP *scip, LPINPUT *lpinput)
Definition: reader_lp.c:2215
static SCIP_RETCODE readBinaries(SCIP *scip, LPINPUT *lpinput)
Definition: reader_lp.c:2866
static SCIP_RETCODE readSemicontinuous(SCIP *scip, LPINPUT *lpinput)
Definition: reader_lp.c:2936
@ LP_EXP_UNSIGNED
Definition: reader_lp.c:111
@ LP_EXP_SIGNED
Definition: reader_lp.c:111
@ LP_EXP_NONE
Definition: reader_lp.c:111
static SCIP_Bool getNextToken(SCIP *scip, LPINPUT *lpinput)
Definition: reader_lp.c:365
static void printSosCons(SCIP *scip, FILE *file, const char *rowname, SCIP_VAR **vars, SCIP_Real *weights, int nvars, int type)
Definition: reader_lp.c:3972
static const char commentchars[]
Definition: reader_lp.c:147
static void checkVarnames(SCIP *scip, SCIP_VAR **vars, int nvars)
Definition: reader_lp.c:4228
static SCIP_Bool isValueChar(char c, char nextc, SCIP_Bool firstchar, SCIP_Bool *hasdot, LPEXPTYPE *exptype)
Definition: reader_lp.c:239
#define LP_MAX_LINELEN
Definition: reader_lp.c:85
#define LP_MAX_PRINTLEN
Definition: reader_lp.c:89
static SCIP_RETCODE printAggregatedCons(SCIP *scip, FILE *file, SCIP_Bool transformed, int nvars, int nAggregatedVars, SCIP_VAR **aggregatedVars)
Definition: reader_lp.c:4174
static SCIP_RETCODE readGenerals(SCIP *scip, LPINPUT *lpinput)
Definition: reader_lp.c:2821
#define READER_DESC
Definition: reader_lp.c:75
static SCIP_RETCODE readConstraintsRational(SCIP *scip, LPINPUT *lpinput)
Definition: reader_lp.c:1973
static SCIP_Bool isValueRational(SCIP *scip, LPINPUT *lpinput, SCIP_RATIONAL *value)
Definition: reader_lp.c:777
#define LP_MAX_PUSHEDTOKENS
Definition: reader_lp.c:86
@ LP_SOS
Definition: reader_lp.c:105
@ LP_END
Definition: reader_lp.c:105
@ LP_OBJECTIVE
Definition: reader_lp.c:105
@ LP_START
Definition: reader_lp.c:105
@ LP_GENERALS
Definition: reader_lp.c:105
@ LP_SEMICONTINUOUS
Definition: reader_lp.c:105
@ LP_CONSTRAINTS
Definition: reader_lp.c:105
@ LP_BOUNDS
Definition: reader_lp.c:105
@ LP_BINARIES
Definition: reader_lp.c:105
static SCIP_RETCODE printQuadraticCons(SCIP *scip, FILE *file, const char *rowname, SCIP_VAR **linvars, SCIP_Real *linvals, int nlinvars, SCIP_EXPR *quadexpr, SCIP_Real lhs, SCIP_Real rhs, SCIP_Bool transformed)
Definition: reader_lp.c:3884
#define READER_EXTENSION
Definition: reader_lp.c:76
static SCIP_RETCODE readBoundsRational(SCIP *scip, LPINPUT *lpinput)
Definition: reader_lp.c:2461
static SCIP_RETCODE readObjective(SCIP *scip, LPINPUT *lpinput)
Definition: reader_lp.c:1652
static SCIP_Bool isValue(SCIP *scip, LPINPUT *lpinput, SCIP_Real *value)
Definition: reader_lp.c:745
#define LP_PRINTLEN
Definition: reader_lp.c:91
static SCIP_RETCODE readSos(SCIP *scip, LPINPUT *lpinput)
Definition: reader_lp.c:3034
static SCIP_RETCODE createIndicatorConstraint(SCIP *scip, LPINPUT *lpinput, const char *name, SCIP_VAR *binvar, SCIP_Real binvalue)
Definition: reader_lp.c:1753
static void syntaxError(SCIP *scip, LPINPUT *lpinput, const char *msg)
Definition: reader_lp.c:156
static void pushBufferToken(LPINPUT *lpinput)
Definition: reader_lp.c:485
enum LpSection LPSECTION
Definition: reader_lp.c:107
static void endLine(SCIP *scip, FILE *file, char *linebuffer, int *linecnt)
Definition: reader_lp.c:3426
static SCIP_RETCODE readCoefficients(SCIP *scip, LPINPUT *lpinput, SCIP_Bool isobjective, char *name, int *coefssize, SCIP_VAR ***vars, SCIP_Real **coefs, int *ncoefs, int *quadcoefssize, SCIP_VAR ***quadvars1, SCIP_VAR ***quadvars2, SCIP_Real **quadcoefs, int *nquadcoefs, SCIP_Real *objoffset, SCIP_Bool *newsection)
Definition: reader_lp.c:908
#define READER_NAME
Definition: reader_lp.c:74
static SCIP_Bool isSense(LPINPUT *lpinput, LPSENSE *sense)
Definition: reader_lp.c:807
static SCIP_Bool isDelimChar(char c)
Definition: reader_lp.c:194
static void swapPointers(char **pointer1, char **pointer2)
Definition: reader_lp.c:351
static SCIP_DECL_HASHKEYEQ(hashKeyEqVar)
Definition: reader_lp.c:3333
static SCIP_DECL_HASHKEYVAL(hashKeyValVar)
Definition: reader_lp.c:3342
static SCIP_RETCODE readBounds(SCIP *scip, LPINPUT *lpinput)
Definition: reader_lp.c:2644
static SCIP_RETCODE readObjectiveRational(SCIP *scip, LPINPUT *lpinput)
Definition: reader_lp.c:1594
static SCIP_DECL_READERFREE(readerFreeLp)
Definition: reader_lp.c:4348
#define DEFAULT_AGGRLINEARIZATION_ANDS
Definition: reader_lp.c:79
enum LpSense LPSENSE
Definition: reader_lp.c:119
static SCIP_RETCODE printRow(SCIP *scip, FILE *file, const char *rowname, const char *rownameextension, const char *type, SCIP_VAR **linvars, SCIP_Real *linvals, int nlinvars, SCIP_EXPR *quadexpr, SCIP_Real rhs, SCIP_Bool transformed)
Definition: reader_lp.c:3479
static SCIP_RETCODE readCoefficientsRational(SCIP *scip, LPINPUT *lpinput, SCIP_Bool isobjective, char *name, int *coefssize, SCIP_VAR ***vars, SCIP_RATIONAL ***coefs, int *ncoefs, SCIP_RATIONAL *objoffset, SCIP_Bool *newsection)
Definition: reader_lp.c:1329
static SCIP_RETCODE readStart(SCIP *scip, LPINPUT *lpinput)
Definition: reader_lp.c:887
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:4118
static SCIP_RETCODE readLPFile(SCIP *scip, LPINPUT *lpinput, const char *filename)
Definition: reader_lp.c:3244
static SCIP_RETCODE printRowExact(SCIP *scip, FILE *file, const char *rowname, const char *rownameextension, const char *type, SCIP_VAR **linvars, SCIP_RATIONAL **linvals, int nlinvars, SCIP_RATIONAL *rhs)
Definition: reader_lp.c:3774
static void checkConsnames(SCIP *scip, SCIP_CONS **conss, int nconss, SCIP_Bool transformed)
Definition: reader_lp.c:4265
static void appendLine(SCIP *scip, FILE *file, char *linebuffer, int *linecnt, const char *extension)
Definition: reader_lp.c:3449
static SCIP_RETCODE getVariable(SCIP *scip, char *name, SCIP_VAR **var, SCIP_Bool *created)
Definition: reader_lp.c:838
@ LP_SENSE_LE
Definition: reader_lp.c:117
@ LP_SENSE_GE
Definition: reader_lp.c:117
@ LP_SENSE_NOTHING
Definition: reader_lp.c:117
@ LP_SENSE_EQ
Definition: reader_lp.c:117
#define DEFAULT_LINEARIZE_ANDS
Definition: reader_lp.c:78
static SCIP_Bool isTokenChar(char c)
Definition: reader_lp.c:215
LP file reader.
public methods for constraint handler plugins and constraints
public methods for exact solving
public methods for memory management
public methods for message handling
public methods for numerical tolerances
public methods for SCIP parameter handling
public methods for global and local (sub)problems
public methods for reader plugins
public methods for SCIP variables
static SCIP_RETCODE separate(SCIP *scip, SCIP_SEPA *sepa, SCIP_SOL *sol, SCIP_RESULT *result)
Main separation function.
Definition: sepa_flower.c:1221
@ SCIP_BOUNDTYPE_UPPER
Definition: type_lp.h:58
@ SCIP_BOUNDTYPE_LOWER
Definition: type_lp.h:57
enum SCIP_BoundType SCIP_BOUNDTYPE
Definition: type_lp.h:60
@ SCIP_VERBLEVEL_MINIMAL
Definition: type_message.h:59
@ SCIP_OBJSENSE_MAXIMIZE
Definition: type_prob.h:47
@ SCIP_OBJSENSE_MINIMIZE
Definition: type_prob.h:48
enum SCIP_Objsense SCIP_OBJSENSE
Definition: type_prob.h:50
struct SCIP_ReaderData SCIP_READERDATA
Definition: type_reader.h:54
@ SCIP_SUCCESS
Definition: type_result.h:58
enum SCIP_Result SCIP_RESULT
Definition: type_result.h:61
@ SCIP_NOFILE
Definition: type_retcode.h:47
@ SCIP_READERROR
Definition: type_retcode.h:45
@ SCIP_INVALIDDATA
Definition: type_retcode.h:52
@ SCIP_PLUGINNOTFOUND
Definition: type_retcode.h:54
@ SCIP_OKAY
Definition: type_retcode.h:42
enum SCIP_Retcode SCIP_RETCODE
Definition: type_retcode.h:63
@ SCIP_VARTYPE_INTEGER
Definition: type_var.h:65
@ SCIP_VARTYPE_CONTINUOUS
Definition: type_var.h:71
@ SCIP_VARTYPE_BINARY
Definition: type_var.h:64
@ SCIP_VARSTATUS_ORIGINAL
Definition: type_var.h:51
@ SCIP_VARSTATUS_MULTAGGR
Definition: type_var.h:56
@ SCIP_VARSTATUS_NEGATED
Definition: type_var.h:57
@ SCIP_VARSTATUS_AGGREGATED
Definition: type_var.h:55
enum SCIP_Varstatus SCIP_VARSTATUS
Definition: type_var.h:59