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