SCIP Doxygen Documentation
Loading...
Searching...
No Matches
reader_mps.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-2026 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_mps.c
26 * @ingroup DEFPLUGINS_READER
27 * @brief (extended) MPS file reader
28 * @author Thorsten Koch
29 * @author Tobias Achterberg
30 * @author Marc Pfetsch
31 * @author Stefan Heinz
32 * @author Stefan Vigerske
33 * @author Michael Winkler
34 *
35 * This reader/writer handles MPS files in extended MPS format, as it
36 * is used by CPLEX. In the extended format the limits on variable
37 * name lengths and coefficients are considerably relaxed. The columns
38 * in the format are then separated by whitespaces.
39 *
40 * @todo Check whether constructing the names for aggregated constraint yields name clashes (aggrXXX).
41 */
42
43/*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
44
46#include <ctype.h>
47#include "scip/cons_and.h"
49#include "scip/cons_nonlinear.h"
51#include "scip/cons_indicator.h"
52#include "scip/cons_knapsack.h"
53#include "scip/cons_linear.h"
54#include "scip/cons_logicor.h"
55#include "scip/cons_setppc.h"
56#include "scip/cons_sos1.h"
57#include "scip/cons_sos2.h"
58#include "scip/cons_varbound.h"
59#include "scip/pub_cons.h"
60#include "scip/pub_fileio.h"
61#include "scip/pub_message.h"
62#include "scip/pub_misc.h"
63#include "scip/pub_misc_sort.h"
64#include "scip/pub_reader.h"
65#include "scip/pub_var.h"
66#include "scip/reader_mps.h"
67#include "scip/rational.h"
68#include "scip/scip_cons.h"
69#include "scip/scip_exact.h"
70#include "scip/scip_mem.h"
71#include "scip/scip_message.h"
72#include "scip/scip_numerics.h"
73#include "scip/scip_param.h"
74#include "scip/scip_prob.h"
75#include "scip/scip_reader.h"
77#include "scip/scip_var.h"
78#include <stdlib.h>
79
80
81#define READER_NAME "mpsreader"
82#define READER_DESC "file reader for MIQPs in IBM's Mathematical Programming System format"
83#define READER_EXTENSION "mps"
84
85#define DEFAULT_LINEARIZE_ANDS TRUE /**< should possible \"and\" constraint be linearized when writing the mps file? */
86#define DEFAULT_AGGRLINEARIZATION_ANDS TRUE /**< should an aggregated linearization for and constraints be used? */
87
88/*
89 * mps reader internal methods
90 */
91
92#define MPS_MAX_LINELEN 1024
93#define MPS_MAX_NAMELEN 256
94#define MPS_MAX_VALUELEN 26
95#define MPS_MAX_FIELDLEN 20
96
97#define PATCH_CHAR '_'
98#define BLANK ' '
99
100/** MPS reading data */
101struct SCIP_ReaderData
102{
103 SCIP_Bool linearizeands;
104 SCIP_Bool aggrlinearizationands;
105};
106
107/** enum containing all mps sections */
128
129/** mps input structure */
130struct MpsInput
131{
132 MPSSECTION section;
133 SCIP_FILE* fp;
134 int lineno;
135 SCIP_OBJSENSE objsense;
136 SCIP_Bool haserror;
137 char buf[MPS_MAX_LINELEN];
138 const char* f0;
139 const char* f1;
140 const char* f2;
141 const char* f3;
142 const char* f4;
143 const char* f5;
144 char probname[MPS_MAX_NAMELEN];
145 char objname [MPS_MAX_NAMELEN];
146 SCIP_Bool initialconss; /**< should model constraints be marked as initial? */
147 SCIP_Bool dynamicconss; /**< should model constraints be subject to aging? */
148 SCIP_Bool dynamiccols; /**< should columns be added and removed dynamically to the LP? */
149 SCIP_Bool dynamicrows; /**< should rows be added and removed dynamically to the LP? */
150 SCIP_Bool isinteger;
151 SCIP_Bool isnewformat;
152};
153typedef struct MpsInput MPSINPUT;
154
155/** sparse matrix representation */
156struct SparseMatrix
157{
158 SCIP_Real* values; /**< matrix element */
159 SCIP_VAR** columns; /**< corresponding variables */
160 const char** rows; /**< corresponding constraint names */
161 int nentries; /**< number of elements in the arrays */
162 int sentries; /**< number of slots in the arrays */
163};
164typedef struct SparseMatrix SPARSEMATRIX;
165
166/** struct for mapping cons names to numbers */
168{
169 const char* consname; /**< name of the constraint */
170 int freq; /**< how often we have seen the name */
171};
173
174/** creates the mps input structure */
175static
177 SCIP* scip, /**< SCIP data structure */
178 MPSINPUT** mpsi, /**< mps input structure */
179 SCIP_FILE* fp /**< file object for the input file */
180 )
181{
182 assert(mpsi != NULL);
183 assert(fp != NULL);
184
186
187 (*mpsi)->section = MPS_NAME;
188 (*mpsi)->fp = fp;
189 (*mpsi)->lineno = 0;
190 (*mpsi)->objsense = SCIP_OBJSENSE_MINIMIZE;
191 (*mpsi)->haserror = FALSE;
192 (*mpsi)->isinteger = FALSE;
193 (*mpsi)->isnewformat = FALSE;
194 (*mpsi)->buf [0] = '\0';
195 (*mpsi)->probname[0] = '\0';
196 (*mpsi)->objname [0] = '\0';
197 (*mpsi)->f0 = NULL;
198 (*mpsi)->f1 = NULL;
199 (*mpsi)->f2 = NULL;
200 (*mpsi)->f3 = NULL;
201 (*mpsi)->f4 = NULL;
202 (*mpsi)->f5 = NULL;
203
204 SCIP_CALL( SCIPgetBoolParam(scip, "reading/initialconss", &((*mpsi)->initialconss)) );
205 SCIP_CALL( SCIPgetBoolParam(scip, "reading/dynamicconss", &((*mpsi)->dynamicconss)) );
206 SCIP_CALL( SCIPgetBoolParam(scip, "reading/dynamiccols", &((*mpsi)->dynamiccols)) );
207 SCIP_CALL( SCIPgetBoolParam(scip, "reading/dynamicrows", &((*mpsi)->dynamicrows)) );
208
209 return SCIP_OKAY;
210}
211
212/** free the mps input structure */
213static
215 SCIP* scip, /**< SCIP data structure */
216 MPSINPUT** mpsi /**< mps input structure */
217 )
218{
220}
221
222/** returns the current section */
223static
225 const MPSINPUT* mpsi /**< mps input structure */
226 )
227{
228 assert(mpsi != NULL);
229
230 return mpsi->section;
231}
232
233/** return the current value of field 0 */
234static
235const char* mpsinputField0(
236 const MPSINPUT* mpsi /**< mps input structure */
237 )
238{
239 assert(mpsi != NULL);
240
241 return mpsi->f0;
242}
243
244/** return the current value of field 1 */
245static
246const char* mpsinputField1(
247 const MPSINPUT* mpsi /**< mps input structure */
248 )
249{
250 assert(mpsi != NULL);
251
252 return mpsi->f1;
253}
254
255/** return the current value of field 2 */
256static
257const char* mpsinputField2(
258 const MPSINPUT* mpsi /**< mps input structure */
259 )
260{
261 assert(mpsi != NULL);
262
263 return mpsi->f2;
264}
265
266/** return the current value of field 3 */
267static
268const char* mpsinputField3(
269 const MPSINPUT* mpsi /**< mps input structure */
270 )
271{
272 assert(mpsi != NULL);
273
274 return mpsi->f3;
275}
276
277/** return the current value of field 4 */
278static
279const char* mpsinputField4(
280 const MPSINPUT* mpsi /**< mps input structure */
281 )
282{
283 assert(mpsi != NULL);
284
285 return mpsi->f4;
286}
287
288/** return the current value of field 5 */
289static
290const char* mpsinputField5(
291 const MPSINPUT* mpsi /**< mps input structure */
292 )
293{
294 assert(mpsi != NULL);
295
296 return mpsi->f5;
297}
298
299/** returns the objective name */
300static
301const char* mpsinputObjname(
302 const MPSINPUT* mpsi /**< mps input structure */
303 )
304{
305 assert(mpsi != NULL);
306
307 return mpsi->objname;
308}
309
310/** returns the objective sense */
311static
313 const MPSINPUT* mpsi /**< mps input structure */
314 )
315{
316 assert(mpsi != NULL);
317
318 return mpsi->objsense;
319}
320
321/** returns if an error was detected */
322static
324 const MPSINPUT* mpsi /**< mps input structure */
325 )
326{
327 assert(mpsi != NULL);
328
329 return mpsi->haserror;
330}
331
332/** returns the value of the Bool "is integer" in the mps input */
333static
335 const MPSINPUT* mpsi /**< mps input structure */
336 )
337{
338 assert(mpsi != NULL);
339
340 return mpsi->isinteger;
341}
342
343/** set the section in the mps input structure to given section */
344static
346 MPSINPUT* mpsi, /**< mps input structure */
347 MPSSECTION section /**< section that is set */
348 )
349{
350 assert(mpsi != NULL);
351
352 mpsi->section = section;
353}
354
355/** set the problem name in the mps input structure to given problem name */
356static
358 MPSINPUT* mpsi, /**< mps input structure */
359 const char* probname /**< name of the problem to set */
360 )
361{
362 assert(mpsi != NULL);
363 assert(probname != NULL);
364 assert(strlen(probname) < sizeof(mpsi->probname));
365
366 (void)SCIPmemccpy(mpsi->probname, probname, '\0', MPS_MAX_NAMELEN - 1);
367}
368
369/** set the objective name in the mps input structure to given objective name */
370static
372 MPSINPUT* mpsi, /**< mps input structure */
373 const char* objname /**< name of the objective function to set */
374 )
375{
376 assert(mpsi != NULL);
377 assert(objname != NULL);
378 assert(strlen(objname) < sizeof(mpsi->objname));
379
380 (void)SCIPmemccpy(mpsi->objname, objname, '\0', MPS_MAX_NAMELEN - 1);
381}
382
383/** set the objective sense in the mps input structure to given objective sense */
384static
386 MPSINPUT* mpsi, /**< mps input structure */
387 SCIP_OBJSENSE sense /**< sense of the objective function */
388 )
389{
390 assert(mpsi != NULL);
391
392 mpsi->objsense = sense;
393}
394
395static
397 MPSINPUT* mpsi /**< mps input structure */
398 )
399{
400 assert(mpsi != NULL);
401
402 SCIPerrorMessage("Syntax error in line %d\n", mpsi->lineno);
403 mpsi->section = MPS_ENDATA;
404 mpsi->haserror = TRUE;
405}
406
407/** method post a ignore message */
408static
410 SCIP* scip, /**< SCIP data structure */
411 MPSINPUT* mpsi, /**< mps input structure */
412 const char* what, /**< what get ignored */
413 const char* what_name, /**< name of that object */
414 const char* entity, /**< entity */
415 const char* entity_name, /**< entity name */
416 SCIP_VERBLEVEL verblevel /**< SCIP verblevel for this message */
417 )
418{
419 assert(mpsi != NULL);
420 assert(what != NULL);
421 assert(what_name != NULL);
422 assert(entity != NULL);
423 assert(entity_name != NULL);
424
425 SCIPverbMessage(scip, verblevel, NULL,
426 "Warning line %d: %s \"%s\" for %s \"%s\" ignored\n", mpsi->lineno, what, what_name, entity, entity_name);
427}
428
429/** fill the line from \p pos up to column 80 with blanks. */
430static
432 char* buf, /**< buffer to clear */
433 unsigned int pos /**< position to start the clearing process */
434 )
435{
436 unsigned int i;
437
438 for(i = pos; i < 80; i++)
439 buf[i] = BLANK;
440 buf[80] = '\0';
441}
442
443/** change all blanks inside a field to #PATCH_CHAR. */
444static
446 char* buf, /**< buffer to patch */
447 int beg, /**< position to begin */
448 int end /**< position to end */
449 )
450{
451 int i;
452
453 while( (beg <= end) && (buf[end] == BLANK) )
454 end--;
455
456 while( (beg <= end) && (buf[beg] == BLANK) )
457 beg++;
458
459 for( i = beg; i <= end; i++ )
460 if( buf[i] == BLANK )
461 buf[i] = PATCH_CHAR;
462}
463
464/** read a mps format data line and parse the fields. */
465static
467 MPSINPUT* mpsi /**< mps input structure */
468 )
469{
470 unsigned int len;
471 unsigned int i;
472 int space;
473 char* s;
474 SCIP_Bool is_marker;
475 SCIP_Bool is_empty;
476 char* nexttok;
477
478 do
479 {
480 mpsi->f0 = mpsi->f1 = mpsi->f2 = mpsi->f3 = mpsi->f4 = mpsi->f5 = 0;
481 is_marker = FALSE;
482
483 /* Read until we have not a comment line. */
484 do
485 {
486 mpsi->buf[MPS_MAX_LINELEN-1] = '\0';
487 if( NULL == SCIPfgets(mpsi->buf, (int) sizeof(mpsi->buf), mpsi->fp) )
488 return FALSE;
489 mpsi->lineno++;
490 }
491 while( *mpsi->buf == '*' ); /* coverity[a_loop_bound] */
492
493 /* Normalize line */
494 len = (unsigned int) strlen(mpsi->buf);
495
496 for( i = 0; i < len; i++ )
497 {
498 if( (mpsi->buf[i] == '\t') || (mpsi->buf[i] == '\n') || (mpsi->buf[i] == '\r') )
499 mpsi->buf[i] = BLANK;
500 }
501
502 /* remove trailing whitespace, for len < 14 check to succeed on forplan.mps again */
503 assert(len < MPS_MAX_LINELEN);
504 while( len > 0 && mpsi->buf[len-1] == BLANK )
505 --len;
506
507 if( len < 80 )
508 clearFrom(mpsi->buf, len);
509
510 SCIPdebugMessage("line %d: <%s>\n", mpsi->lineno, mpsi->buf);
511
512 assert(strlen(mpsi->buf) >= 80);
513
514 /* Look for new section */
515 if( *mpsi->buf != BLANK )
516 {
517 mpsi->f0 = SCIPstrtok(&mpsi->buf[0], " ", &nexttok);
518
519 assert(mpsi->f0 != 0);
520
521 mpsi->f1 = SCIPstrtok(NULL, " ", &nexttok);
522
523 return TRUE;
524 }
525
526 /* If we decide to use the new format we never revert this decision */
527 if( !mpsi->isnewformat )
528 {
529 /* Test for fixed format comments */
530 if( (mpsi->buf[14] == '$') && (mpsi->buf[13] == ' ') )
531 clearFrom(mpsi->buf, 14);
532 else if( (mpsi->buf[39] == '$') && (mpsi->buf[38] == ' ') )
533 clearFrom(mpsi->buf, 39);
534
535 /* Test for fixed format */
536 space = mpsi->buf[12] | mpsi->buf[13]
537 | mpsi->buf[22] | mpsi->buf[23]
538 | mpsi->buf[36] | mpsi->buf[37] | mpsi->buf[38]
539 | mpsi->buf[47] | mpsi->buf[48]
540 | mpsi->buf[61] | mpsi->buf[62] | mpsi->buf[63];
541
542 if( space == BLANK )
543 {
544 /* Now we have space at the right positions.
545 * But are there also the non space where they
546 * should be ?
547 */
549
550 number = isdigit((unsigned char)mpsi->buf[24]) || isdigit((unsigned char)mpsi->buf[25])
551 || isdigit((unsigned char)mpsi->buf[26]) || isdigit((unsigned char)mpsi->buf[27])
552 || isdigit((unsigned char)mpsi->buf[28]) || isdigit((unsigned char)mpsi->buf[29])
553 || isdigit((unsigned char)mpsi->buf[30]) || isdigit((unsigned char)mpsi->buf[31])
554 || isdigit((unsigned char)mpsi->buf[32]) || isdigit((unsigned char)mpsi->buf[33])
555 || isdigit((unsigned char)mpsi->buf[34]) || isdigit((unsigned char)mpsi->buf[35]);
556
557 /* len < 14 is to handle ROW lines with embedded spaces
558 * in the names correctly
559 */
560 if( number || (len < 14 && mpsi->section == MPS_ROWS) )
561 {
562 /* We assume fixed format, so we patch possible embedded spaces. */
563 patchField(mpsi->buf, 4, 12);
564 patchField(mpsi->buf, 14, 22);
565 patchField(mpsi->buf, 39, 47);
566 }
567 else
568 {
569 if( mpsi->section == MPS_COLUMNS || mpsi->section == MPS_RHS
570 || mpsi->section == MPS_RANGES || mpsi->section == MPS_BOUNDS )
571 mpsi->isnewformat = TRUE;
572 }
573 }
574 else
575 {
576 mpsi->isnewformat = TRUE;
577 }
578 }
579 s = &mpsi->buf[1];
580
581 /* At this point it is not clear if we have a indicator field.
582 * If there is none (e.g. empty) f1 will be the first name field.
583 * If there is one, f2 will be the first name field.
584 *
585 * Initially comment marks '$' are only allowed in the beginning
586 * of the 2nd and 3rd name field. We test all fields but the first.
587 * This makes no difference, since if the $ is at the start of a value
588 * field, the line will be erroneous anyway.
589 */
590 do
591 {
592 if( NULL == (mpsi->f1 = SCIPstrtok(s, " ", &nexttok)) )
593 break;
594
595 if( (NULL == (mpsi->f2 = SCIPstrtok(NULL, " ", &nexttok))) || (*mpsi->f2 == '$') )
596 {
597 mpsi->f2 = 0;
598 break;
599 }
600 if( !strcmp(mpsi->f2, "'MARKER'") )
601 is_marker = TRUE;
602
603 if( (NULL == (mpsi->f3 = SCIPstrtok(NULL, " ", &nexttok))) || (*mpsi->f3 == '$') )
604 {
605 mpsi->f3 = 0;
606 break;
607 }
608 if( is_marker )
609 {
610 if( !strcmp(mpsi->f3, "'INTORG'") )
611 mpsi->isinteger = TRUE;
612 else if( !strcmp(mpsi->f3, "'INTEND'") )
613 mpsi->isinteger = FALSE;
614 else
615 break; /* unknown marker */
616 }
617 if( !strcmp(mpsi->f3, "'MARKER'") )
618 is_marker = TRUE;
619
620 if( (NULL == (mpsi->f4 = SCIPstrtok(NULL, " ", &nexttok))) || (*mpsi->f4 == '$') )
621 {
622 mpsi->f4 = 0;
623 break;
624 }
625 if( is_marker )
626 {
627 if( !strcmp(mpsi->f4, "'INTORG'") )
628 mpsi->isinteger = TRUE;
629 else if( !strcmp(mpsi->f4, "'INTEND'") )
630 mpsi->isinteger = FALSE;
631 else
632 break; /* unknown marker */
633 }
634 if( (NULL == (mpsi->f5 = SCIPstrtok(NULL, " ", &nexttok))) || (*mpsi->f5 == '$') )
635 mpsi->f5 = 0;
636 }
637 while( FALSE );
638
639 /* check for empty lines */
640 is_empty = (mpsi->f0 == NULL && mpsi->f1 == NULL);
641 }
642 while( is_marker || is_empty );
643
644 return TRUE;
645}
646
647/** Insert \p str as field 4 and shift all other fields up. */
648static
650 MPSINPUT* mpsi, /**< mps input structure */
651 const char* str /**< str to insert */
652 )
653{
654 assert(mpsi != NULL);
655 assert(str != NULL);
656
657 mpsi->f5 = mpsi->f4;
658 mpsi->f4 = str;
659}
660
661/** Insert \p name as field 1 or 2 and shift all other fields up. */
662static
664 MPSINPUT* mpsi, /**< mps input structure */
665 const char* name, /**< name to insert */
666 SCIP_Bool second /**< insert as second field? */
667 )
668{
669 assert(mpsi != NULL);
670 assert(name != NULL);
671
672 mpsi->f5 = mpsi->f4;
673 mpsi->f4 = mpsi->f3;
674 mpsi->f3 = mpsi->f2;
675
676 if( second )
677 mpsi->f2 = name;
678 else
679 {
680 mpsi->f2 = mpsi->f1;
681 mpsi->f1 = name;
682 }
683}
684
685/** Add variable name to storage */
686static
688 SCIP* scip, /**< SCIP data structure */
689 const char*** varnames, /**< the variable name storage */
690 int* varnamessize, /**< the size of the variable names storage */
691 int* nvars, /**< the number of variables */
692 const char* colname /**< the name of the variable */
693 )
694{
695 assert(scip != NULL);
696
697 if( varnames != NULL )
698 {
699 SCIP_CALL( SCIPensureBlockMemoryArray(scip, varnames, varnamessize, (*nvars) + 1) );
700 SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &(*varnames)[(*nvars)], colname, strlen(colname) + 1) ); /*lint !e866*/
701 (*nvars)++;
702 }
703
704 return SCIP_OKAY;
705}
706
707/** Add constraint name to storage */
708static
710 SCIP* scip, /**< SCIP data structure */
711 const char*** consnames, /**< the constraint name storage */
712 int* consnamessize, /**< the size of the constraint names storage */
713 int* ncons, /**< the number of constraint */
714 const char* rowname /**< the name of the constraint */
715 )
716{
717 assert(scip != NULL);
718
719 if( consnames != NULL )
720 {
721 SCIP_CALL( SCIPensureBlockMemoryArray(scip, consnames, consnamessize, (*ncons) + 1) );
722 SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &(*consnames)[(*ncons)], rowname, strlen(rowname) + 1) ); /*lint !e866*/
723 (*ncons)++;
724 }
725
726 return SCIP_OKAY;
727}
728
729/** Process NAME section. */
730static
732 SCIP* scip, /**< SCIP data structure */
733 MPSINPUT* mpsi /**< mps input structure */
734 )
735{
736 assert(mpsi != NULL);
737
738 SCIPdebugMsg(scip, "read problem name\n");
739
740 /* This has to be the Line with the NAME section. */
741 if( !mpsinputReadLine(mpsi) || mpsinputField0(mpsi) == NULL || strcmp(mpsinputField0(mpsi), "NAME") )
742 {
744 return SCIP_OKAY;
745 }
746
747 /* Sometimes the name is omitted. */
748 mpsinputSetProbname(mpsi, (mpsinputField1(mpsi) == 0) ? "_MPS_" : mpsinputField1(mpsi));
749
750 /* This hat to be a new section */
751 /* coverity[tainted_data] */
752 if( !mpsinputReadLine(mpsi) || (mpsinputField0(mpsi) == NULL) )
753 {
755 return SCIP_OKAY;
756 }
757
758 if( !strncmp(mpsinputField0(mpsi), "ROWS", 4) )
760 else if( !strncmp(mpsinputField0(mpsi), "USERCUTS", 8) )
762 else if( !strncmp(mpsinputField0(mpsi), "LAZYCONS", 8) )
764 else if( !strncmp(mpsinputField0(mpsi), "OBJSEN", 6) )
766 else if( !strncmp(mpsinputField0(mpsi), "OBJNAME", 7) )
768 else
769 {
771 return SCIP_OKAY;
772 }
773
774 return SCIP_OKAY;
775}
776
777/** Process OBJSEN section. This Section is a CPLEX extension. */
778static
780 SCIP* scip, /**< SCIP data structure */
781 MPSINPUT* mpsi /**< mps input structure */
782 )
783{
784 assert(mpsi != NULL);
785
786 SCIPdebugMsg(scip, "read objective sense\n");
787
788 /* Although this is not explicitly in the MPS extensions as provided by CPLEX, some other MIP solvers
789 * (in particular gurobi), put 'MIN' or 'MAX' as the input field on the same line as the section declaration */
790 if( mpsinputField1(mpsi) == NULL){
791 /* Normal Cplex extension; info should be on the next line, in field 1 */
792 /* This has to be the Line with MIN or MAX. */
793 if( !mpsinputReadLine(mpsi) || (mpsinputField1(mpsi) == NULL) )
794 {
796 return SCIP_OKAY;
797 }
798 }
799 /* Otherwise, the input should read e.g. "OBJSENSE MAX" so that MAX is also the first field */
800
801 if( !strncmp(mpsinputField1(mpsi), "MIN", 3) )
803 else if( !strncmp(mpsinputField1(mpsi), "MAX", 3) )
805 else
806 {
808 return SCIP_OKAY;
809 }
810
811 /* Look for ROWS, USERCUTS, LAZYCONS, or OBJNAME Section */
812 /* coverity[tainted_data] */
813 if( !mpsinputReadLine(mpsi) || mpsinputField0(mpsi) == NULL )
814 {
816 return SCIP_OKAY;
817 }
818
819 if( !strcmp(mpsinputField0(mpsi), "ROWS") )
821 else if( !strcmp(mpsinputField0(mpsi), "USERCUTS") )
823 else if( !strcmp(mpsinputField0(mpsi), "LAZYCONS") )
825 else if( !strcmp(mpsinputField0(mpsi), "OBJNAME") )
827 else
828 {
830 return SCIP_OKAY;
831 }
832
833 return SCIP_OKAY;
834}
835
836/** Process OBJNAME section. This Section is a CPLEX extension. */
837static
839 SCIP* scip, /**< SCIP data structure */
840 MPSINPUT* mpsi /**< mps input structure */
841 )
842{
843 assert(mpsi != NULL);
844
845 SCIPdebugMsg(scip, "read objective name\n");
846
847 /* This has to be the Line with the name. */
848 if( !mpsinputReadLine(mpsi) || mpsinputField1(mpsi) == NULL )
849 {
851 return SCIP_OKAY;
852 }
853
855
856 /* Look for ROWS, USERCUTS, or LAZYCONS Section */
857 /* coverity[tainted_data] */
858 if( !mpsinputReadLine(mpsi) || mpsinputField0(mpsi) == NULL )
859 {
861 return SCIP_OKAY;
862 }
863 if( !strcmp(mpsinputField0(mpsi), "ROWS") )
865 else if( !strcmp(mpsinputField0(mpsi), "USERCUTS") )
867 else if( !strcmp(mpsinputField0(mpsi), "LAZYCONS") )
869 else
871
872 return SCIP_OKAY;
873}
874
875/** Process ROWS, USERCUTS, or LAZYCONS section. */
876static
878 MPSINPUT* mpsi, /**< mps input structure */
879 SCIP* scip, /**< SCIP data structure */
880 const char*** consnames, /**< storage for the constraint names, or NULL */
881 int* consnamessize, /**< the size of the constraint names storage, or NULL */
882 int* nconsnames /**< the number of stored constraint names, or NULL */
883 )
884{
885 SCIPdebugMsg(scip, "read rows\n");
886
887 /* coverity[tainted_data] */
888 while( mpsinputReadLine(mpsi) )
889 {
890 if( mpsinputField0(mpsi) != NULL )
891 {
892 if( !strcmp(mpsinputField0(mpsi), "ROWS") )
894 else if( !strcmp(mpsinputField0(mpsi), "USERCUTS") )
896 else if( !strcmp(mpsinputField0(mpsi), "LAZYCONS") )
898 else if( !strcmp(mpsinputField0(mpsi), "COLUMNS") )
900 else
902
903 return SCIP_OKAY;
904 }
905
906 if( *mpsinputField1(mpsi) == 'N' )
907 {
908 if( *mpsinputObjname(mpsi) == '\0' )
910 else if( strcmp(mpsinputObjname(mpsi), mpsinputField2(mpsi)) != 0 )
911 /* if OBJNAME was given and N-row is named differently, then warn that the N-row is not used as objective (OBJNAME takes precedence) */
912 mpsinputEntryIgnored(scip, mpsi, "row", mpsinputField2(mpsi), "objective function", "N", SCIP_VERBLEVEL_NORMAL);
913 }
914 else
915 {
916 SCIP_CONS* cons;
917 SCIP_Bool initial;
919 SCIP_Bool enforce;
920 SCIP_Bool check;
922 SCIP_Bool local;
923 SCIP_Bool modifiable;
924 SCIP_Bool dynamic;
925 SCIP_Bool removable;
926
927 cons = SCIPfindCons(scip, mpsinputField2(mpsi));
928 if( cons != NULL )
929 break;
930
931 initial = mpsi->initialconss && (mpsinputSection(mpsi) == MPS_ROWS);
932 separate = TRUE;
933 enforce = (mpsinputSection(mpsi) != MPS_USERCUTS);
934 check = (mpsinputSection(mpsi) != MPS_USERCUTS);
935 propagate = TRUE;
936 local = FALSE;
937 modifiable = FALSE;
938 dynamic = mpsi->dynamicconss;
939 removable = mpsi->dynamicrows || (mpsinputSection(mpsi) == MPS_USERCUTS);
940
941 switch(*mpsinputField1(mpsi))
942 {
943 case 'G' :
945 initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, FALSE) );
946 break;
947 case 'E' :
948 SCIP_CALL( SCIPcreateConsLinear(scip, &cons, mpsinputField2(mpsi), 0, NULL, NULL, 0.0, 0.0,
949 initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, FALSE) );
950 break;
951 case 'L' :
953 initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, FALSE) );
954 break;
955 default :
957 return SCIP_OKAY;
958 }
959 SCIP_CALL( SCIPaddCons(scip, cons) );
960 SCIP_CALL( SCIPreleaseCons(scip, &cons) );
961
962 /* if the file is of type cor, then the constraint names must be stored */
963 SCIP_CALL( addConsNameToStorage(scip, consnames, consnamessize, nconsnames, mpsinputField2(mpsi)) );
964 }
965 }
967
968 return SCIP_OKAY;
969}
970
971/** Process ROWS, USERCUTS, or LAZYCONS section. (exact version) */
972static
974 MPSINPUT* mpsi, /**< mps input structure */
975 SCIP* scip, /**< SCIP data structure */
976 const char*** consnames, /**< storage for the constraint names, or NULL */
977 int* consnamessize, /**< the size of the constraint names storage, or NULL */
978 int* nconsnames /**< the number of stored constraint names, or NULL */
979 )
980{
981 SCIPdebugMsg(scip, "read rows\n");
982
983 while( mpsinputReadLine(mpsi) )
984 {
985 if( mpsinputField0(mpsi) != NULL )
986 {
987 if( !strcmp(mpsinputField0(mpsi), "ROWS") )
989 else if( !strcmp(mpsinputField0(mpsi), "USERCUTS") )
991 else if( !strcmp(mpsinputField0(mpsi), "LAZYCONS") )
993 else if( !strcmp(mpsinputField0(mpsi), "COLUMNS") )
995 else
997
998 return SCIP_OKAY;
999 }
1000
1001 if( *mpsinputField1(mpsi) == 'N' )
1002 {
1003 if( *mpsinputObjname(mpsi) == '\0' )
1005 else
1006 mpsinputEntryIgnored(scip, mpsi, "row", mpsinputField2(mpsi), "objective function", "N", SCIP_VERBLEVEL_NORMAL);
1007 }
1008 else
1009 {
1010 SCIP_RATIONAL* lhs;
1011 SCIP_RATIONAL* rhs;
1012 SCIP_CONS* cons;
1013 SCIP_Bool initial;
1015 SCIP_Bool enforce;
1016 SCIP_Bool check;
1018 SCIP_Bool local;
1019 SCIP_Bool modifiable;
1020 SCIP_Bool dynamic;
1021 SCIP_Bool removable;
1022
1023 cons = SCIPfindCons(scip, mpsinputField2(mpsi));
1024 if( cons != NULL )
1025 break;
1026
1027 initial = mpsi->initialconss && (mpsinputSection(mpsi) == MPS_ROWS);
1028 separate = TRUE;
1029 enforce = (mpsinputSection(mpsi) != MPS_USERCUTS);
1030 check = (mpsinputSection(mpsi) != MPS_USERCUTS);
1031 propagate = TRUE;
1032 local = FALSE;
1033 modifiable = FALSE;
1034 dynamic = mpsi->dynamicconss;
1035 removable = mpsi->dynamicrows || (mpsinputSection(mpsi) == MPS_USERCUTS);
1036
1039
1040 switch(*mpsinputField1(mpsi))
1041 {
1042 case 'G' :
1044 SCIPrationalSetReal(lhs, 0.0);
1045 break;
1046 case 'E' :
1047 SCIPrationalSetReal(rhs, 0.0);
1048 SCIPrationalSetReal(lhs, 0.0);
1049 break;
1050 case 'L' :
1052 SCIPrationalSetReal(rhs, 0.0);
1053 break;
1054 default :
1055 mpsinputSyntaxerror(mpsi);
1056 return SCIP_OKAY;
1057 }
1058
1059 SCIP_CALL( SCIPcreateConsExactLinear(scip, &cons, mpsinputField2(mpsi), 0, NULL, NULL, lhs, rhs,
1060 initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, FALSE) );
1061
1062 SCIP_CALL( SCIPaddCons(scip, cons) );
1063 SCIP_CALL( SCIPreleaseCons(scip, &cons) );
1064
1067
1068 /* if the file is of type cor, then the constraint names must be stored */
1069 SCIP_CALL( addConsNameToStorage(scip, consnames, consnamessize, nconsnames, mpsinputField2(mpsi)) );
1070 }
1071 }
1072 mpsinputSyntaxerror(mpsi);
1073
1074 return SCIP_OKAY;
1075}
1076
1077/** Process COLUMNS section. */
1078static
1080 MPSINPUT* mpsi, /**< mps input structure */
1081 SCIP* scip, /**< SCIP data structure */
1082 const char*** varnames, /**< storage for the variable names, or NULL */
1083 int* varnamessize, /**< the size of the variable names storage, or NULL */
1084 int* nvarnames /**< the number of stored variable names, or NULL */
1085 )
1086{
1087 char colname[MPS_MAX_NAMELEN] = { '\0' };
1088 SCIP_CONS* cons;
1089 SCIP_VAR* var;
1090 SCIP_Real val;
1091 SCIP_Bool usevartable;
1092
1093 SCIPdebugMsg(scip, "read columns\n");
1094
1095 var = NULL;
1096 SCIP_CALL( SCIPgetBoolParam(scip, "misc/usevartable", &usevartable) );
1097
1098 while( mpsinputReadLine(mpsi) )
1099 {
1100 if( mpsinputField0(mpsi) != 0 )
1101 {
1102 if( strcmp(mpsinputField0(mpsi), "RHS") )
1103 break;
1104
1105 /* add the last variable to the problem */
1106 if( var != NULL )
1107 {
1110 }
1111 assert(var == NULL);
1112
1114 return SCIP_OKAY;
1115 }
1116 if( mpsinputField1(mpsi) == NULL || mpsinputField2(mpsi) == NULL || mpsinputField3(mpsi) == NULL )
1117 break;
1118
1119 /* new column? */
1120 if( strcmp(colname, mpsinputField1(mpsi)) )
1121 {
1122 /* add the last variable to the problem */
1123 if( var != NULL )
1124 {
1127 }
1128 assert(var == NULL);
1129
1130 (void)SCIPmemccpy(colname, mpsinputField1(mpsi), '\0', MPS_MAX_NAMELEN - 1);
1131
1132 /* check whether we have seen this variable before, this would not allowed */
1133 if( usevartable && SCIPfindVar(scip, colname) != NULL )
1134 {
1135 SCIPerrorMessage("Coeffients of column <%s> don't appear consecutively (line: %d)\n",
1136 colname, mpsi->lineno);
1137
1138 return SCIP_READERROR;
1139 }
1140
1141 /* if the file type is a cor file, the the variable name must be stored */
1142 SCIP_CALL( addVarNameToStorage(scip, varnames, varnamessize, nvarnames, colname) );
1143
1144 if( mpsinputIsInteger(mpsi) )
1145 {
1146 /* for integer variables, default bounds are 0 <= x < 1(not +infinity, like it is for continuous variables), and default cost is 0 */
1147 SCIP_CALL( SCIPcreateVar(scip, &var, colname, 0.0, 1.0, 0.0, SCIP_VARTYPE_BINARY,
1148 !mpsi->dynamiccols, mpsi->dynamiccols, NULL, NULL, NULL, NULL, NULL) );
1149 }
1150 else
1151 {
1152 /* for continuous variables, default bounds are 0 <= x, and default cost is 0 */
1154 !mpsi->dynamiccols, mpsi->dynamiccols, NULL, NULL, NULL, NULL, NULL) );
1155 }
1156 }
1157 assert(var != NULL);
1158
1159 val = atof(mpsinputField3(mpsi));
1160
1161 if( !strcmp(mpsinputField2(mpsi), mpsinputObjname(mpsi)) )
1162 {
1163 SCIP_CALL( SCIPchgVarObj(scip, var, val) );
1164 }
1165 else
1166 {
1167 cons = SCIPfindCons(scip, mpsinputField2(mpsi));
1168 if( cons == NULL )
1169 mpsinputEntryIgnored(scip, mpsi, "Column", mpsinputField1(mpsi), "row", mpsinputField2(mpsi), SCIP_VERBLEVEL_FULL);
1170 else if( !SCIPisZero(scip, val) )
1171 {
1172 /* warn the user in case the coefficient is infinite */
1173 if( SCIPisInfinity(scip, REALABS(val)) )
1174 {
1175 SCIPwarningMessage(scip, "Coefficient of variable <%s> in constraint <%s> contains infinite value <%e>,"
1176 " consider adjusting SCIP infinity.\n", SCIPvarGetName(var), SCIPconsGetName(cons), val);
1177 }
1178 SCIP_CALL( SCIPaddCoefLinear(scip, cons, var, val) );
1179 }
1180 }
1181 if( mpsinputField5(mpsi) != NULL )
1182 {
1183 assert(mpsinputField4(mpsi) != NULL);
1184
1185 val = atof(mpsinputField5(mpsi));
1186
1187 if( !strcmp(mpsinputField4(mpsi), mpsinputObjname(mpsi)) )
1188 {
1189 SCIP_CALL( SCIPchgVarObj(scip, var, val) );
1190 }
1191 else
1192 {
1193 cons = SCIPfindCons(scip, mpsinputField4(mpsi));
1194 if( cons == NULL )
1195 mpsinputEntryIgnored(scip, mpsi, "Column", mpsinputField1(mpsi), "row", mpsinputField4(mpsi), SCIP_VERBLEVEL_FULL);
1196 else if( !SCIPisZero(scip, val) )
1197 {
1198 SCIP_CALL( SCIPaddCoefLinear(scip, cons, var, val) );
1199 }
1200 }
1201 }
1202 }
1203 mpsinputSyntaxerror(mpsi);
1204
1205 return SCIP_OKAY;
1206}
1207
1208/** Process COLUMNS section. (exact version) */
1209static
1211 MPSINPUT* mpsi, /**< mps input structure */
1212 SCIP* scip, /**< SCIP data structure */
1213 const char*** varnames, /**< storage for the variable names, or NULL */
1214 int* varnamessize, /**< the size of the variable names storage, or NULL */
1215 int* nvarnames /**< the number of stored variable names, or NULL */
1216 )
1217{
1218 SCIP_RETCODE retcode = SCIP_OKAY;
1219 char colname[MPS_MAX_NAMELEN] = { '\0' };
1220 SCIP_CONS* cons;
1221 SCIP_VAR* var;
1222 SCIP_RATIONAL* val;
1223 SCIP_Bool usevartable;
1224
1225 SCIPdebugMsg(scip, "read columns\n");
1226
1227 var = NULL;
1228 SCIP_CALL( SCIPgetBoolParam(scip, "misc/usevartable", &usevartable) );
1229
1230 while( mpsinputReadLine(mpsi) )
1231 {
1232 if( mpsinputField0(mpsi) != 0 )
1233 {
1234 if( strcmp(mpsinputField0(mpsi), "RHS") )
1235 break;
1236
1237 /* add the last variable to the problem */
1238 if( var != NULL )
1239 {
1242 }
1243 assert(var == NULL);
1244
1246 return SCIP_OKAY;
1247 }
1248 if( mpsinputField1(mpsi) == NULL || mpsinputField2(mpsi) == NULL || mpsinputField3(mpsi) == NULL )
1249 break;
1250
1251 /* new column? */
1252 if( strcmp(colname, mpsinputField1(mpsi)) )
1253 {
1254 /* add the last variable to the problem */
1255 if( var != NULL )
1256 {
1259 }
1260 assert(var == NULL);
1261
1262 (void)SCIPmemccpy(colname, mpsinputField1(mpsi), '\0', MPS_MAX_NAMELEN - 1);
1263
1264 /* check whether we have seen this variable before, this would not allowed */
1265 if( usevartable && SCIPfindVar(scip, colname) != NULL )
1266 {
1267 SCIPerrorMessage("Coeffients of column <%s> don't appear consecutively (line: %d)\n",
1268 colname, mpsi->lineno);
1269
1270 return SCIP_READERROR;
1271 }
1272
1273 /* if the file type is a cor file, the the variable name must be stored */
1274 SCIP_CALL( addVarNameToStorage(scip, varnames, varnamessize, nvarnames, colname) );
1275
1276 if( mpsinputIsInteger(mpsi) )
1277 {
1278 /* for integer variables, default bounds are 0 <= x < 1(not +infinity, like it is for continuous variables), and default cost is 0 */
1279 SCIP_CALL( SCIPcreateVar(scip, &var, colname, 0.0, 1.0, 0.0, SCIP_VARTYPE_BINARY,
1280 !mpsi->dynamiccols, mpsi->dynamiccols, NULL, NULL, NULL, NULL, NULL) );
1281 }
1282 else
1283 {
1284 /* for continuous variables, default bounds are 0 <= x, and default cost is 0 */
1286 !mpsi->dynamiccols, mpsi->dynamiccols, NULL, NULL, NULL, NULL, NULL) );
1287 }
1288 /* create exact data if we are in exact solving mode */
1289 if( SCIPisExact(scip) )
1290 {
1292 }
1293 }
1294 assert(var != NULL);
1295
1299
1300 if( !strcmp(mpsinputField2(mpsi), mpsinputObjname(mpsi)) )
1301 {
1302 SCIP_CALL_TERMINATE( retcode, SCIPchgVarObjExact(scip, var, val), TERMINATE );
1303 }
1304 else
1305 {
1306 cons = SCIPfindCons(scip, mpsinputField2(mpsi));
1307 if( cons == NULL )
1308 mpsinputEntryIgnored(scip, mpsi, "Column", mpsinputField1(mpsi), "row", mpsinputField2(mpsi), SCIP_VERBLEVEL_FULL);
1309 else if( !SCIPrationalIsZero(val) )
1310 {
1311 /* this method returns an error if the coefficient is infinite */
1312 SCIP_CALL_TERMINATE( retcode, SCIPaddCoefExactLinear(scip, cons, var, val), TERMINATE );
1313 }
1314 }
1315 if( mpsinputField5(mpsi) != NULL )
1316 {
1317 assert(mpsinputField4(mpsi) != NULL);
1318
1321
1322 if( !strcmp(mpsinputField4(mpsi), mpsinputObjname(mpsi)) )
1323 {
1324 SCIP_CALL_TERMINATE( retcode, SCIPchgVarObjExact(scip, var, val), TERMINATE );
1325 }
1326 else
1327 {
1328 cons = SCIPfindCons(scip, mpsinputField4(mpsi));
1329 if( cons == NULL )
1330 {
1331 mpsinputEntryIgnored(scip, mpsi, "Column", mpsinputField1(mpsi), "row", mpsinputField4(mpsi), SCIP_VERBLEVEL_FULL);
1332 }
1333 else if( !SCIPrationalIsZero(val) )
1334 {
1335 SCIP_CALL_TERMINATE( retcode, SCIPaddCoefExactLinear(scip, cons, var, val), TERMINATE );
1336 }
1337 }
1338 }
1339 TERMINATE:
1340 /* free rational buffer */
1342 if( retcode != SCIP_OKAY )
1343 {
1345 return retcode;
1346 }
1347 }
1348 mpsinputSyntaxerror(mpsi);
1349
1350 return SCIP_OKAY;
1351}
1352
1353/** Process RHS section. */
1354static
1356 MPSINPUT* mpsi, /**< mps input structure */
1357 SCIP* scip /**< SCIP data structure */
1358 )
1359{
1360 char rhsname[MPS_MAX_NAMELEN] = { '\0' };
1361 SCIP_CONS* cons;
1362 SCIP_Real lhs;
1363 SCIP_Real rhs;
1364 SCIP_Real val;
1365
1366 SCIPdebugMsg(scip, "read right hand sides\n");
1367
1368 while( mpsinputReadLine(mpsi) )
1369 {
1370 if( mpsinputField0(mpsi) != NULL )
1371 {
1372 if( !strcmp(mpsinputField0(mpsi), "RANGES") )
1374 else if( !strcmp(mpsinputField0(mpsi), "BOUNDS") )
1376 else if( !strcmp(mpsinputField0(mpsi), "SOS") )
1378 else if( !strcmp(mpsinputField0(mpsi), "QMATRIX") )
1380 else if( !strcmp(mpsinputField0(mpsi), "QUADOBJ") )
1382 else if( !strcmp(mpsinputField0(mpsi), "QCMATRIX") )
1384 else if( !strcmp(mpsinputField0(mpsi), "INDICATORS") )
1386 else if( !strcmp(mpsinputField0(mpsi), "ENDATA") )
1388 else
1389 break;
1390 return SCIP_OKAY;
1391 }
1392 if( (mpsinputField2(mpsi) != NULL && mpsinputField3(mpsi) == NULL)
1393 || (mpsinputField4(mpsi) != NULL && mpsinputField5(mpsi) == NULL) )
1394 {
1395 SCIPwarningMessage(scip, "reading rhs section, a field is missing, assuming that the vector name is the missing one(, row identfier <%s>)\n", mpsinputField2(mpsi));
1396
1397 mpsinputInsertName(mpsi, "_RHS_", FALSE);
1398 }
1399
1400 if( mpsinputField1(mpsi) == NULL || mpsinputField2(mpsi) == NULL || mpsinputField3(mpsi) == NULL )
1401 break;
1402
1403 if( *rhsname == '\0' )
1404 (void)SCIPmemccpy(rhsname, mpsinputField1(mpsi), '\0', MPS_MAX_NAMELEN - 1);
1405
1406 if( !strcmp(rhsname, mpsinputField1(mpsi)) )
1407 {
1408 cons = SCIPfindCons(scip, mpsinputField2(mpsi));
1409 if( cons == NULL )
1410 {
1411 /* the rhs of the objective row is treated as objective constant */
1412 if( strcmp(mpsinputField2(mpsi), mpsinputObjname(mpsi)) == 0 )
1413 {
1414 val = atof(mpsinputField3(mpsi));
1416 }
1417 else
1419 }
1420 else
1421 {
1422 val = atof(mpsinputField3(mpsi));
1423
1424 /* find out the row sense */
1425 lhs = SCIPgetLhsLinear(scip, cons);
1426 rhs = SCIPgetRhsLinear(scip, cons);
1427 if( SCIPisInfinity(scip, -lhs) )
1428 {
1429 /* lhs = -infinity -> lower or equal */
1430 assert(SCIPisZero(scip, rhs));
1431 SCIP_CALL( SCIPchgRhsLinear(scip, cons, val) );
1432 }
1433 else if( SCIPisInfinity(scip, rhs) )
1434 {
1435 /* rhs = +infinity -> greater or equal */
1436 assert(SCIPisZero(scip, lhs));
1437 SCIP_CALL( SCIPchgLhsLinear(scip, cons, val) );
1438 }
1439 else
1440 {
1441 /* lhs > -infinity, rhs < infinity -> equality */
1442 assert(SCIPisZero(scip, lhs));
1443 assert(SCIPisZero(scip, rhs));
1444 SCIP_CALL( SCIPchgLhsLinear(scip, cons, val) );
1445 SCIP_CALL( SCIPchgRhsLinear(scip, cons, val) );
1446 }
1447 SCIPdebugMsg(scip, "RHS <%s> lhs: %g rhs: %g val: <%22.12g>\n", mpsinputField2(mpsi), lhs, rhs, val);
1448 }
1449 if( mpsinputField5(mpsi) != NULL )
1450 {
1451 cons = SCIPfindCons(scip, mpsinputField4(mpsi));
1452 if( cons == NULL )
1453 {
1454 /* the rhs of the objective row is treated as objective constant */
1455 if( strcmp(mpsinputField4(mpsi), mpsinputObjname(mpsi)) == 0 )
1456 {
1457 val = atof(mpsinputField5(mpsi));
1459 }
1460 else
1462 }
1463 else
1464 {
1465 val = atof(mpsinputField5(mpsi));
1466
1467 /* find out the row sense */
1468 lhs = SCIPgetLhsLinear(scip, cons);
1469 rhs = SCIPgetRhsLinear(scip, cons);
1470 if( SCIPisInfinity(scip, -lhs) )
1471 {
1472 /* lhs = -infinity -> lower or equal */
1473 assert(SCIPisZero(scip, rhs));
1474 SCIP_CALL( SCIPchgRhsLinear(scip, cons, val) );
1475 }
1476 else if( SCIPisInfinity(scip, rhs) )
1477 {
1478 /* rhs = +infinity -> greater or equal */
1479 assert(SCIPisZero(scip, lhs));
1480 SCIP_CALL( SCIPchgLhsLinear(scip, cons, val) );
1481 }
1482 else
1483 {
1484 /* lhs > -infinity, rhs < infinity -> equality */
1485 assert(SCIPisZero(scip, lhs));
1486 assert(SCIPisZero(scip, rhs));
1487 SCIP_CALL( SCIPchgLhsLinear(scip, cons, val) );
1488 SCIP_CALL( SCIPchgRhsLinear(scip, cons, val) );
1489 }
1490 SCIPdebugMsg(scip, "RHS <%s> lhs: %g rhs: %g val: <%22.12g>\n", mpsinputField4(mpsi), lhs, rhs, val);
1491 }
1492 }
1493 }
1494 }
1495 mpsinputSyntaxerror(mpsi);
1496
1497 return SCIP_OKAY;
1498}
1499
1500/** Process RHS section (exact version). */
1501static
1503 MPSINPUT* mpsi, /**< mps input structure */
1504 SCIP* scip /**< SCIP data structure */
1505 )
1506{
1507 char rhsname[MPS_MAX_NAMELEN] = { '\0' };
1508 SCIP_CONS* cons;
1509 SCIP_Real val;
1510 SCIP_RATIONAL* lhs;
1511 SCIP_RATIONAL* rhs;
1512 SCIP_RATIONAL* valexact;
1513
1515
1516 SCIPdebugMsg(scip, "read right hand sides\n");
1517
1518 while( mpsinputReadLine(mpsi) )
1519 {
1520 if( mpsinputField0(mpsi) != NULL )
1521 {
1522 if( !strcmp(mpsinputField0(mpsi), "RANGES") )
1524 else if( !strcmp(mpsinputField0(mpsi), "BOUNDS") )
1526 else if( !strcmp(mpsinputField0(mpsi), "SOS") )
1528 else if( !strcmp(mpsinputField0(mpsi), "QMATRIX") )
1530 else if( !strcmp(mpsinputField0(mpsi), "QUADOBJ") )
1532 else if( !strcmp(mpsinputField0(mpsi), "QCMATRIX") )
1534 else if( !strcmp(mpsinputField0(mpsi), "INDICATORS") )
1536 else if( !strcmp(mpsinputField0(mpsi), "ENDATA") )
1538 else
1539 break;
1540
1542
1543 return SCIP_OKAY;
1544 }
1545 if( (mpsinputField2(mpsi) != NULL && mpsinputField3(mpsi) == NULL)
1546 || (mpsinputField4(mpsi) != NULL && mpsinputField5(mpsi) == NULL) )
1547 {
1548 SCIPwarningMessage(scip, "reading rhs section, a field is missing, assuming that the vector name is the missing one(, row identfier <%s>)\n", mpsinputField2(mpsi));
1549
1550 mpsinputInsertName(mpsi, "_RHS_", FALSE);
1551 }
1552
1553 if( mpsinputField1(mpsi) == NULL || mpsinputField2(mpsi) == NULL || mpsinputField3(mpsi) == NULL )
1554 break;
1555
1556 if( *rhsname == '\0' )
1557 (void)SCIPmemccpy(rhsname, mpsinputField1(mpsi), '\0', MPS_MAX_NAMELEN - 1);
1558
1559 if( !strcmp(rhsname, mpsinputField1(mpsi)) )
1560 {
1561 cons = SCIPfindCons(scip, mpsinputField2(mpsi));
1562 if( cons == NULL )
1563 {
1564 /* the rhs of the objective row is treated as objective constant */
1565 if( !strcmp(mpsinputField2(mpsi), mpsinputObjname(mpsi)) )
1566 {
1567 val = atof(mpsinputField3(mpsi));
1569 }
1570 else
1572 }
1573 else
1574 {
1575 SCIPrationalSetString(valexact, mpsinputField3(mpsi));
1576 SCIPrationalCanonicalize(valexact);
1577
1578 /* find out the row sense */
1579 lhs = SCIPgetLhsExactLinear(scip, cons);
1580 rhs = SCIPgetRhsExactLinear(scip, cons);
1581 if( SCIPrationalIsNegInfinity(lhs) )
1582 {
1583 /* lhs = -infinity -> lower or equal */
1585 SCIP_CALL( SCIPchgRhsExactLinear(scip, cons, valexact) );
1586 }
1587 else if( SCIPrationalIsInfinity(rhs) )
1588 {
1589 /* rhs = +infinity -> greater or equal */
1591 SCIP_CALL( SCIPchgLhsExactLinear(scip, cons, valexact) );
1592 }
1593 else
1594 {
1595 /* lhs > -infinity, rhs < infinity -> equality */
1598 SCIP_CALL( SCIPchgLhsExactLinear(scip, cons, valexact) );
1599 SCIP_CALL( SCIPchgRhsExactLinear(scip, cons, valexact) );
1600 }
1601 SCIPrationalDebugMessage("RHS <%s> lhs: %q rhs: %q val: <%q>\n", mpsinputField2(mpsi), lhs, rhs, valexact);
1602 }
1603 if( mpsinputField5(mpsi) != NULL )
1604 {
1605 cons = SCIPfindCons(scip, mpsinputField4(mpsi));
1606 if( cons == NULL )
1607 {
1608 /* the rhs of the objective row is treated as objective constant */
1609 if( !strcmp(mpsinputField2(mpsi), mpsinputObjname(mpsi)) )
1610 {
1611 val = atof(mpsinputField3(mpsi));
1613 }
1614 else
1616 }
1617 else
1618 {
1619 SCIPrationalSetString(valexact, mpsinputField5(mpsi));
1620 SCIPrationalCanonicalize(valexact);
1621
1622 /* find out the row sense */
1623 lhs = SCIPgetLhsExactLinear(scip, cons);
1624 rhs = SCIPgetRhsExactLinear(scip, cons);
1625 if( SCIPrationalIsNegInfinity(lhs) )
1626 {
1627 /* lhs = -infinity -> lower or equal */
1629 SCIP_CALL( SCIPchgRhsExactLinear(scip, cons, valexact) );
1630 }
1631 else if( SCIPrationalIsInfinity(rhs) )
1632 {
1633 /* rhs = +infinity -> greater or equal */
1635 SCIP_CALL( SCIPchgLhsExactLinear(scip, cons, valexact) );
1636 }
1637 else
1638 {
1639 /* lhs > -infinity, rhs < infinity -> equality */
1642 SCIP_CALL( SCIPchgLhsExactLinear(scip, cons, valexact) );
1643 SCIP_CALL( SCIPchgRhsExactLinear(scip, cons, valexact) );
1644 }
1645 SCIPrationalDebugMessage("RHS <%s> lhs: %q rhs: %q val: <%q>\n", mpsinputField4(mpsi), lhs, rhs, valexact);
1646 }
1647 }
1648 }
1649 }
1650 mpsinputSyntaxerror(mpsi);
1651
1652 return SCIP_OKAY;
1653}
1654
1655/** Process RANGES section */
1656static
1658 MPSINPUT* mpsi, /**< mps input structure */
1659 SCIP* scip /**< SCIP data structure */
1660 )
1661{
1662 char rngname[MPS_MAX_NAMELEN] = { '\0' };
1663 SCIP_CONS* cons;
1664 SCIP_Real lhs;
1665 SCIP_Real rhs;
1666 SCIP_Real val;
1667
1668 SCIPdebugMsg(scip, "read ranges\n");
1669
1670 while( mpsinputReadLine(mpsi) )
1671 {
1672 if( mpsinputField0(mpsi) != NULL )
1673 {
1674 if( !strcmp(mpsinputField0(mpsi), "BOUNDS") )
1676 else if( !strcmp(mpsinputField0(mpsi), "SOS") )
1678 else if( !strcmp(mpsinputField0(mpsi), "QMATRIX") )
1680 else if( !strcmp(mpsinputField0(mpsi), "QUADOBJ") )
1682 else if( !strcmp(mpsinputField0(mpsi), "QCMATRIX") )
1684 else if( !strcmp(mpsinputField0(mpsi), "INDICATORS") )
1686 else if( !strcmp(mpsinputField0(mpsi), "ENDATA") )
1688 else
1689 break;
1690 return SCIP_OKAY;
1691 }
1692 if( (mpsinputField2(mpsi) != NULL && mpsinputField3(mpsi) == NULL)
1693 || (mpsinputField4(mpsi) != NULL && mpsinputField5(mpsi) == NULL) )
1694 {
1695 SCIPwarningMessage(scip, "reading ranged section, a field is missing, assuming that the vector name is the missing one(, row identfier <%s>)\n", mpsinputField2(mpsi));
1696
1697 mpsinputInsertName(mpsi, "_RNG_", FALSE);
1698 }
1699
1700 if( mpsinputField1(mpsi) == NULL || mpsinputField2(mpsi) == NULL || mpsinputField3(mpsi) == NULL )
1701 break;
1702
1703 if( *rngname == '\0' )
1704 (void)SCIPmemccpy(rngname, mpsinputField1(mpsi), '\0', MPS_MAX_NAMELEN - 1);
1705
1706 /* The rules are:
1707 * Row Sign LHS RHS
1708 * ----------------------------------------
1709 * G +/- rhs rhs + |range|
1710 * L +/- rhs - |range| rhs
1711 * E + rhs rhs + range
1712 * E - rhs + range rhs
1713 * ----------------------------------------
1714 */
1715 if( !strcmp(rngname, mpsinputField1(mpsi)) )
1716 {
1717 cons = SCIPfindCons(scip, mpsinputField2(mpsi));
1718 if( cons == NULL )
1719 mpsinputEntryIgnored(scip, mpsi, "Range", mpsinputField1(mpsi), "row", mpsinputField2(mpsi), SCIP_VERBLEVEL_NORMAL);
1720 else
1721 {
1722 val = atof(mpsinputField3(mpsi));
1723
1724 /* find out the row sense */
1725 lhs = SCIPgetLhsLinear(scip, cons);
1726 rhs = SCIPgetRhsLinear(scip, cons);
1727 if( SCIPisInfinity(scip, -lhs) )
1728 {
1729 /* lhs = -infinity -> lower or equal */
1730 SCIP_CALL( SCIPchgLhsLinear(scip, cons, rhs - REALABS(val)) );
1731 }
1732 else if( SCIPisInfinity(scip, rhs) )
1733 {
1734 /* rhs = +infinity -> greater or equal */
1735 SCIP_CALL( SCIPchgRhsLinear(scip, cons, lhs + REALABS(val)) );
1736 }
1737 else
1738 {
1739 /* lhs > -infinity, rhs < infinity -> equality */
1740 assert(SCIPisEQ(scip, lhs, rhs));
1741 if( val >= 0.0 )
1742 {
1743 SCIP_CALL( SCIPchgRhsLinear(scip, cons, rhs + val) );
1744 }
1745 else
1746 {
1747 SCIP_CALL( SCIPchgLhsLinear(scip, cons, lhs + val) );
1748 }
1749 }
1750 }
1751 if( mpsinputField5(mpsi) != NULL )
1752 {
1753 cons = SCIPfindCons(scip, mpsinputField4(mpsi));
1754 if( cons == NULL )
1755 mpsinputEntryIgnored(scip, mpsi, "Range", mpsinputField1(mpsi), "row", mpsinputField4(mpsi), SCIP_VERBLEVEL_NORMAL);
1756 else
1757 {
1758 val = atof(mpsinputField5(mpsi));
1759
1760 /* find out the row sense */
1761 lhs = SCIPgetLhsLinear(scip, cons);
1762 rhs = SCIPgetRhsLinear(scip, cons);
1763 if( SCIPisInfinity(scip, -lhs) )
1764 {
1765 /* lhs = -infinity -> lower or equal */
1766 SCIP_CALL( SCIPchgLhsLinear(scip, cons, rhs - REALABS(val)) );
1767 }
1768 else if( SCIPisInfinity(scip, rhs) )
1769 {
1770 /* rhs = +infinity -> greater or equal */
1771 SCIP_CALL( SCIPchgRhsLinear(scip, cons, lhs + REALABS(val)) );
1772 }
1773 else
1774 {
1775 /* lhs > -infinity, rhs < infinity -> equality */
1776 assert(SCIPisEQ(scip, lhs, rhs));
1777 if( val >= 0.0 )
1778 {
1779 SCIP_CALL( SCIPchgRhsLinear(scip, cons, rhs + val) );
1780 }
1781 else
1782 {
1783 SCIP_CALL( SCIPchgLhsLinear(scip, cons, lhs + val) );
1784 }
1785 }
1786 }
1787 }
1788 }
1789 }
1790 mpsinputSyntaxerror(mpsi);
1791
1792 return SCIP_OKAY;
1793}
1794
1795/** Process RANGES section (exact version) */
1796static
1798 MPSINPUT* mpsi, /**< mps input structure */
1799 SCIP* scip /**< SCIP data structure */
1800 )
1801{
1802 char rngname[MPS_MAX_NAMELEN] = { '\0' };
1803 SCIP_CONS* cons;
1804 SCIP_RATIONAL* lhs;
1805 SCIP_RATIONAL* rhs;
1806 SCIP_RATIONAL* val;
1807
1808 SCIPdebugMsg(scip, "read ranges\n");
1809
1811
1812 while( mpsinputReadLine(mpsi) )
1813 {
1814 if( mpsinputField0(mpsi) != NULL )
1815 {
1816 if( !strcmp(mpsinputField0(mpsi), "BOUNDS") )
1818 else if( !strcmp(mpsinputField0(mpsi), "SOS") )
1820 else if( !strcmp(mpsinputField0(mpsi), "QMATRIX") )
1822 else if( !strcmp(mpsinputField0(mpsi), "QUADOBJ") )
1824 else if( !strcmp(mpsinputField0(mpsi), "QCMATRIX") )
1826 else if( !strcmp(mpsinputField0(mpsi), "INDICATORS") )
1828 else if( !strcmp(mpsinputField0(mpsi), "ENDATA") )
1830 else
1831 break;
1832
1834
1835 return SCIP_OKAY;
1836 }
1837 if( (mpsinputField2(mpsi) != NULL && mpsinputField3(mpsi) == NULL)
1838 || (mpsinputField4(mpsi) != NULL && mpsinputField5(mpsi) == NULL) )
1839 {
1840 SCIPwarningMessage(scip, "reading ranged section, a field is missing, assuming that the vector name is the missing one(, row identfier <%s>)\n", mpsinputField2(mpsi));
1841
1842 mpsinputInsertName(mpsi, "_RNG_", FALSE);
1843 }
1844
1845 if( mpsinputField1(mpsi) == NULL || mpsinputField2(mpsi) == NULL || mpsinputField3(mpsi) == NULL )
1846 break;
1847
1848 if( *rngname == '\0' )
1849 (void)SCIPmemccpy(rngname, mpsinputField1(mpsi), '\0', MPS_MAX_NAMELEN - 1);
1850
1851 /* The rules are:
1852 * Row Sign LHS RHS
1853 * ----------------------------------------
1854 * G +/- rhs rhs + |range|
1855 * L +/- rhs - |range| rhs
1856 * E + rhs rhs + range
1857 * E - rhs + range rhs
1858 * ----------------------------------------
1859 */
1860 if( !strcmp(rngname, mpsinputField1(mpsi)) )
1861 {
1862 cons = SCIPfindCons(scip, mpsinputField2(mpsi));
1863 if( cons == NULL )
1864 mpsinputEntryIgnored(scip, mpsi, "Range", mpsinputField1(mpsi), "row", mpsinputField2(mpsi), SCIP_VERBLEVEL_NORMAL);
1865 else
1866 {
1869
1870 /* find out the row sense */
1871 lhs = SCIPgetLhsExactLinear(scip, cons);
1872 rhs = SCIPgetRhsExactLinear(scip, cons);
1873 if( SCIPrationalIsNegInfinity(lhs) )
1874 {
1875 /* lhs = -infinity -> lower or equal */
1876 SCIPrationalAbs(val, val);
1877 SCIPrationalDiff(val, rhs, val);
1878 SCIP_CALL( SCIPchgLhsExactLinear(scip, cons, val) );
1879 }
1880 else if( SCIPrationalIsInfinity(rhs) )
1881 {
1882 /* rhs = +infinity -> greater or equal */
1883 SCIPrationalAbs(val, val);
1884 SCIPrationalAdd(val, val, lhs);
1885 SCIP_CALL( SCIPchgRhsExactLinear(scip, cons, val) );
1886 }
1887 else
1888 {
1889 /* lhs > -infinity, rhs < infinity -> equality */
1890 assert(SCIPrationalIsEQ(lhs, rhs));
1891 if( !SCIPrationalIsNegative(val) )
1892 {
1893 SCIPrationalAdd(val, val, rhs);
1894 SCIP_CALL( SCIPchgRhsExactLinear(scip, cons, val) );
1895 }
1896 else
1897 {
1898 SCIPrationalAdd(val, val, lhs);
1899 SCIP_CALL( SCIPchgLhsExactLinear(scip, cons, val) );
1900 }
1901 }
1902 }
1903 if( mpsinputField5(mpsi) != NULL )
1904 {
1905 cons = SCIPfindCons(scip, mpsinputField4(mpsi));
1906 if( cons == NULL )
1907 mpsinputEntryIgnored(scip, mpsi, "Range", mpsinputField1(mpsi), "row", mpsinputField4(mpsi), SCIP_VERBLEVEL_NORMAL);
1908 else
1909 {
1912
1913 /* find out the row sense */
1914 lhs = SCIPgetLhsExactLinear(scip, cons);
1915 rhs = SCIPgetRhsExactLinear(scip, cons);
1916 if( SCIPrationalIsNegInfinity(lhs) )
1917 {
1918 /* lhs = -infinity -> lower or equal */
1919 SCIPrationalAbs(val, val);
1920 SCIPrationalDiff(val, rhs, val);
1921 SCIP_CALL( SCIPchgLhsExactLinear(scip, cons, val) );
1922 }
1923 else if( SCIPrationalIsInfinity(rhs) )
1924 {
1925 /* rhs = +infinity -> greater or equal */
1926 SCIPrationalAbs(val, val);
1927 SCIPrationalAdd(val, lhs, val);
1928 SCIP_CALL( SCIPchgRhsExactLinear(scip, cons, val) );
1929 }
1930 else
1931 {
1932 /* lhs > -infinity, rhs < infinity -> equality */
1933 assert(SCIPrationalIsEQ(lhs, rhs));
1934 if( !SCIPrationalIsNegative(val) )
1935 {
1936 SCIPrationalAdd(val, val, rhs);
1937 SCIP_CALL( SCIPchgRhsExactLinear(scip, cons, val) );
1938 }
1939 else
1940 {
1941 SCIPrationalAdd(val, val, lhs);
1942 SCIP_CALL( SCIPchgLhsExactLinear(scip, cons, val) );
1943 }
1944 }
1945 }
1946 }
1947 }
1948 }
1949 mpsinputSyntaxerror(mpsi);
1950
1951 return SCIP_OKAY;
1952}
1953
1954/** Process BOUNDS section. */
1955static
1957 MPSINPUT* mpsi, /**< mps input structure */
1958 SCIP* scip /**< SCIP data structure */
1959 )
1960{
1961 char bndname[MPS_MAX_NAMELEN] = { '\0' };
1962 SCIP_VAR* var;
1963 SCIP_RETCODE retcode;
1964 SCIP_Real val;
1965 SCIP_Bool shifted;
1966
1967 SCIP_VAR** semicont;
1968 int nsemicont;
1969 int semicontsize;
1970
1971 retcode = SCIP_OKAY;
1972
1973 semicont = NULL;
1974 nsemicont = 0;
1975 semicontsize = 0;
1976
1977 SCIPdebugMsg(scip, "read bounds\n");
1978
1979 while( mpsinputReadLine(mpsi) )
1980 {
1981 if( mpsinputField0(mpsi) != 0 )
1982 {
1983 if( !strcmp(mpsinputField0(mpsi), "SOS") )
1985 else if( !strcmp(mpsinputField0(mpsi), "QMATRIX") )
1987 else if( !strcmp(mpsinputField0(mpsi), "QUADOBJ") )
1989 else if( !strcmp(mpsinputField0(mpsi), "QCMATRIX") )
1991 else if( !strcmp(mpsinputField0(mpsi), "INDICATORS") )
1993 else if( !strcmp(mpsinputField0(mpsi), "ENDATA") )
1995 else
1996 break;
1997 goto READBOUNDS_FINISH;
1998 }
1999
2000 shifted = FALSE;
2001
2002 /* Is the value field used ? */
2003 if( !strcmp(mpsinputField1(mpsi), "LO") /* lower bound given in field 4 */
2004 || !strcmp(mpsinputField1(mpsi), "UP") /* upper bound given in field 4 */
2005 || !strcmp(mpsinputField1(mpsi), "FX") /* fixed value given in field 4 */
2006 || !strcmp(mpsinputField1(mpsi), "LI") /* CPLEX extension: lower bound of integer variable given in field 4 */
2007 || !strcmp(mpsinputField1(mpsi), "UI") /* CPLEX extension: upper bound of integer variable given in field 4 */
2008 || !strcmp(mpsinputField1(mpsi), "SC") /* CPLEX extension: semi-continuous variable, upper bound given in field 4 */
2009 || !strcmp(mpsinputField1(mpsi), "SI") )/* CPLEX extension: semi-integer variable, upper bound given in field 4 */
2010 {
2011 if( mpsinputField3(mpsi) != NULL && mpsinputField4(mpsi) == NULL )
2012 {
2013 int l;
2014
2015 /* check what might be missing, if field 3 is a number the bound name might be missing */
2016 for( l = (int) strlen(mpsinputField3(mpsi)) - 1; l >= 0; --l )
2017 {
2018 if( mpsinputField3(mpsi)[l] != '.' && !isdigit((unsigned char)mpsinputField3(mpsi)[l]) )
2019 break;
2020 }
2021
2022 /* the bound name?! is missing */
2023 if( l < 0 )
2024 {
2025 SCIPwarningMessage(scip, "in bound section a name for value <%s> might be missing\n", mpsinputField3(mpsi));
2026
2027 mpsinputInsertName(mpsi, "_BND_", TRUE);
2028 shifted = TRUE;
2029 }
2030 /* the bound is be missing */
2031 else
2032 {
2033 SCIPwarningMessage(scip, "in bound section a value for column <%s> is missing, assuming 0.0\n", mpsinputField3(mpsi));
2034
2035 mpsinputInsertField4(mpsi, "0.0");
2036 shifted = TRUE;
2037 }
2038 }
2039 }
2040 else if( !strcmp(mpsinputField1(mpsi), "FR") /* free variable */
2041 || !strcmp(mpsinputField1(mpsi), "MI") /* lower bound is minus infinity */
2042 || !strcmp(mpsinputField1(mpsi), "PL") /* upper bound is plus infinity */
2043 || !strcmp(mpsinputField1(mpsi), "BV") ) /* CPLEX extension: binary variable */
2044 {
2045 if( mpsinputField2(mpsi) != NULL && mpsinputField3(mpsi) == NULL )
2046 {
2047 SCIPwarningMessage(scip, "in bound section a name for a column is missing\n");
2048
2049 mpsinputInsertName(mpsi, "_BND_", TRUE);
2050 shifted = TRUE;
2051 }
2052 }
2053 else
2054 {
2055 mpsinputSyntaxerror(mpsi);
2056 return SCIP_OKAY;
2057 }
2058
2059 if( mpsinputField1(mpsi) == NULL || mpsinputField2(mpsi) == NULL || mpsinputField3(mpsi) == NULL )
2060 break;
2061
2062 if( *bndname == '\0' )
2063 (void)SCIPmemccpy(bndname, mpsinputField2(mpsi), '\0', MPS_MAX_NAMELEN - 1);
2064
2065 /* Only read the first Bound in section */
2066 if( !strcmp(bndname, mpsinputField2(mpsi)) )
2067 {
2068 SCIP_VARTYPE oldvartype;
2069 SCIP_Bool infeasible;
2070
2072 /* if variable did not appear in columns section before, then it may still come in later sections (QCMATRIX, QMATRIX, SOS, ...)
2073 * thus add it as continuous variables, which has default bounds 0.0 <= x, and default cost 0.0 */
2074 if( var == NULL )
2075 {
2076 SCIP_VAR* varcpy;
2077
2079 SCIP_VARTYPE_CONTINUOUS, !mpsi->dynamiccols, mpsi->dynamiccols, NULL, NULL, NULL, NULL, NULL) );
2080
2082 varcpy = var;
2083 SCIP_CALL( SCIPreleaseVar(scip, &varcpy) );
2084 /* mpsinputEntryIgnored(scip, mpsi, "column", mpsinputField3(mpsi), "bound", bndname, SCIP_VERBLEVEL_NORMAL); */
2085 }
2086 assert(var != NULL);
2087
2088 if( mpsinputField4(mpsi) == NULL )
2089 val = 0.0;
2090 else
2091 val = atof(mpsinputField4(mpsi));
2092
2093 /* remember variable type */
2094 oldvartype = SCIPvarGetType(var);
2096
2097 /* convert into an integer variable with default bounds 0 <= x <= infinity if binary variable is not declared
2098 * binary and not equipped with binary bounds, note that the default integer type is binary
2099 */
2100 if( oldvartype == SCIP_VARTYPE_BINARY
2101 && ( mpsinputField1(mpsi)[0] != 'B' || mpsinputField1(mpsi)[1] != 'V' )
2102 && ( mpsinputField1(mpsi)[0] != 'U' || SCIPisFeasGT(scip, val, 1.0) )
2103 && ( mpsinputField1(mpsi)[0] != 'F' || mpsinputField1(mpsi)[1] != 'X'
2104 || SCIPisFeasNegative(scip, val) || SCIPisFeasGT(scip, val, 1.0) ) )
2105 {
2107 assert(!infeasible);
2108
2109 oldvartype = SCIP_VARTYPE_INTEGER;
2111 }
2112
2113 /* switch variable type to continuous before applying the bound, this is necessary for stupid non-integral
2114 * bounds on general variables, which even might lead to infeasibility
2115 */
2116 if( oldvartype != SCIP_VARTYPE_CONTINUOUS )
2117 {
2118 /* relaxing variable type */
2120 }
2122
2123 switch( mpsinputField1(mpsi)[0] )
2124 {
2125 case 'L':
2127 {
2128 SCIPwarningMessage(scip, "Relaxing already defined lower bound %g of variable <%s> to %g not allowed.\n", SCIPvarGetLbGlobal(var), SCIPvarGetName(var), val);
2129 }
2130
2131 SCIP_CALL( SCIPchgVarLb(scip, var, val) );
2132
2133 if( mpsinputField1(mpsi)[1] == 'I' ) /* CPLEX extension (Integer Bound) */
2134 {
2135 if( !SCIPisFeasIntegral(scip, val) )
2136 {
2137 SCIPwarningMessage(scip, "variable <%s> declared as integral has a non-integral lower bound (%.14g) -> if feasible, bounds will be adjusted\n", SCIPvarGetName(var), val);
2138 }
2140 /* don't assert feasibility here because the presolver will and should detect a infeasibility */
2141 }
2142 else if( oldvartype < SCIP_VARTYPE_CONTINUOUS )
2143 {
2144 if( !SCIPisFeasIntegral(scip, val) )
2145 {
2146 SCIPwarningMessage(scip, "variable <%s> declared as integral has a non-integral lower bound (%.14g) -> if feasible, bounds will be adjusted\n", SCIPvarGetName(var), val);
2147 }
2148 }
2149
2150 break;
2151 case 'U':
2152 if( SCIPisGT(scip, val, SCIPvarGetUbGlobal(var)) )
2153 {
2154 SCIPwarningMessage(scip, "Relaxing already defined upper bound %g of variable <%s> to %g not allowed.\n", SCIPvarGetUbGlobal(var), SCIPvarGetName(var), val);
2155 }
2156
2157 SCIP_CALL( SCIPchgVarUb(scip, var, val) );
2158 if( mpsinputField1(mpsi)[1] == 'I' ) /* CPLEX extension (Integer Bound) */
2159 {
2160 if( !SCIPisFeasIntegral(scip, val) )
2161 {
2162 SCIPwarningMessage(scip, "variable <%s> declared as integral has a non-integral upper bound (%.14g) -> if feasible, bounds will be adjusted\n", SCIPvarGetName(var), val);
2163 }
2164
2166 /* don't assert feasibility here because the presolver will and should detect an infeasibility */
2167 }
2168 else if( oldvartype < SCIP_VARTYPE_CONTINUOUS )
2169 {
2170 if( !SCIPisFeasIntegral(scip, val) )
2171 {
2172 SCIPwarningMessage(scip, "variable <%s> declared as integral has a non-integral upper bound (%.14g) -> if feasible, bounds will be adjusted\n", SCIPvarGetName(var), val);
2173 }
2174 }
2175 break;
2176 case 'S':
2177 assert(mpsinputField1(mpsi)[1] == 'C' || mpsinputField1(mpsi)[1] == 'I'); /* semi-continuous or semi-integer (CPLEX extension) */
2178 /* remember that variable is semi-continuous/-integer */
2179 if( semicontsize <= nsemicont )
2180 {
2181 semicontsize = SCIPcalcMemGrowSize(scip, nsemicont+1);
2182 if( semicont == NULL )
2183 {
2184 SCIP_CALL( SCIPallocBufferArray(scip, &semicont, semicontsize) );
2185 }
2186 else
2187 {
2188 SCIP_CALL( SCIPreallocBufferArray(scip, &semicont, semicontsize) );
2189 }
2190 }
2191 assert(semicont != NULL);
2192 semicont[nsemicont] = var;
2193 ++nsemicont;
2194
2195 if( mpsinputField1(mpsi)[1] == 'I' ) /* variable is semi-integer, hence change its type to integer (the "semi" part will be handled below) */
2196 {
2198 /* don't assert feasibility here because the presolver will and should detect an infeasibility */
2199 }
2200
2201 /* if both bounds are infinite anyway, we do not need to print a warning or change the bound */
2203 {
2204 if( SCIPisGT(scip, val, SCIPvarGetUbGlobal(var)) )
2205 {
2206 SCIPwarningMessage(scip, "Relaxing already defined upper bound %g of variable <%s> to %g not allowed.\n", SCIPvarGetUbGlobal(var), SCIPvarGetName(var), val);
2207 }
2208
2209 SCIP_CALL( SCIPchgVarUb(scip, var, val) );
2210 }
2211 break;
2212 case 'F':
2213 if( mpsinputField1(mpsi)[1] == 'X' )
2214 {
2215 SCIP_CALL( SCIPchgVarLb(scip, var, val) );
2216 SCIP_CALL( SCIPchgVarUb(scip, var, val) );
2217 }
2218 else
2219 {
2222 }
2223 break;
2224 case 'M':
2226 break;
2227 case 'P':
2229 break;
2230 case 'B':
2231 if( oldvartype != SCIP_VARTYPE_BINARY )
2232 {
2233 SCIP_CALL( SCIPtightenVarLb(scip, var, 0.0, TRUE, &infeasible, NULL) );
2234 SCIP_CALL( SCIPtightenVarUb(scip, var, 1.0, TRUE, &infeasible, NULL) );
2236 /* presolving detects infeasibility */
2237 }
2238 break;
2239 default:
2240 mpsinputSyntaxerror(mpsi);
2241 return SCIP_OKAY;
2242 }
2243
2244 /* switch variable type back to old type if necessary */
2245 if( oldvartype < SCIPvarGetType(var) )
2246 {
2247 SCIP_CALL( SCIPchgVarType(scip, var, oldvartype, &infeasible) );
2248 }
2249 }
2250 else
2251 {
2252 /* check for syntax error */
2253 assert(*bndname != '\0');
2254 if( strcmp(bndname, mpsinputField3(mpsi)) == 0 && shifted )
2255 {
2256 mpsinputSyntaxerror(mpsi);
2257 return SCIP_OKAY;
2258 }
2259
2260 mpsinputEntryIgnored(scip, mpsi, "bound", mpsinputField2(mpsi), "variable", mpsinputField3(mpsi), SCIP_VERBLEVEL_NORMAL);
2261 }
2262 }
2263 mpsinputSyntaxerror(mpsi);
2264
2265 READBOUNDS_FINISH:
2266 if( nsemicont > 0 )
2267 {
2268 SCIP_CONS* cons;
2269 SCIP_VAR* vars[2];
2270 SCIP_BOUNDTYPE boundtypes[2];
2271 SCIP_Real bounds[2];
2272 char name[SCIP_MAXSTRLEN];
2273 SCIP_Real oldlb;
2274 int i;
2275
2276 assert(semicont != NULL);
2277
2278 /* add bound disjunction constraints for semi-continuous and semi-integer variables */
2279 for( i = 0; i < nsemicont; ++i )
2280 {
2281 var = semicont[i];
2283
2284 oldlb = SCIPvarGetLbGlobal(var);
2285 assert(oldlb >= 0.0);
2286
2287 /* if no bound was specified (which we assume if we see lower bound 0.0),
2288 * then the default lower bound for a semi-continuous variable is 1.0 */
2289 if( oldlb == 0.0 )
2290 oldlb = 1.0;
2291
2292 /* change the lower bound to 0.0 */
2293 SCIP_CALL( SCIPchgVarLb(scip, var, 0.0) );
2294
2295 /* add a bound disjunction constraint to say var <= 0.0 or var >= oldlb */
2296 (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "semicont_%s", SCIPvarGetName(var));
2297
2298 vars[0] = var;
2299 vars[1] = var;
2300 boundtypes[0] = SCIP_BOUNDTYPE_UPPER;
2301 boundtypes[1] = SCIP_BOUNDTYPE_LOWER;
2302 bounds[0] = 0.0;
2303 bounds[1] = oldlb;
2304
2305 retcode = SCIPcreateConsBounddisjunction(scip, &cons, name, 2, vars, boundtypes, bounds,
2306 !mpsi->dynamiccols, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, mpsi->dynamicconss, mpsi->dynamiccols, FALSE);
2307
2308 if( retcode != SCIP_OKAY )
2309 break;
2310
2311 SCIP_CALL( SCIPaddCons(scip, cons) );
2312
2313 SCIPdebugMsg(scip, "add bound disjunction constraint for semi-continuity/-integrality of <%s>:\n\t", SCIPvarGetName(var));
2315
2316 SCIP_CALL( SCIPreleaseCons(scip, &cons) );
2317 }
2318 }
2319
2320 SCIPfreeBufferArrayNull(scip, &semicont);
2321
2322 SCIP_CALL( retcode );
2323
2324 return SCIP_OKAY;
2325}
2326
2327/** Process BOUNDS section. */
2328static
2330 MPSINPUT* mpsi, /**< mps input structure */
2331 SCIP* scip /**< SCIP data structure */
2332 )
2333{
2334 char bndname[MPS_MAX_NAMELEN] = { '\0' };
2335 SCIP_VAR* var;
2336 SCIP_RETCODE retcode;
2337 SCIP_RATIONAL* val;
2338 SCIP_Bool shifted;
2339
2340 SCIP_VAR** semicont;
2341 int nsemicont;
2342 int semicontsize;
2343
2344 retcode = SCIP_OKAY;
2345
2346 semicont = NULL;
2347 nsemicont = 0;
2348 semicontsize = 0;
2349
2351
2352 SCIPdebugMsg(scip, "read bounds\n");
2353
2354 while( mpsinputReadLine(mpsi) )
2355 {
2356 if( mpsinputField0(mpsi) != 0 )
2357 {
2358 if( !strcmp(mpsinputField0(mpsi), "SOS") )
2360 else if( !strcmp(mpsinputField0(mpsi), "QMATRIX") )
2362 else if( !strcmp(mpsinputField0(mpsi), "QUADOBJ") )
2364 else if( !strcmp(mpsinputField0(mpsi), "QCMATRIX") )
2366 else if( !strcmp(mpsinputField0(mpsi), "INDICATORS") )
2368 else if( !strcmp(mpsinputField0(mpsi), "ENDATA") )
2370 else
2371 break;
2372 goto READBOUNDS_FINISH;
2373 }
2374
2375 shifted = FALSE;
2376
2377 /* Is the value field used ? */
2378 if( !strcmp(mpsinputField1(mpsi), "LO") /* lower bound given in field 4 */
2379 || !strcmp(mpsinputField1(mpsi), "UP") /* upper bound given in field 4 */
2380 || !strcmp(mpsinputField1(mpsi), "FX") /* fixed value given in field 4 */
2381 || !strcmp(mpsinputField1(mpsi), "LI") /* CPLEX extension: lower bound of integer variable given in field 4 */
2382 || !strcmp(mpsinputField1(mpsi), "UI") /* CPLEX extension: upper bound of integer variable given in field 4 */
2383 || !strcmp(mpsinputField1(mpsi), "SC") /* CPLEX extension: semi-continuous variable, upper bound given in field 4 */
2384 || !strcmp(mpsinputField1(mpsi), "SI") )/* CPLEX extension: semi-integer variable, upper bound given in field 4 */
2385 {
2386 if( mpsinputField3(mpsi) != NULL && mpsinputField4(mpsi) == NULL )
2387 {
2388 int l;
2389
2390 /* check what might be missing, if field 3 is a number the bound name might be missing */
2391 for( l = (int) strlen(mpsinputField3(mpsi)) - 1; l >= 0; --l )
2392 {
2393 if( mpsinputField3(mpsi)[l] != '.' && !isdigit((unsigned char)mpsinputField3(mpsi)[l]) )
2394 break;
2395 }
2396
2397 /* the bound name?! is missing */
2398 if( l < 0 )
2399 {
2400 SCIPwarningMessage(scip, "in bound section a name for value <%s> might be missing\n", mpsinputField3(mpsi));
2401
2402 mpsinputInsertName(mpsi, "_BND_", TRUE);
2403 shifted = TRUE;
2404 }
2405 /* the bound is be missing */
2406 else
2407 {
2408 SCIPwarningMessage(scip, "in bound section a value for column <%s> is missing, assuming 0.0\n", mpsinputField3(mpsi));
2409
2410 mpsinputInsertField4(mpsi, "0.0");
2411 shifted = TRUE;
2412 }
2413 }
2414 }
2415 else if( !strcmp(mpsinputField1(mpsi), "FR") /* free variable */
2416 || !strcmp(mpsinputField1(mpsi), "MI") /* lower bound is minus infinity */
2417 || !strcmp(mpsinputField1(mpsi), "PL") /* upper bound is plus infinity */
2418 || !strcmp(mpsinputField1(mpsi), "BV") ) /* CPLEX extension: binary variable */
2419 {
2420 if( mpsinputField2(mpsi) != NULL && mpsinputField3(mpsi) == NULL )
2421 {
2422 SCIPwarningMessage(scip, "in bound section a name for a column is missing\n");
2423
2424 mpsinputInsertName(mpsi, "_BND_", TRUE);
2425 shifted = TRUE;
2426 }
2427 }
2428 else
2429 {
2430 mpsinputSyntaxerror(mpsi);
2431 return SCIP_OKAY;
2432 }
2433
2434 if( mpsinputField1(mpsi) == NULL || mpsinputField2(mpsi) == NULL || mpsinputField3(mpsi) == NULL )
2435 break;
2436
2437 if( *bndname == '\0' )
2438 (void)SCIPmemccpy(bndname, mpsinputField2(mpsi), '\0', MPS_MAX_NAMELEN - 1);
2439
2440 /* Only read the first Bound in section */
2441 if( !strcmp(bndname, mpsinputField2(mpsi)) )
2442 {
2443 SCIP_VARTYPE oldvartype;
2444 SCIP_Bool infeasible;
2445
2447 /* if variable did not appear in columns section before, then it may still come in later sections (QCMATRIX, QMATRIX, SOS, ...)
2448 * thus add it as continuous variables, which has default bounds 0.0 <= x, and default cost 0.0 */
2449 if( var == NULL )
2450 {
2451 SCIP_VAR* varcpy;
2452
2454 SCIP_VARTYPE_CONTINUOUS, !mpsi->dynamiccols, mpsi->dynamiccols, NULL, NULL, NULL, NULL, NULL) );
2455
2457
2459 varcpy = var;
2460 SCIP_CALL( SCIPreleaseVar(scip, &varcpy) );
2461 /* mpsinputEntryIgnored(scip, mpsi, "column", mpsinputField3(mpsi), "bound", bndname, SCIP_VERBLEVEL_NORMAL); */
2462 }
2463 assert(var != NULL);
2464
2465 if( mpsinputField4(mpsi) == NULL )
2466 SCIPrationalSetReal(val, 0.0);
2467 else
2468 {
2471 }
2472
2473 /* remember variable type */
2474 oldvartype = SCIPvarGetType(var);
2476
2477 /* convert into an integer variable with default bounds 0 <= x <= infinity if binary variable is not declared
2478 * binary and not equipped with binary bounds, note that the default integer type is binary
2479 */
2480 if( oldvartype == SCIP_VARTYPE_BINARY
2481 && ( mpsinputField1(mpsi)[0] != 'B' || mpsinputField1(mpsi)[1] != 'V' )
2482 && ( mpsinputField1(mpsi)[0] != 'U' || SCIPrationalIsGTReal(val, 1.0) )
2483 && ( mpsinputField1(mpsi)[0] != 'F' || mpsinputField1(mpsi)[1] != 'X'
2484 || SCIPrationalIsNegative(val) || SCIPrationalIsGTReal(val, 1.0) ) )
2485 {
2486 SCIP_RATIONAL* tmp;
2488 assert(!infeasible);
2489
2492
2493 oldvartype = SCIP_VARTYPE_INTEGER;
2494
2497 }
2498
2499 /* switch variable type to continuous before applying the bound, this is necessary for stupid non-integral
2500 * bounds on general variables, which even might lead to infeasibility
2501 */
2502 if( oldvartype != SCIP_VARTYPE_CONTINUOUS )
2503 {
2504 /* relaxing variable type */
2506 }
2508
2509 switch( mpsinputField1(mpsi)[0] )
2510 {
2511 case 'L':
2513 {
2514 SCIPwarningMessage(scip, "Relaxing already defined lower bound (%.14g) of variable <%s> to (%.14g) not allowed.\n", SCIPvarGetLbGlobal(var), SCIPvarGetName(var), SCIPrationalGetReal(val));
2515 }
2516
2518
2519 if( mpsinputField1(mpsi)[1] == 'I' ) /* CPLEX extension (Integer Bound) */
2520 {
2521 if( !SCIPrationalIsIntegral(val) )
2522 {
2523 SCIPwarningMessage(scip, "variable <%s> declared as integral has a non-integral lower bound (%.14g) -> if feasible, bounds will be adjusted\n", SCIPvarGetName(var), SCIPrationalGetReal(val));
2524 }
2526 /* don't assert feasibility here because the presolver will and should detect a infeasibility */
2527 }
2528 else if( oldvartype < SCIP_VARTYPE_CONTINUOUS )
2529 {
2530 if( !SCIPrationalIsIntegral(val) )
2531 {
2532 SCIPwarningMessage(scip, "variable <%s> declared as integral has a non-integral lower bound (%.14g) -> if feasible, bounds will be adjusted\n", SCIPvarGetName(var), SCIPrationalGetReal(val));
2533 }
2534 }
2535
2536 break;
2537 case 'U':
2539 {
2540 SCIPwarningMessage(scip, "Relaxing already defined upper bound %g of variable <%s> to %g not allowed.\n", SCIPvarGetUbGlobal(var), SCIPvarGetName(var), SCIPrationalGetReal(val));
2541 }
2542
2544 if( mpsinputField1(mpsi)[1] == 'I' ) /* CPLEX extension (Integer Bound) */
2545 {
2546 if( !SCIPrationalIsIntegral(val) )
2547 {
2548 SCIPwarningMessage(scip, "variable <%s> declared as integral has a non-integral upper bound (%.14g) -> if feasible, bounds will be adjusted\n", SCIPvarGetName(var), SCIPrationalGetReal(val));
2549 }
2550
2552 /* don't assert feasibility here because the presolver will and should detect an infeasibility */
2553 }
2554 else if( oldvartype < SCIP_VARTYPE_CONTINUOUS )
2555 {
2556 if( !SCIPrationalIsIntegral(val) )
2557 {
2558 SCIPwarningMessage(scip, "variable <%s> declared as integral has a non-integral upper bound (%.14g) -> if feasible, bounds will be adjusted\n", SCIPvarGetName(var), SCIPrationalGetReal(val));
2559 }
2560 }
2561 break;
2562 case 'S':
2563 assert(mpsinputField1(mpsi)[1] == 'C' || mpsinputField1(mpsi)[1] == 'I'); /* semi-continuous or semi-integer (CPLEX extension) */
2564 /* remember that variable is semi-continuous/-integer */
2565 if( semicontsize <= nsemicont )
2566 {
2567 semicontsize = SCIPcalcMemGrowSize(scip, nsemicont+1);
2568 if( semicont == NULL )
2569 {
2570 SCIP_CALL( SCIPallocBufferArray(scip, &semicont, semicontsize) );
2571 }
2572 else
2573 {
2574 SCIP_CALL( SCIPreallocBufferArray(scip, &semicont, semicontsize) );
2575 }
2576 }
2577 assert(semicont != NULL);
2578 semicont[nsemicont] = var;
2579 ++nsemicont;
2580
2581 if( mpsinputField1(mpsi)[1] == 'I' ) /* variable is semi-integer, hence change its type to integer (the "semi" part will be handled below) */
2582 {
2584 /* don't assert feasibility here because the presolver will and should detect an infeasibility */
2585 }
2586
2587 /* if both bounds are infinite anyway, we do not need to print a warning or change the bound */
2589 {
2591 {
2592 SCIPwarningMessage(scip, "Relaxing already defined upper bound %g of variable <%s> to %g not allowed.\n", SCIPvarGetUbGlobal(var), SCIPvarGetName(var), SCIPrationalGetReal(val));
2593 }
2594
2596 }
2597 break;
2598 case 'F':
2599 if( mpsinputField1(mpsi)[1] == 'X' )
2600 {
2603 }
2604 else
2605 {
2610 }
2611 break;
2612 case 'M':
2615 break;
2616 case 'P':
2619 break;
2620 case 'B':
2621 if( oldvartype != SCIP_VARTYPE_BINARY )
2622 {
2623 SCIPrationalSetReal(val, 0.0);
2624 SCIP_CALL( SCIPtightenVarLbExact(scip, var, val, &infeasible, NULL) );
2625 SCIPrationalSetReal(val, 1.0);
2626 SCIP_CALL( SCIPtightenVarUbExact(scip, var, val, &infeasible, NULL) );
2628 /* presolving detects infeasibility */
2629 }
2630 break;
2631 default:
2632 mpsinputSyntaxerror(mpsi);
2633 return SCIP_OKAY;
2634 }
2635
2636 /* switch variable type back to old type if necessary */
2637 if( oldvartype < SCIPvarGetType(var) )
2638 {
2639 SCIP_CALL( SCIPchgVarType(scip, var, oldvartype, &infeasible) );
2640 }
2641 }
2642 else
2643 {
2644 /* check for syntax error */
2645 assert(*bndname != '\0');
2646 if( strcmp(bndname, mpsinputField3(mpsi)) == 0 && shifted )
2647 {
2648 mpsinputSyntaxerror(mpsi);
2649 return SCIP_OKAY;
2650 }
2651
2652 mpsinputEntryIgnored(scip, mpsi, "bound", mpsinputField2(mpsi), "variable", mpsinputField3(mpsi), SCIP_VERBLEVEL_NORMAL);
2653 }
2654 }
2655 mpsinputSyntaxerror(mpsi);
2656
2657 READBOUNDS_FINISH:
2658 if( nsemicont > 0 )
2659 {
2660 SCIPerrorMessage("Exact solving mode cannot handle semicontinous variables at the moment \n");
2661 SCIPABORT();
2662 }
2663
2664 SCIPfreeBufferArrayNull(scip, &semicont);
2666
2667 SCIP_CALL( retcode );
2668
2669 return SCIP_OKAY;
2670}
2671
2672
2673/** Process SOS section.
2674 *
2675 * We read the SOS section, which is a nonstandard section introduced by CPLEX.
2676 *
2677 * @note Currently we do not support the standard way of specifying SOS constraints via markers.
2678 */
2679static
2681 MPSINPUT* mpsi, /**< mps input structure */
2682 SCIP* scip /**< SCIP data structure */
2683 )
2684{
2685 SCIP_Bool initial;
2687 SCIP_Bool enforce;
2688 SCIP_Bool check;
2690 SCIP_Bool local;
2691 SCIP_Bool dynamic;
2692 SCIP_Bool removable;
2693 char name[MPS_MAX_NAMELEN] = { '\0' };
2694 SCIP_CONS* cons = NULL;
2695 int consType = -1;
2696 int cnt = 0;
2697
2698 SCIPdebugMsg(scip, "read SOS constraints\n");
2699
2700 /* standard settings for SOS constraints: */
2701 initial = mpsi->initialconss;
2702 separate = TRUE;
2703 enforce = TRUE;
2704 check = TRUE;
2705 propagate = TRUE;
2706 local = FALSE;
2707 dynamic = mpsi->dynamicconss;
2708 removable = mpsi->dynamicrows;
2709
2710 if( SCIPisExact(scip) )
2711 {
2712 SCIPerrorMessage("Exact solving mode cannot handle SOS constraints currently \n");
2713 return SCIP_READERROR;
2714 }
2715
2716 /* loop through section */
2717 while( mpsinputReadLine(mpsi) )
2718 {
2719 int type = -1;
2720
2721 /* check if next section is found */
2722 if( mpsinputField0(mpsi) != NULL )
2723 {
2724 if( !strcmp(mpsinputField0(mpsi), "ENDATA") )
2726 else if( !strcmp(mpsinputField0(mpsi), "QMATRIX") )
2728 else if( !strcmp(mpsinputField0(mpsi), "QUADOBJ") )
2730 else if( !strcmp(mpsinputField0(mpsi), "QCMATRIX") )
2732 else if( !strcmp(mpsinputField0(mpsi), "INDICATORS") )
2734 break;
2735 }
2736 if( mpsinputField1(mpsi) == NULL )
2737 {
2738 SCIPerrorMessage("empty data in a non-comment line.\n");
2739 mpsinputSyntaxerror(mpsi);
2740 return SCIP_OKAY;
2741 }
2742
2743 /* check for new SOS set */
2744 if( strcmp(mpsinputField1(mpsi), "S1") == 0 )
2745 type = 1;
2746 if( strcmp(mpsinputField1(mpsi), "S2") == 0 )
2747 type = 2;
2748
2749 /* add last constraint and create a new one */
2750 if( type > 0 )
2751 {
2752 assert( type == 1 || type == 2 );
2753 if( cons != NULL )
2754 {
2755 /* add last constraint */
2756 SCIP_CALL( SCIPaddCons(scip, cons) );
2757 SCIPdebugMsg(scip, "(line %d) added constraint <%s>: ", mpsi->lineno, SCIPconsGetName(cons));
2759 SCIP_CALL( SCIPreleaseCons(scip, &cons) );
2760 }
2761
2762 /* check name */
2763 if( mpsinputField2(mpsi) != NULL )
2764 (void)SCIPmemccpy(name, mpsinputField2(mpsi), '\0', MPS_MAX_NAMELEN - 1);
2765 else
2766 {
2767 /* create new name */
2768 (void) SCIPsnprintf(name, MPS_MAX_NAMELEN, "SOS%d", ++cnt);
2769 }
2770
2771 /* create new SOS constraint */
2772 if( type == 1 )
2773 {
2774 /* we do not know the name of the constraint */
2775 SCIP_CALL( SCIPcreateConsSOS1(scip, &cons, name, 0, NULL, NULL, initial, separate, enforce, check, propagate,
2776 local, dynamic, removable, FALSE) );
2777 }
2778 else
2779 {
2780 assert( type == 2 );
2781 SCIP_CALL( SCIPcreateConsSOS2(scip, &cons, name, 0, NULL, NULL, initial, separate, enforce, check, propagate,
2782 local, dynamic, removable, FALSE) );
2783 }
2784 consType = type;
2785 SCIPdebugMsg(scip, "created constraint <%s> of type %d.\n", name, type);
2786 /* note: we ignore the priorities! */
2787 }
2788 else
2789 {
2790 /* otherwise we are in the section given variables */
2791 SCIP_VAR* var;
2792 SCIP_Real weight;
2793 char* endptr;
2794
2795 if( consType != 1 && consType != 2 )
2796 {
2797 SCIPerrorMessage("missing SOS type specification.\n");
2798 mpsinputSyntaxerror(mpsi);
2799 return SCIP_OKAY;
2800 }
2801
2802 /* get variable */
2804 if( var == NULL )
2805 {
2806 /* ignore unknown variables - we would not know the type anyway */
2807 mpsinputEntryIgnored(scip, mpsi, "column", mpsinputField1(mpsi), "SOS", name, SCIP_VERBLEVEL_NORMAL);
2808 }
2809 else
2810 {
2811 /* get weight */
2812 if( NULL == mpsinputField2(mpsi) )
2813 {
2814 SCIPerrorMessage("weight for variable <%s> not specified.\n", mpsinputField1(mpsi));
2815 mpsinputSyntaxerror(mpsi);
2816 return SCIP_OKAY;
2817 }
2818
2819 weight = strtod(mpsinputField2(mpsi), &endptr);
2820 if( endptr == mpsinputField2(mpsi) || *endptr != '\0' )
2821 {
2822 SCIPerrorMessage("weight for variable <%s> not specified.\n", mpsinputField1(mpsi));
2823 mpsinputSyntaxerror(mpsi);
2824 return SCIP_OKAY;
2825 }
2826
2827 /* add variable and weight */
2828 assert( consType == 1 || consType == 2 );
2829 switch( consType )
2830 {
2831 case 1:
2832 SCIP_CALL( SCIPaddVarSOS1(scip, cons, var, weight) );
2833 break;
2834 case 2:
2835 SCIP_CALL( SCIPaddVarSOS2(scip, cons, var, weight) );
2836 break;
2837 /* coverity[dead_error_begin] */
2838 default:
2839 SCIPerrorMessage("unknown SOS type: <%d>\n", type); /* should not happen */
2840 SCIPABORT();
2841 return SCIP_INVALIDDATA; /*lint !e527*/
2842 }
2843 SCIPdebugMsg(scip, "added variable <%s> with weight %g.\n", SCIPvarGetName(var), weight);
2844 }
2845 /* check other fields */
2846 if( (mpsinputField3(mpsi) != NULL && *mpsinputField3(mpsi) != '\0' ) ||
2847 (mpsinputField4(mpsi) != NULL && *mpsinputField4(mpsi) != '\0' ) ||
2848 (mpsinputField5(mpsi) != NULL && *mpsinputField5(mpsi) != '\0' ) )
2849 {
2850 SCIPwarningMessage(scip, "ignoring data in fields 3-5 <%s> <%s> <%s>.\n",
2851 mpsinputField3(mpsi), mpsinputField4(mpsi), mpsinputField5(mpsi));
2852 }
2853 }
2854 }
2855
2856 if( cons != NULL )
2857 {
2858 /* add last constraint */
2859 SCIP_CALL( SCIPaddCons(scip, cons) );
2860 SCIPdebugMsg(scip, "(line %d) added constraint <%s>: ", mpsi->lineno, SCIPconsGetName(cons));
2862 SCIP_CALL( SCIPreleaseCons(scip, &cons) );
2863 }
2864
2865 return SCIP_OKAY;
2866}
2867
2868
2869/** Process QMATRIX or QUADOBJ section.
2870 *
2871 * - We read the QMATRIX or QUADOBJ section, which is a nonstandard section introduced by CPLEX.
2872 * - We create a quadratic constraint for this matrix and add a variable to the objective to
2873 * represent the value of the QMATRIX.
2874 * - For a QMATRIX, we expect that both lower and upper diagonal elements are given and every
2875 * coefficient has to be divided by 2.0.
2876 * - For a QUADOBJ, we expect that only the upper diagonal elements are given and thus only
2877 * coefficients on the diagonal have to be divided by 2.0.
2878 */
2879static
2881 MPSINPUT* mpsi, /**< mps input structure */
2882 SCIP_Bool isQuadObj, /**< whether we actually read a QUADOBJ section */
2883 SCIP* scip /**< SCIP data structure */
2884 )
2885{
2886 SCIP_VAR** quadvars1;
2887 SCIP_VAR** quadvars2;
2888 SCIP_Real* quadcoefs;
2889 SCIP_RETCODE retcode;
2890 int cnt = 0; /* number of qmatrix elements processed so far */
2891 int size; /* size of quad* arrays */
2892
2893 SCIPdebugMsg(scip, "read %s objective\n", isQuadObj ? "QUADOBJ" : "QMATRIX");
2894
2895 if( SCIPisExact(scip) )
2896 {
2897 SCIPerrorMessage("Exact solving mode cannot handle QMatrix constraints currently \n");
2898 return SCIP_READERROR;
2899 }
2900
2901 retcode = SCIP_OKAY;
2902
2903 size = 1;
2904 SCIP_CALL( SCIPallocBufferArray(scip, &quadvars1, size) );
2905 SCIP_CALL( SCIPallocBufferArray(scip, &quadvars2, size) );
2906 SCIP_CALL( SCIPallocBufferArray(scip, &quadcoefs, size) );
2907
2908 /* loop through section */
2909 /* coverity[tainted_data] */
2910 while( mpsinputReadLine(mpsi) )
2911 {
2912 /* otherwise we are in the section given variables */
2913 SCIP_VAR* var1;
2914 SCIP_VAR* var2;
2915 SCIP_Real coef;
2916
2917 /* check if next section is found */
2918 if( mpsinputField0(mpsi) != NULL )
2919 {
2920 if( !strcmp(mpsinputField0(mpsi), "QCMATRIX") )
2922 else if( !strcmp(mpsinputField0(mpsi), "INDICATORS") )
2924 else if( !strcmp(mpsinputField0(mpsi), "ENDATA") )
2926 break;
2927 }
2928 if( mpsinputField1(mpsi) == NULL && mpsinputField2(mpsi) == NULL )
2929 {
2930 SCIPerrorMessage("empty data in a non-comment line.\n");
2931 mpsinputSyntaxerror(mpsi);
2932 SCIPfreeBufferArray(scip, &quadvars1);
2933 SCIPfreeBufferArray(scip, &quadvars2);
2934 SCIPfreeBufferArray(scip, &quadcoefs);
2935 return SCIP_OKAY;
2936 }
2937
2938 /* get first variable */
2939 var1 = SCIPfindVar(scip, mpsinputField1(mpsi));
2940 if( var1 == NULL )
2941 {
2942 /* ignore unknown variables - we would not know the type anyway */
2943 mpsinputEntryIgnored(scip, mpsi, "column", mpsinputField1(mpsi), "QMatrix", "QMATRIX", SCIP_VERBLEVEL_NORMAL);
2944 }
2945 else
2946 {
2947 int k;
2948 for( k = 1; k <= 2; ++k )
2949 {
2950 /* get second variable */
2951 var2 = SCIPfindVar(scip, k == 1 ? mpsinputField2(mpsi) : mpsinputField4(mpsi));
2952 if( var2 == NULL )
2953 {
2954 /* ignore unknown variables - we would not know the type anyway */
2955 mpsinputEntryIgnored(scip, mpsi, "column", mpsinputField2(mpsi), "QMatrix", "QMATRIX", SCIP_VERBLEVEL_NORMAL);
2956 }
2957 else
2958 {
2959 const char* field;
2960 char* endptr;
2961
2962 /* get coefficient */
2963 field = (k == 1 ? mpsinputField3(mpsi) : mpsinputField5(mpsi));
2964 if( NULL == field )
2965 {
2966 SCIPerrorMessage("coefficient of term <%s>*<%s> not specified.\n", SCIPvarGetName(var1), SCIPvarGetName(var2));
2967 mpsinputSyntaxerror(mpsi);
2968 SCIPfreeBufferArray(scip, &quadvars1);
2969 SCIPfreeBufferArray(scip, &quadvars2);
2970 SCIPfreeBufferArray(scip, &quadcoefs);
2971 return SCIP_OKAY;
2972 }
2973
2974 coef = strtod(field, &endptr);
2975 if( endptr == field || *endptr != '\0' )
2976 {
2977 SCIPerrorMessage("coefficient of term <%s>*<%s> not specified.\n", SCIPvarGetName(var1), SCIPvarGetName(var2));
2978 mpsinputSyntaxerror(mpsi);
2979 SCIPfreeBufferArray(scip, &quadvars1);
2980 SCIPfreeBufferArray(scip, &quadvars2);
2981 SCIPfreeBufferArray(scip, &quadcoefs);
2982 return SCIP_OKAY;
2983 }
2984
2985 /* store variables and coefficient */
2986 if( cnt >= size )
2987 {
2988 int newsize = SCIPcalcMemGrowSize(scip, size+1);
2989 assert(newsize > size);
2990 SCIP_CALL( SCIPreallocBufferArray(scip, &quadvars1, newsize) );
2991 SCIP_CALL( SCIPreallocBufferArray(scip, &quadvars2, newsize) );
2992 SCIP_CALL( SCIPreallocBufferArray(scip, &quadcoefs, newsize) );
2993 size = newsize;
2994 }
2995 assert(cnt < size);
2996 quadvars1[cnt] = var1;
2997 quadvars2[cnt] = var2;
2998 quadcoefs[cnt] = coef;
2999
3000 /* diagonal elements have to be divided by 2.0
3001 * in a QMATRIX section also off-diagonal have to be divided by 2.0, since both lower and upper diagonal elements are given
3002 */
3003 if( var1 == var2 || !isQuadObj )
3004 quadcoefs[cnt] /= 2.0;
3005 ++cnt;
3006
3007 SCIPdebugMsg(scip, "stored term %g*<%s>*<%s>.\n", coef, SCIPvarGetName(var1), SCIPvarGetName(var2));
3008 }
3009
3010 if( mpsinputField4(mpsi) == NULL || *mpsinputField4(mpsi) == '\0' )
3011 break;
3012
3013 if( mpsinputField5(mpsi) == NULL || *mpsinputField5(mpsi) == '\0' )
3014 {
3015 /* ignore unknown variables - we would not know the type anyway */
3016 mpsinputEntryIgnored(scip, mpsi, "column", mpsinputField4(mpsi), "QMatrix", "QMATRIX", SCIP_VERBLEVEL_NORMAL);
3017 break;
3018 }
3019 }
3020 }
3021 }
3022
3023 /* add constraint */
3024 if( cnt )
3025 {
3026 SCIP_Bool initial, separate, enforce, check, propagate;
3027 SCIP_Bool local, modifiable, dynamic, removable;
3028 SCIP_CONS* cons = NULL;
3029 SCIP_VAR* qmatrixvar = NULL;
3030 SCIP_Real lhs, rhs;
3031 SCIP_Real minusone = -1.0;
3032
3033 /* determine settings; note that reading/{initialconss,dynamicconss,dynamicrows,dynamiccols} apply only to model
3034 * constraints and variables, not to an auxiliary objective constraint (otherwise it can happen that an auxiliary
3035 * objective variable is loose with infinite best bound, triggering the problem that an LP that is unbounded
3036 * because of loose variables with infinite best bound cannot be solved)
3037 */
3038 initial = TRUE;
3039 separate = TRUE;
3040 enforce = TRUE;
3041 check = TRUE;
3042 propagate = TRUE;
3043 local = FALSE;
3044 modifiable = FALSE;
3045 dynamic = FALSE;
3046 removable = FALSE;
3047
3048 SCIP_CALL( SCIPcreateVar(scip, &qmatrixvar, "qmatrixvar", -SCIPinfinity(scip), SCIPinfinity(scip), 1.0,
3050 SCIP_CALL( SCIPaddVar(scip, qmatrixvar) );
3051
3053 {
3054 lhs = -SCIPinfinity(scip);
3055 rhs = 0.0;
3056 }
3057 else
3058 {
3059 lhs = 0.0;
3060 rhs = SCIPinfinity(scip);
3061 }
3062
3063 retcode = SCIPcreateConsQuadraticNonlinear(scip, &cons, "qmatrix", 1, &qmatrixvar, &minusone, cnt, quadvars1, quadvars2, quadcoefs, lhs, rhs,
3064 initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable);
3065
3066 if( retcode == SCIP_OKAY )
3067 {
3068 SCIP_CALL( SCIPaddCons(scip, cons) );
3069 SCIPdebugMsg(scip, "(line %d) added constraint <%s>: ", mpsi->lineno, SCIPconsGetName(cons));
3071
3072 SCIP_CALL( SCIPreleaseCons(scip, &cons) );
3073 SCIP_CALL( SCIPreleaseVar(scip, &qmatrixvar) );
3074 }
3075 }
3076 else
3077 {
3078 SCIPwarningMessage(scip, "%s section has no entries.\n", isQuadObj ? "QUADOBJ" : "QMATRIX");
3079 }
3080
3081 SCIPfreeBufferArray(scip, &quadvars1);
3082 SCIPfreeBufferArray(scip, &quadvars2);
3083 SCIPfreeBufferArray(scip, &quadcoefs);
3084
3085 SCIP_CALL( retcode );
3086
3087 return SCIP_OKAY;
3088}
3089
3090
3091/** Process QCMATRIX section.
3092 *
3093 * We read the QCMATRIX section, which is a nonstandard section introduced by CPLEX.
3094 *
3095 * We replace the corresponding linear constraint by a quadratic constraint which contains the
3096 * original linear constraint plus the quadratic part specified in the QCMATRIX.
3097 */
3098static
3100 MPSINPUT* mpsi, /**< mps input structure */
3101 SCIP* scip /**< SCIP data structure */
3102 )
3103{
3104 SCIP_CONS* lincons; /* the linear constraint that was added for the corresponding row */
3105 SCIP_VAR** quadvars1;
3106 SCIP_VAR** quadvars2;
3107 SCIP_Real* quadcoefs;
3108 SCIP_RETCODE retcode;
3109 int cnt = 0; /* number of qcmatrix elements processed so far */
3110 int size; /* size of quad* arrays */
3111
3112 if( mpsinputField1(mpsi) == NULL )
3113 {
3114 SCIPerrorMessage("no row name in QCMATRIX line.\n");
3115 mpsinputSyntaxerror(mpsi);
3116 return SCIP_OKAY;
3117 }
3118
3119 if( SCIPisExact(scip) )
3120 {
3121 SCIPerrorMessage("Exact solving mode cannot handle QCMatrix constraints currently \n");
3122 return SCIP_READERROR;
3123 }
3124
3125 retcode = SCIP_OKAY;
3126
3127 SCIPdebugMsg(scip, "read QCMATRIX section for row <%s>\n", mpsinputField1(mpsi));
3128
3129 lincons = SCIPfindCons(scip, mpsinputField1(mpsi));
3130 if( lincons == NULL )
3131 {
3132 SCIPerrorMessage("no row under name <%s> processed so far.\n", mpsinputField1(mpsi));
3133 mpsinputSyntaxerror(mpsi);
3134 return SCIP_OKAY;
3135 }
3136
3137 size = 1;
3138 SCIP_CALL( SCIPallocBufferArray(scip, &quadvars1, size) );
3139 SCIP_CALL( SCIPallocBufferArray(scip, &quadvars2, size) );
3140 SCIP_CALL( SCIPallocBufferArray(scip, &quadcoefs, size) );
3141
3142 /* loop through section */
3143 /* coverity[tainted_data] */
3144 while( mpsinputReadLine(mpsi) )
3145 {
3146 /* otherwise we are in the section given variables */
3147 SCIP_VAR* var1;
3148 SCIP_VAR* var2;
3149 SCIP_Real coef;
3150
3151 /* check if next section is found */
3152 if( mpsinputField0(mpsi) != NULL )
3153 {
3154 if( !strcmp(mpsinputField0(mpsi), "QMATRIX") )
3156 else if( !strcmp(mpsinputField0(mpsi), "QUADOBJ") )
3158 else if( !strcmp(mpsinputField0(mpsi), "QCMATRIX") )
3160 else if( !strcmp(mpsinputField0(mpsi), "INDICATORS") )
3162 else if( !strcmp(mpsinputField0(mpsi), "ENDATA") )
3164 break;
3165 }
3166 if( mpsinputField1(mpsi) == NULL && mpsinputField2(mpsi) == NULL )
3167 {
3168 SCIPerrorMessage("empty data in a non-comment line.\n");
3169 mpsinputSyntaxerror(mpsi);
3170
3171 goto TERMINATE;
3172 }
3173
3174 /* get first variable */
3175 var1 = SCIPfindVar(scip, mpsinputField1(mpsi));
3176 if( var1 == NULL )
3177 {
3178 /* ignore unknown variables - we would not know the type anyway */
3179 mpsinputEntryIgnored(scip, mpsi, "column", mpsinputField1(mpsi), "QCMatrix", SCIPconsGetName(lincons), SCIP_VERBLEVEL_NORMAL);
3180 }
3181 else
3182 {
3183 /* get second variable */
3184 var2 = SCIPfindVar(scip, mpsinputField2(mpsi));
3185 if( var2 == NULL )
3186 {
3187 /* ignore unknown variables - we would not know the type anyway */
3188 mpsinputEntryIgnored(scip, mpsi, "column", mpsinputField2(mpsi), "QCMatrix", SCIPconsGetName(lincons), SCIP_VERBLEVEL_NORMAL);
3189 }
3190 else
3191 {
3192 char* endptr;
3193 if( mpsinputField3(mpsi) == NULL )
3194 {
3195 SCIPerrorMessage("coefficient of term <%s>*<%s> not specified.\n", mpsinputField1(mpsi), mpsinputField2(mpsi));
3196 mpsinputSyntaxerror(mpsi);
3197
3198 goto TERMINATE;
3199 }
3200
3201 /* get coefficient */
3202 coef = strtod(mpsinputField3(mpsi), &endptr);
3203 if( endptr == mpsinputField3(mpsi) || *endptr != '\0' )
3204 {
3205 SCIPerrorMessage("coefficient of term <%s>*<%s> not specified.\n", mpsinputField1(mpsi), mpsinputField2(mpsi));
3206 mpsinputSyntaxerror(mpsi);
3207
3208 goto TERMINATE;
3209 }
3210
3211 /* store variables and coefficient */
3212 if( cnt >= size )
3213 {
3214 int newsize = SCIPcalcMemGrowSize(scip, size+1);
3215 assert(newsize > size);
3216 SCIP_CALL( SCIPreallocBufferArray(scip, &quadvars1, newsize) );
3217 SCIP_CALL( SCIPreallocBufferArray(scip, &quadvars2, newsize) );
3218 SCIP_CALL( SCIPreallocBufferArray(scip, &quadcoefs, newsize) );
3219 size = newsize;
3220 }
3221 assert(cnt < size);
3222 quadvars1[cnt] = var1;
3223 quadvars2[cnt] = var2;
3224 quadcoefs[cnt] = coef;
3225 ++cnt;
3226
3227 SCIPdebugMsg(scip, "stored term %g*<%s>*<%s>.\n", coef, SCIPvarGetName(var1), SCIPvarGetName(var2));
3228
3229 /* check other fields */
3230 if( (mpsinputField4(mpsi) != NULL && *mpsinputField4(mpsi) != '\0' ) ||
3231 (mpsinputField5(mpsi) != NULL && *mpsinputField5(mpsi) != '\0' ) )
3232 {
3233 SCIPwarningMessage(scip, "ignoring data in fields 4 and 5 <%s> <%s>.\n", mpsinputField4(mpsi), mpsinputField5(mpsi));
3234 }
3235 }
3236 }
3237 }
3238
3239 /* replace linear constraint by quadratic constraint */
3240 if( cnt )
3241 {
3242 SCIP_CONS* cons = NULL;
3243
3244 retcode = SCIPcreateConsQuadraticNonlinear(scip, &cons, SCIPconsGetName(lincons),
3245 SCIPgetNVarsLinear(scip, lincons), SCIPgetVarsLinear(scip, lincons), SCIPgetValsLinear(scip, lincons),
3246 cnt, quadvars1, quadvars2, quadcoefs, SCIPgetLhsLinear(scip, lincons), SCIPgetRhsLinear(scip, lincons),
3247 SCIPconsIsInitial(lincons), SCIPconsIsSeparated(lincons), SCIPconsIsEnforced(lincons), SCIPconsIsChecked(lincons),
3248 SCIPconsIsPropagated(lincons), SCIPconsIsLocal(lincons), SCIPconsIsModifiable(lincons), SCIPconsIsDynamic(lincons),
3249 SCIPconsIsRemovable(lincons));
3250
3251 if( retcode != SCIP_OKAY )
3252 goto TERMINATE;
3253
3254 SCIP_CALL( SCIPaddCons(scip, cons) );
3255 SCIPdebugMsg(scip, "(line %d) added constraint <%s>: ", mpsi->lineno, SCIPconsGetName(cons));
3257
3258 SCIP_CALL( SCIPreleaseCons(scip, &cons) );
3259
3260 SCIP_CALL( SCIPdelCons(scip, lincons) );
3261 }
3262 else
3263 {
3264 SCIPwarningMessage(scip, "QCMATRIX section for constraint <%s> has no entries.\n", SCIPconsGetName(lincons));
3265 }
3266
3267 TERMINATE:
3268 SCIPfreeBufferArray(scip, &quadcoefs);
3269 SCIPfreeBufferArray(scip, &quadvars2);
3270 SCIPfreeBufferArray(scip, &quadvars1);
3271
3272 SCIP_CALL( retcode );
3273
3274 return SCIP_OKAY;
3275}
3276
3277
3278/** Process INDICATORS section.
3279 *
3280 * We read the INDICATORS section, which is a nonstandard section introduced by CPLEX.
3281 * Note that CPLEX does not allow ranged rows.
3282 *
3283 * If the linear constraints are equations or ranged rows, we generate two indicator
3284 * constraints.
3285 *
3286 * The section has to come after the QMATRIX* sections.
3287 */
3288static
3290 MPSINPUT* mpsi, /**< mps input structure */
3291 SCIP* scip /**< SCIP data structure */
3292 )
3293{
3294 SCIP_Bool initial;
3296 SCIP_Bool enforce;
3297 SCIP_Bool check;
3299 SCIP_Bool local;
3300 SCIP_Bool dynamic;
3301 SCIP_Bool removable;
3302 SCIP_Bool stickingatnode;
3303 char name[MPS_MAX_NAMELEN] = { '\0' };
3304
3305 SCIPdebugMsg(scip, "read INDICATORS constraints\n");
3306
3307 if( SCIPisExact(scip) )
3308 {
3309 SCIPerrorMessage("Exact solving mode cannot handle indicator constraints currently \n");
3310 return SCIP_READERROR;
3311 }
3312
3313 /* standard settings for indicator constraints: */
3314 initial = mpsi->initialconss;
3315 separate = TRUE;
3316 enforce = TRUE;
3317 check = TRUE;
3318 propagate = TRUE;
3319 local = FALSE;
3320 dynamic = mpsi->dynamicconss;
3321 removable = mpsi->dynamicrows;
3322 stickingatnode = FALSE;
3323
3324 /* loop through section */
3325 while( mpsinputReadLine(mpsi) )
3326 {
3327 SCIP_CONSHDLR* conshdlr;
3328 SCIP_CONS* cons;
3329 SCIP_CONS* lincons;
3330 SCIP_VAR* binvar;
3331 SCIP_Real lhs;
3332 SCIP_Real rhs;
3333
3334 /* check if next section is found */
3335 if( mpsinputField0(mpsi) != NULL )
3336 {
3337 if( !strcmp(mpsinputField0(mpsi), "ENDATA") )
3339 break;
3340 }
3341
3342 if( mpsinputField1(mpsi) == NULL || mpsinputField2(mpsi) == NULL )
3343 {
3344 SCIPerrorMessage("empty data in a non-comment line.\n");
3345 mpsinputSyntaxerror(mpsi);
3346 return SCIP_OKAY;
3347 }
3348
3349 /* check for new indicator constraint */
3350 if( strcmp(mpsinputField1(mpsi), "IF") != 0 )
3351 {
3352 SCIPerrorMessage("Indicator constraints need to be introduced by 'IF' in column 1.\n");
3353 mpsinputSyntaxerror(mpsi);
3354 return SCIP_OKAY;
3355 }
3356
3357 /* get linear constraint (row) */
3358 lincons = SCIPfindCons(scip, mpsinputField2(mpsi));
3359 if( lincons == NULL )
3360 {
3361 SCIPerrorMessage("row <%s> does not exist.\n", mpsinputField2(mpsi));
3362 mpsinputSyntaxerror(mpsi);
3363 return SCIP_OKAY;
3364 }
3365
3366 /* check whether constraint is really linear */
3367 conshdlr = SCIPconsGetHdlr(lincons);
3368 if( strcmp(SCIPconshdlrGetName(conshdlr), "linear") != 0 )
3369 {
3370 SCIPerrorMessage("constraint <%s> is not linear.\n", mpsinputField2(mpsi));
3371 mpsinputSyntaxerror(mpsi);
3372 return SCIP_OKAY;
3373 }
3374
3375 /* get binary variable */
3376 binvar = SCIPfindVar(scip, mpsinputField3(mpsi));
3377 if( binvar == NULL )
3378 {
3379 SCIPerrorMessage("binary variable <%s> does not exist.\n", mpsinputField3(mpsi));
3380 mpsinputSyntaxerror(mpsi);
3381 return SCIP_OKAY;
3382 }
3383
3384 /* check type */
3385 if( SCIPvarGetType(binvar) != SCIP_VARTYPE_BINARY )
3386 {
3387 SCIPerrorMessage("variable <%s> is not binary.\n", mpsinputField3(mpsi));
3388 mpsinputSyntaxerror(mpsi);
3389 return SCIP_OKAY;
3390 }
3391
3392 /* check whether we need the negated variable */
3393 if( mpsinputField4(mpsi) != NULL )
3394 {
3395 if( *mpsinputField4(mpsi) == '0' )
3396 {
3397 SCIP_VAR* var;
3398 SCIP_CALL( SCIPgetNegatedVar(scip, binvar, &var) );
3399 binvar = var;
3400 assert( binvar != NULL );
3401 }
3402 else
3403 {
3404 if( *mpsinputField4(mpsi) != '1' )
3405 {
3406 SCIPerrorMessage("binary variable <%s> can only take values 0/1 (%s).\n", mpsinputField3(mpsi), mpsinputField4(mpsi));
3407 mpsinputSyntaxerror(mpsi);
3408 return SCIP_OKAY;
3409 }
3410 }
3411 }
3412
3413 /* get lhs/rhs */
3414 lhs = SCIPgetLhsLinear(scip, lincons);
3415 rhs = SCIPgetRhsLinear(scip, lincons);
3416
3417 if( !SCIPisInfinity(scip, -lhs) )
3418 {
3419 if( ! SCIPisInfinity(scip, rhs) )
3420 {
3421 /* create second indicator constraint */
3422 SCIP_VAR** vars;
3423 SCIP_Real* vals;
3424 SCIP_RETCODE retcode;
3425 SCIP_VAR** linvars;
3426 SCIP_Real* linvals;
3427 int nlinvars;
3428 int i;
3429
3430 nlinvars = SCIPgetNVarsLinear(scip, lincons);
3431 linvars = SCIPgetVarsLinear(scip, lincons);
3432 linvals = SCIPgetValsLinear(scip, lincons);
3433
3434 SCIP_CALL( SCIPallocBufferArray(scip, &vars, nlinvars) );
3435 SCIP_CALL( SCIPallocBufferArray(scip, &vals, nlinvars) );
3436 for( i = 0; i < nlinvars; ++i )
3437 {
3438 vars[i] = linvars[i];
3439 vals[i] = -linvals[i];
3440 }
3441
3442 /* create new name */
3443 (void) SCIPsnprintf(name, MPS_MAX_NAMELEN, "indlhs_%s", SCIPconsGetName(lincons));
3444
3445 /* create indicator constraint */
3446 retcode = SCIPcreateConsIndicator(scip, &cons, name, binvar, nlinvars, vars, vals, -lhs,
3447 initial, separate, enforce, check, propagate, local, dynamic, removable, stickingatnode);
3448
3449 if( retcode == SCIP_OKAY )
3450 {
3451 SCIP_CALL( SCIPaddCons(scip, cons) );
3452 SCIPdebugMsg(scip, "created indicator constraint <%s>\n", mpsinputField2(mpsi));
3454 SCIP_CALL( SCIPreleaseCons(scip, &cons) );
3455 }
3456
3457 SCIPfreeBufferArray(scip, &vals);
3459
3460 SCIP_CALL( retcode );
3461 }
3462 }
3463
3464 /* correct linear constraint and create new name */
3465 if ( ! SCIPisInfinity(scip, -lhs) && ! SCIPisInfinity(scip, rhs) )
3466 {
3467 /* we have added lhs above and only need the rhs */
3469 (void) SCIPsnprintf(name, MPS_MAX_NAMELEN, "indrhs_%s", SCIPconsGetName(lincons));
3470 }
3471 else
3472 (void) SCIPsnprintf(name, MPS_MAX_NAMELEN, "ind_%s", SCIPconsGetName(lincons));
3473
3474 /* create indicator constraint */
3475 SCIP_CALL( SCIPcreateConsIndicatorLinConsPure(scip, &cons, name, binvar, lincons,
3476 initial, separate, enforce, check, propagate, local, dynamic, removable, stickingatnode) );
3477
3478 SCIP_CALL( SCIPaddCons(scip, cons) );
3479 SCIPdebugMsg(scip, "created indicator constraint <%s>", mpsinputField2(mpsi));
3481 SCIP_CALL( SCIPreleaseCons(scip, &cons) );
3482 }
3483
3484 return SCIP_OKAY;
3485}
3486
3487
3488/** Read LP in "MPS File Format".
3489 *
3490 * A specification of the MPS format can be found at
3491 *
3492 * http://plato.asu.edu/ftp/mps_format.txt,
3493 * ftp://ftp.caam.rice.edu/pub/people/bixby/miplib/mps_format,
3494 *
3495 * and in the
3496 *
3497 * CPLEX Reference Manual
3498 *
3499 * This routine should read all valid MPS format files.
3500 * What it will not do, is to find all cases where a file is ill formed.
3501 * If this happens it may complain and read nothing or read "something".
3502 */
3503static
3505 SCIP* scip, /**< SCIP data structure */
3506 const char* filename, /**< name of the input file */
3507 const char*** varnames, /**< storage for the variable names, or NULL */
3508 const char*** consnames, /**< storage for the constraint names, or NULL */
3509 int* varnamessize, /**< the size of the variable names storage, or NULL */
3510 int* consnamessize, /**< the size of the constraint names storage, or NULL */
3511 int* nvarnames, /**< the number of stored variable names, or NULL */
3512 int* nconsnames /**< the number of stored constraint names, or NULL */
3513 )
3514{
3515 SCIP_FILE* fp;
3516 MPSINPUT* mpsi;
3517 SCIP_RETCODE retcode;
3518
3519 assert(scip != NULL);
3520 assert(filename != NULL);
3521
3522 fp = SCIPfopen(filename, "r");
3523 if( fp == NULL )
3524 {
3525 SCIPerrorMessage("cannot open file <%s> for reading\n", filename);
3526 SCIPprintSysError(filename);
3527 return SCIP_NOFILE;
3528 }
3529
3530 SCIP_CALL( mpsinputCreate(scip, &mpsi, fp) );
3531
3532 SCIP_CALL_TERMINATE( retcode, readName(scip, mpsi), TERMINATE );
3533
3534 SCIP_CALL_TERMINATE( retcode, SCIPcreateProb(scip, mpsi->probname, NULL, NULL, NULL, NULL, NULL, NULL, NULL), TERMINATE );
3535
3536 if( mpsinputSection(mpsi) == MPS_OBJSEN )
3537 {
3538 SCIP_CALL_TERMINATE( retcode, readObjsen(scip, mpsi), TERMINATE );
3539 }
3540 if( mpsinputSection(mpsi) == MPS_OBJNAME )
3541 {
3542 SCIP_CALL_TERMINATE( retcode, readObjname(scip, mpsi), TERMINATE );
3543 }
3544 while( mpsinputSection(mpsi) == MPS_ROWS
3545 || mpsinputSection(mpsi) == MPS_USERCUTS
3546 || mpsinputSection(mpsi) == MPS_LAZYCONS )
3547 {
3548 SCIP_CALL_TERMINATE( retcode, readRows(mpsi, scip, consnames, consnamessize, nconsnames), TERMINATE );
3549 }
3550 if( mpsinputSection(mpsi) == MPS_COLUMNS )
3551 {
3552 SCIP_CALL_TERMINATE( retcode, readCols(mpsi, scip, varnames, varnamessize, nvarnames), TERMINATE );
3553 }
3554 if( mpsinputSection(mpsi) == MPS_RHS )
3555 {
3556 SCIP_CALL_TERMINATE( retcode, readRhs(mpsi, scip), TERMINATE );
3557 }
3558 if( mpsinputSection(mpsi) == MPS_RANGES )
3559 {
3560 SCIP_CALL_TERMINATE( retcode, readRanges(mpsi, scip), TERMINATE );
3561 }
3562 if( mpsinputSection(mpsi) == MPS_BOUNDS )
3563 {
3564 SCIP_CALL_TERMINATE( retcode, readBounds(mpsi, scip), TERMINATE );
3565 }
3566 if( mpsinputSection(mpsi) == MPS_SOS )
3567 {
3568 SCIP_CALL_TERMINATE( retcode, readSOS(mpsi, scip), TERMINATE );
3569 }
3570 while( mpsinputSection(mpsi) == MPS_QCMATRIX )
3571 {
3572 SCIP_CALL_TERMINATE( retcode, readQCMatrix(mpsi, scip), TERMINATE );
3573 }
3574 if( mpsinputSection(mpsi) == MPS_QMATRIX )
3575 {
3576 SCIP_CALL_TERMINATE( retcode, readQMatrix(mpsi, FALSE, scip), TERMINATE );
3577 }
3578 if( mpsinputSection(mpsi) == MPS_QUADOBJ )
3579 {
3580 SCIP_CALL_TERMINATE( retcode, readQMatrix(mpsi, TRUE, scip), TERMINATE );
3581 }
3582 while( mpsinputSection(mpsi) == MPS_QCMATRIX )
3583 {
3584 SCIP_CALL_TERMINATE( retcode, readQCMatrix(mpsi, scip), TERMINATE );
3585 }
3586 if( mpsinputSection(mpsi) == MPS_INDICATORS )
3587 {
3588 SCIP_CALL_TERMINATE( retcode, readIndicators(mpsi, scip), TERMINATE );
3589 }
3590 if( mpsinputSection(mpsi) != MPS_ENDATA )
3591 mpsinputSyntaxerror(mpsi);
3592
3593 if( mpsinputHasError(mpsi) )
3594 {
3595 retcode = SCIP_READERROR;
3596 goto TERMINATE;
3597 }
3598
3599 SCIP_CALL_TERMINATE( retcode, SCIPsetObjsense(scip, mpsinputObjsense(mpsi)), TERMINATE );
3600
3601 TERMINATE:
3602 mpsinputFree(scip, &mpsi);
3603 SCIPfclose(fp);
3604
3605 return retcode;
3606}
3607
3608/** Read LP in "MPS File Format" (version for exact solving mode, numbers can also be rationals).
3609 *
3610 * A specification of the MPS format can be found at
3611 *
3612 * http://plato.asu.edu/ftp/mps_format.txt,
3613 * ftp://ftp.caam.rice.edu/pub/people/bixby/miplib/mps_format,
3614 *
3615 * and in the
3616 *
3617 * CPLEX Reference Manual
3618 *
3619 * This routine should read all valid MPS format files.
3620 * What it will not do, is to find all cases where a file is ill formed.
3621 * If this happens it may complain and read nothing or read "something".
3622 */
3623static
3625 SCIP* scip, /**< SCIP data structure */
3626 const char* filename, /**< name of the input file */
3627 const char*** varnames, /**< storage for the variable names, or NULL */
3628 const char*** consnames, /**< storage for the constraint names, or NULL */
3629 int* varnamessize, /**< the size of the variable names storage, or NULL */
3630 int* consnamessize, /**< the size of the constraint names storage, or NULL */
3631 int* nvarnames, /**< the number of stored variable names, or NULL */
3632 int* nconsnames /**< the number of stored constraint names, or NULL */
3633 )
3634{
3635 SCIP_FILE* fp;
3636 MPSINPUT* mpsi;
3637 SCIP_RETCODE retcode;
3638
3639 assert(scip != NULL);
3640 assert(filename != NULL);
3642
3643 fp = SCIPfopen(filename, "r");
3644 if( fp == NULL )
3645 {
3646 SCIPerrorMessage("cannot open file <%s> for reading\n", filename);
3647 SCIPprintSysError(filename);
3648 return SCIP_NOFILE;
3649 }
3650
3651 SCIP_CALL( mpsinputCreate(scip, &mpsi, fp) );
3652
3653 SCIP_CALL_TERMINATE( retcode, readName(scip, mpsi), TERMINATE );
3654
3655 SCIP_CALL_TERMINATE( retcode, SCIPcreateProb(scip, mpsi->probname, NULL, NULL, NULL, NULL, NULL, NULL, NULL), TERMINATE );
3656
3657 if( mpsinputSection(mpsi) == MPS_OBJSEN )
3658 {
3659 SCIP_CALL_TERMINATE( retcode, readObjsen(scip, mpsi), TERMINATE );
3660 }
3661 if( mpsinputSection(mpsi) == MPS_OBJNAME )
3662 {
3663 SCIP_CALL_TERMINATE( retcode, readObjname(scip, mpsi), TERMINATE );
3664 }
3665 while( mpsinputSection(mpsi) == MPS_ROWS
3666 || mpsinputSection(mpsi) == MPS_USERCUTS
3667 || mpsinputSection(mpsi) == MPS_LAZYCONS )
3668 {
3669 SCIP_CALL_TERMINATE( retcode, readRowsExact(mpsi, scip, consnames, consnamessize, nconsnames), TERMINATE );
3670 }
3671 if( mpsinputSection(mpsi) == MPS_COLUMNS )
3672 {
3673 SCIP_CALL_TERMINATE( retcode, readColsExact(mpsi, scip, varnames, varnamessize, nvarnames), TERMINATE );
3674 }
3675 if( mpsinputSection(mpsi) == MPS_RHS )
3676 {
3677 SCIP_CALL_TERMINATE( retcode, readRhsExact(mpsi, scip), TERMINATE );
3678 }
3679 if( mpsinputSection(mpsi) == MPS_RANGES )
3680 {
3681 SCIP_CALL_TERMINATE( retcode, readRangesExact(mpsi, scip), TERMINATE );
3682 }
3683 if( mpsinputSection(mpsi) == MPS_BOUNDS )
3684 {
3685 SCIP_CALL_TERMINATE( retcode, readBoundsExact(mpsi, scip), TERMINATE );
3686 }
3687 if( mpsinputSection(mpsi) == MPS_SOS )
3688 {
3689 SCIP_CALL_TERMINATE( retcode, readSOS(mpsi, scip), TERMINATE );
3690 }
3691 while( mpsinputSection(mpsi) == MPS_QCMATRIX )
3692 {
3693 SCIP_CALL_TERMINATE( retcode, readQCMatrix(mpsi, scip), TERMINATE );
3694 }
3695 if( mpsinputSection(mpsi) == MPS_QMATRIX )
3696 {
3697 SCIP_CALL_TERMINATE( retcode, readQMatrix(mpsi, FALSE, scip), TERMINATE );
3698 }
3699 if( mpsinputSection(mpsi) == MPS_QUADOBJ )
3700 {
3701 SCIP_CALL_TERMINATE( retcode, readQMatrix(mpsi, TRUE, scip), TERMINATE );
3702 }
3703 while( mpsinputSection(mpsi) == MPS_QCMATRIX )
3704 {
3705 SCIP_CALL_TERMINATE( retcode, readQCMatrix(mpsi, scip), TERMINATE );
3706 }
3707 if( mpsinputSection(mpsi) == MPS_INDICATORS )
3708 {
3709 SCIP_CALL_TERMINATE( retcode, readIndicators(mpsi, scip), TERMINATE );
3710 }
3711 if( mpsinputSection(mpsi) != MPS_ENDATA )
3712 mpsinputSyntaxerror(mpsi);
3713
3714 if( mpsinputHasError(mpsi) )
3715 {
3716 retcode = SCIP_READERROR;
3717 goto TERMINATE;
3718 }
3719
3720 SCIP_CALL_TERMINATE( retcode, SCIPsetObjsense(scip, mpsinputObjsense(mpsi)), TERMINATE );
3721
3722 TERMINATE:
3723 mpsinputFree(scip, &mpsi);
3724 SCIPfclose(fp);
3725
3726 return retcode;
3727}
3728
3729/*
3730 * local methods for writing problem
3731 */
3732
3733/** gets the key (i.e. the name) of the given namefreq */
3734static
3735SCIP_DECL_HASHGETKEY(hashGetKeyNamefreq)
3736{ /*lint --e{715}*/
3737 CONSNAMEFREQ* consnamefreq = (CONSNAMEFREQ*)elem;
3738
3739 assert(consnamefreq != NULL);
3740 assert(consnamefreq->consname != NULL);
3741
3742 return (void*)consnamefreq->consname;
3743}
3744
3745/** returns TRUE iff both keys (i.e. strings) are equal up to max length*/
3746static
3747SCIP_DECL_HASHKEYEQ(hashKeyEqString)
3748{ /*lint --e{715}*/
3749 const char* string1 = (const char*)key1;
3750 const char* string2 = (const char*)key2;
3751
3752 return (strncmp(string1, string2, MPS_MAX_NAMELEN - 1) == 0);
3753}
3754
3755/** hash key retrieval function for variables */
3756static
3758{ /*lint --e{715}*/
3759 return elem;
3760}
3761
3762/** returns TRUE iff the indices of both variables are equal */
3763static
3765{ /*lint --e{715}*/
3766 if( key1 == key2 )
3767 return TRUE;
3768 return FALSE;
3769}
3770
3771/** returns the hash value of the key */
3772static
3774{ /*lint --e{715}*/
3775 assert( SCIPvarGetIndex((SCIP_VAR*) key) >= 0 );
3776 return (unsigned int) SCIPvarGetIndex((SCIP_VAR*) key);
3777}
3778
3779
3780/** computes the field width such that the output file is nicely arranged */
3781static
3783 unsigned int width /**< required width */
3784 )
3785{
3786 width = MAX(8u, width);
3787 return MIN(MPS_MAX_FIELDLEN, width);
3788}
3789
3790
3791/** output two strings in columns 1 and 2 with computed widths */
3792static
3794 SCIP* scip, /**< SCIP data structure */
3795 FILE* file, /**< output file (or NULL for standard output) */
3796 const char* col1, /**< column 1 */
3797 const char* col2, /**< column 2 */
3798 unsigned int maxnamelen /**< maximum name length */
3799 )
3800{
3801 unsigned int fieldwidth;
3802 char format[32];
3803
3804 assert( scip != NULL );
3805 assert( col1 != NULL );
3806 assert( col2 != NULL );
3807 assert( strlen(col1) < MPS_MAX_NAMELEN );
3808 assert( strlen(col2) < MPS_MAX_VALUELEN );
3809 assert( maxnamelen > 0 );
3810
3811 fieldwidth = computeFieldWidth(maxnamelen);
3812 (void) SCIPsnprintf(format, 32," %%-%ds %%%ds ", fieldwidth, MPS_MAX_VALUELEN - 1);
3813
3814 SCIPinfoMessage(scip, file, (const char *)format, col1, col2);
3815}
3816
3817/** output two strings in columns 1 (width 2) and 2 (width 8) */
3818static
3820 SCIP* scip, /**< SCIP data structure */
3821 FILE* file, /**< output file (or NULL for standard output) */
3822 const char* col1, /**< column 1 */
3823 const char* col2, /**< column 2 */
3824 int maxnamelen /**< maximum name length (-1 if irrelevant) */
3825 )
3826{
3827 unsigned int fieldwidth;
3828 char format[32];
3829
3830 assert( scip != NULL );
3831 assert( col1 != NULL );
3832 assert( col2 != NULL );
3833 assert( strlen(col1) <= 2 );
3834 assert( strlen(col2) < MPS_MAX_NAMELEN );
3835 assert( maxnamelen == -1 || maxnamelen > 0 );
3836
3837 if( maxnamelen < 0 )
3838 {
3839 /* format does not matter */
3840 (void) SCIPsnprintf(format, 32, " %%-2.2s %%-s ");
3841 }
3842 else
3843 {
3844 fieldwidth = computeFieldWidth((unsigned int) maxnamelen);
3845 (void) SCIPsnprintf(format, 32, " %%-2.2s %%-%ds ", fieldwidth);
3846 }
3847
3848 SCIPinfoMessage(scip, file, (const char*)format, col1, col2);
3849}
3850
3851/** prints the given data as column entry */
3852static
3854 SCIP* scip, /**< SCIP data structure */
3855 FILE* file, /**< output file (or NULL for standard output) */
3856 const char* varname, /**< variable name */
3857 const char* consname, /**< constraint name */
3858 SCIP_Real value, /**< value to display */
3859 int* recordcnt, /**< pointer to store the number of records per line */
3860 unsigned int maxnamelen /**< maximum name length */
3861 )
3862{
3863 char valuestr[MPS_MAX_VALUELEN] = { '\0' };
3864
3865 assert( scip != NULL );
3866 assert( recordcnt != NULL );
3867 assert( *recordcnt >= 0 && *recordcnt < 2 );
3868
3869 (void) SCIPsnprintf(valuestr, MPS_MAX_VALUELEN, "%25.15g", value);
3870
3871 if( *recordcnt == 0 )
3872 {
3873 /* start new line with an empty first column and the variable name in the second column */
3874 printStart(scip, file, "", varname, (int) maxnamelen);
3875 *recordcnt = 0;
3876 }
3877
3878 printRecord(scip, file, consname, valuestr, maxnamelen);
3879 (*recordcnt)++;
3880
3881 if( *recordcnt == 2 )
3882 {
3883 /* each line can have at most two records */
3884 SCIPinfoMessage(scip, file, "\n");
3885 *recordcnt = 0;
3886 }
3887}
3888
3889/** prints the constraint type to file stream */
3890static
3892 SCIP* scip, /**< SCIP data structure */
3893 FILE* file, /**< output file (or NULL for standard output) */
3894 SCIP_Real lhs, /**< left hand side */
3895 SCIP_Real rhs, /**< right hand side */
3896 const char* name /**< constraint name */
3897 )
3898{
3899 char rowtype[2];
3900
3901 assert( scip != NULL );
3902 assert( !SCIPisInfinity(scip, -lhs) || !SCIPisInfinity(scip, rhs) );
3903 assert( SCIPisGT(scip, rhs, lhs) || SCIPisEQ(scip, lhs, rhs) );
3904 assert( name != NULL );
3905
3906 if( SCIPisEQ(scip, lhs, rhs) )
3907 (void) SCIPsnprintf(rowtype, 2, "%s", "E");
3908 else
3909 {
3910 /* in case the right hand side and the left hand side are not infinity we print a
3911 * less or equal constraint and put the right hand side in the RHS section and the
3912 * left hand side (hidden) in the RANGE section */
3913 if( !SCIPisInfinity(scip, rhs) )
3914 (void) SCIPsnprintf(rowtype, 2, "%s", "L");
3915 else
3916 {
3917 assert( !SCIPisInfinity(scip, -lhs) );
3918 (void) SCIPsnprintf(rowtype, 2, "%s", "G");
3919 }
3920 }
3921
3922 printStart(scip, file, rowtype, name, -1);
3923 SCIPinfoMessage(scip, file, "\n");
3924}
3925
3926
3927/** initializes the sparse matrix */
3928static
3930 SCIP* scip, /**< SCIP data structure */
3931 SPARSEMATRIX** matrix, /**< pointer to sparse matrix containing the entries */
3932 int slots /**< number of slots */
3933 )
3934{
3935 SCIP_CALL( SCIPallocBuffer(scip, matrix) );
3936 (*matrix)->nentries = 0;
3937 (*matrix)->sentries = slots;
3938 SCIP_CALL( SCIPallocBufferArray(scip, &(*matrix)->values, (*matrix)->sentries) );
3939 SCIP_CALL( SCIPallocBufferArray(scip, &(*matrix)->columns, (*matrix)->sentries) );
3940 SCIP_CALL( SCIPallocBufferArray(scip, &(*matrix)->rows, (*matrix)->sentries) );
3941
3942 return SCIP_OKAY;
3943}
3944
3945/** this method takes care that the required capacity is available in the sparse matrix */
3946static
3948 SCIP* scip, /**< SCIP data structure */
3949 SPARSEMATRIX* matrix, /**< sparse matrix for storing the coefficient */
3950 int capacity /**< needed capacity */
3951 )
3952{
3953 if( matrix->nentries + capacity >= matrix->sentries )
3954 {
3955 matrix->sentries = matrix->sentries * 2 + capacity;
3956 SCIP_CALL( SCIPreallocBufferArray(scip, &matrix->values, matrix->sentries) );
3957 SCIP_CALL( SCIPreallocBufferArray(scip, &matrix->columns, matrix->sentries) );
3958 SCIP_CALL( SCIPreallocBufferArray(scip, &matrix->rows, matrix->sentries) );
3959 }
3960 return SCIP_OKAY;
3961}
3962
3963/** frees the sparse matrix */
3964static
3966 SCIP* scip, /**< SCIP data structure */
3967 SPARSEMATRIX* matrix /**< sparse matrix to free */
3968 )
3969{
3970 SCIPfreeBufferArray(scip, &matrix->rows);
3971 SCIPfreeBufferArray(scip, &matrix->columns);
3972 SCIPfreeBufferArray(scip, &matrix->values);
3973
3974 SCIPfreeBuffer(scip, &matrix);
3975}
3976
3977
3978/** computes the coefficient for the given variables and linear constraint information */
3979static
3981 SCIP* scip, /**< SCIP data structure */
3982 const char* consname, /**< name of the constraint */
3983 SCIP_VAR** vars, /**< array of variables */
3984 SCIP_Real* vals, /**< array of coefficients values (or NULL if all coefficient values are 1) */
3985 int nvars, /**< number of variables */
3986 SCIP_Bool transformed, /**< transformed constraint? */
3987 SPARSEMATRIX* matrix, /**< sparse matrix for storing the coefficient */
3988 SCIP_Real* rhs /**< pointer to right hand side */
3989 )
3990{
3991 SCIP_VAR** activevars;
3992 SCIP_Real* activevals;
3993 SCIP_Real activeconstant = 0.0;
3994
3995 int nactivevars;
3996 int requiredsize;
3997 int v;
3998
3999 assert( scip != NULL );
4000 assert( nvars == 0 || vars != NULL );
4001 assert( !SCIPisInfinity(scip, *rhs) );
4002 assert( matrix != NULL );
4003
4004 /* if the variables array contains no variables, then return without
4005 * doing any thing; The MPS format and LP format do not forbid this
4006 * situation */
4007 if( nvars == 0 )
4008 return SCIP_OKAY;
4009
4010 /* duplicate variable and value array */
4011 nactivevars = nvars;
4012 SCIP_CALL( SCIPduplicateBufferArray(scip, &activevars, vars, nactivevars ) );
4013
4014 if( vals != NULL )
4015 {
4016 SCIP_CALL( SCIPduplicateBufferArray(scip, &activevals, vals, nactivevars ) );
4017 }
4018 else
4019 {
4020 SCIP_CALL( SCIPallocBufferArray(scip, &activevals, nactivevars) );
4021
4022 for( v = 0; v < nactivevars; ++v )
4023 activevals[v] = 1.0;
4024 }
4025
4026 /* retransform given variables to active variables */
4027 if( transformed )
4028 {
4029 SCIP_CALL( SCIPgetProbvarLinearSum(scip, activevars, activevals, &nactivevars, nactivevars, &activeconstant, &requiredsize) );
4030
4031 if( requiredsize > nactivevars )
4032 {
4033 SCIP_CALL( SCIPreallocBufferArray(scip, &activevars, requiredsize) );
4034 SCIP_CALL( SCIPreallocBufferArray(scip, &activevals, requiredsize) );
4035
4036 SCIP_CALL( SCIPgetProbvarLinearSum(scip, activevars, activevals, &nactivevars, requiredsize, &activeconstant, &requiredsize) );
4037 }
4038 assert( requiredsize == nactivevars );
4039 }
4040 else
4041 {
4042 for( v = 0; v < nactivevars; ++v )
4043 {
4044 SCIP_CALL( SCIPvarGetOrigvarSum(&activevars[v], &activevals[v], &activeconstant) );
4045
4046 /* negated variables with an original counterpart may also be returned by SCIPvarGetOrigvarSum();
4047 * make sure we get the original variable in that case
4048 */
4049 if( SCIPvarGetStatus(activevars[v]) == SCIP_VARSTATUS_NEGATED )
4050 {
4051 activevars[v] = SCIPvarGetNegatedVar(activevars[v]);
4052 activeconstant += activevals[v];
4053 activevals[v] *= -1.0;
4054 }
4055 }
4056 }
4057
4058 /* copy the (matrix) row into the sparse matrix */
4059 SCIP_CALL( checkSparseMatrixCapacity(scip, matrix, nactivevars) );
4060 assert( matrix->nentries + nactivevars < matrix->sentries );
4061
4062 for( v = 0; v < nactivevars; ++v )
4063 {
4064 matrix->values[matrix->nentries] = activevals[v];
4065 matrix->columns[matrix->nentries] = activevars[v];
4066 matrix->rows[matrix->nentries] = consname;
4067 matrix->nentries++;
4068 }
4069
4070 /* adjust right hand side */
4071 (*rhs) -= activeconstant;
4072
4073 /* free buffer arrays */
4074 SCIPfreeBufferArray(scip, &activevals);
4075 SCIPfreeBufferArray(scip, &activevars);
4076
4077 return SCIP_OKAY;
4078}
4079
4080
4081/** check whether given variables are aggregated and put them into an array without duplication */
4082static
4084 SCIP* scip, /**< SCIP data structure */
4085 SCIP_VAR** vars, /**< variable array */
4086 int nvars, /**< number of active variables in the problem */
4087 SCIP_VAR*** aggvars, /**< pointer to array storing the aggregated variables on output */
4088 int* naggvars, /**< pointer to number of aggregated variables on output */
4089 int* saggvars, /**< pointer to number of slots in aggvars array */
4090 SCIP_HASHTABLE* varAggregated /**< hashtable for checking duplicates */
4091 )
4092{
4093 int v;
4094
4095 assert( scip != NULL );
4096 assert( aggvars != NULL );
4097 assert( naggvars != NULL );
4098 assert( saggvars != NULL );
4099
4100 /* check variables */
4101 for( v = 0; v < nvars; ++v )
4102 {
4103 SCIP_VARSTATUS status;
4104 SCIP_VAR* var;
4105
4106 var = vars[v];
4107 status = SCIPvarGetStatus(var);
4108
4109 /* collect aggregated variables in a list */
4110 if( status >= SCIP_VARSTATUS_AGGREGATED )
4111 {
4113 assert( varAggregated != NULL );
4114
4115 if( ! SCIPhashtableExists(varAggregated, (void*) var) )
4116 {
4117 /* possibly enlarge array */
4118 if ( *saggvars <= *naggvars )
4119 {
4120 int newsize;
4121 newsize = SCIPcalcMemGrowSize(scip, *naggvars + 1);
4122 assert( newsize > *saggvars );
4123 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &aggvars, *saggvars, newsize) );
4124 *saggvars = newsize;
4125 }
4126
4127 (*aggvars)[*naggvars] = var;
4128 (*naggvars)++;
4129 SCIP_CALL( SCIPhashtableInsert(varAggregated, (void*) var) );
4130 assert( *naggvars <= *saggvars );
4131 }
4132 }
4133 }
4134 return SCIP_OKAY;
4135}
4136
4137
4138/** method check if the variable names are not longer than MPS_MAX_NAMELEN - 1*/
4139static
4141 SCIP* scip, /**< SCIP data structure */
4142 SCIP_VAR** vars, /**< array of variables */
4143 int nvars, /**< number of variables */
4144 unsigned int* maxnamelen, /**< pointer to store the maximum name length */
4145 const char*** varnames, /**< pointer to array of variable names */
4146 SCIP_HASHMAP** varnameHashmap /**< pointer to hash map storing variable, variable name mapping */
4147 )
4148{
4149 int v;
4150 int faulty;
4151 char* varname;
4152 SCIP_VAR* var;
4153
4154 assert( scip != NULL );
4155 assert( vars != NULL );
4156 assert( maxnamelen != NULL );
4157
4158 faulty = 0;
4159
4160 /* allocate memory */
4161 SCIP_CALL( SCIPhashmapCreate(varnameHashmap, SCIPblkmem(scip), nvars) );
4163
4164 /* check if the variable names are not to long */
4165 for( v = 0; v < nvars; ++v )
4166 {
4167 size_t l;
4168
4169 var = vars[v];
4170 assert( var != NULL );
4171
4172 l = strlen(SCIPvarGetName(var));
4173
4174 if( l >= MPS_MAX_NAMELEN )
4175 {
4176 faulty++;
4177 (*maxnamelen) = MPS_MAX_NAMELEN - 1;
4178 }
4179 else
4180 {
4181 (*maxnamelen) = MAX(*maxnamelen, (unsigned int) l);
4182 }
4183
4184 SCIP_CALL( SCIPallocBufferArray(scip, &varname, (int) *maxnamelen + 1) );
4185 (void) SCIPsnprintf(varname, (int)(*maxnamelen) + 1, "%s", SCIPvarGetName(var) );
4186
4187 /* insert variable with variable name into hash map */
4188 assert( !SCIPhashmapExists(*varnameHashmap, var) );
4189 SCIP_CALL( SCIPhashmapInsert(*varnameHashmap, var, (void*) varname) );
4190
4191 (*varnames)[v] = varname;
4192 }
4193
4194 if( faulty > 0 )
4195 {
4196 SCIPwarningMessage(scip, "there are %d variable names which have to be cut down to %d characters; LP might be corrupted\n",
4197 faulty, MPS_MAX_NAMELEN - 1);
4198 }
4199 return SCIP_OKAY;
4200}
4201
4202/** method check if the constraint names are not longer than MPS_MAX_NAMELEN - 1 */
4203static
4205 SCIP* scip, /**< SCIP data structure */
4206 SCIP_CONS** conss, /**< array of all constraints */
4207 int nconss, /**< number of all constraints */
4208 SCIP_Bool transformed, /**< TRUE iff problem is the transformed problem */
4209 unsigned int* maxnamelen, /**< pointer to store the maximum name length */
4210 const char*** consnames, /**< pointer to array of constraint names */
4211 SCIP_Bool* error /**< pointer to store whether all constraint names exist */
4212 )
4213{
4214 SCIP_HASHTABLE* consfreq;
4215 CONSNAMEFREQ* consnamefreqs;
4216 SCIP_CONS* cons;
4217 char* consname;
4218 int i;
4219
4220 assert(scip != NULL);
4221 assert(maxnamelen != NULL);
4222
4223 *error = FALSE;
4224
4225 /* allocate memory */
4226 SCIP_CALL( SCIPallocBufferArray(scip, &consnamefreqs, nconss) );
4227 SCIP_CALL( SCIPallocBufferArray(scip, consnames, nconss) );
4229 hashGetKeyNamefreq, hashKeyEqString, SCIPhashKeyValString, NULL) );
4230
4231 for( i = 0; i < nconss; ++i )
4232 {
4233 CONSNAMEFREQ* consnamefreq;
4234 size_t l;
4235 int freq;
4236
4237 cons = conss[i];
4238 assert( cons != NULL );
4239
4240 /* in case the transformed problem is written, only constraints are posted which are enabled in the current node */
4241 assert(!transformed || SCIPconsIsEnabled(cons));
4242
4243 l = strlen(SCIPconsGetName(cons));
4244
4245 if( l == 0 )
4246 {
4247 SCIPwarningMessage(scip, "At least one name of a constraint is empty, so file will be written with generic names.\n");
4248 *error = TRUE;
4249
4250 goto TERMINATE;
4251 }
4252
4253 consnamefreqs[i].consname = SCIPconsGetName(cons);
4254 consnamefreqs[i].freq = 0;
4255 freq = 0;
4256
4257 /* check for duplicate names */
4258 if( NULL != (consnamefreq = (CONSNAMEFREQ *)SCIPhashtableRetrieve(consfreq, (void*)SCIPconsGetName(cons))) )
4259 {
4260 consnamefreq->freq += 1;
4261 consnamefreqs[i] = *consnamefreq;
4262 freq = consnamefreq->freq;
4263 }
4264 SCIP_CALL( SCIPhashtableInsert(consfreq, (void*)(&consnamefreqs[i])) );
4265
4266 /* the new length is the length of the old name + a '_' and the freq number which has floor(log10(freq)) + 1 characters */
4267 if( freq > 0 )
4268 l = l + 1 + (size_t)log10((SCIP_Real) freq) + 1;
4269
4270 if( l >= MPS_MAX_NAMELEN )
4271 {
4272 SCIPwarningMessage(scip, "Constraints have duplicate name and are too long to fix, so file will be written with generic names.\n");
4273 *error = TRUE;
4274
4275 goto TERMINATE;
4276 }
4277
4278 (*maxnamelen) = MAX(*maxnamelen, (unsigned int) l);
4279
4280 SCIP_CALL( SCIPallocBufferArray(scip, &consname, (int) l + 1) );
4281 if( freq > 0 )
4282 (void) SCIPsnprintf(consname, (int)l + 1, "%s_%d", SCIPconsGetName(cons), freq);
4283 else
4284 (void) SCIPsnprintf(consname, (int)l + 1, "%s", SCIPconsGetName(cons));
4285
4286 (*consnames)[i] = consname;
4287 }
4288
4289TERMINATE:
4290 SCIPfreeBufferArray(scip, &consnamefreqs);
4291
4292 if( *error )
4293 {
4294 --i; /*lint !e445*/
4295 for( ; i >= 0; --i) /*lint !e445*/
4296 {
4297 SCIPfreeBufferArray(scip, &((*consnames)[i]));
4298 }
4299 SCIPfreeBufferArray(scip, consnames);
4300 }
4301
4302 SCIPhashtableFree(&consfreq);
4303
4304 return SCIP_OKAY;
4305}
4306
4307/** returns whether to print an integrality constraint for the given variable */
4308static
4310 SCIP_VAR* var, /**< variable to check */
4311 int implintlevel /**< implied integral level */
4312 )
4313{
4314 assert(implintlevel >= -2);
4315 assert(implintlevel <= 2);
4316
4318 return (int)SCIPvarGetImplType(var) > 2 - implintlevel;
4319 else
4320 return (int)SCIPvarGetImplType(var) <= 2 + implintlevel;
4321}
4322
4323/** template implementation of mpsIntComp for given implied integral level */
4324#define MPSINTCOMP_LEVEL(IMPLINTLEVEL) \
4325{ \
4326 SCIP_Bool integral1 = writeVarIsIntegral((SCIP_VAR*)elem1, IMPLINTLEVEL); \
4327 SCIP_Bool integral2 = writeVarIsIntegral((SCIP_VAR*)elem2, IMPLINTLEVEL); \
4328 \
4329 if( integral1 != integral2 ) \
4330 return integral1 ? -1 : +1; \
4331 \
4332 return SCIPvarComp(elem1, elem2); \
4333}
4334
4335/* comparison methods for sorting variables along their original indices grouping integer variables at the front */
4337static SCIP_DECL_SORTPTRCOMP(mpsIntCompM1) MPSINTCOMP_LEVEL(-1)
4338static SCIP_DECL_SORTPTRCOMP(mpsIntCompZ) MPSINTCOMP_LEVEL(0)
4339static SCIP_DECL_SORTPTRCOMP(mpsIntCompP1) MPSINTCOMP_LEVEL(1)
4340static SCIP_DECL_SORTPTRCOMP(mpsIntCompP2) MPSINTCOMP_LEVEL(2)
4341
4342/** outputs the COLUMNS section of the MPS format */
4343static
4344void printColumnSection(
4345 SCIP* scip, /**< SCIP data structure */
4346 FILE* file, /**< output file, or NULL if standard output should be used */
4347 SPARSEMATRIX* matrix, /**< sparse matrix containing the entries */
4348 SCIP_HASHMAP* varnameHashmap, /**< map from SCIP_VAR* to variable name */
4349 SCIP_HASHTABLE* indicatorSlackHash, /**< hashtable containing slack variables from indicators (or NULL) */
4350 unsigned int maxnamelen, /**< maximum name length */
4351 int implintlevel /**< implied integral level */
4352 )
4353{
4354 SCIP_Bool intSection;
4355 SCIP_VAR* var;
4356 const char* varname;
4357 SCIP_Real value;
4358 int v;
4359 int recordcnt;
4360
4361 /* @todo: create column matrix instead of sort sparse entries */
4362 /* sort sparse matrix w.r.t. the written integralities and variable indices */
4363 switch( implintlevel )
4364 {
4365 case -2:
4366 SCIPsortPtrPtrReal((void**) matrix->columns, (void**) matrix->rows, matrix->values, mpsIntCompM2, matrix->nentries);
4367 break;
4368 case -1:
4369 SCIPsortPtrPtrReal((void**) matrix->columns, (void**) matrix->rows, matrix->values, mpsIntCompM1, matrix->nentries);
4370 break;
4371 case 0:
4372 SCIPsortPtrPtrReal((void**) matrix->columns, (void**) matrix->rows, matrix->values, mpsIntCompZ, matrix->nentries);
4373 break;
4374 case 1:
4375 SCIPsortPtrPtrReal((void**) matrix->columns, (void**) matrix->rows, matrix->values, mpsIntCompP1, matrix->nentries);
4376 break;
4377 case 2:
4378 SCIPsortPtrPtrReal((void**) matrix->columns, (void**) matrix->rows, matrix->values, mpsIntCompP2, matrix->nentries);
4379 break;
4380 default:
4381 SCIPerrorMessage("invalid implintlevel\n");
4382 SCIPABORT();
4383 }
4384
4385 /* print COLUMNS section */
4386 SCIPinfoMessage(scip, file, "COLUMNS\n");
4387
4388 intSection = FALSE;
4389
4390 for( v = 0; v < matrix->nentries; )
4391 {
4392 var = matrix->columns[v];
4393 assert( var != NULL );
4394
4395 /* skip slack variables in output */
4396 if( indicatorSlackHash != NULL && SCIPhashtableExists(indicatorSlackHash, var) )
4397 {
4398 ++v;
4399 continue;
4400 }
4401
4402 /* section integer variables */
4403 if( writeVarIsIntegral(var, implintlevel) != intSection )
4404 {
4405 /* end integer section in MPS format */
4406 if( intSection )
4407 {
4408 printStart(scip, file, "", "INTEND", (int) maxnamelen);
4409 printRecord(scip, file, "'MARKER'", "", maxnamelen);
4410 printRecord(scip, file, "'INTEND'", "", maxnamelen);
4411 SCIPinfoMessage(scip, file, "\n");
4412 intSection = FALSE;
4413 }
4414 /* start integer section in MPS format */
4415 else
4416 {
4417 printStart(scip, file, "", "INTSTART", (int) maxnamelen);
4418 printRecord(scip, file, "'MARKER'", "", maxnamelen);
4419 printRecord(scip, file, "'INTORG'", "", maxnamelen);
4420 SCIPinfoMessage(scip, file, "\n");
4421 intSection = TRUE;
4422 }
4423 }
4424
4425 SCIPdebugMsg(scip, "create entries for variable <%s>\n", SCIPvarGetName(var));
4426
4427 /* record count; there are at most two records per line */
4428 recordcnt = 0;
4429
4430 /* get variable name */
4431 assert ( SCIPhashmapExists(varnameHashmap, var) );
4432 varname = (const char*) SCIPhashmapGetImage(varnameHashmap, var);
4433
4434 /* output all entries of the same variable */
4435 do
4436 {
4437 value = matrix->values[v];
4438
4439 /* print record to file */
4440 printEntry(scip, file, varname, matrix->rows[v], value, &recordcnt, maxnamelen);
4441 v++;
4442 }
4443 while( v < matrix->nentries && var == matrix->columns[v] );
4444
4445 if( recordcnt == 1 )
4446 SCIPinfoMessage(scip, file, "\n");
4447 }
4448 /* end integer section, if the columns sections ends with integer variables */
4449 if( intSection )
4450 {
4451 /* end integer section in MPS format */
4452 printStart(scip, file, "", "INTEND", (int) maxnamelen);
4453 printRecord(scip, file, "'MARKER'", "", maxnamelen);
4454 printRecord(scip, file, "'INTEND'", "", maxnamelen);
4455 SCIPinfoMessage(scip, file, "\n");
4456 }
4457}
4458
4459/** outputs the right hand side section */
4460static
4462 SCIP* scip, /**< SCIP data structure */
4463 FILE* file, /**< output file, or NULL if standard output should be used */
4464 int nconss, /**< number of constraints */
4465 const char** consnames, /**< constraint names */
4466 SCIP_Real* rhss, /**< right hand side array */
4467 unsigned int maxnamelen, /**< maximum name length */
4468 SCIP_Real objoffset /**< objective offset */
4469 )
4470{
4471 int recordcnt = 0;
4472 int c;
4473
4474 assert( rhss != NULL );
4475
4476 SCIPinfoMessage(scip, file, "RHS\n");
4477 SCIPdebugMsg(scip, "start printing RHS section\n");
4478
4479 /* take care of the linear constraints */
4480 for( c = 0; c < nconss; ++c )
4481 {
4482 /* skip all constraints which have a right hand side of infinity */
4483 if( SCIPisInfinity(scip, rhss[c]) )
4484 continue;
4485
4486 assert(consnames[c] != NULL);
4487
4488 printEntry(scip, file, "RHS", consnames[c], rhss[c], &recordcnt, maxnamelen);
4489 }
4490
4491 if( ! SCIPisZero(scip, objoffset) )
4492 {
4493 /* write objective offset (-1 because it is moved to the rhs) */
4494 printEntry(scip, file, "RHS", "Obj", -objoffset, &recordcnt, maxnamelen);
4495 }
4496
4497 if( recordcnt == 1 )
4498 SCIPinfoMessage(scip, file, "\n");
4499}
4500
4501/** outputs the range section */
4502static
4504 SCIP* scip, /**< SCIP data structure */
4505 FILE* file, /**< output file, or NULL if standard output should be used */
4506 SCIP_CONS** conss, /**< constraint array */
4507 int nconss, /**< number of constraints */
4508 const char** consnames, /**< constraint names */
4509 SCIP_Bool transformed, /**< TRUE iff problem is the transformed problem */
4510 unsigned int maxnamelen /**< maximum name length */
4511 )
4512{
4513 int c;
4514 int recordcnt = 0;
4515
4516 SCIP_CONSHDLR* conshdlr;
4517 const char* conshdlrname;
4518
4519 SCIP_CONS* cons;
4520 SCIP_Real lhs;
4521 SCIP_Real rhs;
4522
4523 SCIPinfoMessage(scip, file, "RANGES\n");
4524 SCIPdebugMsg(scip, "start printing RANGES section\n");
4525
4526 for( c = 0; c < nconss; ++c )
4527 {
4528 cons = conss[c];
4529 assert( cons != NULL);
4530
4531 /* in case the transformed problems is written only constraint are posted which are enabled in the current node;
4532 * the conss array should only contain relevant constraints
4533 */
4534 assert( !transformed || SCIPconsIsEnabled(cons) );
4535
4536 assert( consnames[c] != NULL );
4537
4538 conshdlr = SCIPconsGetHdlr(cons);
4539 assert( conshdlr != NULL );
4540
4541 conshdlrname = SCIPconshdlrGetName(conshdlr);
4542
4543 if( strcmp(conshdlrname, "linear") == 0 )
4544 {
4545 lhs = SCIPgetLhsLinear(scip, cons);
4546 rhs = SCIPgetRhsLinear(scip, cons);
4547 }
4548 else if( strcmp(conshdlrname, "varbound") == 0 )
4549 {
4550 lhs = SCIPgetLhsVarbound(scip, cons);
4551 rhs = SCIPgetRhsVarbound(scip, cons);
4552 }
4553 else
4554 continue;
4555
4556 if( !SCIPisInfinity(scip, -lhs) && !SCIPisInfinity(scip, rhs) && !SCIPisEQ(scip, rhs, lhs) )
4557 {
4558 assert( SCIPisGT(scip, rhs, lhs) );
4559 printEntry(scip, file, "RANGE", consnames[c], rhs - lhs, &recordcnt, maxnamelen);
4560 }
4561 }
4562 if(recordcnt == 1 )
4563 SCIPinfoMessage(scip, file, "\n");
4564}
4565
4566/** print bound section name */
4567static
4569 SCIP* scip, /**< SCIP data structure */
4570 FILE* file /**< output file, or NULL if standard output should be used */
4571 )
4572{
4573 SCIPinfoMessage(scip, file, "BOUNDS\n");
4574 SCIPdebugMsg(scip, "start printing BOUNDS section\n");
4575}
4576
4577/** output bound section */
4578static
4580 SCIP* scip, /**< SCIP data structure */
4581 FILE* file, /**< output file, or NULL if standard output should be used */
4582 SCIP_VAR** vars, /**< active variables */
4583 int nvars, /**< number of active variables */
4584 SCIP_VAR** aggvars, /**< needed aggregated variables */
4585 int naggvars, /**< number of aggregated variables */
4586 SCIP_VAR** fixvars, /**< all fixed variables (or NULL if nfixvars is 0) */
4587 int nfixvars, /**< number of fixed variables */
4588 SCIP_Bool transformed, /**< TRUE iff problem is the transformed problem */
4589 const char** varnames, /**< array with variable names */
4590 SCIP_HASHTABLE* indicatorSlackHash, /**< hashtable containing slack variables from indicators (or NULL) */
4591 unsigned int maxnamelen /**< maximum name length */
4592 )
4593{
4594 int v;
4595 SCIP_VAR* var;
4596 SCIP_Real lb;
4597 SCIP_Real ub;
4598 SCIP_Bool sectionName;
4599 const char* varname;
4600 char valuestr[MPS_MAX_VALUELEN] = { '\0' };
4601
4602 assert(scip != NULL);
4603 assert(vars != NULL);
4604 assert(nfixvars == 0 || fixvars != NULL);
4605
4606 sectionName = FALSE;
4607
4608 /* output the active variables */
4609 for( v = 0; v < nvars; ++v )
4610 {
4611 var = vars[v];
4612 assert( var != NULL );
4613
4614 /* skip slack variables in output */
4615 if( indicatorSlackHash != NULL && SCIPhashtableExists(indicatorSlackHash, var) )
4616 continue;
4617
4618 /* get variable name */
4619 varname = varnames[v];
4620 assert(strncmp(varname, SCIPvarGetName(var), maxnamelen) == 0);
4621
4622 if( transformed )
4623 {
4624 /* in case the transformed is written only local bounds are posted
4625 * which are valid in the current node */
4626 lb = SCIPvarGetLbLocal(var);
4627 ub = SCIPvarGetUbLocal(var);
4628 }
4629 else
4630 {
4633 }
4634
4635 /* take care of binary variables */
4637 {
4638 if( !sectionName )
4639 {
4641 sectionName = TRUE;
4642 }
4643
4644 if( !SCIPisFeasZero(scip, lb) || !SCIPisFeasEQ(scip, ub, 1.0) )
4645 {
4646 (void) SCIPsnprintf(valuestr, MPS_MAX_VALUELEN, "%25.15g", lb);
4647 printStart(scip, file, "LO", "Bound", (int) maxnamelen);
4648 printRecord(scip, file, varname, valuestr, maxnamelen);
4649 SCIPinfoMessage(scip, file, "\n");
4650
4651 (void) SCIPsnprintf(valuestr, MPS_MAX_VALUELEN, "%25.15g", ub);
4652 printStart(scip, file, "UP", "Bound", (int) maxnamelen);
4653 printRecord(scip, file, varname, valuestr, maxnamelen);
4654 }
4655 else
4656 {
4657 printStart(scip, file, "BV", "Bound", (int) maxnamelen);
4658 printRecord(scip, file, varname, "", maxnamelen);
4659 }
4660 SCIPinfoMessage(scip, file, "\n");
4661
4662 continue;
4663 }
4664
4665 /* take care of free variables */
4666 if( SCIPisInfinity(scip, -lb) && SCIPisInfinity(scip, ub) )
4667 {
4668 if( !sectionName )
4669 {
4671 sectionName = TRUE;
4672 }
4673
4674 /* variable is free */
4675 printStart(scip, file, "FR", "Bound", (int) maxnamelen);
4676 printRecord(scip, file, varname, "", maxnamelen);
4677 SCIPinfoMessage(scip, file, "\n");
4678 continue;
4679 }
4680
4681 /* take care of fixed variables */
4682 if( SCIPisEQ(scip, lb, ub) )
4683 {
4684 if( !sectionName )
4685 {
4687 sectionName = TRUE;
4688 }
4689
4690 /* variable is fixed */
4691 (void) SCIPsnprintf(valuestr, MPS_MAX_VALUELEN, "%25.15g", lb);
4692 printStart(scip, file, "FX", "Bound", (int) maxnamelen);
4693 printRecord(scip, file, varname, valuestr, maxnamelen);
4694 SCIPinfoMessage(scip, file, "\n");
4695 continue;
4696 }
4697
4698 /* print lower bound */
4699 if( SCIPisInfinity(scip, -lb) )
4700 {
4701 if( !sectionName )
4702 {
4704 sectionName = TRUE;
4705 }
4706
4707 /* the free variables are processed above */
4708 assert( !SCIPisInfinity(scip, ub) );
4709 printStart(scip, file, "MI", "Bound", (int) maxnamelen);
4710 printRecord(scip, file, varname, "", maxnamelen);
4711 SCIPinfoMessage(scip, file, "\n");
4712 }
4713 else
4714 {
4715 if( SCIPisZero(scip, lb) )
4716 {
4717 lb = 0.0;
4718 }
4719 else
4720 {
4721 if( !sectionName )
4722 {
4724 sectionName = TRUE;
4725 }
4726
4727 (void) SCIPsnprintf(valuestr, MPS_MAX_VALUELEN, "%25.15g", lb);
4728 printStart(scip, file, "LO", "Bound", (int) maxnamelen);
4729 printRecord(scip, file, varname, valuestr, maxnamelen);
4730 SCIPinfoMessage(scip, file, "\n");
4731 }
4732 }
4733
4734 /* print upper bound, infinity has to be printed for integer (!) variables, because during
4735 * reading an mps file no upper bound of an integer variable means that the upper bound will
4736 * be set to 1 instead of +infinity (like it is for continuous variables) */
4737 if( SCIPisInfinity(scip, ub) )
4738 {
4739 if( !sectionName )
4740 {
4742 sectionName = TRUE;
4743 }
4744
4745 /* the free variables are processed above */
4746 assert( !SCIPisInfinity(scip, -lb) );
4747 printStart(scip, file, "PL", "Bound", (int) maxnamelen);
4748 printRecord(scip, file, varname, "", maxnamelen);
4749 SCIPinfoMessage(scip, file, "\n");
4750 }
4751 else
4752 {
4753 if( !sectionName )
4754 {
4756 sectionName = TRUE;
4757 }
4758
4759 (void) SCIPsnprintf(valuestr, MPS_MAX_VALUELEN, "%25.15g", ub);
4760 printStart(scip, file, "UP", "Bound", (int) maxnamelen);
4761 printRecord(scip, file, varname, valuestr, maxnamelen);
4762 SCIPinfoMessage(scip, file, "\n");
4763 }
4764 }
4765
4766 /* output aggregated variables as 'free', except if they are binary */
4767 for( v = 0; v < naggvars; ++v )
4768 {
4769 if( !sectionName )
4770 {
4772 sectionName = TRUE;
4773 }
4774
4775 var = aggvars[v];
4776 assert( var != NULL );
4777
4778 /* get variable name */
4779 varname = varnames[nvars + v];
4780 assert(strncmp(varname, SCIPvarGetName(var), maxnamelen) == 0);
4781
4782 /* take care of binary variables */
4784 {
4785 printStart(scip, file, "BV", "Bound", (int) maxnamelen);
4786 printRecord(scip, file, varname, "", maxnamelen);
4787 SCIPinfoMessage(scip, file, "\n");
4788 }
4789 else
4790 {
4791 /* variable is free */
4792 printStart(scip, file, "FR", "Bound", (int) maxnamelen);
4793 printRecord(scip, file, varname, "", maxnamelen);
4794 SCIPinfoMessage(scip, file, "\n");
4795 }
4796 }
4797
4798 /* output all fixed variables */
4799 for( v = 0; v < nfixvars; ++v )
4800 {
4801 /* we should print the transformed problem, otherwise no fixed variable should exists */
4802 assert(transformed);
4803 assert(fixvars != NULL && fixvars[v] != NULL);
4804
4805 var = fixvars[v];
4806
4807 assert(var != NULL);
4809
4810 /* get variable name */
4811 varname = varnames[nvars + naggvars + v];
4812 assert(strncmp(varname, SCIPvarGetName(var), maxnamelen) == 0);
4813
4814 /* only local bounds are posted which are valid in the current node */
4815 lb = SCIPvarGetLbLocal(var);
4816 ub = SCIPvarGetUbLocal(var);
4817 assert(SCIPisEQ(scip, lb, ub));
4818
4819 if( !sectionName )
4820 {
4822 sectionName = TRUE;
4823 }
4824
4825 /* print fixed variable */
4826 (void) SCIPsnprintf(valuestr, MPS_MAX_VALUELEN, "%25.15g", lb);
4827 printStart(scip, file, "FX", "Bound", (int) maxnamelen);
4828 printRecord(scip, file, varname, valuestr, maxnamelen);
4829 SCIPinfoMessage(scip, file, "\n");
4830 }
4831}
4832
4833
4834/*
4835 * Callback methods of reader
4836 */
4837
4838/** copy method for reader plugins (called when SCIP copies plugins) */
4839/**! [SnippetReaderCopyMps] */
4840static
4842{ /*lint --e{715}*/
4843 assert(scip != NULL);
4844 assert(reader != NULL);
4845
4847
4848 /* call inclusion method of reader */
4850
4851 return SCIP_OKAY;
4852}
4853/**! [SnippetReaderCopyMps] */
4854
4855/** destructor of reader to free user data (called when SCIP is exiting) */
4856/**! [SnippetReaderFreeMps] */
4857static
4859{
4860 SCIP_READERDATA* readerdata;
4861
4863
4864 readerdata = SCIPreaderGetData(reader);
4865 assert(readerdata != NULL);
4866 SCIPfreeBlockMemory(scip, &readerdata);
4867
4868 return SCIP_OKAY;
4869}
4870/**! [SnippetReaderFreeMps] */
4871
4872/** problem reading method of reader */
4873static
4875{ /*lint --e{715}*/
4876 assert(reader != NULL);
4877
4879
4880 SCIP_CALL( SCIPreadMps(scip, reader, filename, result, NULL, NULL, NULL, NULL, NULL, NULL) );
4881
4882 return SCIP_OKAY;
4883}
4884
4885
4886/** problem writing method of reader */
4887static
4889{ /*lint --e{715}*/
4890 assert(reader != NULL);
4891
4893
4894 if( SCIPisExact(scip) )
4895 {
4896 SCIPerrorMessage("MPS reader cannot yet write problems in exact solving mode\n");
4897 return SCIP_WRITEERROR;
4898 }
4899
4900 SCIP_CALL( SCIPwriteMps(scip, reader, file, name, transformed, objsense, objoffset, objscale, objoffsetexact, objscaleexact,
4901 vars, nvars, nbinvars, nintvars, nimplvars, ncontvars, fixedvars, nfixedvars, conss, nconss, result) );
4902
4903 return SCIP_OKAY;
4904}
4905
4906
4907/*
4908 * mps file reader specific interface methods
4909 */
4910
4911/** includes the mps file reader in SCIP */
4913 SCIP* scip /**< SCIP data structure */
4914 )
4915{
4916 SCIP_READERDATA* readerdata;
4917 SCIP_READER* reader;
4918
4919 /* create reader data */
4920 SCIP_CALL( SCIPallocBlockMemory(scip, &readerdata) );
4921
4922 /* include reader */
4924
4925 /* reader is safe to use in exact solving mode, but exact writing still needs to be implemented */
4926 SCIPreaderMarkExact(reader);
4927
4928 /* set non fundamental callbacks via setter functions */
4929 SCIP_CALL( SCIPsetReaderCopy(scip, reader, readerCopyMps) );
4930 SCIP_CALL( SCIPsetReaderFree(scip, reader, readerFreeMps) );
4931 SCIP_CALL( SCIPsetReaderRead(scip, reader, readerReadMps) );
4932 SCIP_CALL( SCIPsetReaderWrite(scip, reader, readerWriteMps) );
4933
4934 /* add lp-reader parameters */
4936 "reading/" READER_NAME "/linearize-and-constraints",
4937 "should possible \"and\" constraint be linearized when writing the mps file?",
4938 &readerdata->linearizeands, TRUE, DEFAULT_LINEARIZE_ANDS, NULL, NULL) );
4940 "reading/" READER_NAME "/aggrlinearization-ands",
4941 "should an aggregated linearization for and constraints be used?",
4942 &readerdata->aggrlinearizationands, TRUE, DEFAULT_AGGRLINEARIZATION_ANDS, NULL, NULL) );
4943
4944 return SCIP_OKAY;
4945}
4946
4947
4948/** reads problem from file */
4950 SCIP* scip, /**< SCIP data structure */
4951 SCIP_READER* reader, /**< the file reader itself */
4952 const char* filename, /**< full path and name of file to read, or NULL if stdin should be used */
4953 SCIP_RESULT* result, /**< pointer to store the result of the file reading call */
4954 const char*** varnames, /**< storage for the variable names, or NULL */
4955 const char*** consnames, /**< storage for the constraint names, or NULL */
4956 int* varnamessize, /**< the size of the variable names storage, or NULL */
4957 int* consnamessize, /**< the size of the constraint names storage, or NULL */
4958 int* nvarnames, /**< the number of stored variable names, or NULL */
4959 int* nconsnames /**< the number of stored constraint names, or NULL */
4960 )
4961{
4962 SCIP_RETCODE retcode;
4963
4964 assert(reader != NULL);
4965 assert(scip != NULL);
4966 assert(result != NULL);
4967
4968 if( !SCIPisExact(scip) )
4969 retcode = readMps(scip, filename, varnames, consnames, varnamessize, consnamessize, nvarnames, nconsnames);
4970 else
4971 retcode = readMpsExact(scip, filename, varnames, consnames, varnamessize, consnamessize, nvarnames, nconsnames);
4972
4973 if( retcode == SCIP_PLUGINNOTFOUND )
4974 retcode = SCIP_READERROR;
4975
4976 if( retcode == SCIP_NOFILE || retcode == SCIP_READERROR )
4977 return retcode;
4978
4979 SCIP_CALL( retcode );
4980
4982
4983 return SCIP_OKAY;
4984}
4985
4986/** writes problem to file */
4988 SCIP* scip, /**< SCIP data structure */
4989 SCIP_READER* reader, /**< the file reader itself */
4990 FILE* file, /**< output file, or NULL if standard output should be used */
4991 const char* name, /**< problem name */
4992 SCIP_Bool transformed, /**< TRUE iff problem is the transformed problem */
4993 SCIP_OBJSENSE objsense, /**< objective sense */
4994 SCIP_Real objoffset, /**< objective offset from bound shifting and fixing */
4995 SCIP_Real objscale, /**< scalar applied to objective function; external objective value is
4996 * extobj = objsense * objscale * (intobj + objoffset) */
4997 SCIP_RATIONAL* objoffsetexact, /**< exact objective offset from bound shifting and fixing */
4998 SCIP_RATIONAL* objscaleexact, /**< exact scalar applied to objective function; external objective value is
4999 * extobjexact = objsense * objscaleexact * (intobjexact + objoffsetexact) */
5000 SCIP_VAR** vars, /**< array with active variables ordered binary, integer, implicit, continuous */
5001 int nvars, /**< number of active variables in the problem */
5002 int nbinvars, /**< number of binary variables */
5003 int nintvars, /**< number of general integer variables */
5004 int nimplvars, /**< number of implicit integer variables */
5005 int ncontvars, /**< number of continuous variables */
5006 SCIP_VAR** fixedvars, /**< array with fixed and aggregated variables */
5007 int nfixedvars, /**< number of fixed and aggregated variables in the problem */
5008 SCIP_CONS** conss, /**< array with constraints of the problem */
5009 int nconss, /**< number of constraints in the problem */
5010 SCIP_RESULT* result /**< pointer to store the result of the file writing call */
5011 )
5012{
5013 SCIP_READERDATA* readerdata;
5014 int naddrows;
5015 int faulty = 0;
5016 int c;
5017 int v;
5018 int k;
5019 char* namestr;
5020
5021 SCIP_CONS* cons = NULL;
5022 const char* consname;
5023 const char** consnames;
5024
5025 SCIP_CONSHDLR* conshdlr;
5026 const char* conshdlrname;
5027
5028 SCIP_Real lhs;
5029 SCIP_Real rhs;
5030 SCIP_Real* rhss;
5031 SCIP_Real value;
5032
5033 SCIP_VAR* var = NULL;
5034 const char* varname;
5035 const char** varnames;
5036
5037 char valuestr[MPS_MAX_VALUELEN] = { '\0' };
5038
5039 SCIP_CONS** consIndicator;
5040 SCIP_CONS** consSOS1;
5041 SCIP_CONS** consSOS2;
5042 SCIP_CONS** consQuadratic;
5043 SCIP_EXPR** exprQuadratic; /* expressions to quadratic constraints */
5044 int nConsIndicator;
5045 int nConsSOS1;
5046 int nConsSOS2;
5047 int nConsQuadratic;
5048
5049 SCIP_HASHMAP* varnameHashmap; /* hash map from SCIP_VAR* to variable name */
5050 SPARSEMATRIX* matrix;
5051
5052 SCIP_VAR** aggvars;
5053 int naggvars = 0;
5054 int saggvars;
5055 SCIP_HASHTABLE* varFixedHash;
5056 SCIP_HASHTABLE* indicatorSlackHash;
5057
5058 SCIP_VAR** fixvars = NULL;
5059 int nfixvars = 0;
5060
5061 SCIP_VAR** consvars;
5062 int nconsvars;
5063 SCIP_Real* vals;
5064 SCIP_Longint* weights;
5065
5066 SCIP_Bool needRANGES;
5067 unsigned int maxnamelen;
5068 int implintlevel;
5069
5070 SCIP_Bool error;
5071
5072 assert(reader != NULL);
5073 assert(scip != NULL);
5074 assert(result != NULL);
5075
5077
5078 /* get implied integral level for writeVarIsIntegral() and printColumnSection() */
5079 SCIP_CALL( SCIPgetIntParam(scip, "write/implintlevel", &implintlevel) );
5080
5081 /**@todo write exact offset */
5082 if( objoffsetexact != NULL )
5083 {
5085 objoffset = SCIPrationalGetReal(objoffsetexact);
5086 }
5087
5088 /**@todo write exact scale */
5089 if( objscaleexact != NULL )
5090 {
5092 objscale = SCIPrationalGetReal(objscaleexact);
5093 }
5094
5095 needRANGES = FALSE;
5096 maxnamelen = 0;
5097 nConsSOS1 = 0;
5098 nConsSOS2 = 0;
5099 nConsQuadratic = 0;
5100 nConsIndicator = 0;
5101
5102 /* check if the constraint names are too long and build the constraint names */
5103 SCIP_CALL( checkConsnames(scip, conss, nconss, transformed, &maxnamelen, &consnames, &error) );
5104 if( error )
5105 {
5106 /* call writing with generic names */
5107 if( transformed )
5108 {
5109 SCIPwarningMessage(scip, "write transformed problem with generic variable and constraint names\n");
5110 SCIP_CALL( SCIPprintTransProblem(scip, file, "mps", TRUE) );
5111 }
5112 else
5113 {
5114 SCIPwarningMessage(scip, "write original problem with generic variable and constraint names\n");
5115 SCIP_CALL( SCIPprintOrigProblem(scip, file, "mps", TRUE) );
5116 }
5118
5119 return SCIP_OKAY;
5120 }
5121
5122 /* check if the variable names are not too long and build the "variable" -> "variable name" hash map */
5123 SCIP_CALL( checkVarnames(scip, vars, nvars, &maxnamelen, &varnames, &varnameHashmap) );
5124
5125 /* collect SOS, quadratic, and indicator constraints in array for later output */
5126 SCIP_CALL( SCIPallocBufferArray(scip, &consSOS1, nconss) );
5127 SCIP_CALL( SCIPallocBufferArray(scip, &consSOS2, nconss) );
5128 SCIP_CALL( SCIPallocBufferArray(scip, &consQuadratic, nconss) );
5129 SCIP_CALL( SCIPallocBufferArray(scip, &exprQuadratic, nconss) );
5130 SCIP_CALL( SCIPallocBufferArray(scip, &consIndicator, nconss) );
5131
5132 /* nfixedvars counts all variables with status SCIP_VARSTATUS_FIXED, SCIP_VARSTATUS_AGGREGATED, SCIP_VARSTATUS_MULTAGGR, but not SCIP_VARSTATUS_NEGATED */
5133 saggvars = nfixedvars;
5134 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &aggvars, saggvars) );
5135
5136 /* create hashtable for storing aggregated variables */
5137 if( nfixedvars > 0 )
5138 {
5139 SCIP_CALL( SCIPhashtableCreate(&varFixedHash, SCIPblkmem(scip), nfixedvars, hashGetKeyVar, hashKeyEqVar, hashKeyValVar, NULL) );
5140 }
5141 else
5142 varFixedHash = NULL;
5143
5144 if( nvars > 0 )
5145 {
5146 SCIP_CALL( SCIPhashtableCreate(&indicatorSlackHash, SCIPblkmem(scip), nvars, hashGetKeyVar, hashKeyEqVar, hashKeyValVar, NULL) );
5147 }
5148 else
5149 indicatorSlackHash = NULL;
5150
5151 /* initialize sparse matrix */
5152 SCIP_CALL( initializeMatrix(scip, &matrix, (nvars * 2 + nfixedvars)) );
5153 assert( matrix->sentries >= nvars );
5154
5155 readerdata = SCIPreaderGetData(reader);
5156 assert(readerdata != NULL);
5157
5158 naddrows = 0;
5159
5160 /* determine and-constraints and printing format to resize necessary arrays */
5161 if( readerdata->linearizeands )
5162 {
5163 SCIP_CONSHDLR* andconshdlr = SCIPfindConshdlr(scip, "and");
5164
5165 if( andconshdlr != NULL )
5166 {
5167 /* need to check for and-constraints, note that in the original problem you cannot get the number of
5168 * and-constraints by one call */
5169 for( c = nconss - 1; c >= 0; --c )
5170 {
5171 conshdlr = SCIPconsGetHdlr(conss[c]);
5172 assert(conshdlr != NULL);
5173
5174 conshdlrname = SCIPconshdlrGetName(conshdlr);
5175
5176 if( strcmp(conshdlrname, "and") == 0 )
5177 {
5178 if( readerdata->aggrlinearizationands )
5179 ++naddrows;
5180 else
5181 naddrows += SCIPgetNVarsAnd(scip, conss[c]);
5182 }
5183 }
5184 assert(naddrows >= 0);
5185
5186 if( naddrows > 0 )
5187 {
5188 /* resize consnames vector */
5189 SCIP_CALL( SCIPreallocBufferArray(scip, &consnames, nconss + naddrows) );
5190 }
5191 }
5192 }
5193
5194 /* initialize rhs vector */
5195 SCIP_CALL( SCIPallocBufferArray(scip, &rhss, nconss + naddrows) );
5196
5197 /* print statistics as comment to file stream */
5198 SCIPinfoMessage(scip, file, "* SCIP STATISTICS\n");
5199 SCIPinfoMessage(scip, file, "* Problem name : %s\n", name);
5200 SCIPinfoMessage(scip, file, "* Variables : %d (%d binary, %d integer, %d implicit integer, %d continuous)\n",
5201 nvars, nbinvars, nintvars, nimplvars, ncontvars);
5202 SCIPinfoMessage(scip, file, "* Constraints : %d\n", nconss);
5203
5204 /* print NAME of the problem */
5205 SCIPinfoMessage(scip, file, "%-14s%s\n", "NAME", name);
5206
5207 /* print OBJSENSE of the problem */
5208 SCIPinfoMessage(scip, file, "OBJSENSE\n");
5209 SCIPinfoMessage(scip, file, "%s\n", objsense == SCIP_OBJSENSE_MAXIMIZE ? " MAX" : " MIN");
5210
5211 /* start ROWS section */
5212 SCIPinfoMessage(scip, file, "ROWS\n");
5213
5214 /* print row type for the objective function */
5215 printStart(scip, file, "N", "Obj", -1);
5216 SCIPinfoMessage(scip, file, "\n");
5217
5218 /* first fill the matrix with the objective coefficients */
5219 for( v = 0; v < nvars; ++v )
5220 {
5221 /* take care of the objective entry */
5222 var = vars[v];
5223 value = SCIPvarGetObj(var);
5224
5225 /* @todo: only add entry for empty column */
5226 /* we also want to add integer variables to the columns section, even if the objective value is 0, because it
5227 * might happen that they only exist in non-linear constraints, which leads to no other line in the column section
5228 * and therefore do not mark the variable as an integer
5229 */
5230 if( !SCIPisZero(scip, value) || writeVarIsIntegral(var, implintlevel)
5233 {
5234 assert( matrix->nentries < matrix->sentries );
5235
5236 matrix->values[matrix->nentries] = objscale * value;
5237 matrix->columns[matrix->nentries] = var;
5238 matrix->rows[matrix->nentries] = "Obj";
5239 matrix->nentries++;
5240 }
5241 }
5242
5243 /* loop over all constraints */
5244 k = nconss;
5245 for( c = 0; c < nconss; ++c )
5246 {
5247 cons = conss[c];
5248 assert( cons != NULL);
5249
5250 /* in case the transformed problems is written only constraint are posted which are enabled in the current node;
5251 * the conss array should only contain relevant constraints
5252 */
5253 assert( !transformed || SCIPconsIsEnabled(cons) );
5254
5255 conshdlr = SCIPconsGetHdlr(cons);
5256 assert( conshdlr != NULL );
5257
5258 conshdlrname = SCIPconshdlrGetName(conshdlr);
5259
5260 /* construct constraint name */
5261 consname = consnames[c];
5262
5263 /* init rhs value to infinity (would then ignored) */
5264 rhss[c] = SCIPinfinity(scip);
5265
5266 if( strcmp(conshdlrname, "linear") == 0 )
5267 {
5268 lhs = SCIPgetLhsLinear(scip, cons);
5269 rhs = SCIPgetRhsLinear(scip, cons);
5270
5271 /* there is nothing to do if the left hand side is minus infinity and the right side is infinity */
5272 if( !SCIPisInfinity(scip, -lhs) || !SCIPisInfinity(scip, rhs) )
5273 {
5274 if( !SCIPisInfinity(scip, -lhs) && !SCIPisInfinity(scip, rhs) && !SCIPisEQ(scip, lhs, rhs) )
5275 needRANGES = TRUE;
5276
5277 /* print row entry */
5278 printRowType(scip, file, lhs, rhs, consname);
5279
5280 if( SCIPisInfinity(scip, rhs) )
5281 rhss[c] = lhs;
5282 else
5283 rhss[c] = rhs;
5284
5285 assert( !SCIPisInfinity(scip, rhss[c]) );
5286
5287 /* compute column entries */
5289 SCIPgetNVarsLinear(scip, cons), transformed, matrix, &rhss[c]) );
5290 }
5291 }
5292 else if( strcmp(conshdlrname, "setppc") == 0 )
5293 {
5294 /* print row entry */
5295 switch( SCIPgetTypeSetppc(scip, cons) )
5296 {
5298 printRowType(scip, file, 1.0, 1.0, consname);
5299 break;
5301 printRowType(scip, file, -SCIPinfinity(scip), 1.0, consname);
5302 break;
5305 break;
5306 }
5307
5308 rhss[c] = 1.0;
5309
5310 /* compute column entries */
5311 SCIP_CALL( getLinearCoeffs(scip, consname, SCIPgetVarsSetppc(scip, cons), NULL, SCIPgetNVarsSetppc(scip, cons), transformed, matrix, &rhss[c]) );
5312 }
5313 else if( strcmp(conshdlrname, "logicor") == 0 )
5314 {
5315 /* print row entry */
5317
5318 rhss[c] = 1.0;
5319
5320 /* compute column entries */
5321 SCIP_CALL( getLinearCoeffs(scip, consname, SCIPgetVarsLogicor(scip, cons), NULL, SCIPgetNVarsLogicor(scip, cons), transformed, matrix, &rhss[c]) );
5322 }
5323 else if( strcmp(conshdlrname, "knapsack") == 0 )
5324 {
5325 int i;
5326
5327 /* print row entry */
5329
5330 nconsvars = SCIPgetNVarsKnapsack(scip, cons);
5331 weights = SCIPgetWeightsKnapsack(scip, cons);
5332
5333 /* copy Longint array to SCIP_Real array */
5334 SCIP_CALL( SCIPallocBufferArray(scip, &vals, nconsvars ) );
5335 for( i = 0; i < nconsvars; ++i )
5336 vals[i] = (SCIP_Real)weights[i];
5337
5338 rhss[c] = (SCIP_Real) SCIPgetCapacityKnapsack(scip, cons);
5339
5340 /* compute column entries */
5341 SCIP_CALL( getLinearCoeffs(scip, consname, SCIPgetVarsKnapsack(scip, cons), vals, nconsvars, transformed, matrix, &rhss[c]) );
5342
5343 SCIPfreeBufferArray(scip, &vals);
5344 }
5345 else if( strcmp(conshdlrname, "varbound") == 0 )
5346 {
5347 lhs = SCIPgetLhsVarbound(scip, cons);
5348 rhs = SCIPgetRhsVarbound(scip, cons);
5349
5350 /* there is nothing to do if the left hand side is minus infinity and the right side is infinity */
5351 if( !SCIPisInfinity(scip, -lhs) || !SCIPisInfinity(scip, rhs) )
5352 {
5353 if( !SCIPisInfinity(scip, -lhs) && !SCIPisInfinity(scip, rhs) && !SCIPisEQ(scip, lhs, rhs) )
5354 needRANGES = TRUE;
5355
5356 /* print row entry */
5357 printRowType(scip, file, lhs, rhs, consname);
5358
5359 /* allocate memory */
5360 SCIP_CALL( SCIPallocBufferArray(scip, &consvars, 2) );
5361 SCIP_CALL( SCIPallocBufferArray(scip, &vals, 2) );
5362
5363 consvars[0] = SCIPgetVarVarbound(scip, cons);
5364 consvars[1] = SCIPgetVbdvarVarbound(scip, cons);
5365
5366 vals[0] = 1.0;
5367 vals[1] = SCIPgetVbdcoefVarbound(scip, cons);
5368
5369 if( SCIPisInfinity(scip, rhs) )
5370 rhss[c] = lhs;
5371 else
5372 rhss[c] = rhs;
5373
5374 assert( !SCIPisInfinity(scip, rhss[c]) );
5375
5376 /* compute column entries */
5377 SCIP_CALL( getLinearCoeffs(scip, consname, consvars, vals, 2, transformed, matrix, &rhss[c]) );
5378
5379 SCIPfreeBufferArray(scip, &vals);
5380 SCIPfreeBufferArray(scip, &consvars);
5381 }
5382 }
5383 else if( strcmp(conshdlrname, "indicator") == 0 )
5384 {
5385 SCIP_VAR* slackvar;
5386 SCIP_VAR* binvar;
5387
5388 /* store slack variable in hash */
5389 slackvar = SCIPgetSlackVarIndicator(cons);
5390 assert( slackvar != NULL );
5391 assert( indicatorSlackHash != NULL );
5392 assert( !SCIPhashtableExists(indicatorSlackHash, (void*) slackvar) );
5393 SCIP_CALL( SCIPhashtableInsert(indicatorSlackHash, (void*) slackvar) );
5394
5395 /* if slackvariable is aggregated, we store it in the list of aggregated variables */
5397 {
5398 SCIP_CALL( collectAggregatedVars(scip, &slackvar, 1, &aggvars, &naggvars, &saggvars, varFixedHash) );
5399 }
5400
5401 /* store aggregated variables */
5402 binvar = SCIPgetBinaryVarIndicator(cons);
5403 if( SCIPvarIsNegated(binvar) )
5404 binvar = SCIPvarGetNegatedVar(binvar);
5405 assert( binvar != NULL );
5406 SCIP_CALL( collectAggregatedVars(scip, &binvar, 1, &aggvars, &naggvars, &saggvars, varFixedHash) );
5407
5408 /* indicator constraint do not have a right hand side; mark this with SCIPinfinity(scip) */
5409 rhss[c] = SCIPinfinity(scip);
5410
5411 /* store constraint */
5412 consIndicator[nConsIndicator++] = cons;
5413 continue;
5414 }
5415 else if( strcmp(conshdlrname, "SOS1") == 0 )
5416 {
5417 /* store constraint */
5418 consSOS1[nConsSOS1++] = cons;
5419
5420 /* check for aggregated variables in SOS1 constraints for later output
5421 * of aggregations as linear constraints */
5422 consvars = SCIPgetVarsSOS1(scip, cons);
5423 nconsvars = SCIPgetNVarsSOS1(scip, cons);
5424
5425 /* SOS constraint do not have a right hand side; mark this with SCIPinfinity(scip) */
5426 rhss[c] = SCIPinfinity(scip);
5427
5428 SCIP_CALL( collectAggregatedVars(scip, consvars, nconsvars, &aggvars, &naggvars, &saggvars, varFixedHash) );
5429 }
5430 else if( strcmp(conshdlrname, "SOS2") == 0 )
5431 {
5432 /* store constraint */
5433 consSOS2[nConsSOS2++] = cons;
5434
5435 /* check for aggregated variables in SOS2 constraints for later output aggregations as linear constraints */
5436 consvars = SCIPgetVarsSOS2(scip, cons);
5437 nconsvars = SCIPgetNVarsSOS2(scip, cons);
5438
5439 /* SOS constraint do not have a right hand side; mark this with SCIPinfinity(scip) */
5440 rhss[c] = SCIPinfinity(scip);
5441
5442 SCIP_CALL( collectAggregatedVars(scip, consvars, nconsvars, &aggvars, &naggvars, &saggvars, varFixedHash) );
5443 }
5444 else if( strcmp(conshdlrname, "nonlinear") == 0 )
5445 {
5446 SCIP_EXPR* expr;
5447 SCIP_VAR** quadvars;
5448 SCIP_Real* quadvarlincoefs;
5449 SCIP_Real* lincoefs;
5450 SCIP_Real constant;
5451 SCIP_EXPR** linexprs;
5452 SCIP_Bool isquadratic;
5453 int nquadexprs;
5454 int nlinexprs;
5455 int j;
5456
5457 /* check if it is a quadratic constraint */
5458 expr = SCIPgetExprNonlinear(cons);
5459 SCIP_CALL( SCIPcheckExprQuadratic(scip, expr, &isquadratic) );
5460 if( !isquadratic || !SCIPexprAreQuadraticExprsVariables(expr) )
5461 {
5462 SCIP_EXPR* exprcopy;
5463 SCIP_Bool changed;
5464 SCIP_Bool infeasible;
5465
5466 SCIP_CALL( SCIPduplicateExpr(scip, expr, &exprcopy, NULL, NULL, NULL, NULL) );
5467 SCIP_CALL( SCIPsimplifyExpr(scip, exprcopy, &expr, &changed, &infeasible, NULL, NULL) );
5468 SCIP_CALL( SCIPreleaseExpr(scip, &exprcopy) );
5469 /* the corresponding releaseExpr is in the writing of the QCMATRIX sections at the end */
5470 if( changed && !infeasible )
5471 {
5472 SCIP_CALL( SCIPcheckExprQuadratic(scip, expr, &isquadratic) );
5473 isquadratic &= SCIPexprAreQuadraticExprsVariables(expr);
5474 }
5475 }
5476
5477 if( !isquadratic )
5478 {
5479 /* unknown constraint type; mark this with SCIPinfinity(scip) */
5480 rhss[c] = SCIPinfinity(scip);
5481
5482 SCIPwarningMessage(scip, "nonlinear constraint <%s> not recognized as quadratic: cannot print as MPS\n", SCIPconsGetName(cons));
5483 if( expr != SCIPgetExprNonlinear(cons) )
5484 {
5485 SCIP_CALL( SCIPreleaseExpr(scip, &expr) );
5486 }
5487 continue;
5488 }
5489
5490 /* store constraint and corresponding expression (may be the simplified one) */
5491 consQuadratic[nConsQuadratic] = cons;
5492 exprQuadratic[nConsQuadratic] = expr;
5493 ++nConsQuadratic;
5494
5495 /* collect linear coefficients of quadratic part */
5496 SCIPexprGetQuadraticData(expr, &constant, &nlinexprs, &linexprs, &lincoefs, &nquadexprs, NULL, NULL,
5497 NULL);
5498
5499 SCIP_CALL( SCIPallocBufferArray(scip, &quadvars, nquadexprs) );
5500 SCIP_CALL( SCIPallocBufferArray(scip, &quadvarlincoefs, nquadexprs) );
5501 for( j = 0; j < nquadexprs; ++j )
5502 {
5503 SCIP_EXPR* qexpr;
5504
5505 SCIPexprGetQuadraticQuadTerm(expr, j, &qexpr, &quadvarlincoefs[j], NULL, NULL, NULL, NULL);
5506
5507 assert(SCIPisExprVar(scip, qexpr));
5508 quadvars[j] = SCIPgetVarExprVar(qexpr);
5509 }
5510
5511 lhs = SCIPgetLhsNonlinear(cons);
5512 rhs = SCIPgetRhsNonlinear(cons);
5513
5514 /* correct side by constant */
5515 lhs -= SCIPisInfinity(scip, -lhs) ? 0.0 : constant;
5516 rhs -= SCIPisInfinity(scip, rhs) ? 0.0 : constant;
5517
5518 /* there is nothing to do if the left hand side is minus infinity and the right side is infinity */
5519 if( !SCIPisInfinity(scip, -lhs) || !SCIPisInfinity(scip, rhs) )
5520 {
5521 SCIP_VAR** linvars;
5522
5523 if( !SCIPisInfinity(scip, -lhs) && !SCIPisInfinity(scip, rhs) && !SCIPisEQ(scip, lhs, rhs) )
5524 needRANGES = TRUE;
5525
5526 /* print row entry */
5527 printRowType(scip, file, lhs, rhs, consname);
5528
5529 if( SCIPisInfinity(scip, rhs) )
5530 rhss[c] = lhs;
5531 else
5532 rhss[c] = rhs;
5533
5534 assert( !SCIPisInfinity(scip, rhss[c]) );
5535
5536 /* get linear vars */
5537 SCIP_CALL( SCIPallocBufferArray(scip, &linvars, nlinexprs) );
5538 for( j = 0; j < nlinexprs; ++j )
5539 linvars[j] = SCIPgetVarExprVar(linexprs[j]);
5540
5541 /* compute column entries for linear part */
5542 SCIP_CALL( getLinearCoeffs(scip, consname, linvars, lincoefs, nlinexprs, transformed, matrix, &rhss[c]) );
5543
5544 /* compute column entries for linear part in quadratic part */
5545 SCIP_CALL( getLinearCoeffs(scip, consname, quadvars, quadvarlincoefs, nquadexprs, transformed, matrix,
5546 &rhss[c]) );
5547
5548 SCIPfreeBufferArray(scip, &linvars);
5549 }
5550
5551 /* check for aggregated variables in quadratic part of quadratic constraints for later output of
5552 * aggregations as linear constraints */
5553 consvars = quadvars;
5554 nconsvars = nquadexprs;
5555
5556 SCIP_CALL( collectAggregatedVars(scip, consvars, nconsvars, &aggvars, &naggvars, &saggvars, varFixedHash) );
5557
5558 SCIPfreeBufferArray(scip, &quadvars);
5559 SCIPfreeBufferArray(scip, &quadvarlincoefs);
5560 }
5561 else if( strcmp(conshdlrname, "and") == 0 )
5562 {
5563 if( readerdata->linearizeands )
5564 {
5565 SCIP_VAR** rowvars;
5566 SCIP_VAR** operands;
5567 SCIP_VAR* resultant;
5568 SCIP_Real* rowvals;
5569 char* rowname;
5570 int nrowvars;
5571 int l;
5572 int n;
5573
5574 nrowvars = SCIPgetNVarsAnd(scip, cons);
5575 operands = SCIPgetVarsAnd(scip, cons);
5576 resultant = SCIPgetResultantAnd(scip, cons);
5577
5578 /* allocate buffer array */
5579 SCIP_CALL( SCIPallocBufferArray(scip, &rowvars, nrowvars + 1) );
5580 SCIP_CALL( SCIPallocBufferArray(scip, &rowvals, nrowvars + 1) );
5581
5582 /* get length of constraint name */
5583 l = (int) strlen(consname);
5584
5585 /* the tight relaxtion, number of and-constraint operands rows */
5586 if( !readerdata->aggrlinearizationands )
5587 {
5588 rowvars[0] = resultant;
5589 rowvals[0] = 1.0;
5590 rowvals[1] = -1.0;
5591
5592 /* compute maximal length for rowname */
5593 /* coverity[negative_returns] */
5594 n = (int) log10((double)nrowvars) + 1 + l;
5595
5596 /* assure maximal allowed value */
5597 if( n >= MPS_MAX_NAMELEN )
5598 n = MPS_MAX_NAMELEN - 1;
5599
5600 /* update maxnamelen */
5601 maxnamelen = MAX(maxnamelen, (unsigned int) n);
5602
5603 /* print operator rows */
5604 for( v = 0; v < nrowvars; ++v )
5605 {
5606 /* compute maximal length for rowname */
5607 if( v == 0 )
5608 n = 2;
5609 else
5610 n = (int) log10((double)v) + 2;
5611 n += l;
5612
5613 /* assure maximal allowed value */
5614 if( n >= MPS_MAX_NAMELEN )
5615 {
5616 n = MPS_MAX_NAMELEN - 1;
5617 ++faulty;
5618 }
5619
5620 /* need memory for additional row */
5621 SCIP_CALL( SCIPallocBufferArray(scip, &rowname, n + 1) );
5622
5623 assert(k < nconss + naddrows);
5624 consnames[k] = rowname;
5625
5626 (void) SCIPsnprintf(rowname, n + 1, "%s_%d", consname, v);
5627 rowvars[1] = operands[v];
5628
5629 /* print row entry */
5630 printRowType(scip, file, -SCIPinfinity(scip), 0.0, rowname);
5631
5632 rhss[k] = 0.0;
5633
5634 /* compute column entries */
5635 SCIP_CALL( getLinearCoeffs(scip, rowname, rowvars, rowvals, 2, transformed, matrix, &rhss[k]) );
5636 ++k;
5637 }
5638 }
5639
5640 /* prepare for next row */
5641 for( v = nrowvars - 1; v >= 0; --v )
5642 {
5643 rowvars[v] = operands[v];
5644 rowvals[v] = -1.0;
5645 }
5646
5647 rowvars[nrowvars] = resultant;
5648
5649 /* the weak relaxtion, only one constraint */
5650 if( readerdata->aggrlinearizationands )
5651 {
5652 /* compute maximal length for rowname */
5653 n = l + 3;
5654
5655 /* assure maximal allowed value */
5656 if( n >= MPS_MAX_NAMELEN )
5657 {
5658 n = MPS_MAX_NAMELEN - 1;
5659 ++faulty;
5660 }
5661
5662 /* update maxnamelen */
5663 maxnamelen = MAX(maxnamelen, (unsigned int) n);
5664
5665 /* need memory for additional row */
5666 SCIP_CALL( SCIPallocBufferArray(scip, &rowname, n + 1) );
5667
5668 assert(k < nconss + naddrows);
5669 consnames[k] = rowname;
5670
5671 /* adjust rowname of constraint */
5672 (void) SCIPsnprintf(rowname, n + 1, "%s_op", consname);
5673
5674 rowvals[nrowvars] = (SCIP_Real) nrowvars;
5675
5676 /* print row entry */
5677 printRowType(scip, file, -SCIPinfinity(scip), 0.0, rowname);
5678
5679 rhss[k] = 0.0;
5680
5681 /* compute column entries */
5682 SCIP_CALL( getLinearCoeffs(scip, rowname, rowvars, rowvals, nrowvars + 1, transformed, matrix, &rhss[k]) );
5683
5684 SCIPdebugMsg(scip, "%g, %g\n", rowvals[1], rhss[k]);
5685 ++k;
5686 }
5687
5688 rowvals[nrowvars] = 1.0;
5689
5690 /* print row entry */
5691 printRowType(scip, file, -nrowvars + 1.0, SCIPinfinity(scip), consname);
5692
5693 rhss[c] = -nrowvars + 1.0;
5694
5695 /* compute column entries */
5696 SCIP_CALL( getLinearCoeffs(scip, consname, rowvars, rowvals, nrowvars + 1, transformed, matrix, &rhss[c]) );
5697
5698 /* free buffer array */
5699 SCIPfreeBufferArray(scip, &rowvals);
5700 SCIPfreeBufferArray(scip, &rowvars);
5701 }
5702 else
5703 {
5704 /* and constraint printing not enabled; mark this with SCIPinfinity(scip) */
5705 rhss[c] = SCIPinfinity(scip);
5706
5707 SCIPwarningMessage(scip, "change parameter \"reading/" READER_NAME "/linearize-and-constraints\" to TRUE to print and-constraints\n");
5708 }
5709 }
5710 else
5711 {
5712 /* unknown constraint type; mark this with SCIPinfinity(scip) */
5713 rhss[c] = SCIPinfinity(scip);
5714
5715 SCIPwarningMessage(scip, "constraint handler <%s> cannot print requested format\n", conshdlrname );
5716 }
5717 }
5718
5719 if( faulty > 0 )
5720 {
5721 SCIPwarningMessage(scip, "there are %d and-constraint-rownames which have to be cut down to %d characters; MPS file might be corrupted\n",
5722 faulty, MPS_MAX_NAMELEN - 1);
5723 }
5724
5725 /* free hash table */
5726 if( varFixedHash != NULL )
5727 SCIPhashtableFree(&varFixedHash);
5728
5729 if( indicatorSlackHash != NULL && nConsIndicator == 0 )
5730 {
5731 SCIPhashtableFree(&indicatorSlackHash);
5732 assert( indicatorSlackHash == NULL );
5733 }
5734
5735 if( naggvars > 0 )
5736 {
5737 /* construct variables name of the needed aggregated variables and the constraint names for the aggregation constraints */
5738
5739 /* realloc memory */
5740 SCIP_CALL( SCIPreallocBufferArray(scip, &consnames, nconss + naddrows + naggvars) );
5741 SCIP_CALL( SCIPreallocBufferArray(scip, &rhss, nconss + naddrows + naggvars) );
5742 SCIP_CALL( SCIPreallocBufferArray(scip, &varnames, nvars + naggvars) );
5743
5744 for( c = 0; c < naggvars; ++c )
5745 {
5746 size_t l;
5747
5748 /* create variable name */
5749 var = aggvars[c];
5750
5751 l = strlen(SCIPvarGetName(var));
5752 if( l >= MPS_MAX_NAMELEN )
5753 maxnamelen = MPS_MAX_NAMELEN - 1;
5754 else
5755 maxnamelen = MAX(maxnamelen, (unsigned int) l);
5756
5758 (void) SCIPsnprintf(namestr, MPS_MAX_NAMELEN, "%s", SCIPvarGetName(var) );
5759
5760 /* insert variable with variable name into hash map */
5761 varnames[nvars + c] = namestr;
5762 assert( !SCIPhashmapExists(varnameHashmap, var) );
5763 SCIP_CALL( SCIPhashmapInsert(varnameHashmap, var, (void*) namestr) );
5764
5765 /* output row type (it is an equation) */
5766 SCIP_CALL( SCIPallocBufferArray(scip, &namestr, MPS_MAX_NAMELEN) ); /* note that namestr above is freed via varnames */
5767 (void) SCIPsnprintf(namestr, MPS_MAX_NAMELEN, "aggr_%s", SCIPvarGetName(var));
5768 printRowType(scip, file, 1.0, 1.0, namestr);
5769
5770 l = strlen(namestr);
5771 maxnamelen = MAX(maxnamelen, (unsigned int) l);
5772 consnames[nconss + naddrows + c] = namestr;
5773 rhss[nconss + naddrows + c] = 0.0;
5774
5775 /* compute column entries */
5776 SCIP_CALL( getLinearCoeffs(scip, namestr, &(aggvars[c]), NULL, 1, transformed, matrix, &rhss[nconss + naddrows + c]) );
5777
5778 /* add the aggregated variables to the sparse matrix */
5780 matrix->values[matrix->nentries] = -1.0;
5781 matrix->columns[matrix->nentries] = aggvars[c];
5782 matrix->rows[matrix->nentries] = namestr;
5783 matrix->nentries++;
5784 }
5785 }
5786
5787 /* collect also fixed variables, because they might not be removed from all constraints */
5788 /* @todo only collect fixed variables in the non-linear constraint types, where they (could not be)/(were not) removed */
5789 if( nfixedvars > 0 )
5790 {
5791 int startpos = nvars + naggvars;
5792 /* construct variables name of fixed variables */
5793
5794 /* realloc memory */
5795 SCIP_CALL( SCIPreallocBufferArray(scip, &varnames, startpos + nfixedvars) );
5796
5797 /* allocate memory for fixed variables */
5798 SCIP_CALL( SCIPallocBufferArray(scip, &fixvars, nfixedvars) );
5799
5800 for( v = nfixedvars - 1; v >= 0; --v )
5801 {
5802 /* create variable name */
5803 var = fixedvars[v];
5804
5806 {
5807 size_t l;
5808 l = strlen(SCIPvarGetName(var));
5809 if( l >= MPS_MAX_NAMELEN )
5810 maxnamelen = MPS_MAX_NAMELEN - 1;
5811 else
5812 maxnamelen = MAX(maxnamelen, (unsigned int) l);
5813
5815 (void) SCIPsnprintf(namestr, MPS_MAX_NAMELEN, "%s", SCIPvarGetName(var) );
5816
5817 varnames[startpos + nfixvars] = namestr;
5818 fixvars[nfixvars] = var;
5819 ++nfixvars;
5820
5821 /* insert variable with variable name into hash map */
5822 assert(!SCIPhashmapExists(varnameHashmap, var));
5823 SCIP_CALL( SCIPhashmapInsert(varnameHashmap, var, (void*) namestr) );
5824
5825 /* add the fixed variables to the sparse matrix, needed for columns section */
5827 matrix->values[matrix->nentries] = 0.0;
5828 matrix->columns[matrix->nentries] = var;
5829 matrix->rows[matrix->nentries] = "Obj";
5830 matrix->nentries++;
5831 }
5832 }
5833 }
5834
5835 /* output COLUMNS section */
5836 printColumnSection(scip, file, matrix, varnameHashmap, indicatorSlackHash, maxnamelen, implintlevel);
5837
5838 /* output RHS section */
5839 printRhsSection(scip, file, nconss + naddrows +naggvars, consnames, rhss, maxnamelen, objscale * objoffset);
5840
5841 /* output RANGES section */
5842 if( needRANGES )
5843 printRangeSection(scip, file, conss, nconss, consnames, transformed, maxnamelen);
5844
5845 /* output BOUNDS section */
5846 printBoundSection(scip, file, vars, nvars, aggvars, naggvars, fixvars, nfixvars, transformed, varnames, indicatorSlackHash, maxnamelen);
5847
5848 if( nfixedvars > 0 )
5849 {
5850 SCIPfreeBufferArray(scip, &fixvars);
5851 }
5852
5853 /* print SOS section */
5854 if( nConsSOS1 > 0 || nConsSOS2 > 0 )
5855 {
5856 SCIP_Real* sosweights;
5857
5858 SCIPinfoMessage(scip, file, "SOS\n");
5859 SCIPdebugMsg(scip, "start printing SOS section\n");
5860
5862
5863 /* first output SOS1 constraints */
5864 for( c = 0; c < nConsSOS1; ++c )
5865 {
5866 cons = consSOS1[c];
5867 consvars = SCIPgetVarsSOS1(scip, cons);
5868 nconsvars = SCIPgetNVarsSOS1(scip, cons);
5869 sosweights = SCIPgetWeightsSOS1(scip, cons);
5870 (void) SCIPsnprintf(namestr, MPS_MAX_NAMELEN, "%s", SCIPconsGetName(cons) );
5871
5872 printStart(scip, file, "S1", namestr, -1);
5873 SCIPinfoMessage(scip, file, "\n");
5874
5875 for( v = 0; v < nconsvars; ++v )
5876 {
5877 /* get variable name */
5878 assert ( SCIPhashmapExists(varnameHashmap, consvars[v]) );
5879 varname = (const char*) SCIPhashmapGetImage(varnameHashmap, consvars[v]);
5880
5881 printStart(scip, file, "", varname, (int) maxnamelen);
5882
5883 if( sosweights != NULL )
5884 (void) SCIPsnprintf(valuestr, MPS_MAX_VALUELEN, "%25.15g", sosweights[v]);
5885 else
5886 (void) SCIPsnprintf(valuestr, MPS_MAX_VALUELEN, "%25d ", v);
5887
5888 SCIPinfoMessage(scip, file, "%25s\n", valuestr);
5889 }
5890 }
5891
5892 /* next output SOS2 constraints */
5893 for( c = 0; c < nConsSOS2; ++c )
5894 {
5895 cons = consSOS2[c];
5896 consvars = SCIPgetVarsSOS2(scip, cons);
5897 nconsvars = SCIPgetNVarsSOS2(scip, cons);
5898 sosweights = SCIPgetWeightsSOS2(scip, cons);
5899 (void) SCIPsnprintf(namestr, MPS_MAX_NAMELEN, "%s", SCIPconsGetName(cons) );
5900
5901 printStart(scip, file, "S2", namestr, -1);
5902 SCIPinfoMessage(scip, file, "\n");
5903
5904 for( v = 0; v < nconsvars; ++v )
5905 {
5906 /* get variable name */
5907 assert ( SCIPhashmapExists(varnameHashmap, consvars[v]) );
5908 varname = (const char*) SCIPhashmapGetImage(varnameHashmap, consvars[v]);
5909
5910 printStart(scip, file, "", varname, (int) maxnamelen);
5911
5912 if( sosweights != NULL )
5913 (void) SCIPsnprintf(valuestr, MPS_MAX_VALUELEN, "%25.15g", sosweights[v]);
5914 else
5915 (void) SCIPsnprintf(valuestr, MPS_MAX_VALUELEN, "%25d ", v);
5916
5917 SCIPinfoMessage(scip, file, "%25s\n", valuestr);
5918 }
5919 }
5920 SCIPfreeBufferArray(scip, &namestr);
5921 }
5922
5923 /* print QCMATRIX sections for quadratic constraints
5924 * in difference to a quadratic term in the objective function, the quadratic part is not divided by 2 here
5925 */
5926 if( nConsQuadratic > 0 )
5927 {
5928 const char* varname2;
5929 int nbilin;
5930
5931 SCIPdebugMsg(scip, "start printing QCMATRIX sections for quadratic constraints\n");
5933
5934 for( c = 0; c < nConsQuadratic; ++c )
5935 {
5936 SCIP_EXPR* expr;
5937
5938 cons = consQuadratic[c];
5939 expr = exprQuadratic[c];
5940
5941 SCIPexprGetQuadraticData(expr, NULL, NULL, NULL, NULL, &nconsvars, &nbilin, NULL, NULL);
5942
5943 (void) SCIPsnprintf(namestr, MPS_MAX_NAMELEN, "%s", SCIPconsGetName(cons) );
5944
5945 SCIPinfoMessage(scip, file, "QCMATRIX %s\n", namestr);
5946
5947 /* print x^2 terms */
5948 for( v = 0; v < nconsvars; ++v )
5949 {
5950 SCIP_EXPR* qexpr;
5951 SCIP_VAR* qvar;
5952 SCIP_Real sqrcoef;
5953
5954 SCIPexprGetQuadraticQuadTerm(expr, v, &qexpr, NULL, &sqrcoef, NULL, NULL, NULL);
5955 if( sqrcoef == 0.0 )
5956 continue;
5957
5958 assert(SCIPisExprVar(scip, qexpr));
5959 qvar = SCIPgetVarExprVar(qexpr);
5960
5961 /* get variable name */
5962 assert(SCIPhashmapExists(varnameHashmap, qvar));
5963 varname = (const char*) SCIPhashmapGetImage(varnameHashmap, qvar);
5964
5965 /* get coefficient as string */
5966 (void) SCIPsnprintf(valuestr, MPS_MAX_VALUELEN, "%25.15g", sqrcoef);
5967
5968 /* print "x x coeff" line */
5969 printStart(scip, file, "", varname, (int) maxnamelen);
5970 printRecord(scip, file, varname, valuestr, maxnamelen);
5971 SCIPinfoMessage(scip, file, "\n");
5972 }
5973
5974 /* print bilinear terms; CPLEX format expects a symmetric matrix with all coefficients specified,
5975 * i.e., we have to split bilinear coefficients into two off diagonal elements */
5976 for( v = 0; v < nbilin; ++v )
5977 {
5978 SCIP_EXPR* expr1;
5979 SCIP_EXPR* expr2;
5980 SCIP_VAR* var1;
5981 SCIP_VAR* var2;
5982 SCIP_Real coef;
5983
5984 SCIPexprGetQuadraticBilinTerm(expr, v, &expr1, &expr2, &coef, NULL, NULL);
5985 assert(SCIPisExprVar(scip, expr1));
5986 assert(SCIPisExprVar(scip, expr2));
5987
5988 if( coef == 0.0 )
5989 continue;
5990
5991 var1 = SCIPgetVarExprVar(expr1);
5992 var2 = SCIPgetVarExprVar(expr2);
5993
5994 /* get name of first variable */
5995 assert ( SCIPhashmapExists(varnameHashmap, var1) );
5996 varname = (const char*) SCIPhashmapGetImage(varnameHashmap, var1);
5997
5998 /* get name of second variable */
5999 assert ( SCIPhashmapExists(varnameHashmap, var2) );
6000 varname2 = (const char*) SCIPhashmapGetImage(varnameHashmap, var2);
6001
6002 /* get coefficient as string */
6003 (void) SCIPsnprintf(valuestr, MPS_MAX_VALUELEN, "%25.15g", 0.5*coef);
6004
6005 /* print "x y coeff/2" line */
6006 printStart(scip, file, "", varname, (int) maxnamelen);
6007 printRecord(scip, file, varname2, valuestr, maxnamelen);
6008 SCIPinfoMessage(scip, file, "\n");
6009
6010 /* print "y x coeff/2" line */
6011 printStart(scip, file, "", varname2, (int) maxnamelen);
6012 printRecord(scip, file, varname, valuestr, maxnamelen);
6013 SCIPinfoMessage(scip, file, "\n");
6014 }
6015
6016 if( expr != SCIPgetExprNonlinear(cons) )
6017 {
6018 SCIP_CALL( SCIPreleaseExpr(scip, &expr) );
6019 }
6020 }
6021
6022 SCIPfreeBufferArray(scip, &namestr);
6023 }
6024
6025 /* print indicator section */
6026 if( nConsIndicator > 0 )
6027 {
6029
6030 SCIPinfoMessage(scip, file, "INDICATORS\n");
6031 SCIPdebugMsg(scip, "start printing INDICATOR section\n");
6032
6033 /* output each indicator constraint */
6034 for( c = 0; c < nConsIndicator; ++c )
6035 {
6036 SCIP_CONS* lincons;
6037 SCIP_VAR* slackvar;
6038 SCIP_VAR* binvar;
6039
6040 cons = consIndicator[c];
6041 binvar = SCIPgetBinaryVarIndicator(cons);
6042 lincons = SCIPgetLinearConsIndicator(cons);
6043 slackvar = SCIPgetSlackVarIndicator(cons);
6044
6045 /* linvars always contains slack variable, thus nlinvars >= 1 */
6046 if( SCIPgetNVarsLinear(scip, lincons) <= 1 || SCIPconsIsDeleted(lincons) )
6047 continue;
6048
6049 /* create variable and value strings */
6050 if( SCIPvarIsNegated(binvar) )
6051 {
6052 (void) SCIPsnprintf(valuestr, MPS_MAX_VALUELEN, "%25d", 0);
6053 assert( SCIPvarGetNegatedVar(binvar) != NULL );
6054 assert( SCIPhashmapExists(varnameHashmap, SCIPvarGetNegatedVar(binvar)) );
6055 varname = (const char*) SCIPhashmapGetImage(varnameHashmap, SCIPvarGetNegatedVar(binvar));
6056 }
6057 else
6058 {
6059 (void) SCIPsnprintf(valuestr, MPS_MAX_VALUELEN, "%25d", 1);
6060 assert ( SCIPhashmapExists(varnameHashmap, binvar) );
6061 varname = (const char*) SCIPhashmapGetImage(varnameHashmap, binvar);
6062 }
6063
6064 /* write records */
6066 {
6067 /* for aggregated variables output name of aggregating constraint */
6068 (void) SCIPsnprintf(namestr, MPS_MAX_NAMELEN, "aggr_%s", SCIPvarGetName(slackvar));
6069 printStart(scip, file, "IF", namestr, (int) maxnamelen);
6070 printRecord(scip, file, varname, valuestr, maxnamelen);
6071 SCIPinfoMessage(scip, file, "\n");
6072 }
6073 else
6074 {
6075 printStart(scip, file, "IF", SCIPconsGetName(lincons), (int) maxnamelen);
6076 printRecord(scip, file, varname, valuestr, maxnamelen);
6077 SCIPinfoMessage(scip, file, "\n");
6078 }
6079 }
6080 SCIPfreeBufferArray(scip, &namestr);
6081 }
6082
6083 /* free matrix data structure */
6084 freeMatrix(scip, matrix);
6085
6086 /* free slackvar hashtable */
6087 if( indicatorSlackHash != NULL )
6088 SCIPhashtableFree(&indicatorSlackHash);
6089
6090 /* free variable hashmap */
6091 SCIPhashmapFree(&varnameHashmap);
6092
6093 SCIPfreeBlockMemoryArray(scip, &aggvars, saggvars);
6094 SCIPfreeBufferArray(scip, &rhss);
6095
6096 /* free buffer arrays for SOS1, SOS2, and quadratic */
6097 SCIPfreeBufferArray(scip, &consIndicator);
6098 SCIPfreeBufferArray(scip, &exprQuadratic);
6099 SCIPfreeBufferArray(scip, &consQuadratic);
6100 SCIPfreeBufferArray(scip, &consSOS2);
6101 SCIPfreeBufferArray(scip, &consSOS1);
6102
6103 /* free variable and constraint name array */
6104 for( v = nvars + naggvars + nfixvars - 1; v >= 0; --v )
6105 SCIPfreeBufferArray(scip, &varnames[v]);
6106 SCIPfreeBufferArray(scip, &varnames);
6107
6108 for( c = nconss + naddrows + naggvars - 1; c >= 0; --c )
6109 SCIPfreeBufferArray(scip, &consnames[c]);
6110 SCIPfreeBufferArray(scip, &consnames);
6111
6112 /* print end of data line */
6113 SCIPinfoMessage(scip, file, "ENDATA");
6114
6116
6117 return SCIP_OKAY;
6118}
static long * number
Constraint handler for AND constraints, .
constraint handler for bound disjunction constraints
Constraint handler for linear constraints in their most general form, .
constraint handler for indicator constraints
Constraint handler for knapsack constraints of the form , x binary and .
Constraint handler for linear constraints in their most general form, .
Constraint handler for logicor constraints (equivalent to set covering, but algorithms are suited fo...
constraint handler for nonlinear constraints specified by algebraic expressions
Constraint handler for the set partitioning / packing / covering constraints .
constraint handler for SOS type 1 constraints
constraint handler for SOS type 2 constraints
Constraint handler for variable bound constraints .
#define NULL
Definition def.h:257
#define SCIP_MAXSTRLEN
Definition def.h:278
#define SCIP_Longint
Definition def.h:150
#define SCIP_Bool
Definition def.h:100
#define MIN(x, y)
Definition def.h:233
#define SCIP_STRINGEQ(name, reference, retcode)
Definition def.h:454
#define SCIP_Real
Definition def.h:165
#define SCIP_HASHSIZE_NAMES
Definition def.h:289
#define TRUE
Definition def.h:102
#define FALSE
Definition def.h:103
#define MAX(x, y)
Definition def.h:229
#define SCIP_CALL_TERMINATE(retcode, x, TERM)
Definition def.h:385
#define SCIPABORT()
Definition def.h:336
#define REALABS(x)
Definition def.h:191
#define SCIP_CALL(x)
Definition def.h:364
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
int SCIPgetNVarsKnapsack(SCIP *scip, SCIP_CONS *cons)
SCIP_RETCODE SCIPchgLhsExactLinear(SCIP *scip, SCIP_CONS *cons, SCIP_RATIONAL *lhs)
SCIP_Real SCIPgetVbdcoefVarbound(SCIP *scip, SCIP_CONS *cons)
SCIP_RATIONAL * SCIPgetLhsExactLinear(SCIP *scip, SCIP_CONS *cons)
int SCIPgetNVarsLogicor(SCIP *scip, SCIP_CONS *cons)
SCIP_Real SCIPgetRhsLinear(SCIP *scip, SCIP_CONS *cons)
SCIP_VAR ** SCIPgetVarsLinear(SCIP *scip, SCIP_CONS *cons)
SCIP_RETCODE SCIPchgRhsLinear(SCIP *scip, SCIP_CONS *cons, SCIP_Real rhs)
SCIP_RATIONAL * SCIPgetRhsExactLinear(SCIP *scip, SCIP_CONS *cons)
SCIP_RETCODE SCIPchgRhsExactLinear(SCIP *scip, SCIP_CONS *cons, SCIP_RATIONAL *rhs)
SCIP_RETCODE SCIPcreateConsExactLinear(SCIP *scip, SCIP_CONS **cons, const char *name, int nvars, SCIP_VAR **vars, SCIP_RATIONAL **vals, SCIP_RATIONAL *lhs, SCIP_RATIONAL *rhs, SCIP_Bool initial, SCIP_Bool separate, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool propagate, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool dynamic, SCIP_Bool removable, SCIP_Bool stickingatnode)
SCIP_Real * SCIPgetWeightsSOS2(SCIP *scip, SCIP_CONS *cons)
Definition cons_sos2.c:2791
SCIP_VAR ** SCIPgetVarsSOS2(SCIP *scip, SCIP_CONS *cons)
Definition cons_sos2.c:2771
SCIP_RETCODE SCIPaddCoefLinear(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *var, SCIP_Real val)
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:5238
SCIP_RETCODE SCIPaddVarSOS1(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *var, SCIP_Real weight)
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)
SCIP_RETCODE SCIPaddCoefExactLinear(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *var, SCIP_RATIONAL *val)
SCIP_VAR * SCIPgetVbdvarVarbound(SCIP *scip, SCIP_CONS *cons)
int SCIPgetNVarsSetppc(SCIP *scip, SCIP_CONS *cons)
int SCIPgetNVarsSOS2(SCIP *scip, SCIP_CONS *cons)
Definition cons_sos2.c:2751
SCIP_Real * SCIPgetWeightsSOS1(SCIP *scip, SCIP_CONS *cons)
SCIP_VAR ** SCIPgetVarsSetppc(SCIP *scip, SCIP_CONS *cons)
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)
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:2597
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)
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:5218
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)
SCIP_RETCODE SCIPcreateConsIndicatorLinConsPure(SCIP *scip, SCIP_CONS **cons, const char *name, SCIP_VAR *binvar, SCIP_CONS *lincons, SCIP_Bool initial, SCIP_Bool separate, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool propagate, SCIP_Bool local, SCIP_Bool dynamic, SCIP_Bool removable, SCIP_Bool stickingatnode)
SCIP_RETCODE SCIPchgLhsLinear(SCIP *scip, SCIP_CONS *cons, SCIP_Real lhs)
int SCIPgetNVarsSOS1(SCIP *scip, SCIP_CONS *cons)
SCIP_Real SCIPgetLhsNonlinear(SCIP_CONS *cons)
SCIP_RETCODE SCIPaddVarSOS2(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *var, SCIP_Real weight)
Definition cons_sos2.c:2706
@ 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 SCIPwriteMps(SCIP *scip, SCIP_READER *reader, FILE *file, const char *name, SCIP_Bool transformed, SCIP_OBJSENSE objsense, SCIP_Real objoffset, SCIP_Real objscale, SCIP_RATIONAL *objoffsetexact, SCIP_RATIONAL *objscaleexact, SCIP_VAR **vars, int nvars, int nbinvars, int nintvars, int nimplvars, int ncontvars, SCIP_VAR **fixedvars, int nfixedvars, SCIP_CONS **conss, int nconss, SCIP_RESULT *result)
SCIP_RETCODE SCIPreadMps(SCIP *scip, SCIP_READER *reader, const char *filename, SCIP_RESULT *result, const char ***varnames, const char ***consnames, int *varnamessize, int *consnamessize, int *nvarnames, int *nconsnames)
SCIP_RETCODE SCIPincludeReaderMps(SCIP *scip)
SCIP_RETCODE SCIPaddVar(SCIP *scip, SCIP_VAR *var)
Definition scip_prob.c:1907
SCIP_RETCODE SCIPaddCons(SCIP *scip, SCIP_CONS *cons)
Definition scip_prob.c:3274
SCIP_RETCODE SCIPdelCons(SCIP *scip, SCIP_CONS *cons)
Definition scip_prob.c:3420
SCIP_RETCODE SCIPprintTransProblem(SCIP *scip, FILE *file, const char *extension, SCIP_Bool genericnames)
Definition scip_prob.c:696
SCIP_RETCODE SCIPprintOrigProblem(SCIP *scip, FILE *file, const char *extension, SCIP_Bool genericnames)
Definition scip_prob.c:652
SCIP_RETCODE SCIPsetObjsense(SCIP *scip, SCIP_OBJSENSE objsense)
Definition scip_prob.c:1417
SCIP_RETCODE SCIPaddOrigObjoffset(SCIP *scip, SCIP_Real addval)
Definition scip_prob.c:1486
SCIP_RETCODE SCIPcreateProb(SCIP *scip, const char *name, SCIP_DECL_PROBDELORIG((*probdelorig)), SCIP_DECL_PROBTRANS((*probtrans)), SCIP_DECL_PROBDELTRANS((*probdeltrans)), SCIP_DECL_PROBINITSOL((*probinitsol)), SCIP_DECL_PROBEXITSOL((*probexitsol)), SCIP_DECL_PROBCOPY((*probcopy)), SCIP_PROBDATA *probdata)
Definition scip_prob.c:119
SCIP_VAR * SCIPfindVar(SCIP *scip, const char *name)
Definition scip_prob.c:3189
SCIP_CONS * SCIPfindCons(SCIP *scip, const char *name)
Definition scip_prob.c:3525
void SCIPhashmapFree(SCIP_HASHMAP **hashmap)
Definition misc.c:3095
void * SCIPhashmapGetImage(SCIP_HASHMAP *hashmap, void *origin)
Definition misc.c:3284
SCIP_RETCODE SCIPhashmapInsert(SCIP_HASHMAP *hashmap, void *origin, void *image)
Definition misc.c:3143
SCIP_RETCODE SCIPhashmapCreate(SCIP_HASHMAP **hashmap, BMS_BLKMEM *blkmem, int mapsize)
Definition misc.c:3061
SCIP_Bool SCIPhashmapExists(SCIP_HASHMAP *hashmap, void *origin)
Definition misc.c:3466
void SCIPhashtableFree(SCIP_HASHTABLE **hashtable)
Definition misc.c:2348
SCIP_Bool SCIPhashtableExists(SCIP_HASHTABLE *hashtable, void *element)
Definition misc.c:2647
SCIP_RETCODE SCIPhashtableCreate(SCIP_HASHTABLE **hashtable, BMS_BLKMEM *blkmem, int tablesize, SCIP_DECL_HASHGETKEY((*hashgetkey)), SCIP_DECL_HASHKEYEQ((*hashkeyeq)), SCIP_DECL_HASHKEYVAL((*hashkeyval)), void *userptr)
Definition misc.c:2298
void * SCIPhashtableRetrieve(SCIP_HASHTABLE *hashtable, void *key)
Definition misc.c:2596
SCIP_RETCODE SCIPhashtableInsert(SCIP_HASHTABLE *hashtable, void *element)
Definition misc.c:2535
void SCIPinfoMessage(SCIP *scip, FILE *file, const char *formatstr,...)
void SCIPverbMessage(SCIP *scip, SCIP_VERBLEVEL msgverblevel, FILE *file, const char *formatstr,...)
#define SCIPdebugMsg
void SCIPwarningMessage(SCIP *scip, const char *formatstr,...)
SCIP_RETCODE SCIPgetBoolParam(SCIP *scip, const char *name, SCIP_Bool *value)
Definition scip_param.c:250
SCIP_RETCODE SCIPaddBoolParam(SCIP *scip, const char *name, const char *desc, SCIP_Bool *valueptr, SCIP_Bool isadvanced, SCIP_Bool defaultvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
Definition scip_param.c:57
SCIP_RETCODE SCIPgetIntParam(SCIP *scip, const char *name, int *value)
Definition scip_param.c:269
const char * SCIPconshdlrGetName(SCIP_CONSHDLR *conshdlr)
Definition cons.c:4320
SCIP_CONSHDLR * SCIPfindConshdlr(SCIP *scip, const char *name)
Definition scip_cons.c:940
SCIP_Bool SCIPconsIsDynamic(SCIP_CONS *cons)
Definition cons.c:8652
SCIP_CONSHDLR * SCIPconsGetHdlr(SCIP_CONS *cons)
Definition cons.c:8413
SCIP_Bool SCIPconsIsInitial(SCIP_CONS *cons)
Definition cons.c:8562
SCIP_Bool SCIPconsIsChecked(SCIP_CONS *cons)
Definition cons.c:8592
SCIP_Bool SCIPconsIsDeleted(SCIP_CONS *cons)
Definition cons.c:8522
SCIP_Bool SCIPconsIsEnforced(SCIP_CONS *cons)
Definition cons.c:8582
SCIP_Bool SCIPconsIsPropagated(SCIP_CONS *cons)
Definition cons.c:8612
SCIP_Bool SCIPconsIsLocal(SCIP_CONS *cons)
Definition cons.c:8632
SCIP_Bool SCIPconsIsEnabled(SCIP_CONS *cons)
Definition cons.c:8490
const char * SCIPconsGetName(SCIP_CONS *cons)
Definition cons.c:8393
SCIP_Bool SCIPconsIsModifiable(SCIP_CONS *cons)
Definition cons.c:8642
SCIP_RETCODE SCIPreleaseCons(SCIP *scip, SCIP_CONS **cons)
Definition scip_cons.c:1173
SCIP_Bool SCIPconsIsSeparated(SCIP_CONS *cons)
Definition cons.c:8572
SCIP_Bool SCIPconsIsRemovable(SCIP_CONS *cons)
Definition cons.c:8662
SCIP_Bool SCIPisExact(SCIP *scip)
Definition scip_exact.c:193
void SCIPexprGetQuadraticBilinTerm(SCIP_EXPR *expr, int termidx, SCIP_EXPR **expr1, SCIP_EXPR **expr2, SCIP_Real *coef, int *pos2, SCIP_EXPR **prodexpr)
Definition expr.c:4226
SCIP_Bool SCIPexprAreQuadraticExprsVariables(SCIP_EXPR *expr)
Definition expr.c:4262
void SCIPexprGetQuadraticData(SCIP_EXPR *expr, SCIP_Real *constant, int *nlinexprs, SCIP_EXPR ***linexprs, SCIP_Real **lincoefs, int *nquadexprs, int *nbilinexprs, SCIP_Real **eigenvalues, SCIP_Real **eigenvectors)
Definition expr.c:4141
SCIP_RETCODE SCIPreleaseExpr(SCIP *scip, SCIP_EXPR **expr)
Definition scip_expr.c:1443
SCIP_Bool SCIPisExprVar(SCIP *scip, SCIP_EXPR *expr)
Definition scip_expr.c:1457
SCIP_RETCODE SCIPcheckExprQuadratic(SCIP *scip, SCIP_EXPR *expr, SCIP_Bool *isquadratic)
Definition scip_expr.c:2402
SCIP_VAR * SCIPgetVarExprVar(SCIP_EXPR *expr)
Definition expr_var.c:423
void SCIPexprGetQuadraticQuadTerm(SCIP_EXPR *quadexpr, int termidx, SCIP_EXPR **expr, SCIP_Real *lincoef, SCIP_Real *sqrcoef, int *nadjbilin, int **adjbilin, SCIP_EXPR **sqrexpr)
Definition expr.c:4186
SCIP_RETCODE SCIPduplicateExpr(SCIP *scip, SCIP_EXPR *expr, SCIP_EXPR **copyexpr, SCIP_DECL_EXPR_MAPEXPR((*mapexpr)), void *mapexprdata, SCIP_DECL_EXPR_OWNERCREATE((*ownercreate)), void *ownercreatedata)
Definition scip_expr.c:1307
SCIP_RETCODE SCIPsimplifyExpr(SCIP *scip, SCIP_EXPR *rootexpr, SCIP_EXPR **simplified, SCIP_Bool *changed, SCIP_Bool *infeasible, SCIP_DECL_EXPR_OWNERCREATE((*ownercreate)), void *ownercreatedata)
Definition scip_expr.c:1798
#define SCIPfreeBuffer(scip, ptr)
Definition scip_mem.h:134
#define SCIPfreeBlockMemoryArray(scip, ptr, num)
Definition scip_mem.h:110
BMS_BLKMEM * SCIPblkmem(SCIP *scip)
Definition scip_mem.c:57
#define SCIPensureBlockMemoryArray(scip, ptr, arraysizeptr, minsize)
Definition scip_mem.h:107
BMS_BUFMEM * SCIPbuffer(SCIP *scip)
Definition scip_mem.c:72
int SCIPcalcMemGrowSize(SCIP *scip, int num)
Definition scip_mem.c:139
#define SCIPallocBufferArray(scip, ptr, num)
Definition scip_mem.h:124
#define SCIPreallocBufferArray(scip, ptr, num)
Definition scip_mem.h:128
#define SCIPfreeBufferArray(scip, ptr)
Definition scip_mem.h:136
#define SCIPduplicateBufferArray(scip, ptr, source, num)
Definition scip_mem.h:132
#define SCIPallocBlockMemoryArray(scip, ptr, num)
Definition scip_mem.h:93
#define SCIPallocBuffer(scip, ptr)
Definition scip_mem.h:122
#define SCIPreallocBlockMemoryArray(scip, ptr, oldnum, newnum)
Definition scip_mem.h:99
#define SCIPfreeBlockMemory(scip, ptr)
Definition scip_mem.h:108
#define SCIPfreeBufferArrayNull(scip, ptr)
Definition scip_mem.h:137
#define SCIPallocBlockMemory(scip, ptr)
Definition scip_mem.h:89
#define SCIPduplicateBlockMemoryArray(scip, ptr, source, num)
Definition scip_mem.h:105
void SCIPrationalSetInfinity(SCIP_RATIONAL *res)
Definition rational.cpp:619
void SCIPrationalAdd(SCIP_RATIONAL *res, SCIP_RATIONAL *op1, SCIP_RATIONAL *op2)
Definition rational.cpp:936
SCIP_Real SCIPrationalGetReal(SCIP_RATIONAL *rational)
#define SCIPrationalDebugMessage
Definition rational.h:641
void SCIPrationalAbs(SCIP_RATIONAL *res, SCIP_RATIONAL *op)
SCIP_Bool SCIPrationalIsLT(SCIP_RATIONAL *rat1, SCIP_RATIONAL *rat2)
void SCIPrationalSetReal(SCIP_RATIONAL *res, SCIP_Real real)
Definition rational.cpp:604
SCIP_Bool SCIPrationalIsGT(SCIP_RATIONAL *rat1, SCIP_RATIONAL *rat2)
void SCIPrationalFreeBuffer(BMS_BUFMEM *bufmem, SCIP_RATIONAL **rational)
Definition rational.cpp:474
void SCIPrationalDiff(SCIP_RATIONAL *res, SCIP_RATIONAL *op1, SCIP_RATIONAL *op2)
Definition rational.cpp:984
SCIP_RETCODE SCIPrationalCreateBuffer(BMS_BUFMEM *bufmem, SCIP_RATIONAL **rational)
Definition rational.cpp:124
SCIP_Bool SCIPrationalIsZero(SCIP_RATIONAL *rational)
void SCIPrationalSetString(SCIP_RATIONAL *res, const char *desc)
Definition rational.cpp:717
SCIP_Bool SCIPrationalIsIntegral(SCIP_RATIONAL *rational)
void SCIPrationalCanonicalize(SCIP_RATIONAL *rational)
Definition rational.cpp:539
void SCIPrationalSetNegInfinity(SCIP_RATIONAL *res)
Definition rational.cpp:631
SCIP_Bool SCIPrationalIsNegative(SCIP_RATIONAL *rational)
SCIP_Bool SCIPrationalIsInfinity(SCIP_RATIONAL *rational)
SCIP_Bool SCIPrationalIsNegInfinity(SCIP_RATIONAL *rational)
SCIP_Bool SCIPrationalIsGTReal(SCIP_RATIONAL *rat, SCIP_Real real)
SCIP_Bool SCIPrationalIsEQ(SCIP_RATIONAL *rat1, SCIP_RATIONAL *rat2)
SCIP_RETCODE SCIPsetReaderCopy(SCIP *scip, SCIP_READER *reader,)
SCIP_RETCODE SCIPincludeReaderBasic(SCIP *scip, SCIP_READER **readerptr, const char *name, const char *desc, const char *extension, SCIP_READERDATA *readerdata)
SCIP_READERDATA * SCIPreaderGetData(SCIP_READER *reader)
Definition reader.c:625
SCIP_RETCODE SCIPsetReaderWrite(SCIP *scip, SCIP_READER *reader,)
SCIP_RETCODE SCIPsetReaderRead(SCIP *scip, SCIP_READER *reader,)
const char * SCIPreaderGetName(SCIP_READER *reader)
Definition reader.c:700
SCIP_RETCODE SCIPsetReaderFree(SCIP *scip, SCIP_READER *reader,)
void SCIPreaderMarkExact(SCIP_READER *reader)
Definition reader.c:690
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 SCIPisFeasNegative(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisFeasIntegral(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisGT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisFeasGT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisZero(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisLT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_RETCODE SCIPtightenVarLb(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound, SCIP_Bool force, SCIP_Bool *infeasible, SCIP_Bool *tightened)
Definition scip_var.c:6401
SCIP_RETCODE SCIPvarGetOrigvarSum(SCIP_VAR **var, SCIP_Real *scalar, SCIP_Real *constant)
Definition var.c:18365
SCIP_RETCODE SCIPtightenVarUbExact(SCIP *scip, SCIP_VAR *var, SCIP_RATIONAL *newbound, SCIP_Bool *infeasible, SCIP_Bool *tightened)
Definition scip_var.c:6768
SCIP_VAR * SCIPvarGetNegatedVar(SCIP_VAR *var)
Definition var.c:23900
SCIP_RETCODE SCIPchgVarUbExact(SCIP *scip, SCIP_VAR *var, SCIP_RATIONAL *newbound)
Definition scip_var.c:5964
SCIP_RETCODE SCIPchgVarLb(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound)
Definition scip_var.c:5697
SCIP_VARSTATUS SCIPvarGetStatus(SCIP_VAR *var)
Definition var.c:23418
int SCIPvarGetNLocksUpType(SCIP_VAR *var, SCIP_LOCKTYPE locktype)
Definition var.c:4380
SCIP_Bool SCIPvarIsImpliedIntegral(SCIP_VAR *var)
Definition var.c:23530
SCIP_Real SCIPvarGetUbLocal(SCIP_VAR *var)
Definition var.c:24300
SCIP_Real SCIPvarGetLbOriginal(SCIP_VAR *var)
Definition var.c:24052
SCIP_RETCODE SCIPaddVarExactData(SCIP *scip, SCIP_VAR *var, SCIP_RATIONAL *lb, SCIP_RATIONAL *ub, SCIP_RATIONAL *obj)
Definition scip_var.c:299
SCIP_RETCODE SCIPchgVarUb(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound)
Definition scip_var.c:5875
SCIP_Real SCIPvarGetObj(SCIP_VAR *var)
Definition var.c:23932
SCIP_RETCODE SCIPtightenVarUb(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound, SCIP_Bool force, SCIP_Bool *infeasible, SCIP_Bool *tightened)
Definition scip_var.c:6651
SCIP_VARTYPE SCIPvarGetType(SCIP_VAR *var)
Definition var.c:23485
SCIP_Real SCIPvarGetUbGlobal(SCIP_VAR *var)
Definition var.c:24174
int SCIPvarGetIndex(SCIP_VAR *var)
Definition var.c:23684
const char * SCIPvarGetName(SCIP_VAR *var)
Definition var.c:23299
SCIP_Real SCIPvarGetUbOriginal(SCIP_VAR *var)
Definition var.c:24095
SCIP_RETCODE SCIPreleaseVar(SCIP *scip, SCIP_VAR **var)
Definition scip_var.c:1887
SCIP_RETCODE SCIPgetProbvarLinearSum(SCIP *scip, SCIP_VAR **vars, SCIP_Real *scalars, int *nvars, int varssize, SCIP_Real *constant, int *requiredsize)
Definition scip_var.c:2378
SCIP_RETCODE SCIPchgVarType(SCIP *scip, SCIP_VAR *var, SCIP_VARTYPE vartype, SCIP_Bool *infeasible)
Definition scip_var.c:10113
SCIP_RETCODE SCIPgetNegatedVar(SCIP *scip, SCIP_VAR *var, SCIP_VAR **negvar)
Definition scip_var.c:2166
SCIP_Real SCIPvarGetLbLocal(SCIP_VAR *var)
Definition var.c:24266
SCIP_Bool SCIPvarIsNegated(SCIP_VAR *var)
Definition var.c:23475
SCIP_RATIONAL * SCIPvarGetLbGlobalExact(SCIP_VAR *var)
Definition var.c:24162
SCIP_RETCODE SCIPcreateVar(SCIP *scip, SCIP_VAR **var, const char *name, SCIP_Real lb, SCIP_Real ub, SCIP_Real obj, SCIP_VARTYPE vartype, SCIP_Bool initial, SCIP_Bool removable, SCIP_DECL_VARDELORIG((*vardelorig)), SCIP_DECL_VARTRANS((*vartrans)), SCIP_DECL_VARDELTRANS((*vardeltrans)), SCIP_DECL_VARCOPY((*varcopy)), SCIP_VARDATA *vardata)
Definition scip_var.c:120
SCIP_Real SCIPvarGetLbGlobal(SCIP_VAR *var)
Definition var.c:24152
SCIP_IMPLINTTYPE SCIPvarGetImplType(SCIP_VAR *var)
Definition var.c:23495
SCIP_RETCODE SCIPchgVarObjExact(SCIP *scip, SCIP_VAR *var, SCIP_RATIONAL *newobj)
Definition scip_var.c:5420
SCIP_RETCODE SCIPchgVarObj(SCIP *scip, SCIP_VAR *var, SCIP_Real newobj)
Definition scip_var.c:5372
SCIP_RETCODE SCIPchgVarLbExact(SCIP *scip, SCIP_VAR *var, SCIP_RATIONAL *newbound)
Definition scip_var.c:5786
int SCIPvarGetNLocksDownType(SCIP_VAR *var, SCIP_LOCKTYPE locktype)
Definition var.c:4322
SCIP_RETCODE SCIPtightenVarLbExact(SCIP *scip, SCIP_VAR *var, SCIP_RATIONAL *newbound, SCIP_Bool *infeasible, SCIP_Bool *tightened)
Definition scip_var.c:6518
SCIP_RATIONAL * SCIPvarGetUbGlobalExact(SCIP_VAR *var)
Definition var.c:24184
void SCIPsortPtrPtrReal(void **ptrarray1, void **ptrarray2, SCIP_Real *realarray, SCIP_DECL_SORTPTRCOMP((*ptrcomp)), int len)
int SCIPsnprintf(char *t, int len, const char *s,...)
Definition misc.c:10827
void SCIPprintSysError(const char *message)
Definition misc.c:10719
char * SCIPstrtok(char *s, const char *delim, char **ptrptr)
Definition misc.c:10768
int SCIPmemccpy(char *dest, const char *src, char stop, unsigned int cnt)
Definition misc.c:10694
return SCIP_OKAY
int c
assert(minobj< SCIPgetCutoffbound(scip))
int nvars
SCIP_VAR * var
SCIP_Real objscale
static SCIP_Bool propagate
static SCIP_VAR ** vars
memory allocation routines
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)
#define SCIPdebugMessage
Definition pub_message.h:96
public data structures and miscellaneous methods
methods for sorting joint arrays of various types
public methods for input file readers
public methods for problem variables
wrapper for rational number arithmetic
#define READER_DESC
Definition reader_bnd.c:62
#define READER_EXTENSION
Definition reader_bnd.c:63
#define READER_NAME
Definition reader_bnd.c:61
#define DEFAULT_AGGRLINEARIZATION_ANDS
Definition reader_lp.c:79
#define DEFAULT_LINEARIZE_ANDS
Definition reader_lp.c:78
static void mpsinputEntryIgnored(SCIP *scip, MPSINPUT *mpsi, const char *what, const char *what_name, const char *entity, const char *entity_name, SCIP_VERBLEVEL verblevel)
Definition reader_mps.c:409
static void mpsinputInsertField4(MPSINPUT *mpsi, const char *str)
Definition reader_mps.c:649
static const char * mpsinputField5(const MPSINPUT *mpsi)
Definition reader_mps.c:290
static SCIP_RETCODE checkVarnames(SCIP *scip, SCIP_VAR **vars, int nvars, unsigned int *maxnamelen, const char ***varnames, SCIP_HASHMAP **varnameHashmap)
static SCIP_RETCODE readMpsExact(SCIP *scip, const char *filename, const char ***varnames, const char ***consnames, int *varnamessize, int *consnamessize, int *nvarnames, int *nconsnames)
static SCIP_RETCODE readSOS(MPSINPUT *mpsi, SCIP *scip)
static void printRhsSection(SCIP *scip, FILE *file, int nconss, const char **consnames, SCIP_Real *rhss, unsigned int maxnamelen, SCIP_Real objoffset)
struct SparseMatrix SPARSEMATRIX
Definition reader_mps.c:164
static const char * mpsinputField1(const MPSINPUT *mpsi)
Definition reader_mps.c:246
MpsSection
Definition reader_mps.c:109
@ MPS_QCMATRIX
Definition reader_mps.c:123
@ MPS_COLUMNS
Definition reader_mps.c:116
@ MPS_NAME
Definition reader_mps.c:110
@ MPS_BOUNDS
Definition reader_mps.c:119
@ MPS_USERCUTS
Definition reader_mps.c:114
@ MPS_SOS
Definition reader_mps.c:120
@ MPS_ROWS
Definition reader_mps.c:113
@ MPS_LAZYCONS
Definition reader_mps.c:115
@ MPS_INDICATORS
Definition reader_mps.c:124
@ MPS_OBJSEN
Definition reader_mps.c:111
@ MPS_OBJNAME
Definition reader_mps.c:112
@ MPS_QMATRIX
Definition reader_mps.c:122
@ MPS_RHS
Definition reader_mps.c:117
@ MPS_RANGES
Definition reader_mps.c:118
@ MPS_ENDATA
Definition reader_mps.c:125
@ MPS_QUADOBJ
Definition reader_mps.c:121
static SCIP_RETCODE readObjsen(SCIP *scip, MPSINPUT *mpsi)
Definition reader_mps.c:779
static SCIP_RETCODE checkSparseMatrixCapacity(SCIP *scip, SPARSEMATRIX *matrix, int capacity)
static SCIP_RETCODE readQMatrix(MPSINPUT *mpsi, SCIP_Bool isQuadObj, SCIP *scip)
#define MPSINTCOMP_LEVEL(IMPLINTLEVEL)
static SCIP_Bool mpsinputHasError(const MPSINPUT *mpsi)
Definition reader_mps.c:323
static SCIP_RETCODE readRows(MPSINPUT *mpsi, SCIP *scip, const char ***consnames, int *consnamessize, int *nconsnames)
Definition reader_mps.c:877
static void printBoundSectionName(SCIP *scip, FILE *file)
static const char * mpsinputField2(const MPSINPUT *mpsi)
Definition reader_mps.c:257
static void clearFrom(char *buf, unsigned int pos)
Definition reader_mps.c:431
static SCIP_RETCODE readColsExact(MPSINPUT *mpsi, SCIP *scip, const char ***varnames, int *varnamessize, int *nvarnames)
static SCIP_RETCODE readRhs(MPSINPUT *mpsi, SCIP *scip)
static void mpsinputSetObjname(MPSINPUT *mpsi, const char *objname)
Definition reader_mps.c:371
static SCIP_RETCODE initializeMatrix(SCIP *scip, SPARSEMATRIX **matrix, int slots)
static void freeMatrix(SCIP *scip, SPARSEMATRIX *matrix)
static SCIP_RETCODE readObjname(SCIP *scip, MPSINPUT *mpsi)
Definition reader_mps.c:838
enum MpsSection MPSSECTION
Definition reader_mps.c:127
static SCIP_Bool mpsinputIsInteger(const MPSINPUT *mpsi)
Definition reader_mps.c:334
struct MpsInput MPSINPUT
Definition reader_mps.c:153
static SCIP_RETCODE getLinearCoeffs(SCIP *scip, const char *consname, SCIP_VAR **vars, SCIP_Real *vals, int nvars, SCIP_Bool transformed, SPARSEMATRIX *matrix, SCIP_Real *rhs)
static void mpsinputSetProbname(MPSINPUT *mpsi, const char *probname)
Definition reader_mps.c:357
static void printRangeSection(SCIP *scip, FILE *file, SCIP_CONS **conss, int nconss, const char **consnames, SCIP_Bool transformed, unsigned int maxnamelen)
#define BLANK
Definition reader_mps.c:98
static SCIP_OBJSENSE mpsinputObjsense(const MPSINPUT *mpsi)
Definition reader_mps.c:312
static SCIP_RETCODE readCols(MPSINPUT *mpsi, SCIP *scip, const char ***varnames, int *varnamessize, int *nvarnames)
static SCIP_Bool mpsinputReadLine(MPSINPUT *mpsi)
Definition reader_mps.c:466
static void mpsinputSetObjsense(MPSINPUT *mpsi, SCIP_OBJSENSE sense)
Definition reader_mps.c:385
static void mpsinputInsertName(MPSINPUT *mpsi, const char *name, SCIP_Bool second)
Definition reader_mps.c:663
static MPSSECTION mpsinputSection(const MPSINPUT *mpsi)
Definition reader_mps.c:224
static SCIP_RETCODE addVarNameToStorage(SCIP *scip, const char ***varnames, int *varnamessize, int *nvars, const char *colname)
Definition reader_mps.c:687
static const char * mpsinputField3(const MPSINPUT *mpsi)
Definition reader_mps.c:268
static SCIP_RETCODE checkConsnames(SCIP *scip, SCIP_CONS **conss, int nconss, SCIP_Bool transformed, unsigned int *maxnamelen, const char ***consnames, SCIP_Bool *error)
#define MPS_MAX_FIELDLEN
Definition reader_mps.c:95
static SCIP_RETCODE readRhsExact(MPSINPUT *mpsi, SCIP *scip)
static SCIP_RETCODE addConsNameToStorage(SCIP *scip, const char ***consnames, int *consnamessize, int *ncons, const char *rowname)
Definition reader_mps.c:709
#define MPS_MAX_VALUELEN
Definition reader_mps.c:94
static SCIP_RETCODE readMps(SCIP *scip, const char *filename, const char ***varnames, const char ***consnames, int *varnamessize, int *consnamessize, int *nvarnames, int *nconsnames)
static void printRowType(SCIP *scip, FILE *file, SCIP_Real lhs, SCIP_Real rhs, const char *name)
static SCIP_RETCODE readRanges(MPSINPUT *mpsi, SCIP *scip)
static SCIP_RETCODE mpsinputCreate(SCIP *scip, MPSINPUT **mpsi, SCIP_FILE *fp)
Definition reader_mps.c:176
static unsigned int computeFieldWidth(unsigned int width)
struct ConsNameFreq CONSNAMEFREQ
Definition reader_mps.c:172
static void printBoundSection(SCIP *scip, FILE *file, SCIP_VAR **vars, int nvars, SCIP_VAR **aggvars, int naggvars, SCIP_VAR **fixvars, int nfixvars, SCIP_Bool transformed, const char **varnames, SCIP_HASHTABLE *indicatorSlackHash, unsigned int maxnamelen)
static const char * mpsinputField4(const MPSINPUT *mpsi)
Definition reader_mps.c:279
static void printEntry(SCIP *scip, FILE *file, const char *varname, const char *consname, SCIP_Real value, int *recordcnt, unsigned int maxnamelen)
static void printStart(SCIP *scip, FILE *file, const char *col1, const char *col2, int maxnamelen)
static SCIP_RETCODE readIndicators(MPSINPUT *mpsi, SCIP *scip)
static void mpsinputSetSection(MPSINPUT *mpsi, MPSSECTION section)
Definition reader_mps.c:345
static void printRecord(SCIP *scip, FILE *file, const char *col1, const char *col2, unsigned int maxnamelen)
static SCIP_RETCODE readRowsExact(MPSINPUT *mpsi, SCIP *scip, const char ***consnames, int *consnamessize, int *nconsnames)
Definition reader_mps.c:973
static const char * mpsinputObjname(const MPSINPUT *mpsi)
Definition reader_mps.c:301
static const char * mpsinputField0(const MPSINPUT *mpsi)
Definition reader_mps.c:235
static void mpsinputSyntaxerror(MPSINPUT *mpsi)
Definition reader_mps.c:396
static SCIP_RETCODE collectAggregatedVars(SCIP *scip, SCIP_VAR **vars, int nvars, SCIP_VAR ***aggvars, int *naggvars, int *saggvars, SCIP_HASHTABLE *varAggregated)
static SCIP_RETCODE readName(SCIP *scip, MPSINPUT *mpsi)
Definition reader_mps.c:731
#define MPS_MAX_NAMELEN
Definition reader_mps.c:93
#define PATCH_CHAR
Definition reader_mps.c:97
static SCIP_RETCODE readQCMatrix(MPSINPUT *mpsi, SCIP *scip)
static SCIP_RETCODE readRangesExact(MPSINPUT *mpsi, SCIP *scip)
static SCIP_RETCODE readBounds(MPSINPUT *mpsi, SCIP *scip)
#define MPS_MAX_LINELEN
Definition reader_mps.c:92
static SCIP_RETCODE readBoundsExact(MPSINPUT *mpsi, SCIP *scip)
static SCIP_Bool writeVarIsIntegral(SCIP_VAR *var, int implintlevel)
static void patchField(char *buf, int beg, int end)
Definition reader_mps.c:445
static void mpsinputFree(SCIP *scip, MPSINPUT **mpsi)
Definition reader_mps.c:214
(extended) MPS file reader
public methods for constraint handler plugins and constraints
public methods for exact solving
public methods for memory management
public methods for message handling
public methods for numerical tolerances
public methods for SCIP parameter handling
public methods for global and local (sub)problems
public methods for reader plugins
public methods for querying solving statistics
public methods for SCIP variables
static SCIP_RETCODE separate(SCIP *scip, SCIP_SEPA *sepa, SCIP_SOL *sol, SCIP_RESULT *result)
Main separation function.
const char * consname
Definition reader_mps.c:169
struct SCIP_Cons SCIP_CONS
Definition type_cons.h:63
struct SCIP_Conshdlr SCIP_CONSHDLR
Definition type_cons.h:62
struct SCIP_Expr SCIP_EXPR
Definition type_expr.h:55
@ SCIP_BOUNDTYPE_UPPER
Definition type_lp.h:58
@ SCIP_BOUNDTYPE_LOWER
Definition type_lp.h:57
enum SCIP_BoundType SCIP_BOUNDTYPE
Definition type_lp.h:60
enum SCIP_VerbLevel SCIP_VERBLEVEL
@ SCIP_VERBLEVEL_NORMAL
@ SCIP_VERBLEVEL_FULL
struct SCIP_HashMap SCIP_HASHMAP
Definition type_misc.h:106
#define SCIP_DECL_SORTPTRCOMP(x)
Definition type_misc.h:189
#define SCIP_DECL_HASHKEYEQ(x)
Definition type_misc.h:195
#define SCIP_DECL_HASHGETKEY(x)
Definition type_misc.h:192
#define SCIP_DECL_HASHKEYVAL(x)
Definition type_misc.h:198
struct SCIP_HashTable SCIP_HASHTABLE
Definition type_misc.h:88
@ 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_Rational SCIP_RATIONAL
#define SCIP_DECL_READERWRITE(x)
struct SCIP_ReaderData SCIP_READERDATA
Definition type_reader.h:54
struct SCIP_Reader SCIP_READER
Definition type_reader.h:53
#define SCIP_DECL_READERREAD(x)
Definition type_reader.h:88
#define SCIP_DECL_READERCOPY(x)
Definition type_reader.h:63
#define SCIP_DECL_READERFREE(x)
Definition type_reader.h:72
@ SCIP_SUCCESS
Definition type_result.h:58
enum SCIP_Result SCIP_RESULT
Definition type_result.h:61
@ SCIP_NOFILE
@ SCIP_READERROR
@ SCIP_INVALIDDATA
@ SCIP_PLUGINNOTFOUND
@ SCIP_WRITEERROR
@ SCIP_INVALIDCALL
enum SCIP_Retcode SCIP_RETCODE
struct Scip SCIP
Definition type_scip.h:39
struct SCIP_Var SCIP_VAR
Definition type_var.h:166
@ SCIP_VARTYPE_INTEGER
Definition type_var.h:65
@ SCIP_VARTYPE_CONTINUOUS
Definition type_var.h:71
@ SCIP_VARTYPE_BINARY
Definition type_var.h:64
@ SCIP_VARSTATUS_FIXED
Definition type_var.h:54
@ SCIP_VARSTATUS_MULTAGGR
Definition type_var.h:56
@ SCIP_VARSTATUS_NEGATED
Definition type_var.h:57
@ SCIP_VARSTATUS_AGGREGATED
Definition type_var.h:55
@ SCIP_LOCKTYPE_MODEL
Definition type_var.h:141
enum SCIP_Vartype SCIP_VARTYPE
Definition type_var.h:73
enum SCIP_Varstatus SCIP_VARSTATUS
Definition type_var.h:59