1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 2 /* */ 3 /* This file is part of the program and library */ 4 /* SCIP --- Solving Constraint Integer Programs */ 5 /* */ 6 /* Copyright (c) 2002-2023 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 45 #include "blockmemshell/memory.h" 46 #include <ctype.h> 47 #include "scip/cons_and.h" 48 #include "scip/cons_bounddisjunction.h" 49 #include "scip/cons_nonlinear.h" 50 #include "scip/cons_indicator.h" 51 #include "scip/cons_knapsack.h" 52 #include "scip/cons_linear.h" 53 #include "scip/cons_logicor.h" 54 #include "scip/cons_setppc.h" 55 #include "scip/cons_sos1.h" 56 #include "scip/cons_sos2.h" 57 #include "scip/cons_varbound.h" 58 #include "scip/pub_cons.h" 59 #include "scip/pub_fileio.h" 60 #include "scip/pub_message.h" 61 #include "scip/pub_misc.h" 62 #include "scip/pub_misc_sort.h" 63 #include "scip/pub_reader.h" 64 #include "scip/pub_var.h" 65 #include "scip/reader_mps.h" 66 #include "scip/scip_cons.h" 67 #include "scip/scip_mem.h" 68 #include "scip/scip_message.h" 69 #include "scip/scip_numerics.h" 70 #include "scip/scip_param.h" 71 #include "scip/scip_prob.h" 72 #include "scip/scip_reader.h" 73 #include "scip/scip_solvingstats.h" 74 #include "scip/scip_var.h" 75 #include <stdlib.h> 76 #include <string.h> 77 78 #define READER_NAME "mpsreader" 79 #define READER_DESC "file reader for MIQPs in IBM's Mathematical Programming System format" 80 #define READER_EXTENSION "mps" 81 82 #define DEFAULT_LINEARIZE_ANDS TRUE /**< should possible \"and\" constraint be linearized when writing the mps file? */ 83 #define DEFAULT_AGGRLINEARIZATION_ANDS TRUE /**< should an aggregated linearization for and constraints be used? */ 84 85 /* 86 * mps reader internal methods 87 */ 88 89 #define MPS_MAX_LINELEN 1024 90 #define MPS_MAX_NAMELEN 256 91 #define MPS_MAX_VALUELEN 26 92 #define MPS_MAX_FIELDLEN 20 93 94 #define PATCH_CHAR '_' 95 #define BLANK ' ' 96 97 /** MPS reading data */ 98 struct SCIP_ReaderData 99 { 100 SCIP_Bool linearizeands; 101 SCIP_Bool aggrlinearizationands; 102 }; 103 104 /** enum containing all mps sections */ 105 enum MpsSection 106 { 107 MPS_NAME, 108 MPS_OBJSEN, 109 MPS_OBJNAME, 110 MPS_ROWS, 111 MPS_USERCUTS, 112 MPS_LAZYCONS, 113 MPS_COLUMNS, 114 MPS_RHS, 115 MPS_RANGES, 116 MPS_BOUNDS, 117 MPS_SOS, 118 MPS_QUADOBJ, 119 MPS_QMATRIX, 120 MPS_QCMATRIX, 121 MPS_INDICATORS, 122 MPS_ENDATA 123 }; 124 typedef enum MpsSection MPSSECTION; 125 126 /** mps input structure */ 127 struct MpsInput 128 { 129 MPSSECTION section; 130 SCIP_FILE* fp; 131 int lineno; 132 SCIP_OBJSENSE objsense; 133 SCIP_Bool haserror; 134 char buf[MPS_MAX_LINELEN]; 135 const char* f0; 136 const char* f1; 137 const char* f2; 138 const char* f3; 139 const char* f4; 140 const char* f5; 141 char probname[MPS_MAX_NAMELEN]; 142 char objname [MPS_MAX_NAMELEN]; 143 SCIP_Bool initialconss; /**< should model constraints be marked as initial? */ 144 SCIP_Bool dynamicconss; /**< should model constraints be subject to aging? */ 145 SCIP_Bool dynamiccols; /**< should columns be added and removed dynamically to the LP? */ 146 SCIP_Bool dynamicrows; /**< should rows be added and removed dynamically to the LP? */ 147 SCIP_Bool isinteger; 148 SCIP_Bool isnewformat; 149 }; 150 typedef struct MpsInput MPSINPUT; 151 152 /** sparse matrix representation */ 153 struct SparseMatrix 154 { 155 SCIP_Real* values; /**< matrix element */ 156 SCIP_VAR** columns; /**< corresponding variables */ 157 const char** rows; /**< corresponding constraint names */ 158 int nentries; /**< number of elements in the arrays */ 159 int sentries; /**< number of slots in the arrays */ 160 }; 161 typedef struct SparseMatrix SPARSEMATRIX; 162 163 /** struct for mapping cons names to numbers */ 164 struct ConsNameFreq 165 { 166 const char* consname; /**< name of the constraint */ 167 int freq; /**< how often we have seen the name */ 168 }; 169 typedef struct ConsNameFreq CONSNAMEFREQ; 170 171 /** creates the mps input structure */ 172 static 173 SCIP_RETCODE mpsinputCreate( 174 SCIP* scip, /**< SCIP data structure */ 175 MPSINPUT** mpsi, /**< mps input structure */ 176 SCIP_FILE* fp /**< file object for the input file */ 177 ) 178 { 179 assert(mpsi != NULL); 180 assert(fp != NULL); 181 182 SCIP_CALL( SCIPallocBlockMemory(scip, mpsi) ); 183 184 (*mpsi)->section = MPS_NAME; 185 (*mpsi)->fp = fp; 186 (*mpsi)->lineno = 0; 187 (*mpsi)->objsense = SCIP_OBJSENSE_MINIMIZE; 188 (*mpsi)->haserror = FALSE; 189 (*mpsi)->isinteger = FALSE; 190 (*mpsi)->isnewformat = FALSE; 191 (*mpsi)->buf [0] = '\0'; 192 (*mpsi)->probname[0] = '\0'; 193 (*mpsi)->objname [0] = '\0'; 194 (*mpsi)->f0 = NULL; 195 (*mpsi)->f1 = NULL; 196 (*mpsi)->f2 = NULL; 197 (*mpsi)->f3 = NULL; 198 (*mpsi)->f4 = NULL; 199 (*mpsi)->f5 = NULL; 200 201 SCIP_CALL( SCIPgetBoolParam(scip, "reading/initialconss", &((*mpsi)->initialconss)) ); 202 SCIP_CALL( SCIPgetBoolParam(scip, "reading/dynamicconss", &((*mpsi)->dynamicconss)) ); 203 SCIP_CALL( SCIPgetBoolParam(scip, "reading/dynamiccols", &((*mpsi)->dynamiccols)) ); 204 SCIP_CALL( SCIPgetBoolParam(scip, "reading/dynamicrows", &((*mpsi)->dynamicrows)) ); 205 206 return SCIP_OKAY; 207 } 208 209 /** free the mps input structure */ 210 static 211 void mpsinputFree( 212 SCIP* scip, /**< SCIP data structure */ 213 MPSINPUT** mpsi /**< mps input structure */ 214 ) 215 { 216 SCIPfreeBlockMemory(scip, mpsi); 217 } 218 219 /** returns the current section */ 220 static 221 MPSSECTION mpsinputSection( 222 const MPSINPUT* mpsi /**< mps input structure */ 223 ) 224 { 225 assert(mpsi != NULL); 226 227 return mpsi->section; 228 } 229 230 /** return the current value of field 0 */ 231 static 232 const char* mpsinputField0( 233 const MPSINPUT* mpsi /**< mps input structure */ 234 ) 235 { 236 assert(mpsi != NULL); 237 238 return mpsi->f0; 239 } 240 241 /** return the current value of field 1 */ 242 static 243 const char* mpsinputField1( 244 const MPSINPUT* mpsi /**< mps input structure */ 245 ) 246 { 247 assert(mpsi != NULL); 248 249 return mpsi->f1; 250 } 251 252 /** return the current value of field 2 */ 253 static 254 const char* mpsinputField2( 255 const MPSINPUT* mpsi /**< mps input structure */ 256 ) 257 { 258 assert(mpsi != NULL); 259 260 return mpsi->f2; 261 } 262 263 /** return the current value of field 3 */ 264 static 265 const char* mpsinputField3( 266 const MPSINPUT* mpsi /**< mps input structure */ 267 ) 268 { 269 assert(mpsi != NULL); 270 271 return mpsi->f3; 272 } 273 274 /** return the current value of field 4 */ 275 static 276 const char* mpsinputField4( 277 const MPSINPUT* mpsi /**< mps input structure */ 278 ) 279 { 280 assert(mpsi != NULL); 281 282 return mpsi->f4; 283 } 284 285 /** return the current value of field 5 */ 286 static 287 const char* mpsinputField5( 288 const MPSINPUT* mpsi /**< mps input structure */ 289 ) 290 { 291 assert(mpsi != NULL); 292 293 return mpsi->f5; 294 } 295 296 /** returns the objective name */ 297 static 298 const char* mpsinputObjname( 299 const MPSINPUT* mpsi /**< mps input structure */ 300 ) 301 { 302 assert(mpsi != NULL); 303 304 return mpsi->objname; 305 } 306 307 /** returns the objective sense */ 308 static 309 SCIP_OBJSENSE mpsinputObjsense( 310 const MPSINPUT* mpsi /**< mps input structure */ 311 ) 312 { 313 assert(mpsi != NULL); 314 315 return mpsi->objsense; 316 } 317 318 /** returns if an error was detected */ 319 static 320 SCIP_Bool mpsinputHasError( 321 const MPSINPUT* mpsi /**< mps input structure */ 322 ) 323 { 324 assert(mpsi != NULL); 325 326 return mpsi->haserror; 327 } 328 329 /** returns the value of the Bool "is integer" in the mps input */ 330 static 331 SCIP_Bool mpsinputIsInteger( 332 const MPSINPUT* mpsi /**< mps input structure */ 333 ) 334 { 335 assert(mpsi != NULL); 336 337 return mpsi->isinteger; 338 } 339 340 /** set the section in the mps input structure to given section */ 341 static 342 void mpsinputSetSection( 343 MPSINPUT* mpsi, /**< mps input structure */ 344 MPSSECTION section /**< section that is set */ 345 ) 346 { 347 assert(mpsi != NULL); 348 349 mpsi->section = section; 350 } 351 352 /** set the problem name in the mps input structure to given problem name */ 353 static 354 void mpsinputSetProbname( 355 MPSINPUT* mpsi, /**< mps input structure */ 356 const char* probname /**< name of the problem to set */ 357 ) 358 { 359 assert(mpsi != NULL); 360 assert(probname != NULL); 361 assert(strlen(probname) < sizeof(mpsi->probname)); 362 363 (void)SCIPmemccpy(mpsi->probname, probname, '\0', MPS_MAX_NAMELEN - 1); 364 } 365 366 /** set the objective name in the mps input structure to given objective name */ 367 static 368 void mpsinputSetObjname( 369 MPSINPUT* mpsi, /**< mps input structure */ 370 const char* objname /**< name of the objective function to set */ 371 ) 372 { 373 assert(mpsi != NULL); 374 assert(objname != NULL); 375 assert(strlen(objname) < sizeof(mpsi->objname)); 376 377 (void)SCIPmemccpy(mpsi->objname, objname, '\0', MPS_MAX_NAMELEN - 1); 378 } 379 380 /** set the objective sense in the mps input structure to given objective sense */ 381 static 382 void mpsinputSetObjsense( 383 MPSINPUT* mpsi, /**< mps input structure */ 384 SCIP_OBJSENSE sense /**< sense of the objective function */ 385 ) 386 { 387 assert(mpsi != NULL); 388 389 mpsi->objsense = sense; 390 } 391 392 static 393 void mpsinputSyntaxerror( 394 MPSINPUT* mpsi /**< mps input structure */ 395 ) 396 { 397 assert(mpsi != NULL); 398 399 SCIPerrorMessage("Syntax error in line %d\n", mpsi->lineno); 400 mpsi->section = MPS_ENDATA; 401 mpsi->haserror = TRUE; 402 } 403 404 /** method post a ignore message */ 405 static 406 void mpsinputEntryIgnored( 407 SCIP* scip, /**< SCIP data structure */ 408 MPSINPUT* mpsi, /**< mps input structure */ 409 const char* what, /**< what get ignored */ 410 const char* what_name, /**< name of that object */ 411 const char* entity, /**< entity */ 412 const char* entity_name, /**< entity name */ 413 SCIP_VERBLEVEL verblevel /**< SCIP verblevel for this message */ 414 ) 415 { 416 assert(mpsi != NULL); 417 assert(what != NULL); 418 assert(what_name != NULL); 419 assert(entity != NULL); 420 assert(entity_name != NULL); 421 422 SCIPverbMessage(scip, verblevel, NULL, 423 "Warning line %d: %s \"%s\" for %s \"%s\" ignored\n", mpsi->lineno, what, what_name, entity, entity_name); 424 } 425 426 /** fill the line from \p pos up to column 80 with blanks. */ 427 static 428 void clearFrom( 429 char* buf, /**< buffer to clear */ 430 unsigned int pos /**< position to start the clearing process */ 431 ) 432 { 433 unsigned int i; 434 435 for(i = pos; i < 80; i++) 436 buf[i] = BLANK; 437 buf[80] = '\0'; 438 } 439 440 /** change all blanks inside a field to #PATCH_CHAR. */ 441 static 442 void patchField( 443 char* buf, /**< buffer to patch */ 444 int beg, /**< position to begin */ 445 int end /**< position to end */ 446 ) 447 { 448 int i; 449 450 while( (beg <= end) && (buf[end] == BLANK) ) 451 end--; 452 453 while( (beg <= end) && (buf[beg] == BLANK) ) 454 beg++; 455 456 for( i = beg; i <= end; i++ ) 457 if( buf[i] == BLANK ) 458 buf[i] = PATCH_CHAR; 459 } 460 461 /** read a mps format data line and parse the fields. */ 462 static 463 SCIP_Bool mpsinputReadLine( 464 MPSINPUT* mpsi /**< mps input structure */ 465 ) 466 { 467 unsigned int len; 468 unsigned int i; 469 int space; 470 char* s; 471 SCIP_Bool is_marker; 472 SCIP_Bool is_empty; 473 char* nexttok; 474 475 do 476 { 477 mpsi->f0 = mpsi->f1 = mpsi->f2 = mpsi->f3 = mpsi->f4 = mpsi->f5 = 0; 478 is_marker = FALSE; 479 480 /* Read until we have not a comment line. */ 481 do 482 { 483 mpsi->buf[MPS_MAX_LINELEN-1] = '\0'; 484 if( NULL == SCIPfgets(mpsi->buf, (int) sizeof(mpsi->buf), mpsi->fp) ) 485 return FALSE; 486 mpsi->lineno++; 487 } 488 while( *mpsi->buf == '*' ); /* coverity[a_loop_bound] */ 489 490 /* Normalize line */ 491 len = (unsigned int) strlen(mpsi->buf); 492 493 for( i = 0; i < len; i++ ) 494 if( (mpsi->buf[i] == '\t') || (mpsi->buf[i] == '\n') || (mpsi->buf[i] == '\r') ) 495 mpsi->buf[i] = BLANK; 496 497 if( len < 80 ) 498 clearFrom(mpsi->buf, len); 499 500 SCIPdebugMessage("line %d: <%s>\n", mpsi->lineno, mpsi->buf); 501 502 assert(strlen(mpsi->buf) >= 80); 503 504 /* Look for new section */ 505 if( *mpsi->buf != BLANK ) 506 { 507 mpsi->f0 = SCIPstrtok(&mpsi->buf[0], " ", &nexttok); 508 509 assert(mpsi->f0 != 0); 510 511 mpsi->f1 = SCIPstrtok(NULL, " ", &nexttok); 512 513 return TRUE; 514 } 515 516 /* If we decide to use the new format we never revert this decision */ 517 if( !mpsi->isnewformat ) 518 { 519 /* Test for fixed format comments */ 520 if( (mpsi->buf[14] == '$') && (mpsi->buf[13] == ' ') ) 521 clearFrom(mpsi->buf, 14); 522 else if( (mpsi->buf[39] == '$') && (mpsi->buf[38] == ' ') ) 523 clearFrom(mpsi->buf, 39); 524 525 /* Test for fixed format */ 526 space = mpsi->buf[12] | mpsi->buf[13] 527 | mpsi->buf[22] | mpsi->buf[23] 528 | mpsi->buf[36] | mpsi->buf[37] | mpsi->buf[38] 529 | mpsi->buf[47] | mpsi->buf[48] 530 | mpsi->buf[61] | mpsi->buf[62] | mpsi->buf[63]; 531 532 if( space == BLANK ) 533 { 534 /* Now we have space at the right positions. 535 * But are there also the non space where they 536 * should be ? 537 */ 538 SCIP_Bool number; 539 540 number = isdigit((unsigned char)mpsi->buf[24]) || isdigit((unsigned char)mpsi->buf[25]) 541 || isdigit((unsigned char)mpsi->buf[26]) || isdigit((unsigned char)mpsi->buf[27]) 542 || isdigit((unsigned char)mpsi->buf[28]) || isdigit((unsigned char)mpsi->buf[29]) 543 || isdigit((unsigned char)mpsi->buf[30]) || isdigit((unsigned char)mpsi->buf[31]) 544 || isdigit((unsigned char)mpsi->buf[32]) || isdigit((unsigned char)mpsi->buf[33]) 545 || isdigit((unsigned char)mpsi->buf[34]) || isdigit((unsigned char)mpsi->buf[35]); 546 547 /* len < 14 is handle ROW lines with embedded spaces 548 * in the names correctly 549 */ 550 if( number || len < 14 ) 551 { 552 /* We assume fixed format, so we patch possible embedded spaces. */ 553 patchField(mpsi->buf, 4, 12); 554 patchField(mpsi->buf, 14, 22); 555 patchField(mpsi->buf, 39, 47); 556 } 557 else 558 { 559 if( mpsi->section == MPS_COLUMNS || mpsi->section == MPS_RHS 560 || mpsi->section == MPS_RANGES || mpsi->section == MPS_BOUNDS ) 561 mpsi->isnewformat = TRUE; 562 } 563 } 564 else 565 { 566 mpsi->isnewformat = TRUE; 567 } 568 } 569 s = &mpsi->buf[1]; 570 571 /* At this point it is not clear if we have a indicator field. 572 * If there is none (e.g. empty) f1 will be the first name field. 573 * If there is one, f2 will be the first name field. 574 * 575 * Initially comment marks '$' are only allowed in the beginning 576 * of the 2nd and 3rd name field. We test all fields but the first. 577 * This makes no difference, since if the $ is at the start of a value 578 * field, the line will be erroneous anyway. 579 */ 580 do 581 { 582 if( NULL == (mpsi->f1 = SCIPstrtok(s, " ", &nexttok)) ) 583 break; 584 585 if( (NULL == (mpsi->f2 = SCIPstrtok(NULL, " ", &nexttok))) || (*mpsi->f2 == '$') ) 586 { 587 mpsi->f2 = 0; 588 break; 589 } 590 if( !strcmp(mpsi->f2, "'MARKER'") ) 591 is_marker = TRUE; 592 593 if( (NULL == (mpsi->f3 = SCIPstrtok(NULL, " ", &nexttok))) || (*mpsi->f3 == '$') ) 594 { 595 mpsi->f3 = 0; 596 break; 597 } 598 if( is_marker ) 599 { 600 if( !strcmp(mpsi->f3, "'INTORG'") ) 601 mpsi->isinteger = TRUE; 602 else if( !strcmp(mpsi->f3, "'INTEND'") ) 603 mpsi->isinteger = FALSE; 604 else 605 break; /* unknown marker */ 606 } 607 if( !strcmp(mpsi->f3, "'MARKER'") ) 608 is_marker = TRUE; 609 610 if( (NULL == (mpsi->f4 = SCIPstrtok(NULL, " ", &nexttok))) || (*mpsi->f4 == '$') ) 611 { 612 mpsi->f4 = 0; 613 break; 614 } 615 if( is_marker ) 616 { 617 if( !strcmp(mpsi->f4, "'INTORG'") ) 618 mpsi->isinteger = TRUE; 619 else if( !strcmp(mpsi->f4, "'INTEND'") ) 620 mpsi->isinteger = FALSE; 621 else 622 break; /* unknown marker */ 623 } 624 if( (NULL == (mpsi->f5 = SCIPstrtok(NULL, " ", &nexttok))) || (*mpsi->f5 == '$') ) 625 mpsi->f5 = 0; 626 } 627 while( FALSE ); 628 629 /* check for empty lines */ 630 is_empty = (mpsi->f0 == NULL && mpsi->f1 == NULL); 631 } 632 while( is_marker || is_empty ); 633 634 return TRUE; 635 } 636 637 /** Insert \p str as field 4 and shift all other fields up. */ 638 static 639 void mpsinputInsertField4( 640 MPSINPUT* mpsi, /**< mps input structure */ 641 const char* str /**< str to insert */ 642 ) 643 { 644 assert(mpsi != NULL); 645 assert(str != NULL); 646 647 mpsi->f5 = mpsi->f4; 648 mpsi->f4 = str; 649 } 650 651 /** Insert \p name as field 1 or 2 and shift all other fields up. */ 652 static 653 void mpsinputInsertName( 654 MPSINPUT* mpsi, /**< mps input structure */ 655 const char* name, /**< name to insert */ 656 SCIP_Bool second /**< insert as second field? */ 657 ) 658 { 659 assert(mpsi != NULL); 660 assert(name != NULL); 661 662 mpsi->f5 = mpsi->f4; 663 mpsi->f4 = mpsi->f3; 664 mpsi->f3 = mpsi->f2; 665 666 if( second ) 667 mpsi->f2 = name; 668 else 669 { 670 mpsi->f2 = mpsi->f1; 671 mpsi->f1 = name; 672 } 673 } 674 675 /** Add variable name to storage */ 676 static 677 SCIP_RETCODE addVarNameToStorage( 678 SCIP* scip, /**< SCIP data structure */ 679 const char*** varnames, /**< the variable name storage */ 680 int* varnamessize, /**< the size of the variable names storage */ 681 int* nvars, /**< the number of variables */ 682 const char* colname /**< the name of the variable */ 683 ) 684 { 685 assert(scip != NULL); 686 687 if( varnames != NULL ) 688 { 689 SCIP_CALL( SCIPensureBlockMemoryArray(scip, varnames, varnamessize, (*nvars) + 1) ); 690 SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &(*varnames)[(*nvars)], colname, strlen(colname) + 1) ); /*lint !e866*/ 691 (*nvars)++; 692 } 693 694 return SCIP_OKAY; 695 } 696 697 /** Add constraint name to storage */ 698 static 699 SCIP_RETCODE addConsNameToStorage( 700 SCIP* scip, /**< SCIP data structure */ 701 const char*** consnames, /**< the constraint name storage */ 702 int* consnamessize, /**< the size of the constraint names storage */ 703 int* ncons, /**< the number of constraint */ 704 const char* rowname /**< the name of the constraint */ 705 ) 706 { 707 assert(scip != NULL); 708 709 if( consnames != NULL ) 710 { 711 SCIP_CALL( SCIPensureBlockMemoryArray(scip, consnames, consnamessize, (*ncons) + 1) ); 712 SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &(*consnames)[(*ncons)], rowname, strlen(rowname) + 1) ); /*lint !e866*/ 713 (*ncons)++; 714 } 715 716 return SCIP_OKAY; 717 } 718 719 /** Process NAME section. */ 720 static 721 SCIP_RETCODE readName( 722 SCIP* scip, /**< SCIP data structure */ 723 MPSINPUT* mpsi /**< mps input structure */ 724 ) 725 { 726 assert(mpsi != NULL); 727 728 SCIPdebugMsg(scip, "read problem name\n"); 729 730 /* This has to be the Line with the NAME section. */ 731 if( !mpsinputReadLine(mpsi) || mpsinputField0(mpsi) == NULL || strcmp(mpsinputField0(mpsi), "NAME") ) 732 { 733 mpsinputSyntaxerror(mpsi); 734 return SCIP_OKAY; 735 } 736 737 /* Sometimes the name is omitted. */ 738 mpsinputSetProbname(mpsi, (mpsinputField1(mpsi) == 0) ? "_MPS_" : mpsinputField1(mpsi)); 739 740 /* This hat to be a new section */ 741 /* coverity[tainted_data] */ 742 if( !mpsinputReadLine(mpsi) || (mpsinputField0(mpsi) == NULL) ) 743 { 744 mpsinputSyntaxerror(mpsi); 745 return SCIP_OKAY; 746 } 747 748 if( !strncmp(mpsinputField0(mpsi), "ROWS", 4) ) 749 mpsinputSetSection(mpsi, MPS_ROWS); 750 else if( !strncmp(mpsinputField0(mpsi), "USERCUTS", 8) ) 751 mpsinputSetSection(mpsi, MPS_USERCUTS); 752 else if( !strncmp(mpsinputField0(mpsi), "LAZYCONS", 8) ) 753 mpsinputSetSection(mpsi, MPS_LAZYCONS); 754 else if( !strncmp(mpsinputField0(mpsi), "OBJSEN", 6) ) 755 mpsinputSetSection(mpsi, MPS_OBJSEN); 756 else if( !strncmp(mpsinputField0(mpsi), "OBJNAME", 7) ) 757 mpsinputSetSection(mpsi, MPS_OBJNAME); 758 else 759 { 760 mpsinputSyntaxerror(mpsi); 761 return SCIP_OKAY; 762 } 763 764 return SCIP_OKAY; 765 } 766 767 /** Process OBJSEN section. This Section is a CPLEX extension. */ 768 static 769 SCIP_RETCODE readObjsen( 770 SCIP* scip, /**< SCIP data structure */ 771 MPSINPUT* mpsi /**< mps input structure */ 772 ) 773 { 774 assert(mpsi != NULL); 775 776 SCIPdebugMsg(scip, "read objective sense\n"); 777 778 /* Although this is not explicitly in the MPS extensions as provided by CPLEX, some other MIP solvers 779 * (in particular gurobi), put 'MIN' or 'MAX' as the input field on the same line as the section declaration */ 780 if( mpsinputField1(mpsi) == NULL){ 781 /* Normal Cplex extension; info should be on the next line, in field 1 */ 782 /* This has to be the Line with MIN or MAX. */ 783 if( !mpsinputReadLine(mpsi) || (mpsinputField1(mpsi) == NULL) ) 784 { 785 mpsinputSyntaxerror(mpsi); 786 return SCIP_OKAY; 787 } 788 } 789 /* Otherwise, the input should read e.g. "OBJSENSE MAX" so that MAX is also the first field */ 790 791 if( !strncmp(mpsinputField1(mpsi), "MIN", 3) ) 792 mpsinputSetObjsense(mpsi, SCIP_OBJSENSE_MINIMIZE); 793 else if( !strncmp(mpsinputField1(mpsi), "MAX", 3) ) 794 mpsinputSetObjsense(mpsi, SCIP_OBJSENSE_MAXIMIZE); 795 else 796 { 797 mpsinputSyntaxerror(mpsi); 798 return SCIP_OKAY; 799 } 800 801 /* Look for ROWS, USERCUTS, LAZYCONS, or OBJNAME Section */ 802 /* coverity[tainted_data] */ 803 if( !mpsinputReadLine(mpsi) || mpsinputField0(mpsi) == NULL ) 804 { 805 mpsinputSyntaxerror(mpsi); 806 return SCIP_OKAY; 807 } 808 809 if( !strcmp(mpsinputField0(mpsi), "ROWS") ) 810 mpsinputSetSection(mpsi, MPS_ROWS); 811 else if( !strcmp(mpsinputField0(mpsi), "USERCUTS") ) 812 mpsinputSetSection(mpsi, MPS_USERCUTS); 813 else if( !strcmp(mpsinputField0(mpsi), "LAZYCONS") ) 814 mpsinputSetSection(mpsi, MPS_LAZYCONS); 815 else if( !strcmp(mpsinputField0(mpsi), "OBJNAME") ) 816 mpsinputSetSection(mpsi, MPS_OBJNAME); 817 else 818 { 819 mpsinputSyntaxerror(mpsi); 820 return SCIP_OKAY; 821 } 822 823 return SCIP_OKAY; 824 } 825 826 /** Process OBJNAME section. This Section is a CPLEX extension. */ 827 static 828 SCIP_RETCODE readObjname( 829 SCIP* scip, /**< SCIP data structure */ 830 MPSINPUT* mpsi /**< mps input structure */ 831 ) 832 { 833 assert(mpsi != NULL); 834 835 SCIPdebugMsg(scip, "read objective name\n"); 836 837 /* This has to be the Line with the name. */ 838 if( !mpsinputReadLine(mpsi) || mpsinputField1(mpsi) == NULL ) 839 { 840 mpsinputSyntaxerror(mpsi); 841 return SCIP_OKAY; 842 } 843 844 mpsinputSetObjname(mpsi, mpsinputField1(mpsi)); 845 846 /* Look for ROWS, USERCUTS, or LAZYCONS Section */ 847 /* coverity[tainted_data] */ 848 if( !mpsinputReadLine(mpsi) || mpsinputField0(mpsi) == NULL ) 849 { 850 mpsinputSyntaxerror(mpsi); 851 return SCIP_OKAY; 852 } 853 if( !strcmp(mpsinputField0(mpsi), "ROWS") ) 854 mpsinputSetSection(mpsi, MPS_ROWS); 855 else if( !strcmp(mpsinputField0(mpsi), "USERCUTS") ) 856 mpsinputSetSection(mpsi, MPS_USERCUTS); 857 else if( !strcmp(mpsinputField0(mpsi), "LAZYCONS") ) 858 mpsinputSetSection(mpsi, MPS_LAZYCONS); 859 else 860 mpsinputSyntaxerror(mpsi); 861 862 return SCIP_OKAY; 863 } 864 865 /** Process ROWS, USERCUTS, or LAZYCONS section. */ 866 static 867 SCIP_RETCODE readRows( 868 MPSINPUT* mpsi, /**< mps input structure */ 869 SCIP* scip, /**< SCIP data structure */ 870 const char*** consnames, /**< storage for the constraint names, or NULL */ 871 int* consnamessize, /**< the size of the constraint names storage, or NULL */ 872 int* nconsnames /**< the number of stored constraint names, or NULL */ 873 ) 874 { 875 SCIPdebugMsg(scip, "read rows\n"); 876 877 /* coverity[tainted_data] */ 878 while( mpsinputReadLine(mpsi) ) 879 { 880 if( mpsinputField0(mpsi) != NULL ) 881 { 882 if( !strcmp(mpsinputField0(mpsi), "ROWS") ) 883 mpsinputSetSection(mpsi, MPS_ROWS); 884 else if( !strcmp(mpsinputField0(mpsi), "USERCUTS") ) 885 mpsinputSetSection(mpsi, MPS_USERCUTS); 886 else if( !strcmp(mpsinputField0(mpsi), "LAZYCONS") ) 887 mpsinputSetSection(mpsi, MPS_LAZYCONS); 888 else if( !strcmp(mpsinputField0(mpsi), "COLUMNS") ) 889 mpsinputSetSection(mpsi, MPS_COLUMNS); 890 else 891 mpsinputSyntaxerror(mpsi); 892 893 return SCIP_OKAY; 894 } 895 896 if( *mpsinputField1(mpsi) == 'N' ) 897 { 898 if( *mpsinputObjname(mpsi) == '\0' ) 899 mpsinputSetObjname(mpsi, mpsinputField2(mpsi)); 900 else 901 mpsinputEntryIgnored(scip, mpsi, "row", mpsinputField2(mpsi), "objective function", "N", SCIP_VERBLEVEL_NORMAL); 902 } 903 else 904 { 905 SCIP_CONS* cons; 906 SCIP_Bool initial; 907 SCIP_Bool separate; 908 SCIP_Bool enforce; 909 SCIP_Bool check; 910 SCIP_Bool propagate; 911 SCIP_Bool local; 912 SCIP_Bool modifiable; 913 SCIP_Bool dynamic; 914 SCIP_Bool removable; 915 916 cons = SCIPfindCons(scip, mpsinputField2(mpsi)); 917 if( cons != NULL ) 918 break; 919 920 initial = mpsi->initialconss && (mpsinputSection(mpsi) == MPS_ROWS); 921 separate = TRUE; 922 enforce = (mpsinputSection(mpsi) != MPS_USERCUTS); 923 check = (mpsinputSection(mpsi) != MPS_USERCUTS); 924 propagate = TRUE; 925 local = FALSE; 926 modifiable = FALSE; 927 dynamic = mpsi->dynamicconss; 928 removable = mpsi->dynamicrows || (mpsinputSection(mpsi) == MPS_USERCUTS); 929 930 switch(*mpsinputField1(mpsi)) 931 { 932 case 'G' : 933 SCIP_CALL( SCIPcreateConsLinear(scip, &cons, mpsinputField2(mpsi), 0, NULL, NULL, 0.0, SCIPinfinity(scip), 934 initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, FALSE) ); 935 break; 936 case 'E' : 937 SCIP_CALL( SCIPcreateConsLinear(scip, &cons, mpsinputField2(mpsi), 0, NULL, NULL, 0.0, 0.0, 938 initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, FALSE) ); 939 break; 940 case 'L' : 941 SCIP_CALL( SCIPcreateConsLinear(scip, &cons, mpsinputField2(mpsi), 0, NULL, NULL, -SCIPinfinity(scip), 0.0, 942 initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, FALSE) ); 943 break; 944 default : 945 mpsinputSyntaxerror(mpsi); 946 return SCIP_OKAY; 947 } 948 SCIP_CALL( SCIPaddCons(scip, cons) ); 949 SCIP_CALL( SCIPreleaseCons(scip, &cons) ); 950 951 /* if the file is of type cor, then the constraint names must be stored */ 952 SCIP_CALL( addConsNameToStorage(scip, consnames, consnamessize, nconsnames, mpsinputField2(mpsi)) ); 953 } 954 } 955 mpsinputSyntaxerror(mpsi); 956 957 return SCIP_OKAY; 958 } 959 960 /** Process COLUMNS section. */ 961 static 962 SCIP_RETCODE readCols( 963 MPSINPUT* mpsi, /**< mps input structure */ 964 SCIP* scip, /**< SCIP data structure */ 965 const char*** varnames, /**< storage for the variable names, or NULL */ 966 int* varnamessize, /**< the size of the variable names storage, or NULL */ 967 int* nvarnames /**< the number of stored variable names, or NULL */ 968 ) 969 { 970 char colname[MPS_MAX_NAMELEN] = { '\0' }; 971 SCIP_CONS* cons; 972 SCIP_VAR* var; 973 SCIP_Real val; 974 SCIP_Bool usevartable; 975 976 SCIPdebugMsg(scip, "read columns\n"); 977 978 var = NULL; 979 SCIP_CALL( SCIPgetBoolParam(scip, "misc/usevartable", &usevartable) ); 980 981 while( mpsinputReadLine(mpsi) ) 982 { 983 if( mpsinputField0(mpsi) != 0 ) 984 { 985 if( strcmp(mpsinputField0(mpsi), "RHS") ) 986 break; 987 988 /* add the last variable to the problem */ 989 if( var != NULL ) 990 { 991 SCIP_CALL( SCIPaddVar(scip, var) ); 992 SCIP_CALL( SCIPreleaseVar(scip, &var) ); 993 } 994 assert(var == NULL); 995 996 mpsinputSetSection(mpsi, MPS_RHS); 997 return SCIP_OKAY; 998 } 999 if( mpsinputField1(mpsi) == NULL || mpsinputField2(mpsi) == NULL || mpsinputField3(mpsi) == NULL ) 1000 break; 1001 1002 /* new column? */ 1003 if( strcmp(colname, mpsinputField1(mpsi)) ) 1004 { 1005 /* add the last variable to the problem */ 1006 if( var != NULL ) 1007 { 1008 SCIP_CALL( SCIPaddVar(scip, var) ); 1009 SCIP_CALL( SCIPreleaseVar(scip, &var) ); 1010 } 1011 assert(var == NULL); 1012 1013 (void)SCIPmemccpy(colname, mpsinputField1(mpsi), '\0', MPS_MAX_NAMELEN - 1); 1014 1015 /* check whether we have seen this variable before, this would not allowed */ 1016 if( usevartable && SCIPfindVar(scip, colname) != NULL ) 1017 { 1018 SCIPerrorMessage("Coeffients of column <%s> don't appear consecutively (line: %d)\n", 1019 colname, mpsi->lineno); 1020 1021 return SCIP_READERROR; 1022 } 1023 1024 /* if the file type is a cor file, the the variable name must be stored */ 1025 SCIP_CALL( addVarNameToStorage(scip, varnames, varnamessize, nvarnames, colname) ); 1026 1027 if( mpsinputIsInteger(mpsi) ) 1028 { 1029 /* for integer variables, default bounds are 0 <= x < 1(not +infinity, like it is for continuous variables), and default cost is 0 */ 1030 SCIP_CALL( SCIPcreateVar(scip, &var, colname, 0.0, 1.0, 0.0, SCIP_VARTYPE_BINARY, 1031 !mpsi->dynamiccols, mpsi->dynamiccols, NULL, NULL, NULL, NULL, NULL) ); 1032 } 1033 else 1034 { 1035 /* for continuous variables, default bounds are 0 <= x, and default cost is 0 */ 1036 SCIP_CALL( SCIPcreateVar(scip, &var, colname, 0.0, SCIPinfinity(scip), 0.0, SCIP_VARTYPE_CONTINUOUS, 1037 !mpsi->dynamiccols, mpsi->dynamiccols, NULL, NULL, NULL, NULL, NULL) ); 1038 } 1039 } 1040 assert(var != NULL); 1041 1042 val = atof(mpsinputField3(mpsi)); 1043 1044 if( !strcmp(mpsinputField2(mpsi), mpsinputObjname(mpsi)) ) 1045 { 1046 SCIP_CALL( SCIPchgVarObj(scip, var, val) ); 1047 } 1048 else 1049 { 1050 cons = SCIPfindCons(scip, mpsinputField2(mpsi)); 1051 if( cons == NULL ) 1052 mpsinputEntryIgnored(scip, mpsi, "Column", mpsinputField1(mpsi), "row", mpsinputField2(mpsi), SCIP_VERBLEVEL_FULL); 1053 else if( !SCIPisZero(scip, val) ) 1054 { 1055 /* warn the user in case the coefficient is infinite */ 1056 if( SCIPisInfinity(scip, REALABS(val)) ) 1057 { 1058 SCIPwarningMessage(scip, "Coefficient of variable <%s> in constraint <%s> contains infinite value <%e>," 1059 " consider adjusting SCIP infinity.\n", SCIPvarGetName(var), SCIPconsGetName(cons), val); 1060 } 1061 SCIP_CALL( SCIPaddCoefLinear(scip, cons, var, val) ); 1062 } 1063 } 1064 if( mpsinputField5(mpsi) != NULL ) 1065 { 1066 assert(mpsinputField4(mpsi) != NULL); 1067 1068 val = atof(mpsinputField5(mpsi)); 1069 1070 if( !strcmp(mpsinputField4(mpsi), mpsinputObjname(mpsi)) ) 1071 { 1072 SCIP_CALL( SCIPchgVarObj(scip, var, val) ); 1073 } 1074 else 1075 { 1076 cons = SCIPfindCons(scip, mpsinputField4(mpsi)); 1077 if( cons == NULL ) 1078 mpsinputEntryIgnored(scip, mpsi, "Column", mpsinputField1(mpsi), "row", mpsinputField4(mpsi), SCIP_VERBLEVEL_FULL); 1079 else if( !SCIPisZero(scip, val) ) 1080 { 1081 SCIP_CALL( SCIPaddCoefLinear(scip, cons, var, val) ); 1082 } 1083 } 1084 } 1085 } 1086 mpsinputSyntaxerror(mpsi); 1087 1088 return SCIP_OKAY; 1089 } 1090 1091 /** Process RHS section. */ 1092 static 1093 SCIP_RETCODE readRhs( 1094 MPSINPUT* mpsi, /**< mps input structure */ 1095 SCIP* scip /**< SCIP data structure */ 1096 ) 1097 { 1098 char rhsname[MPS_MAX_NAMELEN] = { '\0' }; 1099 SCIP_CONS* cons; 1100 SCIP_Real lhs; 1101 SCIP_Real rhs; 1102 SCIP_Real val; 1103 1104 SCIPdebugMsg(scip, "read right hand sides\n"); 1105 1106 while( mpsinputReadLine(mpsi) ) 1107 { 1108 if( mpsinputField0(mpsi) != NULL ) 1109 { 1110 if( !strcmp(mpsinputField0(mpsi), "RANGES") ) 1111 mpsinputSetSection(mpsi, MPS_RANGES); 1112 else if( !strcmp(mpsinputField0(mpsi), "BOUNDS") ) 1113 mpsinputSetSection(mpsi, MPS_BOUNDS); 1114 else if( !strcmp(mpsinputField0(mpsi), "SOS") ) 1115 mpsinputSetSection(mpsi, MPS_SOS); 1116 else if( !strcmp(mpsinputField0(mpsi), "QMATRIX") ) 1117 mpsinputSetSection(mpsi, MPS_QMATRIX); 1118 else if( !strcmp(mpsinputField0(mpsi), "QUADOBJ") ) 1119 mpsinputSetSection(mpsi, MPS_QUADOBJ); 1120 else if( !strcmp(mpsinputField0(mpsi), "QCMATRIX") ) 1121 mpsinputSetSection(mpsi, MPS_QCMATRIX); 1122 else if( !strcmp(mpsinputField0(mpsi), "INDICATORS") ) 1123 mpsinputSetSection(mpsi, MPS_INDICATORS); 1124 else if( !strcmp(mpsinputField0(mpsi), "ENDATA") ) 1125 mpsinputSetSection(mpsi, MPS_ENDATA); 1126 else 1127 break; 1128 return SCIP_OKAY; 1129 } 1130 if( (mpsinputField2(mpsi) != NULL && mpsinputField3(mpsi) == NULL) 1131 || (mpsinputField4(mpsi) != NULL && mpsinputField5(mpsi) == NULL) ) 1132 { 1133 SCIPwarningMessage(scip, "reading rhs section, a field is missing, assuming that the vector name is the missing one(, row identfier <%s>)\n", mpsinputField2(mpsi)); 1134 1135 mpsinputInsertName(mpsi, "_RHS_", FALSE); 1136 } 1137 1138 if( mpsinputField1(mpsi) == NULL || mpsinputField2(mpsi) == NULL || mpsinputField3(mpsi) == NULL ) 1139 break; 1140 1141 if( *rhsname == '\0' ) 1142 (void)SCIPmemccpy(rhsname, mpsinputField1(mpsi), '\0', MPS_MAX_NAMELEN - 1); 1143 1144 if( !strcmp(rhsname, mpsinputField1(mpsi)) ) 1145 { 1146 cons = SCIPfindCons(scip, mpsinputField2(mpsi)); 1147 if( cons == NULL ) 1148 { 1149 /* the rhs of the objective row is treated as objective constant */ 1150 if( strcmp(mpsinputField2(mpsi), mpsinputObjname(mpsi)) == 0 ) 1151 { 1152 val = atof(mpsinputField3(mpsi)); 1153 SCIP_CALL( SCIPaddOrigObjoffset(scip, -val) ); 1154 } 1155 else 1156 mpsinputEntryIgnored(scip, mpsi, "RHS", mpsinputField1(mpsi), "row", mpsinputField2(mpsi), SCIP_VERBLEVEL_NORMAL); 1157 } 1158 else 1159 { 1160 val = atof(mpsinputField3(mpsi)); 1161 1162 /* find out the row sense */ 1163 lhs = SCIPgetLhsLinear(scip, cons); 1164 rhs = SCIPgetRhsLinear(scip, cons); 1165 if( SCIPisInfinity(scip, -lhs) ) 1166 { 1167 /* lhs = -infinity -> lower or equal */ 1168 assert(SCIPisZero(scip, rhs)); 1169 SCIP_CALL( SCIPchgRhsLinear(scip, cons, val) ); 1170 } 1171 else if( SCIPisInfinity(scip, rhs) ) 1172 { 1173 /* rhs = +infinity -> greater or equal */ 1174 assert(SCIPisZero(scip, lhs)); 1175 SCIP_CALL( SCIPchgLhsLinear(scip, cons, val) ); 1176 } 1177 else 1178 { 1179 /* lhs > -infinity, rhs < infinity -> equality */ 1180 assert(SCIPisZero(scip, lhs)); 1181 assert(SCIPisZero(scip, rhs)); 1182 SCIP_CALL( SCIPchgLhsLinear(scip, cons, val) ); 1183 SCIP_CALL( SCIPchgRhsLinear(scip, cons, val) ); 1184 } 1185 SCIPdebugMsg(scip, "RHS <%s> lhs: %g rhs: %g val: <%22.12g>\n", mpsinputField2(mpsi), lhs, rhs, val); 1186 } 1187 if( mpsinputField5(mpsi) != NULL ) 1188 { 1189 cons = SCIPfindCons(scip, mpsinputField4(mpsi)); 1190 if( cons == NULL ) 1191 { 1192 /* the rhs of the objective row is treated as objective constant */ 1193 if( strcmp(mpsinputField4(mpsi), mpsinputObjname(mpsi)) == 0 ) 1194 { 1195 val = atof(mpsinputField5(mpsi)); 1196 SCIP_CALL( SCIPaddOrigObjoffset(scip, -val) ); 1197 } 1198 else 1199 mpsinputEntryIgnored(scip, mpsi, "RHS", mpsinputField1(mpsi), "row", mpsinputField4(mpsi), SCIP_VERBLEVEL_NORMAL); 1200 } 1201 else 1202 { 1203 val = atof(mpsinputField5(mpsi)); 1204 1205 /* find out the row sense */ 1206 lhs = SCIPgetLhsLinear(scip, cons); 1207 rhs = SCIPgetRhsLinear(scip, cons); 1208 if( SCIPisInfinity(scip, -lhs) ) 1209 { 1210 /* lhs = -infinity -> lower or equal */ 1211 assert(SCIPisZero(scip, rhs)); 1212 SCIP_CALL( SCIPchgRhsLinear(scip, cons, val) ); 1213 } 1214 else if( SCIPisInfinity(scip, rhs) ) 1215 { 1216 /* rhs = +infinity -> greater or equal */ 1217 assert(SCIPisZero(scip, lhs)); 1218 SCIP_CALL( SCIPchgLhsLinear(scip, cons, val) ); 1219 } 1220 else 1221 { 1222 /* lhs > -infinity, rhs < infinity -> equality */ 1223 assert(SCIPisZero(scip, lhs)); 1224 assert(SCIPisZero(scip, rhs)); 1225 SCIP_CALL( SCIPchgLhsLinear(scip, cons, val) ); 1226 SCIP_CALL( SCIPchgRhsLinear(scip, cons, val) ); 1227 } 1228 SCIPdebugMsg(scip, "RHS <%s> lhs: %g rhs: %g val: <%22.12g>\n", mpsinputField4(mpsi), lhs, rhs, val); 1229 } 1230 } 1231 } 1232 } 1233 mpsinputSyntaxerror(mpsi); 1234 1235 return SCIP_OKAY; 1236 } 1237 1238 /** Process RANGES section */ 1239 static 1240 SCIP_RETCODE readRanges( 1241 MPSINPUT* mpsi, /**< mps input structure */ 1242 SCIP* scip /**< SCIP data structure */ 1243 ) 1244 { 1245 char rngname[MPS_MAX_NAMELEN] = { '\0' }; 1246 SCIP_CONS* cons; 1247 SCIP_Real lhs; 1248 SCIP_Real rhs; 1249 SCIP_Real val; 1250 1251 SCIPdebugMsg(scip, "read ranges\n"); 1252 1253 while( mpsinputReadLine(mpsi) ) 1254 { 1255 if( mpsinputField0(mpsi) != NULL ) 1256 { 1257 if( !strcmp(mpsinputField0(mpsi), "BOUNDS") ) 1258 mpsinputSetSection(mpsi, MPS_BOUNDS); 1259 else if( !strcmp(mpsinputField0(mpsi), "SOS") ) 1260 mpsinputSetSection(mpsi, MPS_SOS); 1261 else if( !strcmp(mpsinputField0(mpsi), "QMATRIX") ) 1262 mpsinputSetSection(mpsi, MPS_QMATRIX); 1263 else if( !strcmp(mpsinputField0(mpsi), "QUADOBJ") ) 1264 mpsinputSetSection(mpsi, MPS_QUADOBJ); 1265 else if( !strcmp(mpsinputField0(mpsi), "QCMATRIX") ) 1266 mpsinputSetSection(mpsi, MPS_QCMATRIX); 1267 else if( !strcmp(mpsinputField0(mpsi), "INDICATORS") ) 1268 mpsinputSetSection(mpsi, MPS_INDICATORS); 1269 else if( !strcmp(mpsinputField0(mpsi), "ENDATA") ) 1270 mpsinputSetSection(mpsi, MPS_ENDATA); 1271 else 1272 break; 1273 return SCIP_OKAY; 1274 } 1275 if( (mpsinputField2(mpsi) != NULL && mpsinputField3(mpsi) == NULL) 1276 || (mpsinputField4(mpsi) != NULL && mpsinputField5(mpsi) == NULL) ) 1277 { 1278 SCIPwarningMessage(scip, "reading ranged section, a field is missing, assuming that the vector name is the missing one(, row identfier <%s>)\n", mpsinputField2(mpsi)); 1279 1280 mpsinputInsertName(mpsi, "_RNG_", FALSE); 1281 } 1282 1283 if( mpsinputField1(mpsi) == NULL || mpsinputField2(mpsi) == NULL || mpsinputField3(mpsi) == NULL ) 1284 break; 1285 1286 if( *rngname == '\0' ) 1287 (void)SCIPmemccpy(rngname, mpsinputField1(mpsi), '\0', MPS_MAX_NAMELEN - 1); 1288 1289 /* The rules are: 1290 * Row Sign LHS RHS 1291 * ---------------------------------------- 1292 * G +/- rhs rhs + |range| 1293 * L +/- rhs - |range| rhs 1294 * E + rhs rhs + range 1295 * E - rhs + range rhs 1296 * ---------------------------------------- 1297 */ 1298 if( !strcmp(rngname, mpsinputField1(mpsi)) ) 1299 { 1300 cons = SCIPfindCons(scip, mpsinputField2(mpsi)); 1301 if( cons == NULL ) 1302 mpsinputEntryIgnored(scip, mpsi, "Range", mpsinputField1(mpsi), "row", mpsinputField2(mpsi), SCIP_VERBLEVEL_NORMAL); 1303 else 1304 { 1305 val = atof(mpsinputField3(mpsi)); 1306 1307 /* find out the row sense */ 1308 lhs = SCIPgetLhsLinear(scip, cons); 1309 rhs = SCIPgetRhsLinear(scip, cons); 1310 if( SCIPisInfinity(scip, -lhs) ) 1311 { 1312 /* lhs = -infinity -> lower or equal */ 1313 SCIP_CALL( SCIPchgLhsLinear(scip, cons, rhs - REALABS(val)) ); 1314 } 1315 else if( SCIPisInfinity(scip, rhs) ) 1316 { 1317 /* rhs = +infinity -> greater or equal */ 1318 SCIP_CALL( SCIPchgRhsLinear(scip, cons, lhs + REALABS(val)) ); 1319 } 1320 else 1321 { 1322 /* lhs > -infinity, rhs < infinity -> equality */ 1323 assert(SCIPisEQ(scip, lhs, rhs)); 1324 if( val >= 0.0 ) 1325 { 1326 SCIP_CALL( SCIPchgRhsLinear(scip, cons, rhs + val) ); 1327 } 1328 else 1329 { 1330 SCIP_CALL( SCIPchgLhsLinear(scip, cons, lhs + val) ); 1331 } 1332 } 1333 } 1334 if( mpsinputField5(mpsi) != NULL ) 1335 { 1336 cons = SCIPfindCons(scip, mpsinputField4(mpsi)); 1337 if( cons == NULL ) 1338 mpsinputEntryIgnored(scip, mpsi, "Range", mpsinputField1(mpsi), "row", mpsinputField4(mpsi), SCIP_VERBLEVEL_NORMAL); 1339 else 1340 { 1341 val = atof(mpsinputField5(mpsi)); 1342 1343 /* find out the row sense */ 1344 lhs = SCIPgetLhsLinear(scip, cons); 1345 rhs = SCIPgetRhsLinear(scip, cons); 1346 if( SCIPisInfinity(scip, -lhs) ) 1347 { 1348 /* lhs = -infinity -> lower or equal */ 1349 SCIP_CALL( SCIPchgLhsLinear(scip, cons, rhs - REALABS(val)) ); 1350 } 1351 else if( SCIPisInfinity(scip, rhs) ) 1352 { 1353 /* rhs = +infinity -> greater or equal */ 1354 SCIP_CALL( SCIPchgRhsLinear(scip, cons, lhs + REALABS(val)) ); 1355 } 1356 else 1357 { 1358 /* lhs > -infinity, rhs < infinity -> equality */ 1359 assert(SCIPisEQ(scip, lhs, rhs)); 1360 if( val >= 0.0 ) 1361 { 1362 SCIP_CALL( SCIPchgRhsLinear(scip, cons, rhs + val) ); 1363 } 1364 else 1365 { 1366 SCIP_CALL( SCIPchgLhsLinear(scip, cons, lhs + val) ); 1367 } 1368 } 1369 } 1370 } 1371 } 1372 } 1373 mpsinputSyntaxerror(mpsi); 1374 1375 return SCIP_OKAY; 1376 } 1377 1378 /** Process BOUNDS section. */ 1379 static 1380 SCIP_RETCODE readBounds( 1381 MPSINPUT* mpsi, /**< mps input structure */ 1382 SCIP* scip /**< SCIP data structure */ 1383 ) 1384 { 1385 char bndname[MPS_MAX_NAMELEN] = { '\0' }; 1386 SCIP_VAR* var; 1387 SCIP_RETCODE retcode; 1388 SCIP_Real val; 1389 SCIP_Bool shifted; 1390 1391 SCIP_VAR** semicont; 1392 int nsemicont; 1393 int semicontsize; 1394 1395 retcode = SCIP_OKAY; 1396 1397 semicont = NULL; 1398 nsemicont = 0; 1399 semicontsize = 0; 1400 1401 SCIPdebugMsg(scip, "read bounds\n"); 1402 1403 while( mpsinputReadLine(mpsi) ) 1404 { 1405 if( mpsinputField0(mpsi) != 0 ) 1406 { 1407 if( !strcmp(mpsinputField0(mpsi), "SOS") ) 1408 mpsinputSetSection(mpsi, MPS_SOS); 1409 else if( !strcmp(mpsinputField0(mpsi), "QMATRIX") ) 1410 mpsinputSetSection(mpsi, MPS_QMATRIX); 1411 else if( !strcmp(mpsinputField0(mpsi), "QUADOBJ") ) 1412 mpsinputSetSection(mpsi, MPS_QUADOBJ); 1413 else if( !strcmp(mpsinputField0(mpsi), "QCMATRIX") ) 1414 mpsinputSetSection(mpsi, MPS_QCMATRIX); 1415 else if( !strcmp(mpsinputField0(mpsi), "INDICATORS") ) 1416 mpsinputSetSection(mpsi, MPS_INDICATORS); 1417 else if( !strcmp(mpsinputField0(mpsi), "ENDATA") ) 1418 mpsinputSetSection(mpsi, MPS_ENDATA); 1419 else 1420 break; 1421 goto READBOUNDS_FINISH; 1422 } 1423 1424 shifted = FALSE; 1425 1426 /* Is the value field used ? */ 1427 if( !strcmp(mpsinputField1(mpsi), "LO") /* lower bound given in field 4 */ 1428 || !strcmp(mpsinputField1(mpsi), "UP") /* upper bound given in field 4 */ 1429 || !strcmp(mpsinputField1(mpsi), "FX") /* fixed value given in field 4 */ 1430 || !strcmp(mpsinputField1(mpsi), "LI") /* CPLEX extension: lower bound of integer variable given in field 4 */ 1431 || !strcmp(mpsinputField1(mpsi), "UI") /* CPLEX extension: upper bound of integer variable given in field 4 */ 1432 || !strcmp(mpsinputField1(mpsi), "SC") /* CPLEX extension: semi-continuous variable, upper bound given in field 4 */ 1433 || !strcmp(mpsinputField1(mpsi), "SI") )/* CPLEX extension: semi-integer variable, upper bound given in field 4 */ 1434 { 1435 if( mpsinputField3(mpsi) != NULL && mpsinputField4(mpsi) == NULL ) 1436 { 1437 int l; 1438 1439 /* check what might be missing, if field 3 is a number the bound name might be missing */ 1440 for( l = (int) strlen(mpsinputField3(mpsi)) - 1; l >= 0; --l ) 1441 { 1442 if( mpsinputField3(mpsi)[l] != '.' && !isdigit(mpsinputField3(mpsi)[l]) ) 1443 break; 1444 } 1445 1446 /* the bound name?! is missing */ 1447 if( l < 0 ) 1448 { 1449 SCIPwarningMessage(scip, "in bound section a name for value <%s> might be missing\n", mpsinputField3(mpsi)); 1450 1451 mpsinputInsertName(mpsi, "_BND_", TRUE); 1452 shifted = TRUE; 1453 } 1454 /* the bound is be missing */ 1455 else 1456 { 1457 SCIPwarningMessage(scip, "in bound section a value for column <%s> is missing, assuming 0.0\n", mpsinputField3(mpsi)); 1458 1459 mpsinputInsertField4(mpsi, "0.0"); 1460 shifted = TRUE; 1461 } 1462 } 1463 } 1464 else if( !strcmp(mpsinputField1(mpsi), "FR") /* free variable */ 1465 || !strcmp(mpsinputField1(mpsi), "MI") /* lower bound is minus infinity */ 1466 || !strcmp(mpsinputField1(mpsi), "PL") /* upper bound is plus infinity */ 1467 || !strcmp(mpsinputField1(mpsi), "BV") ) /* CPLEX extension: binary variable */ 1468 { 1469 if( mpsinputField2(mpsi) != NULL && mpsinputField3(mpsi) == NULL ) 1470 { 1471 SCIPwarningMessage(scip, "in bound section a name for a column is missing\n"); 1472 1473 mpsinputInsertName(mpsi, "_BND_", TRUE); 1474 shifted = TRUE; 1475 } 1476 } 1477 else 1478 { 1479 mpsinputSyntaxerror(mpsi); 1480 return SCIP_OKAY; 1481 } 1482 1483 if( mpsinputField1(mpsi) == NULL || mpsinputField2(mpsi) == NULL || mpsinputField3(mpsi) == NULL ) 1484 break; 1485 1486 if( *bndname == '\0' ) 1487 (void)SCIPmemccpy(bndname, mpsinputField2(mpsi), '\0', MPS_MAX_NAMELEN - 1); 1488 1489 /* Only read the first Bound in section */ 1490 if( !strcmp(bndname, mpsinputField2(mpsi)) ) 1491 { 1492 SCIP_VARTYPE oldvartype; 1493 SCIP_Bool infeasible; 1494 1495 var = SCIPfindVar(scip, mpsinputField3(mpsi)); 1496 /* if variable did not appear in columns section before, then it may still come in later sections (QCMATRIX, QMATRIX, SOS, ...) 1497 * thus add it as continuous variables, which has default bounds 0.0 <= x, and default cost 0.0 */ 1498 if( var == NULL ) 1499 { 1500 SCIP_VAR* varcpy; 1501 1502 SCIP_CALL( SCIPcreateVar(scip, &var, mpsinputField3(mpsi), 0.0, SCIPinfinity(scip), 0.0, 1503 SCIP_VARTYPE_CONTINUOUS, !mpsi->dynamiccols, mpsi->dynamiccols, NULL, NULL, NULL, NULL, NULL) ); 1504 1505 SCIP_CALL( SCIPaddVar(scip, var) ); 1506 varcpy = var; 1507 SCIP_CALL( SCIPreleaseVar(scip, &varcpy) ); 1508 /* mpsinputEntryIgnored(scip, mpsi, "column", mpsinputField3(mpsi), "bound", bndname, SCIP_VERBLEVEL_NORMAL); */ 1509 } 1510 assert(var != NULL); 1511 1512 if( mpsinputField4(mpsi) == NULL ) 1513 val = 0.0; 1514 else 1515 val = atof(mpsinputField4(mpsi)); 1516 1517 /* remember variable type */ 1518 oldvartype = SCIPvarGetType(var); 1519 1520 /* If a bound of a binary variable is given, the variable is converted into an integer variable 1521 * with default bounds 0 <= x <= infinity before applying the bound. Note that integer variables 1522 * are by default assumed to be binary, but an explicit lower bound of 0 turns them into integer variables. 1523 * Only if the upper bound is explicitly set to 1, we leave the variable as a binary one. 1524 */ 1525 if( oldvartype == SCIP_VARTYPE_BINARY && !((mpsinputField1(mpsi)[0] == 'U' || 1526 (mpsinputField1(mpsi)[0] == 'F' && mpsinputField1(mpsi)[1] == 'X')) && SCIPisFeasEQ(scip, val, 1.0)) 1527 && !(mpsinputField1(mpsi)[0] == 'F' && mpsinputField1(mpsi)[1] == 'X'&& SCIPisFeasEQ(scip, val, 0.0)) ) 1528 { 1529 SCIP_CALL( SCIPchgVarType(scip, var, SCIP_VARTYPE_INTEGER, &infeasible) ); 1530 assert(!infeasible); 1531 1532 oldvartype = SCIP_VARTYPE_INTEGER; 1533 SCIP_CALL( SCIPchgVarUb(scip, var, SCIPinfinity(scip)) ); 1534 } 1535 1536 /* switch variable type to continuous before applying the bound, this is necessary for stupid non-integral 1537 * bounds on general variables, which even might lead to infeasibility 1538 */ 1539 if( oldvartype != SCIP_VARTYPE_CONTINUOUS ) 1540 { 1541 assert(SCIP_VARTYPE_CONTINUOUS >= SCIP_VARTYPE_IMPLINT && SCIP_VARTYPE_IMPLINT >= SCIP_VARTYPE_INTEGER && SCIP_VARTYPE_INTEGER >= SCIP_VARTYPE_BINARY); /*lint !e506*//*lint !e1564*/ 1542 /* relaxing variable type */ 1543 SCIP_CALL( SCIPchgVarType(scip, var, SCIP_VARTYPE_CONTINUOUS, &infeasible) ); 1544 } 1545 assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS); 1546 1547 switch( mpsinputField1(mpsi)[0] ) 1548 { 1549 case 'L': 1550 if( !SCIPisZero(scip, SCIPvarGetLbGlobal(var)) && SCIPisLT(scip, val, SCIPvarGetLbGlobal(var)) ) 1551 { 1552 SCIPwarningMessage(scip, "Relaxing already defined lower bound %g of variable <%s> to %g not allowed.\n", SCIPvarGetLbGlobal(var), SCIPvarGetName(var), val); 1553 } 1554 1555 SCIP_CALL( SCIPchgVarLb(scip, var, val) ); 1556 1557 if( mpsinputField1(mpsi)[1] == 'I' ) /* CPLEX extension (Integer Bound) */ 1558 { 1559 if( !SCIPisFeasIntegral(scip, val) ) 1560 { 1561 SCIPwarningMessage(scip, "variable <%s> declared as integral has a non-integral lower bound (%.14g) -> if feasible, bounds will be adjusted\n", SCIPvarGetName(var), val); 1562 } 1563 SCIP_CALL( SCIPchgVarType(scip, var, SCIP_VARTYPE_INTEGER, &infeasible) ); 1564 /* don't assert feasibility here because the presolver will and should detect a infeasibility */ 1565 } 1566 else if( oldvartype < SCIP_VARTYPE_CONTINUOUS ) 1567 { 1568 if( !SCIPisFeasIntegral(scip, val) ) 1569 { 1570 SCIPwarningMessage(scip, "variable <%s> declared as integral has a non-integral lower bound (%.14g) -> if feasible, bounds will be adjusted\n", SCIPvarGetName(var), val); 1571 } 1572 } 1573 1574 break; 1575 case 'U': 1576 if( SCIPisGT(scip, val, SCIPvarGetUbGlobal(var)) ) 1577 { 1578 SCIPwarningMessage(scip, "Relaxing already defined upper bound %g of variable <%s> to %g not allowed.\n", SCIPvarGetUbGlobal(var), SCIPvarGetName(var), val); 1579 } 1580 1581 SCIP_CALL( SCIPchgVarUb(scip, var, val) ); 1582 if( mpsinputField1(mpsi)[1] == 'I' ) /* CPLEX extension (Integer Bound) */ 1583 { 1584 if( !SCIPisFeasIntegral(scip, val) ) 1585 { 1586 SCIPwarningMessage(scip, "variable <%s> declared as integral has a non-integral upper bound (%.14g) -> if feasible, bounds will be adjusted\n", SCIPvarGetName(var), val); 1587 } 1588 1589 SCIP_CALL( SCIPchgVarType(scip, var, SCIP_VARTYPE_INTEGER, &infeasible) ); 1590 /* don't assert feasibility here because the presolver will and should detect an infeasibility */ 1591 } 1592 else if( oldvartype < SCIP_VARTYPE_CONTINUOUS ) 1593 { 1594 if( !SCIPisFeasIntegral(scip, val) ) 1595 { 1596 SCIPwarningMessage(scip, "variable <%s> declared as integral has a non-integral upper bound (%.14g) -> if feasible, bounds will be adjusted\n", SCIPvarGetName(var), val); 1597 } 1598 } 1599 break; 1600 case 'S': 1601 assert(mpsinputField1(mpsi)[1] == 'C' || mpsinputField1(mpsi)[1] == 'I'); /* semi-continuous or semi-integer (CPLEX extension) */ 1602 /* remember that variable is semi-continuous/-integer */ 1603 if( semicontsize <= nsemicont ) 1604 { 1605 semicontsize = SCIPcalcMemGrowSize(scip, nsemicont+1); 1606 if( semicont == NULL ) 1607 { 1608 SCIP_CALL( SCIPallocBufferArray(scip, &semicont, semicontsize) ); 1609 } 1610 else 1611 { 1612 SCIP_CALL( SCIPreallocBufferArray(scip, &semicont, semicontsize) ); 1613 } 1614 } 1615 assert(semicont != NULL); 1616 semicont[nsemicont] = var; 1617 ++nsemicont; 1618 1619 if( mpsinputField1(mpsi)[1] == 'I' ) /* variable is semi-integer, hence change its type to integer (the "semi" part will be handled below) */ 1620 { 1621 SCIP_CALL( SCIPchgVarType(scip, var, SCIP_VARTYPE_INTEGER, &infeasible) ); 1622 /* don't assert feasibility here because the presolver will and should detect an infeasibility */ 1623 } 1624 1625 /* if both bounds are infinite anyway, we do not need to print a warning or change the bound */ 1626 if( !SCIPisInfinity(scip, val) || !SCIPisInfinity(scip, SCIPvarGetUbGlobal(var)) ) 1627 { 1628 if( SCIPisGT(scip, val, SCIPvarGetUbGlobal(var)) ) 1629 { 1630 SCIPwarningMessage(scip, "Relaxing already defined upper bound %g of variable <%s> to %g not allowed.\n", SCIPvarGetUbGlobal(var), SCIPvarGetName(var), val); 1631 } 1632 1633 SCIP_CALL( SCIPchgVarUb(scip, var, val) ); 1634 } 1635 break; 1636 case 'F': 1637 if( mpsinputField1(mpsi)[1] == 'X' ) 1638 { 1639 SCIP_CALL( SCIPchgVarLb(scip, var, val) ); 1640 SCIP_CALL( SCIPchgVarUb(scip, var, val) ); 1641 } 1642 else 1643 { 1644 SCIP_CALL( SCIPchgVarLb(scip, var, -SCIPinfinity(scip)) ); 1645 SCIP_CALL( SCIPchgVarUb(scip, var, +SCIPinfinity(scip)) ); 1646 } 1647 break; 1648 case 'M': 1649 SCIP_CALL( SCIPchgVarLb(scip, var, -SCIPinfinity(scip)) ); 1650 break; 1651 case 'P': 1652 SCIP_CALL( SCIPchgVarUb(scip, var, +SCIPinfinity(scip)) ); 1653 break; 1654 case 'B' : /* CPLEX extension (Binary) */ 1655 SCIP_CALL( SCIPchgVarLb(scip, var, 0.0) ); 1656 SCIP_CALL( SCIPchgVarUb(scip, var, 1.0) ); 1657 SCIP_CALL( SCIPchgVarType(scip, var, SCIP_VARTYPE_BINARY, &infeasible) ); 1658 /* don't assert feasibility here because the presolver will and should detect a infeasibility */ 1659 break; 1660 default: 1661 mpsinputSyntaxerror(mpsi); 1662 return SCIP_OKAY; 1663 } 1664 1665 /* switch variable type back to old type if necessary */ 1666 if( oldvartype < SCIPvarGetType(var) ) 1667 { 1668 SCIP_CALL( SCIPchgVarType(scip, var, oldvartype, &infeasible) ); 1669 } 1670 } 1671 else 1672 { 1673 /* check for syntax error */ 1674 assert(*bndname != '\0'); 1675 if( strcmp(bndname, mpsinputField3(mpsi)) == 0 && shifted ) 1676 { 1677 mpsinputSyntaxerror(mpsi); 1678 return SCIP_OKAY; 1679 } 1680 1681 mpsinputEntryIgnored(scip, mpsi, "bound", mpsinputField2(mpsi), "variable", mpsinputField3(mpsi), SCIP_VERBLEVEL_NORMAL); 1682 } 1683 } 1684 mpsinputSyntaxerror(mpsi); 1685 1686 READBOUNDS_FINISH: 1687 if( nsemicont > 0 ) 1688 { 1689 SCIP_CONS* cons; 1690 SCIP_VAR* vars[2]; 1691 SCIP_BOUNDTYPE boundtypes[2]; 1692 SCIP_Real bounds[2]; 1693 char name[SCIP_MAXSTRLEN]; 1694 SCIP_Real oldlb; 1695 int i; 1696 1697 assert(semicont != NULL); 1698 1699 /* add bound disjunction constraints for semi-continuous and semi-integer variables */ 1700 for( i = 0; i < nsemicont; ++i ) 1701 { 1702 var = semicont[i]; 1703 assert(SCIPvarGetType(var) == SCIP_VARTYPE_INTEGER || SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS); 1704 1705 oldlb = SCIPvarGetLbGlobal(var); 1706 assert(oldlb >= 0.0); 1707 1708 /* if no bound was specified (which we assume if we see lower bound 0.0), 1709 * then the default lower bound for a semi-continuous variable is 1.0 */ 1710 if( oldlb == 0.0 ) 1711 oldlb = 1.0; 1712 1713 /* change the lower bound to 0.0 */ 1714 SCIP_CALL( SCIPchgVarLb(scip, var, 0.0) ); 1715 1716 /* add a bound disjunction constraint to say var <= 0.0 or var >= oldlb */ 1717 (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "semicont_%s", SCIPvarGetName(var)); 1718 1719 vars[0] = var; 1720 vars[1] = var; 1721 boundtypes[0] = SCIP_BOUNDTYPE_UPPER; 1722 boundtypes[1] = SCIP_BOUNDTYPE_LOWER; 1723 bounds[0] = 0.0; 1724 bounds[1] = oldlb; 1725 1726 retcode = SCIPcreateConsBounddisjunction(scip, &cons, name, 2, vars, boundtypes, bounds, 1727 !mpsi->dynamiccols, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, mpsi->dynamicconss, mpsi->dynamiccols, FALSE); 1728 1729 if( retcode != SCIP_OKAY ) 1730 break; 1731 1732 SCIP_CALL( SCIPaddCons(scip, cons) ); 1733 1734 SCIPdebugMsg(scip, "add bound disjunction constraint for semi-continuity/-integrality of <%s>:\n\t", SCIPvarGetName(var)); 1735 SCIPdebugPrintCons(scip, cons, NULL); 1736 1737 SCIP_CALL( SCIPreleaseCons(scip, &cons) ); 1738 } 1739 } 1740 1741 SCIPfreeBufferArrayNull(scip, &semicont); 1742 1743 SCIP_CALL( retcode ); 1744 1745 return SCIP_OKAY; 1746 } 1747 1748 1749 /** Process SOS section. 1750 * 1751 * We read the SOS section, which is a nonstandard section introduced by CPLEX. 1752 * 1753 * @note Currently we do not support the standard way of specifying SOS constraints via markers. 1754 */ 1755 static 1756 SCIP_RETCODE readSOS( 1757 MPSINPUT* mpsi, /**< mps input structure */ 1758 SCIP* scip /**< SCIP data structure */ 1759 ) 1760 { 1761 SCIP_Bool initial; 1762 SCIP_Bool separate; 1763 SCIP_Bool enforce; 1764 SCIP_Bool check; 1765 SCIP_Bool propagate; 1766 SCIP_Bool local; 1767 SCIP_Bool dynamic; 1768 SCIP_Bool removable; 1769 char name[MPS_MAX_NAMELEN] = { '\0' }; 1770 SCIP_CONS* cons = NULL; 1771 int consType = -1; 1772 int cnt = 0; 1773 1774 SCIPdebugMsg(scip, "read SOS constraints\n"); 1775 1776 /* standard settings for SOS constraints: */ 1777 initial = mpsi->initialconss; 1778 separate = TRUE; 1779 enforce = TRUE; 1780 check = TRUE; 1781 propagate = TRUE; 1782 local = FALSE; 1783 dynamic = mpsi->dynamicconss; 1784 removable = mpsi->dynamicrows; 1785 1786 /* loop through section */ 1787 while( mpsinputReadLine(mpsi) ) 1788 { 1789 int type = -1; 1790 1791 /* check if next section is found */ 1792 if( mpsinputField0(mpsi) != NULL ) 1793 { 1794 if( !strcmp(mpsinputField0(mpsi), "ENDATA") ) 1795 mpsinputSetSection(mpsi, MPS_ENDATA); 1796 else if( !strcmp(mpsinputField0(mpsi), "QMATRIX") ) 1797 mpsinputSetSection(mpsi, MPS_QMATRIX); 1798 else if( !strcmp(mpsinputField0(mpsi), "QUADOBJ") ) 1799 mpsinputSetSection(mpsi, MPS_QUADOBJ); 1800 else if( !strcmp(mpsinputField0(mpsi), "QCMATRIX") ) 1801 mpsinputSetSection(mpsi, MPS_QCMATRIX); 1802 else if( !strcmp(mpsinputField0(mpsi), "INDICATORS") ) 1803 mpsinputSetSection(mpsi, MPS_INDICATORS); 1804 break; 1805 } 1806 if( mpsinputField1(mpsi) == NULL ) 1807 { 1808 SCIPerrorMessage("empty data in a non-comment line.\n"); 1809 mpsinputSyntaxerror(mpsi); 1810 return SCIP_OKAY; 1811 } 1812 1813 /* check for new SOS set */ 1814 if( strcmp(mpsinputField1(mpsi), "S1") == 0 ) 1815 type = 1; 1816 if( strcmp(mpsinputField1(mpsi), "S2") == 0 ) 1817 type = 2; 1818 1819 /* add last constraint and create a new one */ 1820 if( type > 0 ) 1821 { 1822 assert( type == 1 || type == 2 ); 1823 if( cons != NULL ) 1824 { 1825 /* add last constraint */ 1826 SCIP_CALL( SCIPaddCons(scip, cons) ); 1827 SCIPdebugMsg(scip, "(line %d) added constraint <%s>: ", mpsi->lineno, SCIPconsGetName(cons)); 1828 SCIPdebugPrintCons(scip, cons, NULL); 1829 SCIP_CALL( SCIPreleaseCons(scip, &cons) ); 1830 } 1831 1832 /* check name */ 1833 if( mpsinputField2(mpsi) != NULL ) 1834 (void)SCIPmemccpy(name, mpsinputField2(mpsi), '\0', MPS_MAX_NAMELEN - 1); 1835 else 1836 { 1837 /* create new name */ 1838 (void) SCIPsnprintf(name, MPS_MAX_NAMELEN, "SOS%d", ++cnt); 1839 } 1840 1841 /* create new SOS constraint */ 1842 if( type == 1 ) 1843 { 1844 /* we do not know the name of the constraint */ 1845 SCIP_CALL( SCIPcreateConsSOS1(scip, &cons, name, 0, NULL, NULL, initial, separate, enforce, check, propagate, 1846 local, dynamic, removable, FALSE) ); 1847 } 1848 else 1849 { 1850 assert( type == 2 ); 1851 SCIP_CALL( SCIPcreateConsSOS2(scip, &cons, name, 0, NULL, NULL, initial, separate, enforce, check, propagate, 1852 local, dynamic, removable, FALSE) ); 1853 } 1854 consType = type; 1855 SCIPdebugMsg(scip, "created constraint <%s> of type %d.\n", name, type); 1856 /* note: we ignore the priorities! */ 1857 } 1858 else 1859 { 1860 /* otherwise we are in the section given variables */ 1861 SCIP_VAR* var; 1862 SCIP_Real weight; 1863 char* endptr; 1864 1865 if( consType != 1 && consType != 2 ) 1866 { 1867 SCIPerrorMessage("missing SOS type specification.\n"); 1868 mpsinputSyntaxerror(mpsi); 1869 return SCIP_OKAY; 1870 } 1871 1872 /* get variable */ 1873 var = SCIPfindVar(scip, mpsinputField1(mpsi)); 1874 if( var == NULL ) 1875 { 1876 /* ignore unknown variables - we would not know the type anyway */ 1877 mpsinputEntryIgnored(scip, mpsi, "column", mpsinputField1(mpsi), "SOS", name, SCIP_VERBLEVEL_NORMAL); 1878 } 1879 else 1880 { 1881 /* get weight */ 1882 if( NULL == mpsinputField2(mpsi) ) 1883 { 1884 SCIPerrorMessage("weight for variable <%s> not specified.\n", mpsinputField1(mpsi)); 1885 mpsinputSyntaxerror(mpsi); 1886 return SCIP_OKAY; 1887 } 1888 1889 weight = strtod(mpsinputField2(mpsi), &endptr); 1890 if( endptr == mpsinputField2(mpsi) || *endptr != '\0' ) 1891 { 1892 SCIPerrorMessage("weight for variable <%s> not specified.\n", mpsinputField1(mpsi)); 1893 mpsinputSyntaxerror(mpsi); 1894 return SCIP_OKAY; 1895 } 1896 1897 /* add variable and weight */ 1898 assert( consType == 1 || consType == 2 ); 1899 switch( consType ) 1900 { 1901 case 1: 1902 SCIP_CALL( SCIPaddVarSOS1(scip, cons, var, weight) ); 1903 break; 1904 case 2: 1905 SCIP_CALL( SCIPaddVarSOS2(scip, cons, var, weight) ); 1906 break; 1907 /* coverity[dead_error_begin] */ 1908 default: 1909 SCIPerrorMessage("unknown SOS type: <%d>\n", type); /* should not happen */ 1910 SCIPABORT(); 1911 return SCIP_INVALIDDATA; /*lint !e527*/ 1912 } 1913 SCIPdebugMsg(scip, "added variable <%s> with weight %g.\n", SCIPvarGetName(var), weight); 1914 } 1915 /* check other fields */ 1916 if( (mpsinputField3(mpsi) != NULL && *mpsinputField3(mpsi) != '\0' ) || 1917 (mpsinputField4(mpsi) != NULL && *mpsinputField4(mpsi) != '\0' ) || 1918 (mpsinputField5(mpsi) != NULL && *mpsinputField5(mpsi) != '\0' ) ) 1919 { 1920 SCIPwarningMessage(scip, "ignoring data in fields 3-5 <%s> <%s> <%s>.\n", 1921 mpsinputField3(mpsi), mpsinputField4(mpsi), mpsinputField5(mpsi)); 1922 } 1923 } 1924 } 1925 1926 if( cons != NULL ) 1927 { 1928 /* add last constraint */ 1929 SCIP_CALL( SCIPaddCons(scip, cons) ); 1930 SCIPdebugMsg(scip, "(line %d) added constraint <%s>: ", mpsi->lineno, SCIPconsGetName(cons)); 1931 SCIPdebugPrintCons(scip, cons, NULL); 1932 SCIP_CALL( SCIPreleaseCons(scip, &cons) ); 1933 } 1934 1935 return SCIP_OKAY; 1936 } 1937 1938 1939 /** Process QMATRIX or QUADOBJ section. 1940 * 1941 * - We read the QMATRIX or QUADOBJ section, which is a nonstandard section introduced by CPLEX. 1942 * - We create a quadratic constraint for this matrix and add a variable to the objective to 1943 * represent the value of the QMATRIX. 1944 * - For a QMATRIX, we expect that both lower and upper diagonal elements are given and every 1945 * coefficient has to be divided by 2.0. 1946 * - For a QUADOBJ, we expect that only the upper diagonal elements are given and thus only 1947 * coefficients on the diagonal have to be divided by 2.0. 1948 */ 1949 static 1950 SCIP_RETCODE readQMatrix( 1951 MPSINPUT* mpsi, /**< mps input structure */ 1952 SCIP_Bool isQuadObj, /**< whether we actually read a QUADOBJ section */ 1953 SCIP* scip /**< SCIP data structure */ 1954 ) 1955 { 1956 SCIP_VAR** quadvars1; 1957 SCIP_VAR** quadvars2; 1958 SCIP_Real* quadcoefs; 1959 SCIP_RETCODE retcode; 1960 int cnt = 0; /* number of qmatrix elements processed so far */ 1961 int size; /* size of quad* arrays */ 1962 1963 SCIPdebugMsg(scip, "read %s objective\n", isQuadObj ? "QUADOBJ" : "QMATRIX"); 1964 1965 retcode = SCIP_OKAY; 1966 1967 size = 1; 1968 SCIP_CALL( SCIPallocBufferArray(scip, &quadvars1, size) ); 1969 SCIP_CALL( SCIPallocBufferArray(scip, &quadvars2, size) ); 1970 SCIP_CALL( SCIPallocBufferArray(scip, &quadcoefs, size) ); 1971 1972 /* loop through section */ 1973 /* coverity[tainted_data] */ 1974 while( mpsinputReadLine(mpsi) ) 1975 { 1976 /* otherwise we are in the section given variables */ 1977 SCIP_VAR* var1; 1978 SCIP_VAR* var2; 1979 SCIP_Real coef; 1980 1981 /* check if next section is found */ 1982 if( mpsinputField0(mpsi) != NULL ) 1983 { 1984 if( !strcmp(mpsinputField0(mpsi), "QCMATRIX") ) 1985 mpsinputSetSection(mpsi, MPS_QCMATRIX); 1986 else if( !strcmp(mpsinputField0(mpsi), "INDICATORS") ) 1987 mpsinputSetSection(mpsi, MPS_INDICATORS); 1988 else if( !strcmp(mpsinputField0(mpsi), "ENDATA") ) 1989 mpsinputSetSection(mpsi, MPS_ENDATA); 1990 break; 1991 } 1992 if( mpsinputField1(mpsi) == NULL && mpsinputField2(mpsi) == NULL ) 1993 { 1994 SCIPerrorMessage("empty data in a non-comment line.\n"); 1995 mpsinputSyntaxerror(mpsi); 1996 SCIPfreeBufferArray(scip, &quadvars1); 1997 SCIPfreeBufferArray(scip, &quadvars2); 1998 SCIPfreeBufferArray(scip, &quadcoefs); 1999 return SCIP_OKAY; 2000 } 2001 2002 /* get first variable */ 2003 var1 = SCIPfindVar(scip, mpsinputField1(mpsi)); 2004 if( var1 == NULL ) 2005 { 2006 /* ignore unknown variables - we would not know the type anyway */ 2007 mpsinputEntryIgnored(scip, mpsi, "column", mpsinputField1(mpsi), "QMatrix", "QMATRIX", SCIP_VERBLEVEL_NORMAL); 2008 } 2009 else 2010 { 2011 int k; 2012 for( k = 1; k <= 2; ++k ) 2013 { 2014 /* get second variable */ 2015 var2 = SCIPfindVar(scip, k == 1 ? mpsinputField2(mpsi) : mpsinputField4(mpsi)); 2016 if( var2 == NULL ) 2017 { 2018 /* ignore unknown variables - we would not know the type anyway */ 2019 mpsinputEntryIgnored(scip, mpsi, "column", mpsinputField2(mpsi), "QMatrix", "QMATRIX", SCIP_VERBLEVEL_NORMAL); 2020 } 2021 else 2022 { 2023 const char* field; 2024 char* endptr; 2025 2026 /* get coefficient */ 2027 field = (k == 1 ? mpsinputField3(mpsi) : mpsinputField5(mpsi)); 2028 if( NULL == field ) 2029 { 2030 SCIPerrorMessage("coefficient of term <%s>*<%s> not specified.\n", SCIPvarGetName(var1), SCIPvarGetName(var2)); 2031 mpsinputSyntaxerror(mpsi); 2032 SCIPfreeBufferArray(scip, &quadvars1); 2033 SCIPfreeBufferArray(scip, &quadvars2); 2034 SCIPfreeBufferArray(scip, &quadcoefs); 2035 return SCIP_OKAY; 2036 } 2037 2038 coef = strtod(field, &endptr); 2039 if( endptr == field || *endptr != '\0' ) 2040 { 2041 SCIPerrorMessage("coefficient of term <%s>*<%s> not specified.\n", SCIPvarGetName(var1), SCIPvarGetName(var2)); 2042 mpsinputSyntaxerror(mpsi); 2043 SCIPfreeBufferArray(scip, &quadvars1); 2044 SCIPfreeBufferArray(scip, &quadvars2); 2045 SCIPfreeBufferArray(scip, &quadcoefs); 2046 return SCIP_OKAY; 2047 } 2048 2049 /* store variables and coefficient */ 2050 if( cnt >= size ) 2051 { 2052 int newsize = SCIPcalcMemGrowSize(scip, size+1); 2053 assert(newsize > size); 2054 SCIP_CALL( SCIPreallocBufferArray(scip, &quadvars1, newsize) ); 2055 SCIP_CALL( SCIPreallocBufferArray(scip, &quadvars2, newsize) ); 2056 SCIP_CALL( SCIPreallocBufferArray(scip, &quadcoefs, newsize) ); 2057 size = newsize; 2058 } 2059 assert(cnt < size); 2060 quadvars1[cnt] = var1; 2061 quadvars2[cnt] = var2; 2062 quadcoefs[cnt] = coef; 2063 2064 /* diagonal elements have to be divided by 2.0 2065 * in a QMATRIX section also off-diagonal have to be divided by 2.0, since both lower and upper diagonal elements are given 2066 */ 2067 if( var1 == var2 || !isQuadObj ) 2068 quadcoefs[cnt] /= 2.0; 2069 ++cnt; 2070 2071 SCIPdebugMsg(scip, "stored term %g*<%s>*<%s>.\n", coef, SCIPvarGetName(var1), SCIPvarGetName(var2)); 2072 } 2073 2074 if( mpsinputField4(mpsi) == NULL || *mpsinputField4(mpsi) == '\0' ) 2075 break; 2076 2077 if( mpsinputField5(mpsi) == NULL || *mpsinputField5(mpsi) == '\0' ) 2078 { 2079 /* ignore unknown variables - we would not know the type anyway */ 2080 mpsinputEntryIgnored(scip, mpsi, "column", mpsinputField4(mpsi), "QMatrix", "QMATRIX", SCIP_VERBLEVEL_NORMAL); 2081 break; 2082 } 2083 } 2084 } 2085 } 2086 2087 /* add constraint */ 2088 if( cnt ) 2089 { 2090 SCIP_Bool initial, separate, enforce, check, propagate; 2091 SCIP_Bool local, modifiable, dynamic, removable; 2092 SCIP_CONS* cons = NULL; 2093 SCIP_VAR* qmatrixvar = NULL; 2094 SCIP_Real lhs, rhs; 2095 SCIP_Real minusone = -1.0; 2096 2097 /* determine settings; note that reading/{initialconss,dynamicconss,dynamicrows,dynamiccols} apply only to model 2098 * constraints and variables, not to an auxiliary objective constraint (otherwise it can happen that an auxiliary 2099 * objective variable is loose with infinite best bound, triggering the problem that an LP that is unbounded 2100 * because of loose variables with infinite best bound cannot be solved) 2101 */ 2102 initial = TRUE; 2103 separate = TRUE; 2104 enforce = TRUE; 2105 check = TRUE; 2106 propagate = TRUE; 2107 local = FALSE; 2108 modifiable = FALSE; 2109 dynamic = FALSE; 2110 removable = FALSE; 2111 2112 SCIP_CALL( SCIPcreateVar(scip, &qmatrixvar, "qmatrixvar", -SCIPinfinity(scip), SCIPinfinity(scip), 1.0, 2113 SCIP_VARTYPE_CONTINUOUS, TRUE, FALSE, NULL, NULL, NULL, NULL, NULL) ); 2114 SCIP_CALL( SCIPaddVar(scip, qmatrixvar) ); 2115 2116 if( mpsinputObjsense(mpsi) == SCIP_OBJSENSE_MINIMIZE ) 2117 { 2118 lhs = -SCIPinfinity(scip); 2119 rhs = 0.0; 2120 } 2121 else 2122 { 2123 lhs = 0.0; 2124 rhs = SCIPinfinity(scip); 2125 } 2126 2127 retcode = SCIPcreateConsQuadraticNonlinear(scip, &cons, "qmatrix", 1, &qmatrixvar, &minusone, cnt, quadvars1, quadvars2, quadcoefs, lhs, rhs, 2128 initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable); 2129 2130 if( retcode == SCIP_OKAY ) 2131 { 2132 SCIP_CALL( SCIPaddCons(scip, cons) ); 2133 SCIPdebugMsg(scip, "(line %d) added constraint <%s>: ", mpsi->lineno, SCIPconsGetName(cons)); 2134 SCIPdebugPrintCons(scip, cons, NULL); 2135 2136 SCIP_CALL( SCIPreleaseCons(scip, &cons) ); 2137 SCIP_CALL( SCIPreleaseVar(scip, &qmatrixvar) ); 2138 } 2139 } 2140 else 2141 { 2142 SCIPwarningMessage(scip, "%s section has no entries.\n", isQuadObj ? "QUADOBJ" : "QMATRIX"); 2143 } 2144 2145 SCIPfreeBufferArray(scip, &quadvars1); 2146 SCIPfreeBufferArray(scip, &quadvars2); 2147 SCIPfreeBufferArray(scip, &quadcoefs); 2148 2149 SCIP_CALL( retcode ); 2150 2151 return SCIP_OKAY; 2152 } 2153 2154 2155 /** Process QCMATRIX section. 2156 * 2157 * We read the QCMATRIX section, which is a nonstandard section introduced by CPLEX. 2158 * 2159 * We replace the corresponding linear constraint by a quadratic constraint which contains the 2160 * original linear constraint plus the quadratic part specified in the QCMATRIX. 2161 */ 2162 static 2163 SCIP_RETCODE readQCMatrix( 2164 MPSINPUT* mpsi, /**< mps input structure */ 2165 SCIP* scip /**< SCIP data structure */ 2166 ) 2167 { 2168 SCIP_CONS* lincons; /* the linear constraint that was added for the corresponding row */ 2169 SCIP_VAR** quadvars1; 2170 SCIP_VAR** quadvars2; 2171 SCIP_Real* quadcoefs; 2172 SCIP_RETCODE retcode; 2173 int cnt = 0; /* number of qcmatrix elements processed so far */ 2174 int size; /* size of quad* arrays */ 2175 2176 if( mpsinputField1(mpsi) == NULL ) 2177 { 2178 SCIPerrorMessage("no row name in QCMATRIX line.\n"); 2179 mpsinputSyntaxerror(mpsi); 2180 return SCIP_OKAY; 2181 } 2182 2183 retcode = SCIP_OKAY; 2184 2185 SCIPdebugMsg(scip, "read QCMATRIX section for row <%s>\n", mpsinputField1(mpsi)); 2186 2187 lincons = SCIPfindCons(scip, mpsinputField1(mpsi)); 2188 if( lincons == NULL ) 2189 { 2190 SCIPerrorMessage("no row under name <%s> processed so far.\n", mpsinputField1(mpsi)); 2191 mpsinputSyntaxerror(mpsi); 2192 return SCIP_OKAY; 2193 } 2194 2195 size = 1; 2196 SCIP_CALL( SCIPallocBufferArray(scip, &quadvars1, size) ); 2197 SCIP_CALL( SCIPallocBufferArray(scip, &quadvars2, size) ); 2198 SCIP_CALL( SCIPallocBufferArray(scip, &quadcoefs, size) ); 2199 2200 /* loop through section */ 2201 /* coverity[tainted_data] */ 2202 while( mpsinputReadLine(mpsi) ) 2203 { 2204 /* otherwise we are in the section given variables */ 2205 SCIP_VAR* var1; 2206 SCIP_VAR* var2; 2207 SCIP_Real coef; 2208 2209 /* check if next section is found */ 2210 if( mpsinputField0(mpsi) != NULL ) 2211 { 2212 if( !strcmp(mpsinputField0(mpsi), "QMATRIX") ) 2213 mpsinputSetSection(mpsi, MPS_QMATRIX); 2214 else if( !strcmp(mpsinputField0(mpsi), "QUADOBJ") ) 2215 mpsinputSetSection(mpsi, MPS_QUADOBJ); 2216 else if( !strcmp(mpsinputField0(mpsi), "QCMATRIX") ) 2217 mpsinputSetSection(mpsi, MPS_QCMATRIX); 2218 else if( !strcmp(mpsinputField0(mpsi), "INDICATORS") ) 2219 mpsinputSetSection(mpsi, MPS_INDICATORS); 2220 else if( !strcmp(mpsinputField0(mpsi), "ENDATA") ) 2221 mpsinputSetSection(mpsi, MPS_ENDATA); 2222 break; 2223 } 2224 if( mpsinputField1(mpsi) == NULL && mpsinputField2(mpsi) == NULL ) 2225 { 2226 SCIPerrorMessage("empty data in a non-comment line.\n"); 2227 mpsinputSyntaxerror(mpsi); 2228 2229 goto TERMINATE; 2230 } 2231 2232 /* get first variable */ 2233 var1 = SCIPfindVar(scip, mpsinputField1(mpsi)); 2234 if( var1 == NULL ) 2235 { 2236 /* ignore unknown variables - we would not know the type anyway */ 2237 mpsinputEntryIgnored(scip, mpsi, "column", mpsinputField1(mpsi), "QCMatrix", SCIPconsGetName(lincons), SCIP_VERBLEVEL_NORMAL); 2238 } 2239 else 2240 { 2241 /* get second variable */ 2242 var2 = SCIPfindVar(scip, mpsinputField2(mpsi)); 2243 if( var2 == NULL ) 2244 { 2245 /* ignore unknown variables - we would not know the type anyway */ 2246 mpsinputEntryIgnored(scip, mpsi, "column", mpsinputField2(mpsi), "QCMatrix", SCIPconsGetName(lincons), SCIP_VERBLEVEL_NORMAL); 2247 } 2248 else 2249 { 2250 char* endptr; 2251 if( mpsinputField3(mpsi) == NULL ) 2252 { 2253 SCIPerrorMessage("coefficient of term <%s>*<%s> not specified.\n", mpsinputField1(mpsi), mpsinputField2(mpsi)); 2254 mpsinputSyntaxerror(mpsi); 2255 2256 goto TERMINATE; 2257 } 2258 2259 /* get coefficient */ 2260 coef = strtod(mpsinputField3(mpsi), &endptr); 2261 if( endptr == mpsinputField3(mpsi) || *endptr != '\0' ) 2262 { 2263 SCIPerrorMessage("coefficient of term <%s>*<%s> not specified.\n", mpsinputField1(mpsi), mpsinputField2(mpsi)); 2264 mpsinputSyntaxerror(mpsi); 2265 2266 goto TERMINATE; 2267 } 2268 2269 /* store variables and coefficient */ 2270 if( cnt >= size ) 2271 { 2272 int newsize = SCIPcalcMemGrowSize(scip, size+1); 2273 assert(newsize > size); 2274 SCIP_CALL( SCIPreallocBufferArray(scip, &quadvars1, newsize) ); 2275 SCIP_CALL( SCIPreallocBufferArray(scip, &quadvars2, newsize) ); 2276 SCIP_CALL( SCIPreallocBufferArray(scip, &quadcoefs, newsize) ); 2277 size = newsize; 2278 } 2279 assert(cnt < size); 2280 quadvars1[cnt] = var1; 2281 quadvars2[cnt] = var2; 2282 quadcoefs[cnt] = coef; 2283 ++cnt; 2284 2285 SCIPdebugMsg(scip, "stored term %g*<%s>*<%s>.\n", coef, SCIPvarGetName(var1), SCIPvarGetName(var2)); 2286 2287 /* check other fields */ 2288 if( (mpsinputField4(mpsi) != NULL && *mpsinputField4(mpsi) != '\0' ) || 2289 (mpsinputField5(mpsi) != NULL && *mpsinputField5(mpsi) != '\0' ) ) 2290 { 2291 SCIPwarningMessage(scip, "ignoring data in fields 4 and 5 <%s> <%s>.\n", mpsinputField4(mpsi), mpsinputField5(mpsi)); 2292 } 2293 } 2294 } 2295 } 2296 2297 /* replace linear constraint by quadratic constraint */ 2298 if( cnt ) 2299 { 2300 SCIP_CONS* cons = NULL; 2301 2302 retcode = SCIPcreateConsQuadraticNonlinear(scip, &cons, SCIPconsGetName(lincons), 2303 SCIPgetNVarsLinear(scip, lincons), SCIPgetVarsLinear(scip, lincons), SCIPgetValsLinear(scip, lincons), 2304 cnt, quadvars1, quadvars2, quadcoefs, SCIPgetLhsLinear(scip, lincons), SCIPgetRhsLinear(scip, lincons), 2305 SCIPconsIsInitial(lincons), SCIPconsIsSeparated(lincons), SCIPconsIsEnforced(lincons), SCIPconsIsChecked(lincons), 2306 SCIPconsIsPropagated(lincons), SCIPconsIsLocal(lincons), SCIPconsIsModifiable(lincons), SCIPconsIsDynamic(lincons), 2307 SCIPconsIsRemovable(lincons)); 2308 2309 if( retcode != SCIP_OKAY ) 2310 goto TERMINATE; 2311 2312 SCIP_CALL( SCIPaddCons(scip, cons) ); 2313 SCIPdebugMsg(scip, "(line %d) added constraint <%s>: ", mpsi->lineno, SCIPconsGetName(cons)); 2314 SCIPdebugPrintCons(scip, cons, NULL); 2315 2316 SCIP_CALL( SCIPreleaseCons(scip, &cons) ); 2317 2318 SCIP_CALL( SCIPdelCons(scip, lincons) ); 2319 } 2320 else 2321 { 2322 SCIPwarningMessage(scip, "QCMATRIX section has no entries.\n"); 2323 } 2324 2325 TERMINATE: 2326 SCIPfreeBufferArray(scip, &quadcoefs); 2327 SCIPfreeBufferArray(scip, &quadvars2); 2328 SCIPfreeBufferArray(scip, &quadvars1); 2329 2330 SCIP_CALL( retcode ); 2331 2332 return SCIP_OKAY; 2333 } 2334 2335 2336 /** Process INDICATORS section. 2337 * 2338 * We read the INDICATORS section, which is a nonstandard section introduced by CPLEX. 2339 * Note that CPLEX does not allow ranged rows. 2340 * 2341 * If the linear constraints are equations or ranged rows, we generate two indicator 2342 * constraints. 2343 * 2344 * The section has to come after the QMATRIX* sections. 2345 */ 2346 static 2347 SCIP_RETCODE readIndicators( 2348 MPSINPUT* mpsi, /**< mps input structure */ 2349 SCIP* scip /**< SCIP data structure */ 2350 ) 2351 { 2352 SCIP_Bool initial; 2353 SCIP_Bool separate; 2354 SCIP_Bool enforce; 2355 SCIP_Bool check; 2356 SCIP_Bool propagate; 2357 SCIP_Bool local; 2358 SCIP_Bool dynamic; 2359 SCIP_Bool removable; 2360 SCIP_Bool stickingatnode; 2361 char name[MPS_MAX_NAMELEN] = { '\0' }; 2362 2363 SCIPdebugMsg(scip, "read INDICATORS constraints\n"); 2364 2365 /* standard settings for indicator constraints: */ 2366 initial = mpsi->initialconss; 2367 separate = TRUE; 2368 enforce = TRUE; 2369 check = TRUE; 2370 propagate = TRUE; 2371 local = FALSE; 2372 dynamic = mpsi->dynamicconss; 2373 removable = mpsi->dynamicrows; 2374 stickingatnode = FALSE; 2375 2376 /* loop through section */ 2377 while( mpsinputReadLine(mpsi) ) 2378 { 2379 SCIP_CONSHDLR* conshdlr; 2380 SCIP_CONS* cons; 2381 SCIP_CONS* lincons; 2382 SCIP_VAR* binvar; 2383 SCIP_Real lhs; 2384 SCIP_Real rhs; 2385 2386 /* check if next section is found */ 2387 if( mpsinputField0(mpsi) != NULL ) 2388 { 2389 if( !strcmp(mpsinputField0(mpsi), "ENDATA") ) 2390 mpsinputSetSection(mpsi, MPS_ENDATA); 2391 break; 2392 } 2393 2394 if( mpsinputField1(mpsi) == NULL || mpsinputField2(mpsi) == NULL ) 2395 { 2396 SCIPerrorMessage("empty data in a non-comment line.\n"); 2397 mpsinputSyntaxerror(mpsi); 2398 return SCIP_OKAY; 2399 } 2400 2401 /* check for new indicator constraint */ 2402 if( strcmp(mpsinputField1(mpsi), "IF") != 0 ) 2403 { 2404 SCIPerrorMessage("Indicator constraints need to be introduced by 'IF' in column 1.\n"); 2405 mpsinputSyntaxerror(mpsi); 2406 return SCIP_OKAY; 2407 } 2408 2409 /* get linear constraint (row) */ 2410 lincons = SCIPfindCons(scip, mpsinputField2(mpsi)); 2411 if( lincons == NULL ) 2412 { 2413 SCIPerrorMessage("row <%s> does not exist.\n", mpsinputField2(mpsi)); 2414 mpsinputSyntaxerror(mpsi); 2415 return SCIP_OKAY; 2416 } 2417 2418 /* check whether constraint is really linear */ 2419 conshdlr = SCIPconsGetHdlr(lincons); 2420 if( strcmp(SCIPconshdlrGetName(conshdlr), "linear") != 0 ) 2421 { 2422 SCIPerrorMessage("constraint <%s> is not linear.\n", mpsinputField2(mpsi)); 2423 mpsinputSyntaxerror(mpsi); 2424 return SCIP_OKAY; 2425 } 2426 2427 /* get binary variable */ 2428 binvar = SCIPfindVar(scip, mpsinputField3(mpsi)); 2429 if( binvar == NULL ) 2430 { 2431 SCIPerrorMessage("binary variable <%s> does not exist.\n", mpsinputField3(mpsi)); 2432 mpsinputSyntaxerror(mpsi); 2433 return SCIP_OKAY; 2434 } 2435 2436 /* check type */ 2437 if( SCIPvarGetType(binvar) != SCIP_VARTYPE_BINARY ) 2438 { 2439 SCIPerrorMessage("variable <%s> is not binary.\n", mpsinputField3(mpsi)); 2440 mpsinputSyntaxerror(mpsi); 2441 return SCIP_OKAY; 2442 } 2443 2444 /* check whether we need the negated variable */ 2445 if( mpsinputField4(mpsi) != NULL ) 2446 { 2447 if( *mpsinputField4(mpsi) == '0' ) 2448 { 2449 SCIP_VAR* var; 2450 SCIP_CALL( SCIPgetNegatedVar(scip, binvar, &var) ); 2451 binvar = var; 2452 assert( binvar != NULL ); 2453 } 2454 else 2455 { 2456 if( *mpsinputField4(mpsi) != '1' ) 2457 { 2458 SCIPerrorMessage("binary variable <%s> can only take values 0/1 (%s).\n", mpsinputField3(mpsi), mpsinputField4(mpsi)); 2459 mpsinputSyntaxerror(mpsi); 2460 return SCIP_OKAY; 2461 } 2462 } 2463 } 2464 2465 /* get lhs/rhs */ 2466 lhs = SCIPgetLhsLinear(scip, lincons); 2467 rhs = SCIPgetRhsLinear(scip, lincons); 2468 2469 if( !SCIPisInfinity(scip, -lhs) ) 2470 { 2471 if( ! SCIPisInfinity(scip, rhs) ) 2472 { 2473 /* create second indicator constraint */ 2474 SCIP_VAR** vars; 2475 SCIP_Real* vals; 2476 SCIP_RETCODE retcode; 2477 SCIP_VAR** linvars; 2478 SCIP_Real* linvals; 2479 int nlinvars; 2480 int i; 2481 2482 nlinvars = SCIPgetNVarsLinear(scip, lincons); 2483 linvars = SCIPgetVarsLinear(scip, lincons); 2484 linvals = SCIPgetValsLinear(scip, lincons); 2485 2486 SCIP_CALL( SCIPallocBufferArray(scip, &vars, nlinvars) ); 2487 SCIP_CALL( SCIPallocBufferArray(scip, &vals, nlinvars) ); 2488 for( i = 0; i < nlinvars; ++i ) 2489 { 2490 vars[i] = linvars[i]; 2491 vals[i] = -linvals[i]; 2492 } 2493 2494 /* create new name */ 2495 (void) SCIPsnprintf(name, MPS_MAX_NAMELEN, "indlhs_%s", SCIPconsGetName(lincons)); 2496 2497 /* create indicator constraint */ 2498 retcode = SCIPcreateConsIndicator(scip, &cons, name, binvar, nlinvars, vars, vals, -lhs, 2499 initial, separate, enforce, check, propagate, local, dynamic, removable, stickingatnode); 2500 2501 if( retcode == SCIP_OKAY ) 2502 { 2503 SCIP_CALL( SCIPaddCons(scip, cons) ); 2504 SCIPdebugMsg(scip, "created indicator constraint <%s>\n", mpsinputField2(mpsi)); 2505 SCIPdebugPrintCons(scip, cons, NULL); 2506 SCIP_CALL( SCIPreleaseCons(scip, &cons) ); 2507 } 2508 2509 SCIPfreeBufferArray(scip, &vals); 2510 SCIPfreeBufferArray(scip, &vars); 2511 2512 SCIP_CALL( retcode ); 2513 } 2514 } 2515 2516 /* correct linear constraint and create new name */ 2517 if ( ! SCIPisInfinity(scip, -lhs) && ! SCIPisInfinity(scip, rhs) ) 2518 { 2519 /* we have added lhs above and only need the rhs */ 2520 SCIP_CALL( SCIPchgLhsLinear(scip, lincons, -SCIPinfinity(scip) ) ); 2521 (void) SCIPsnprintf(name, MPS_MAX_NAMELEN, "indrhs_%s", SCIPconsGetName(lincons)); 2522 } 2523 else 2524 (void) SCIPsnprintf(name, MPS_MAX_NAMELEN, "ind_%s", SCIPconsGetName(lincons)); 2525 2526 /* create indicator constraint */ 2527 SCIP_CALL( SCIPcreateConsIndicatorLinConsPure(scip, &cons, name, binvar, lincons, 2528 initial, separate, enforce, check, propagate, local, dynamic, removable, stickingatnode) ); 2529 2530 SCIP_CALL( SCIPaddCons(scip, cons) ); 2531 SCIPdebugMsg(scip, "created indicator constraint <%s>", mpsinputField2(mpsi)); 2532 SCIPdebugPrintCons(scip, cons, NULL); 2533 SCIP_CALL( SCIPreleaseCons(scip, &cons) ); 2534 } 2535 2536 return SCIP_OKAY; 2537 } 2538 2539 2540 /** Read LP in "MPS File Format". 2541 * 2542 * A specification of the MPS format can be found at 2543 * 2544 * http://plato.asu.edu/ftp/mps_format.txt, 2545 * ftp://ftp.caam.rice.edu/pub/people/bixby/miplib/mps_format, 2546 * 2547 * and in the 2548 * 2549 * CPLEX Reference Manual 2550 * 2551 * This routine should read all valid MPS format files. 2552 * What it will not do, is to find all cases where a file is ill formed. 2553 * If this happens it may complain and read nothing or read "something". 2554 */ 2555 static 2556 SCIP_RETCODE readMps( 2557 SCIP* scip, /**< SCIP data structure */ 2558 const char* filename, /**< name of the input file */ 2559 const char*** varnames, /**< storage for the variable names, or NULL */ 2560 const char*** consnames, /**< storage for the constraint names, or NULL */ 2561 int* varnamessize, /**< the size of the variable names storage, or NULL */ 2562 int* consnamessize, /**< the size of the constraint names storage, or NULL */ 2563 int* nvarnames, /**< the number of stored variable names, or NULL */ 2564 int* nconsnames /**< the number of stored constraint names, or NULL */ 2565 ) 2566 { 2567 SCIP_FILE* fp; 2568 MPSINPUT* mpsi; 2569 SCIP_RETCODE retcode; 2570 SCIP_Bool error = TRUE; 2571 2572 assert(scip != NULL); 2573 assert(filename != NULL); 2574 2575 fp = SCIPfopen(filename, "r"); 2576 if( fp == NULL ) 2577 { 2578 SCIPerrorMessage("cannot open file <%s> for reading\n", filename); 2579 SCIPprintSysError(filename); 2580 return SCIP_NOFILE; 2581 } 2582 2583 SCIP_CALL( mpsinputCreate(scip, &mpsi, fp) ); 2584 2585 SCIP_CALL_TERMINATE( retcode, readName(scip, mpsi), TERMINATE ); 2586 2587 SCIP_CALL_TERMINATE( retcode, SCIPcreateProb(scip, mpsi->probname, NULL, NULL, NULL, NULL, NULL, NULL, NULL), TERMINATE ); 2588 2589 if( mpsinputSection(mpsi) == MPS_OBJSEN ) 2590 { 2591 SCIP_CALL_TERMINATE( retcode, readObjsen(scip, mpsi), TERMINATE ); 2592 } 2593 if( mpsinputSection(mpsi) == MPS_OBJNAME ) 2594 { 2595 SCIP_CALL_TERMINATE( retcode, readObjname(scip, mpsi), TERMINATE ); 2596 } 2597 while( mpsinputSection(mpsi) == MPS_ROWS 2598 || mpsinputSection(mpsi) == MPS_USERCUTS 2599 || mpsinputSection(mpsi) == MPS_LAZYCONS ) 2600 { 2601 SCIP_CALL_TERMINATE( retcode, readRows(mpsi, scip, consnames, consnamessize, nconsnames), TERMINATE ); 2602 } 2603 if( mpsinputSection(mpsi) == MPS_COLUMNS ) 2604 { 2605 SCIP_CALL_TERMINATE( retcode, readCols(mpsi, scip, varnames, varnamessize, nvarnames), TERMINATE ); 2606 } 2607 if( mpsinputSection(mpsi) == MPS_RHS ) 2608 { 2609 SCIP_CALL_TERMINATE( retcode, readRhs(mpsi, scip), TERMINATE ); 2610 } 2611 if( mpsinputSection(mpsi) == MPS_RANGES ) 2612 { 2613 SCIP_CALL_TERMINATE( retcode, readRanges(mpsi, scip), TERMINATE ); 2614 } 2615 if( mpsinputSection(mpsi) == MPS_BOUNDS ) 2616 { 2617 SCIP_CALL_TERMINATE( retcode, readBounds(mpsi, scip), TERMINATE ); 2618 } 2619 if( mpsinputSection(mpsi) == MPS_SOS ) 2620 { 2621 SCIP_CALL_TERMINATE( retcode, readSOS(mpsi, scip), TERMINATE ); 2622 } 2623 while( mpsinputSection(mpsi) == MPS_QCMATRIX ) 2624 { 2625 SCIP_CALL_TERMINATE( retcode, readQCMatrix(mpsi, scip), TERMINATE ); 2626 } 2627 if( mpsinputSection(mpsi) == MPS_QMATRIX ) 2628 { 2629 SCIP_CALL_TERMINATE( retcode, readQMatrix(mpsi, FALSE, scip), TERMINATE ); 2630 } 2631 if( mpsinputSection(mpsi) == MPS_QUADOBJ ) 2632 { 2633 SCIP_CALL_TERMINATE( retcode, readQMatrix(mpsi, TRUE, scip), TERMINATE ); 2634 } 2635 while( mpsinputSection(mpsi) == MPS_QCMATRIX ) 2636 { 2637 SCIP_CALL_TERMINATE( retcode, readQCMatrix(mpsi, scip), TERMINATE ); 2638 } 2639 if( mpsinputSection(mpsi) == MPS_INDICATORS ) 2640 { 2641 SCIP_CALL_TERMINATE( retcode, readIndicators(mpsi, scip), TERMINATE ); 2642 } 2643 if( mpsinputSection(mpsi) != MPS_ENDATA ) 2644 mpsinputSyntaxerror(mpsi); 2645 2646 SCIPfclose(fp); 2647 2648 error = mpsinputHasError(mpsi); 2649 2650 if( !error ) 2651 { 2652 SCIP_CALL_TERMINATE( retcode, SCIPsetObjsense(scip, mpsinputObjsense(mpsi)), TERMINATE ); 2653 } 2654 2655 TERMINATE: 2656 mpsinputFree(scip, &mpsi); 2657 2658 if( error ) 2659 return SCIP_READERROR; 2660 else 2661 return SCIP_OKAY; 2662 } 2663 2664 /* 2665 * local methods for writing problem 2666 */ 2667 2668 /** gets the key (i.e. the name) of the given namefreq */ 2669 static 2670 SCIP_DECL_HASHGETKEY(hashGetKeyNamefreq) 2671 { /*lint --e{715}*/ 2672 CONSNAMEFREQ* consnamefreq = (CONSNAMEFREQ*)elem; 2673 2674 assert(consnamefreq != NULL); 2675 assert(consnamefreq->consname != NULL); 2676 2677 return (void*)consnamefreq->consname; 2678 } 2679 2680 /** returns TRUE iff both keys (i.e. strings) are equal up to max length*/ 2681 static 2682 SCIP_DECL_HASHKEYEQ(hashKeyEqString) 2683 { /*lint --e{715}*/ 2684 const char* string1 = (const char*)key1; 2685 const char* string2 = (const char*)key2; 2686 2687 return (strncmp(string1, string2, MPS_MAX_NAMELEN - 1) == 0); 2688 } 2689 2690 /** hash key retrieval function for variables */ 2691 static 2692 SCIP_DECL_HASHGETKEY(hashGetKeyVar) 2693 { /*lint --e{715}*/ 2694 return elem; 2695 } 2696 2697 /** returns TRUE iff the indices of both variables are equal */ 2698 static 2699 SCIP_DECL_HASHKEYEQ(hashKeyEqVar) 2700 { /*lint --e{715}*/ 2701 if( key1 == key2 ) 2702 return TRUE; 2703 return FALSE; 2704 } 2705 2706 /** returns the hash value of the key */ 2707 static 2708 SCIP_DECL_HASHKEYVAL(hashKeyValVar) 2709 { /*lint --e{715}*/ 2710 assert( SCIPvarGetIndex((SCIP_VAR*) key) >= 0 ); 2711 return (unsigned int) SCIPvarGetIndex((SCIP_VAR*) key); 2712 } 2713 2714 2715 /** computes the field width such that the output file is nicely arranged */ 2716 static 2717 unsigned int computeFieldWidth( 2718 unsigned int width /**< required width */ 2719 ) 2720 { 2721 width = MAX(8u, width); 2722 return MIN(MPS_MAX_FIELDLEN, width); 2723 } 2724 2725 2726 /** output two strings in columns 1 and 2 with computed widths */ 2727 static 2728 void printRecord( 2729 SCIP* scip, /**< SCIP data structure */ 2730 FILE* file, /**< output file (or NULL for standard output) */ 2731 const char* col1, /**< column 1 */ 2732 const char* col2, /**< column 2 */ 2733 unsigned int maxnamelen /**< maximum name length */ 2734 ) 2735 { 2736 unsigned int fieldwidth; 2737 char format[32]; 2738 2739 assert( scip != NULL ); 2740 assert( col1 != NULL ); 2741 assert( col2 != NULL ); 2742 assert( strlen(col1) < MPS_MAX_NAMELEN ); 2743 assert( strlen(col2) < MPS_MAX_VALUELEN ); 2744 assert( maxnamelen > 0 ); 2745 2746 fieldwidth = computeFieldWidth(maxnamelen); 2747 (void) SCIPsnprintf(format, 32," %%-%ds %%%ds ", fieldwidth, MPS_MAX_VALUELEN - 1); 2748 2749 SCIPinfoMessage(scip, file, (const char *)format, col1, col2); 2750 } 2751 2752 /** output two strings in columns 1 (width 2) and 2 (width 8) */ 2753 static 2754 void printStart( 2755 SCIP* scip, /**< SCIP data structure */ 2756 FILE* file, /**< output file (or NULL for standard output) */ 2757 const char* col1, /**< column 1 */ 2758 const char* col2, /**< column 2 */ 2759 int maxnamelen /**< maximum name length (-1 if irrelevant) */ 2760 ) 2761 { 2762 unsigned int fieldwidth; 2763 char format[32]; 2764 2765 assert( scip != NULL ); 2766 assert( col1 != NULL ); 2767 assert( col2 != NULL ); 2768 assert( strlen(col1) <= 2 ); 2769 assert( strlen(col2) < MPS_MAX_NAMELEN ); 2770 assert( maxnamelen == -1 || maxnamelen > 0 ); 2771 2772 if( maxnamelen < 0 ) 2773 { 2774 /* format does not matter */ 2775 (void) SCIPsnprintf(format, 32, " %%-2.2s %%-s "); 2776 } 2777 else 2778 { 2779 fieldwidth = computeFieldWidth((unsigned int) maxnamelen); 2780 (void) SCIPsnprintf(format, 32, " %%-2.2s %%-%ds ", fieldwidth); 2781 } 2782 2783 SCIPinfoMessage(scip, file, (const char*)format, col1, col2); 2784 } 2785 2786 /** prints the given data as column entry */ 2787 static 2788 void printEntry( 2789 SCIP* scip, /**< SCIP data structure */ 2790 FILE* file, /**< output file (or NULL for standard output) */ 2791 const char* varname, /**< variable name */ 2792 const char* consname, /**< constraint name */ 2793 SCIP_Real value, /**< value to display */ 2794 int* recordcnt, /**< pointer to store the number of records per line */ 2795 unsigned int maxnamelen /**< maximum name length */ 2796 ) 2797 { 2798 char valuestr[MPS_MAX_VALUELEN] = { '\0' }; 2799 2800 assert( scip != NULL ); 2801 assert( recordcnt != NULL ); 2802 assert( *recordcnt >= 0 && *recordcnt < 2 ); 2803 2804 (void) SCIPsnprintf(valuestr, MPS_MAX_VALUELEN, "%25.15g", value); 2805 2806 if( *recordcnt == 0 ) 2807 { 2808 /* start new line with an empty first column and the variable name in the second column */ 2809 printStart(scip, file, "", varname, (int) maxnamelen); 2810 *recordcnt = 0; 2811 } 2812 2813 printRecord(scip, file, consname, valuestr, maxnamelen); 2814 (*recordcnt)++; 2815 2816 if( *recordcnt == 2 ) 2817 { 2818 /* each line can have at most two records */ 2819 SCIPinfoMessage(scip, file, "\n"); 2820 *recordcnt = 0; 2821 } 2822 } 2823 2824 /** prints the constraint type to file stream */ 2825 static 2826 void printRowType( 2827 SCIP* scip, /**< SCIP data structure */ 2828 FILE* file, /**< output file (or NULL for standard output) */ 2829 SCIP_Real lhs, /**< left hand side */ 2830 SCIP_Real rhs, /**< right hand side */ 2831 const char* name /**< constraint name */ 2832 ) 2833 { 2834 char rowtype[2]; 2835 2836 assert( scip != NULL ); 2837 assert( !SCIPisInfinity(scip, -lhs) || !SCIPisInfinity(scip, rhs) ); 2838 assert( SCIPisGT(scip, rhs, lhs) || SCIPisEQ(scip, lhs, rhs) ); 2839 assert( name != NULL ); 2840 2841 if( SCIPisEQ(scip, lhs, rhs) ) 2842 (void) SCIPsnprintf(rowtype, 2, "%s", "E"); 2843 else 2844 { 2845 /* in case the right hand side and the left hand side are not infinity we print a 2846 * less or equal constraint and put the right hand side in the RHS section and the 2847 * left hand side (hidden) in the RANGE section */ 2848 if( !SCIPisInfinity(scip, rhs) ) 2849 (void) SCIPsnprintf(rowtype, 2, "%s", "L"); 2850 else 2851 { 2852 assert( !SCIPisInfinity(scip, -lhs) ); 2853 (void) SCIPsnprintf(rowtype, 2, "%s", "G"); 2854 } 2855 } 2856 2857 printStart(scip, file, rowtype, name, -1); 2858 SCIPinfoMessage(scip, file, "\n"); 2859 } 2860 2861 2862 /** initializes the sparse matrix */ 2863 static 2864 SCIP_RETCODE initializeMatrix( 2865 SCIP* scip, /**< SCIP data structure */ 2866 SPARSEMATRIX** matrix, /**< pointer to sparse matrix containing the entries */ 2867 int slots /**< number of slots */ 2868 ) 2869 { 2870 SCIP_CALL( SCIPallocBuffer(scip, matrix) ); 2871 (*matrix)->nentries = 0; 2872 (*matrix)->sentries = slots; 2873 SCIP_CALL( SCIPallocBufferArray(scip, &(*matrix)->values, (*matrix)->sentries) ); 2874 SCIP_CALL( SCIPallocBufferArray(scip, &(*matrix)->columns, (*matrix)->sentries) ); 2875 SCIP_CALL( SCIPallocBufferArray(scip, &(*matrix)->rows, (*matrix)->sentries) ); 2876 2877 return SCIP_OKAY; 2878 } 2879 2880 /** this method takes care that the required capacity is available in the sparse matrix */ 2881 static 2882 SCIP_RETCODE checkSparseMatrixCapacity( 2883 SCIP* scip, /**< SCIP data structure */ 2884 SPARSEMATRIX* matrix, /**< sparse matrix for storing the coefficient */ 2885 int capacity /**< needed capacity */ 2886 ) 2887 { 2888 if( matrix->nentries + capacity >= matrix->sentries ) 2889 { 2890 matrix->sentries = matrix->sentries * 2 + capacity; 2891 SCIP_CALL( SCIPreallocBufferArray(scip, &matrix->values, matrix->sentries) ); 2892 SCIP_CALL( SCIPreallocBufferArray(scip, &matrix->columns, matrix->sentries) ); 2893 SCIP_CALL( SCIPreallocBufferArray(scip, &matrix->rows, matrix->sentries) ); 2894 } 2895 return SCIP_OKAY; 2896 } 2897 2898 /** frees the sparse matrix */ 2899 static 2900 void freeMatrix( 2901 SCIP* scip, /**< SCIP data structure */ 2902 SPARSEMATRIX* matrix /**< sparse matrix to free */ 2903 ) 2904 { 2905 SCIPfreeBufferArray(scip, &matrix->rows); 2906 SCIPfreeBufferArray(scip, &matrix->columns); 2907 SCIPfreeBufferArray(scip, &matrix->values); 2908 2909 SCIPfreeBuffer(scip, &matrix); 2910 } 2911 2912 2913 /** computes the coefficient for the given variables and linear constraint information */ 2914 static 2915 SCIP_RETCODE getLinearCoeffs( 2916 SCIP* scip, /**< SCIP data structure */ 2917 const char* consname, /**< name of the constraint */ 2918 SCIP_VAR** vars, /**< array of variables */ 2919 SCIP_Real* vals, /**< array of coefficients values (or NULL if all coefficient values are 1) */ 2920 int nvars, /**< number of variables */ 2921 SCIP_Bool transformed, /**< transformed constraint? */ 2922 SPARSEMATRIX* matrix, /**< sparse matrix for storing the coefficient */ 2923 SCIP_Real* rhs /**< pointer to right hand side */ 2924 ) 2925 { 2926 SCIP_VAR** activevars; 2927 SCIP_Real* activevals; 2928 SCIP_Real activeconstant = 0.0; 2929 2930 int nactivevars; 2931 int requiredsize; 2932 int v; 2933 2934 assert( scip != NULL ); 2935 assert( nvars == 0 || vars != NULL ); 2936 assert( !SCIPisInfinity(scip, *rhs) ); 2937 assert( matrix != NULL ); 2938 2939 /* if the variables array contains no variables, then return without 2940 * doing any thing; The MPS format and LP format do not forbid this 2941 * situation */ 2942 if( nvars == 0 ) 2943 return SCIP_OKAY; 2944 2945 /* duplicate variable and value array */ 2946 nactivevars = nvars; 2947 SCIP_CALL( SCIPduplicateBufferArray(scip, &activevars, vars, nactivevars ) ); 2948 2949 if( vals != NULL ) 2950 { 2951 SCIP_CALL( SCIPduplicateBufferArray(scip, &activevals, vals, nactivevars ) ); 2952 } 2953 else 2954 { 2955 SCIP_CALL( SCIPallocBufferArray(scip, &activevals, nactivevars) ); 2956 2957 for( v = 0; v < nactivevars; ++v ) 2958 activevals[v] = 1.0; 2959 } 2960 2961 /* retransform given variables to active variables */ 2962 if( transformed ) 2963 { 2964 SCIP_CALL( SCIPgetProbvarLinearSum(scip, activevars, activevals, &nactivevars, nactivevars, &activeconstant, &requiredsize, TRUE) ); 2965 2966 if( requiredsize > nactivevars ) 2967 { 2968 SCIP_CALL( SCIPreallocBufferArray(scip, &activevars, requiredsize) ); 2969 SCIP_CALL( SCIPreallocBufferArray(scip, &activevals, requiredsize) ); 2970 2971 SCIP_CALL( SCIPgetProbvarLinearSum(scip, activevars, activevals, &nactivevars, requiredsize, &activeconstant, &requiredsize, TRUE) ); 2972 assert( requiredsize <= nactivevars ); 2973 } 2974 } 2975 else 2976 { 2977 for( v = 0; v < nactivevars; ++v ) 2978 { 2979 SCIP_CALL( SCIPvarGetOrigvarSum(&activevars[v], &activevals[v], &activeconstant) ); 2980 2981 /* negated variables with an original counterpart may also be returned by SCIPvarGetOrigvarSum(); 2982 * make sure we get the original variable in that case 2983 */ 2984 if( SCIPvarGetStatus(activevars[v]) == SCIP_VARSTATUS_NEGATED ) 2985 { 2986 activevars[v] = SCIPvarGetNegatedVar(activevars[v]); 2987 activeconstant += activevals[v]; 2988 activevals[v] *= -1.0; 2989 } 2990 } 2991 } 2992 2993 /* copy the (matrix) row into the sparse matrix */ 2994 SCIP_CALL( checkSparseMatrixCapacity(scip, matrix, nactivevars) ); 2995 assert( matrix->nentries + nactivevars < matrix->sentries ); 2996 2997 for( v = 0; v < nactivevars; ++v ) 2998 { 2999 matrix->values[matrix->nentries] = activevals[v]; 3000 matrix->columns[matrix->nentries] = activevars[v]; 3001 matrix->rows[matrix->nentries] = consname; 3002 matrix->nentries++; 3003 } 3004 3005 /* adjust right hand side */ 3006 (*rhs) -= activeconstant; 3007 3008 /* free buffer arrays */ 3009 SCIPfreeBufferArray(scip, &activevals); 3010 SCIPfreeBufferArray(scip, &activevars); 3011 3012 return SCIP_OKAY; 3013 } 3014 3015 3016 /** check whether given variables are aggregated and put them into an array without duplication */ 3017 static 3018 SCIP_RETCODE collectAggregatedVars( 3019 SCIP* scip, /**< SCIP data structure */ 3020 SCIP_VAR** vars, /**< variable array */ 3021 int nvars, /**< number of active variables in the problem */ 3022 SCIP_VAR*** aggvars, /**< pointer to array storing the aggregated variables on output */ 3023 int* naggvars, /**< pointer to number of aggregated variables on output */ 3024 int* saggvars, /**< pointer to number of slots in aggvars array */ 3025 SCIP_HASHTABLE* varAggregated /**< hashtable for checking duplicates */ 3026 ) 3027 { 3028 int v; 3029 3030 assert( scip != NULL ); 3031 assert( aggvars != NULL ); 3032 assert( naggvars != NULL ); 3033 assert( saggvars != NULL ); 3034 3035 /* check variables */ 3036 for( v = 0; v < nvars; ++v ) 3037 { 3038 SCIP_VARSTATUS status; 3039 SCIP_VAR* var; 3040 3041 var = vars[v]; 3042 status = SCIPvarGetStatus(var); 3043 3044 /* collect aggregated variables in a list */ 3045 if( status >= SCIP_VARSTATUS_AGGREGATED ) 3046 { 3047 assert( status == SCIP_VARSTATUS_AGGREGATED || status == SCIP_VARSTATUS_MULTAGGR || status == SCIP_VARSTATUS_NEGATED ); 3048 assert( varAggregated != NULL ); 3049 3050 if( ! SCIPhashtableExists(varAggregated, (void*) var) ) 3051 { 3052 /* possibly enlarge array */ 3053 if ( *saggvars <= *naggvars ) 3054 { 3055 int newsize; 3056 newsize = SCIPcalcMemGrowSize(scip, *naggvars + 1); 3057 assert( newsize > *saggvars ); 3058 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &aggvars, *saggvars, newsize) ); 3059 *saggvars = newsize; 3060 } 3061 3062 (*aggvars)[*naggvars] = var; 3063 (*naggvars)++; 3064 SCIP_CALL( SCIPhashtableInsert(varAggregated, (void*) var) ); 3065 assert( *naggvars <= *saggvars ); 3066 } 3067 } 3068 } 3069 return SCIP_OKAY; 3070 } 3071 3072 3073 /** method check if the variable names are not longer than MPS_MAX_NAMELEN - 1*/ 3074 static 3075 SCIP_RETCODE checkVarnames( 3076 SCIP* scip, /**< SCIP data structure */ 3077 SCIP_VAR** vars, /**< array of variables */ 3078 int nvars, /**< number of variables */ 3079 unsigned int* maxnamelen, /**< pointer to store the maximum name length */ 3080 const char*** varnames, /**< pointer to array of variable names */ 3081 SCIP_HASHMAP** varnameHashmap /**< pointer to hash map storing variable, variable name mapping */ 3082 ) 3083 { 3084 int v; 3085 int faulty; 3086 char* varname; 3087 SCIP_VAR* var; 3088 3089 assert( scip != NULL ); 3090 assert( vars != NULL ); 3091 assert( maxnamelen != NULL ); 3092 3093 faulty = 0; 3094 3095 /* allocate memory */ 3096 SCIP_CALL( SCIPhashmapCreate(varnameHashmap, SCIPblkmem(scip), nvars) ); 3097 SCIP_CALL( SCIPallocBufferArray(scip, varnames, nvars) ); 3098 3099 /* check if the variable names are not to long */ 3100 for( v = 0; v < nvars; ++v ) 3101 { 3102 size_t l; 3103 3104 var = vars[v]; 3105 assert( var != NULL ); 3106 3107 l = strlen(SCIPvarGetName(var)); 3108 3109 if( l >= MPS_MAX_NAMELEN ) 3110 { 3111 faulty++; 3112 (*maxnamelen) = MPS_MAX_NAMELEN - 1; 3113 } 3114 else 3115 { 3116 (*maxnamelen) = MAX(*maxnamelen, (unsigned int) l); 3117 } 3118 3119 SCIP_CALL( SCIPallocBufferArray(scip, &varname, (int) *maxnamelen + 1) ); 3120 (void) SCIPsnprintf(varname, (int)(*maxnamelen) + 1, "%s", SCIPvarGetName(var) ); 3121 3122 /* insert variable with variable name into hash map */ 3123 assert( !SCIPhashmapExists(*varnameHashmap, var) ); 3124 SCIP_CALL( SCIPhashmapInsert(*varnameHashmap, var, (void*) varname) ); 3125 3126 (*varnames)[v] = varname; 3127 } 3128 3129 if( faulty > 0 ) 3130 { 3131 SCIPwarningMessage(scip, "there are %d variable names which have to be cut down to %d characters; LP might be corrupted\n", 3132 faulty, MPS_MAX_NAMELEN - 1); 3133 } 3134 return SCIP_OKAY; 3135 } 3136 3137 /** method check if the constraint names are not longer than MPS_MAX_NAMELEN - 1 */ 3138 static 3139 SCIP_RETCODE checkConsnames( 3140 SCIP* scip, /**< SCIP data structure */ 3141 SCIP_CONS** conss, /**< array of all constraints */ 3142 int nconss, /**< number of all constraints */ 3143 SCIP_Bool transformed, /**< TRUE iff problem is the transformed problem */ 3144 unsigned int* maxnamelen, /**< pointer to store the maximum name length */ 3145 const char*** consnames, /**< pointer to array of constraint names */ 3146 SCIP_Bool* error /**< pointer to store whether all constraint names exist */ 3147 ) 3148 { 3149 SCIP_HASHTABLE* consfreq; 3150 CONSNAMEFREQ* consnamefreqs; 3151 SCIP_CONS* cons; 3152 char* consname; 3153 int i; 3154 3155 assert(scip != NULL); 3156 assert(maxnamelen != NULL); 3157 3158 *error = FALSE; 3159 3160 /* allocate memory */ 3161 SCIP_CALL( SCIPallocBufferArray(scip, &consnamefreqs, nconss) ); 3162 SCIP_CALL( SCIPallocBufferArray(scip, consnames, nconss) ); 3163 SCIP_CALL( SCIPhashtableCreate(&consfreq, SCIPblkmem(scip), SCIP_HASHSIZE_NAMES, 3164 hashGetKeyNamefreq, hashKeyEqString, SCIPhashKeyValString, NULL) ); 3165 3166 for( i = 0; i < nconss; ++i ) 3167 { 3168 CONSNAMEFREQ* consnamefreq; 3169 size_t l; 3170 int freq; 3171 3172 cons = conss[i]; 3173 assert( cons != NULL ); 3174 3175 /* in case the transformed problem is written, only constraints are posted which are enabled in the current node */ 3176 assert(!transformed || SCIPconsIsEnabled(cons)); 3177 3178 l = strlen(SCIPconsGetName(cons)); 3179 3180 if( l == 0 ) 3181 { 3182 SCIPwarningMessage(scip, "At least one name of a constraint is empty, so file will be written with generic names.\n"); 3183 *error = TRUE; 3184 3185 goto TERMINATE; 3186 } 3187 3188 consnamefreqs[i].consname = SCIPconsGetName(cons); 3189 consnamefreqs[i].freq = 0; 3190 freq = 0; 3191 3192 /* check for duplicate names */ 3193 if( NULL != (consnamefreq = (CONSNAMEFREQ *)SCIPhashtableRetrieve(consfreq, (void*)SCIPconsGetName(cons))) ) 3194 { 3195 consnamefreq->freq += 1; 3196 consnamefreqs[i] = *consnamefreq; 3197 freq = consnamefreq->freq; 3198 } 3199 SCIP_CALL( SCIPhashtableInsert(consfreq, (void*)(&consnamefreqs[i])) ); 3200 3201 /* the new length is the length of the old name + a '_' and the freq number which has floor(log10(freq)) + 1 characters */ 3202 if( freq > 0 ) 3203 l = l + 1 + (size_t)log10((SCIP_Real) freq) + 1; 3204 3205 if( l >= MPS_MAX_NAMELEN ) 3206 { 3207 SCIPwarningMessage(scip, "Constraints have duplicate name and are too long to fix, so file will be written with generic names.\n"); 3208 *error = TRUE; 3209 3210 goto TERMINATE; 3211 } 3212 3213 (*maxnamelen) = MAX(*maxnamelen, (unsigned int) l); 3214 3215 SCIP_CALL( SCIPallocBufferArray(scip, &consname, (int) l + 1) ); 3216 if( freq > 0 ) 3217 (void) SCIPsnprintf(consname, (int)l + 1, "%s_%d", SCIPconsGetName(cons), freq); 3218 else 3219 (void) SCIPsnprintf(consname, (int)l + 1, "%s", SCIPconsGetName(cons)); 3220 3221 (*consnames)[i] = consname; 3222 } 3223 3224 TERMINATE: 3225 SCIPfreeBufferArray(scip, &consnamefreqs); 3226 3227 if( *error ) 3228 { 3229 --i; /*lint !e445*/ 3230 for( ; i >= 0; --i) /*lint !e445*/ 3231 { 3232 SCIPfreeBufferArray(scip, &((*consnames)[i])); 3233 } 3234 SCIPfreeBufferArray(scip, consnames); 3235 } 3236 3237 SCIPhashtableFree(&consfreq); 3238 3239 return SCIP_OKAY; 3240 } 3241 3242 3243 /** outputs the COLUMNS section of the MPS format */ 3244 static 3245 void printColumnSection( 3246 SCIP* scip, /**< SCIP data structure */ 3247 FILE* file, /**< output file, or NULL if standard output should be used */ 3248 SPARSEMATRIX* matrix, /**< sparse matrix containing the entries */ 3249 SCIP_HASHMAP* varnameHashmap, /**< map from SCIP_VAR* to variable name */ 3250 SCIP_HASHTABLE* indicatorSlackHash, /**< hashtable containing slack variables from indicators (or NULL) */ 3251 unsigned int maxnamelen /**< maximum name length */ 3252 ) 3253 { 3254 SCIP_Bool intSection; 3255 SCIP_VAR* var; 3256 const char* varname; 3257 SCIP_Real value; 3258 int v; 3259 int recordcnt; 3260 3261 /* sort sparse matrix w.r.t. the variable indices */ 3262 SCIPsortPtrPtrReal((void**) matrix->columns, (void**) matrix->rows, matrix->values, SCIPvarComp, matrix->nentries); 3263 3264 /* print COLUMNS section */ 3265 SCIPinfoMessage(scip, file, "COLUMNS\n"); 3266 3267 intSection = FALSE; 3268 3269 for( v = 0; v < matrix->nentries; ) 3270 { 3271 var = matrix->columns[v]; 3272 assert( var != NULL ); 3273 3274 /* skip slack variables in output */ 3275 if( indicatorSlackHash != NULL && SCIPhashtableExists(indicatorSlackHash, var) ) 3276 { 3277 ++v; 3278 continue; 3279 } 3280 3281 if( SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS && intSection ) 3282 { 3283 /* end integer section in MPS format */ 3284 printStart(scip, file, "", "INTEND", (int) maxnamelen); 3285 printRecord(scip, file, "'MARKER'", "", maxnamelen); 3286 printRecord(scip, file, "'INTEND'", "", maxnamelen); 3287 SCIPinfoMessage(scip, file, "\n"); 3288 intSection = FALSE; 3289 } 3290 else if( SCIPvarGetType(var) != SCIP_VARTYPE_CONTINUOUS && !intSection ) 3291 { 3292 /* start integer section in MPS format */ 3293 printStart(scip, file, "", "INTSTART", (int) maxnamelen); 3294 printRecord(scip, file, "'MARKER'", "", maxnamelen); 3295 printRecord(scip, file, "'INTORG'", "", maxnamelen); 3296 SCIPinfoMessage(scip, file, "\n"); 3297 intSection = TRUE; 3298 } 3299 3300 SCIPdebugMsg(scip, "create entries for variable <%s>\n", SCIPvarGetName(var)); 3301 3302 /* record count; there are at most two records per line */ 3303 recordcnt = 0; 3304 3305 /* get variable name */ 3306 assert ( SCIPhashmapExists(varnameHashmap, var) ); 3307 varname = (const char*) SCIPhashmapGetImage(varnameHashmap, var); 3308 3309 /* output all entries of the same variable */ 3310 do 3311 { 3312 value = matrix->values[v]; 3313 3314 /* print record to file */ 3315 printEntry(scip, file, varname, matrix->rows[v], value, &recordcnt, maxnamelen); 3316 v++; 3317 } 3318 while( v < matrix->nentries && var == matrix->columns[v] ); 3319 3320 if( recordcnt == 1 ) 3321 SCIPinfoMessage(scip, file, "\n"); 3322 } 3323 /* end integer section, if the columns sections ends with integer variables */ 3324 if( intSection ) 3325 { 3326 /* end integer section in MPS format */ 3327 printStart(scip, file, "", "INTEND", (int) maxnamelen); 3328 printRecord(scip, file, "'MARKER'", "", maxnamelen); 3329 printRecord(scip, file, "'INTEND'", "", maxnamelen); 3330 SCIPinfoMessage(scip, file, "\n"); 3331 } 3332 } 3333 3334 3335 /** outputs the right hand side section */ 3336 static 3337 void printRhsSection( 3338 SCIP* scip, /**< SCIP data structure */ 3339 FILE* file, /**< output file, or NULL if standard output should be used */ 3340 int nconss, /**< number of constraints */ 3341 const char** consnames, /**< constraint names */ 3342 SCIP_Real* rhss, /**< right hand side array */ 3343 unsigned int maxnamelen, /**< maximum name length */ 3344 SCIP_Real objoffset /**< objective offset */ 3345 ) 3346 { 3347 int recordcnt = 0; 3348 int c; 3349 3350 assert( rhss != NULL ); 3351 3352 SCIPinfoMessage(scip, file, "RHS\n"); 3353 SCIPdebugMsg(scip, "start printing RHS section\n"); 3354 3355 /* take care of the linear constraints */ 3356 for( c = 0; c < nconss; ++c ) 3357 { 3358 /* skip all constraints which have a right hand side of infinity */ 3359 if( SCIPisInfinity(scip, rhss[c]) ) 3360 continue; 3361 3362 assert(consnames[c] != NULL); 3363 3364 printEntry(scip, file, "RHS", consnames[c], rhss[c], &recordcnt, maxnamelen); 3365 } 3366 3367 if( ! SCIPisZero(scip, objoffset) ) 3368 { 3369 /* write objective offset (-1 because it is moved to the rhs) */ 3370 printEntry(scip, file, "RHS", "Obj", -objoffset, &recordcnt, maxnamelen); 3371 } 3372 3373 if( recordcnt == 1 ) 3374 SCIPinfoMessage(scip, file, "\n"); 3375 } 3376 3377 3378 /** outputs the range section */ 3379 static 3380 void printRangeSection( 3381 SCIP* scip, /**< SCIP data structure */ 3382 FILE* file, /**< output file, or NULL if standard output should be used */ 3383 SCIP_CONS** conss, /**< constraint array */ 3384 int nconss, /**< number of constraints */ 3385 const char** consnames, /**< constraint names */ 3386 SCIP_Bool transformed, /**< TRUE iff problem is the transformed problem */ 3387 unsigned int maxnamelen /**< maximum name length */ 3388 ) 3389 { 3390 int c; 3391 int recordcnt = 0; 3392 3393 SCIP_CONSHDLR* conshdlr; 3394 const char* conshdlrname; 3395 3396 SCIP_CONS* cons; 3397 SCIP_Real lhs; 3398 SCIP_Real rhs; 3399 3400 SCIPinfoMessage(scip, file, "RANGES\n"); 3401 SCIPdebugMsg(scip, "start printing RANGES section\n"); 3402 3403 for( c = 0; c < nconss; ++c ) 3404 { 3405 cons = conss[c]; 3406 assert( cons != NULL); 3407 3408 /* in case the transformed problems is written only constraint are posted which are enabled in the current node; 3409 * the conss array should only contain relevant constraints 3410 */ 3411 assert( !transformed || SCIPconsIsEnabled(cons) ); 3412 3413 assert( consnames[c] != NULL ); 3414 3415 conshdlr = SCIPconsGetHdlr(cons); 3416 assert( conshdlr != NULL ); 3417 3418 conshdlrname = SCIPconshdlrGetName(conshdlr); 3419 3420 if( strcmp(conshdlrname, "linear") == 0 ) 3421 { 3422 lhs = SCIPgetLhsLinear(scip, cons); 3423 rhs = SCIPgetRhsLinear(scip, cons); 3424 } 3425 else if( strcmp(conshdlrname, "varbound") == 0 ) 3426 { 3427 lhs = SCIPgetLhsVarbound(scip, cons); 3428 rhs = SCIPgetRhsVarbound(scip, cons); 3429 } 3430 else 3431 continue; 3432 3433 if( !SCIPisInfinity(scip, -lhs) && !SCIPisInfinity(scip, rhs) && !SCIPisEQ(scip, rhs, lhs) ) 3434 { 3435 assert( SCIPisGT(scip, rhs, lhs) ); 3436 printEntry(scip, file, "RANGE", consnames[c], rhs - lhs, &recordcnt, maxnamelen); 3437 } 3438 } 3439 if(recordcnt == 1 ) 3440 SCIPinfoMessage(scip, file, "\n"); 3441 } 3442 3443 /** print bound section name */ 3444 static 3445 void printBoundSectionName( 3446 SCIP* scip, /**< SCIP data structure */ 3447 FILE* file /**< output file, or NULL if standard output should be used */ 3448 ) 3449 { 3450 SCIPinfoMessage(scip, file, "BOUNDS\n"); 3451 SCIPdebugMsg(scip, "start printing BOUNDS section\n"); 3452 } 3453 3454 /** output bound section */ 3455 static 3456 void printBoundSection( 3457 SCIP* scip, /**< SCIP data structure */ 3458 FILE* file, /**< output file, or NULL if standard output should be used */ 3459 SCIP_VAR** vars, /**< active variables */ 3460 int nvars, /**< number of active variables */ 3461 SCIP_VAR** aggvars, /**< needed aggregated variables */ 3462 int naggvars, /**< number of aggregated variables */ 3463 SCIP_VAR** fixvars, /**< all fixed variables (or NULL if nfixvars is 0) */ 3464 int nfixvars, /**< number of fixed variables */ 3465 SCIP_Bool transformed, /**< TRUE iff problem is the transformed problem */ 3466 const char** varnames, /**< array with variable names */ 3467 SCIP_HASHTABLE* indicatorSlackHash, /**< hashtable containing slack variables from indicators (or NULL) */ 3468 unsigned int maxnamelen /**< maximum name length */ 3469 ) 3470 { 3471 int v; 3472 SCIP_VAR* var; 3473 SCIP_Real lb; 3474 SCIP_Real ub; 3475 SCIP_Bool sectionName; 3476 const char* varname; 3477 char valuestr[MPS_MAX_VALUELEN] = { '\0' }; 3478 3479 assert(scip != NULL); 3480 assert(vars != NULL); 3481 assert(nfixvars == 0 || fixvars != NULL); 3482 3483 sectionName = FALSE; 3484 3485 /* output the active variables */ 3486 for( v = 0; v < nvars; ++v ) 3487 { 3488 var = vars[v]; 3489 assert( var != NULL ); 3490 3491 /* skip slack variables in output */ 3492 if( indicatorSlackHash != NULL && SCIPhashtableExists(indicatorSlackHash, var) ) 3493 continue; 3494 3495 /* get variable name */ 3496 varname = varnames[v]; 3497 assert(strncmp(varname, SCIPvarGetName(var), maxnamelen) == 0); 3498 3499 if( transformed ) 3500 { 3501 /* in case the transformed is written only local bounds are posted 3502 * which are valid in the current node */ 3503 lb = SCIPvarGetLbLocal(var); 3504 ub = SCIPvarGetUbLocal(var); 3505 } 3506 else 3507 { 3508 lb = SCIPvarGetLbOriginal(var); 3509 ub = SCIPvarGetUbOriginal(var); 3510 } 3511 3512 /* take care of binary variables */ 3513 if( SCIPvarGetType(var) == SCIP_VARTYPE_BINARY ) 3514 { 3515 if( !sectionName ) 3516 { 3517 printBoundSectionName(scip, file); 3518 sectionName = TRUE; 3519 } 3520 3521 if( !SCIPisFeasZero(scip, lb) || !SCIPisFeasEQ(scip, ub, 1.0) ) 3522 { 3523 (void) SCIPsnprintf(valuestr, MPS_MAX_VALUELEN, "%25.15g", lb); 3524 printStart(scip, file, "LO", "Bound", (int) maxnamelen); 3525 printRecord(scip, file, varname, valuestr, maxnamelen); 3526 SCIPinfoMessage(scip, file, "\n"); 3527 3528 (void) SCIPsnprintf(valuestr, MPS_MAX_VALUELEN, "%25.15g", ub); 3529 printStart(scip, file, "UP", "Bound", (int) maxnamelen); 3530 printRecord(scip, file, varname, valuestr, maxnamelen); 3531 } 3532 else 3533 { 3534 printStart(scip, file, "BV", "Bound", (int) maxnamelen); 3535 printRecord(scip, file, varname, "", maxnamelen); 3536 } 3537 SCIPinfoMessage(scip, file, "\n"); 3538 3539 continue; 3540 } 3541 3542 /* take care of free variables */ 3543 if( SCIPisInfinity(scip, -lb) && SCIPisInfinity(scip, ub) ) 3544 { 3545 if( !sectionName ) 3546 { 3547 printBoundSectionName(scip, file); 3548 sectionName = TRUE; 3549 } 3550 3551 /* variable is free */ 3552 printStart(scip, file, "FR", "Bound", (int) maxnamelen); 3553 printRecord(scip, file, varname, "", maxnamelen); 3554 SCIPinfoMessage(scip, file, "\n"); 3555 continue; 3556 } 3557 3558 /* take care of fixed variables */ 3559 if( SCIPisEQ(scip, lb, ub) ) 3560 { 3561 if( !sectionName ) 3562 { 3563 printBoundSectionName(scip, file); 3564 sectionName = TRUE; 3565 } 3566 3567 /* variable is fixed */ 3568 (void) SCIPsnprintf(valuestr, MPS_MAX_VALUELEN, "%25.15g", lb); 3569 printStart(scip, file, "FX", "Bound", (int) maxnamelen); 3570 printRecord(scip, file, varname, valuestr, maxnamelen); 3571 SCIPinfoMessage(scip, file, "\n"); 3572 continue; 3573 } 3574 3575 /* print lower bound */ 3576 if( SCIPisInfinity(scip, -lb) ) 3577 { 3578 if( !sectionName ) 3579 { 3580 printBoundSectionName(scip, file); 3581 sectionName = TRUE; 3582 } 3583 3584 /* the free variables are processed above */ 3585 assert( !SCIPisInfinity(scip, ub) ); 3586 printStart(scip, file, "MI", "Bound", (int) maxnamelen); 3587 printRecord(scip, file, varname, "", maxnamelen); 3588 SCIPinfoMessage(scip, file, "\n"); 3589 } 3590 else 3591 { 3592 if( SCIPisZero(scip, lb) ) 3593 { 3594 lb = 0.0; 3595 } 3596 else 3597 { 3598 if( !sectionName ) 3599 { 3600 printBoundSectionName(scip, file); 3601 sectionName = TRUE; 3602 } 3603 3604 (void) SCIPsnprintf(valuestr, MPS_MAX_VALUELEN, "%25.15g", lb); 3605 printStart(scip, file, "LO", "Bound", (int) maxnamelen); 3606 printRecord(scip, file, varname, valuestr, maxnamelen); 3607 SCIPinfoMessage(scip, file, "\n"); 3608 } 3609 } 3610 3611 /* print upper bound, infinity has to be printed for integer (!) variables, because during 3612 * reading an mps file no upper bound of an integer variable means that the upper bound will 3613 * be set to 1 instead of +infinity (like it is for continuous variables) */ 3614 if( SCIPisInfinity(scip, ub) ) 3615 { 3616 if( !sectionName ) 3617 { 3618 printBoundSectionName(scip, file); 3619 sectionName = TRUE; 3620 } 3621 3622 /* the free variables are processed above */ 3623 assert( !SCIPisInfinity(scip, -lb) ); 3624 printStart(scip, file, "PL", "Bound", (int) maxnamelen); 3625 printRecord(scip, file, varname, "", maxnamelen); 3626 SCIPinfoMessage(scip, file, "\n"); 3627 } 3628 else 3629 { 3630 if( !sectionName ) 3631 { 3632 printBoundSectionName(scip, file); 3633 sectionName = TRUE; 3634 } 3635 3636 (void) SCIPsnprintf(valuestr, MPS_MAX_VALUELEN, "%25.15g", ub); 3637 printStart(scip, file, "UP", "Bound", (int) maxnamelen); 3638 printRecord(scip, file, varname, valuestr, maxnamelen); 3639 SCIPinfoMessage(scip, file, "\n"); 3640 } 3641 } 3642 3643 /* output aggregated variables as 'free', except if they are binary */ 3644 for( v = 0; v < naggvars; ++v ) 3645 { 3646 if( !sectionName ) 3647 { 3648 printBoundSectionName(scip, file); 3649 sectionName = TRUE; 3650 } 3651 3652 var = aggvars[v]; 3653 assert( var != NULL ); 3654 3655 /* get variable name */ 3656 varname = varnames[nvars + v]; 3657 assert(strncmp(varname, SCIPvarGetName(var), maxnamelen) == 0); 3658 3659 /* take care of binary variables */ 3660 if( SCIPvarGetType(var) == SCIP_VARTYPE_BINARY ) 3661 { 3662 printStart(scip, file, "BV", "Bound", (int) maxnamelen); 3663 printRecord(scip, file, varname, "", maxnamelen); 3664 SCIPinfoMessage(scip, file, "\n"); 3665 } 3666 else 3667 { 3668 /* variable is free */ 3669 printStart(scip, file, "FR", "Bound", (int) maxnamelen); 3670 printRecord(scip, file, varname, "", maxnamelen); 3671 SCIPinfoMessage(scip, file, "\n"); 3672 } 3673 } 3674 3675 /* output all fixed variables */ 3676 for( v = 0; v < nfixvars; ++v ) 3677 { 3678 /* we should print the transformed problem, otherwise no fixed variable should exists */ 3679 assert(transformed); 3680 assert(fixvars != NULL && fixvars[v] != NULL); 3681 3682 /* cppcheck-suppress nullPointer */ 3683 var = fixvars[v]; 3684 3685 assert(var != NULL); 3686 assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_FIXED); 3687 3688 /* get variable name */ 3689 varname = varnames[nvars + naggvars + v]; 3690 assert(strncmp(varname, SCIPvarGetName(var), maxnamelen) == 0); 3691 3692 /* only local bounds are posted which are valid in the current node */ 3693 lb = SCIPvarGetLbLocal(var); 3694 ub = SCIPvarGetUbLocal(var); 3695 assert(SCIPisEQ(scip, lb, ub)); 3696 3697 if( !sectionName ) 3698 { 3699 printBoundSectionName(scip, file); 3700 sectionName = TRUE; 3701 } 3702 3703 /* print fixed variable */ 3704 (void) SCIPsnprintf(valuestr, MPS_MAX_VALUELEN, "%25.15g", lb); 3705 printStart(scip, file, "FX", "Bound", (int) maxnamelen); 3706 printRecord(scip, file, varname, valuestr, maxnamelen); 3707 SCIPinfoMessage(scip, file, "\n"); 3708 } 3709 } 3710 3711 3712 /* 3713 * Callback methods of reader 3714 */ 3715 3716 /** copy method for reader plugins (called when SCIP copies plugins) */ 3717 /**! [SnippetReaderCopyMps] */ 3718 static 3719 SCIP_DECL_READERCOPY(readerCopyMps) 3720 { /*lint --e{715}*/ 3721 assert(scip != NULL); 3722 assert(reader != NULL); 3723 assert(strcmp(SCIPreaderGetName(reader), READER_NAME) == 0); 3724 3725 /* call inclusion method of reader */ 3726 SCIP_CALL( SCIPincludeReaderMps(scip) ); 3727 3728 return SCIP_OKAY; 3729 } 3730 /**! [SnippetReaderCopyMps] */ 3731 3732 /** destructor of reader to free user data (called when SCIP is exiting) */ 3733 /**! [SnippetReaderFreeMps] */ 3734 static 3735 SCIP_DECL_READERFREE(readerFreeMps) 3736 { 3737 SCIP_READERDATA* readerdata; 3738 3739 assert(strcmp(SCIPreaderGetName(reader), READER_NAME) == 0); 3740 readerdata = SCIPreaderGetData(reader); 3741 assert(readerdata != NULL); 3742 SCIPfreeBlockMemory(scip, &readerdata); 3743 3744 return SCIP_OKAY; 3745 } 3746 /**! [SnippetReaderFreeMps] */ 3747 3748 /** problem reading method of reader */ 3749 static 3750 SCIP_DECL_READERREAD(readerReadMps) 3751 { /*lint --e{715}*/ 3752 assert(reader != NULL); 3753 assert(strcmp(SCIPreaderGetName(reader), READER_NAME) == 0); 3754 3755 SCIP_CALL( SCIPreadMps(scip, reader, filename, result, NULL, NULL, NULL, NULL, NULL, NULL) ); 3756 3757 return SCIP_OKAY; 3758 } 3759 3760 3761 /** problem writing method of reader */ 3762 static 3763 SCIP_DECL_READERWRITE(readerWriteMps) 3764 { /*lint --e{715}*/ 3765 assert(reader != NULL); 3766 assert(strcmp(SCIPreaderGetName(reader), READER_NAME) == 0); 3767 3768 SCIP_CALL( SCIPwriteMps(scip, reader, file, name, transformed, objsense, objscale, objoffset, vars, 3769 nvars, nbinvars, nintvars, nimplvars, ncontvars, fixedvars, nfixedvars, conss, nconss, result) ); 3770 3771 return SCIP_OKAY; 3772 } 3773 3774 3775 /* 3776 * mps file reader specific interface methods 3777 */ 3778 3779 /** includes the mps file reader in SCIP */ 3780 SCIP_RETCODE SCIPincludeReaderMps( 3781 SCIP* scip /**< SCIP data structure */ 3782 ) 3783 { 3784 SCIP_READERDATA* readerdata; 3785 SCIP_READER* reader; 3786 3787 /* create reader data */ 3788 SCIP_CALL( SCIPallocBlockMemory(scip, &readerdata) ); 3789 3790 /* include reader */ 3791 SCIP_CALL( SCIPincludeReaderBasic(scip, &reader, READER_NAME, READER_DESC, READER_EXTENSION, readerdata) ); 3792 3793 /* set non fundamental callbacks via setter functions */ 3794 SCIP_CALL( SCIPsetReaderCopy(scip, reader, readerCopyMps) ); 3795 SCIP_CALL( SCIPsetReaderFree(scip, reader, readerFreeMps) ); 3796 SCIP_CALL( SCIPsetReaderRead(scip, reader, readerReadMps) ); 3797 SCIP_CALL( SCIPsetReaderWrite(scip, reader, readerWriteMps) ); 3798 3799 /* add lp-reader parameters */ 3800 SCIP_CALL( SCIPaddBoolParam(scip, 3801 "reading/" READER_NAME "/linearize-and-constraints", 3802 "should possible \"and\" constraint be linearized when writing the mps file?", 3803 &readerdata->linearizeands, TRUE, DEFAULT_LINEARIZE_ANDS, NULL, NULL) ); 3804 SCIP_CALL( SCIPaddBoolParam(scip, 3805 "reading/" READER_NAME "/aggrlinearization-ands", 3806 "should an aggregated linearization for and constraints be used?", 3807 &readerdata->aggrlinearizationands, TRUE, DEFAULT_AGGRLINEARIZATION_ANDS, NULL, NULL) ); 3808 3809 return SCIP_OKAY; 3810 } 3811 3812 3813 /** reads problem from file */ 3814 SCIP_RETCODE SCIPreadMps( 3815 SCIP* scip, /**< SCIP data structure */ 3816 SCIP_READER* reader, /**< the file reader itself */ 3817 const char* filename, /**< full path and name of file to read, or NULL if stdin should be used */ 3818 SCIP_RESULT* result, /**< pointer to store the result of the file reading call */ 3819 const char*** varnames, /**< storage for the variable names, or NULL */ 3820 const char*** consnames, /**< storage for the constraint names, or NULL */ 3821 int* varnamessize, /**< the size of the variable names storage, or NULL */ 3822 int* consnamessize, /**< the size of the constraint names storage, or NULL */ 3823 int* nvarnames, /**< the number of stored variable names, or NULL */ 3824 int* nconsnames /**< the number of stored constraint names, or NULL */ 3825 ) 3826 { 3827 SCIP_RETCODE retcode; 3828 3829 assert(reader != NULL); 3830 assert(scip != NULL); 3831 assert(result != NULL); 3832 3833 retcode = readMps(scip, filename, varnames, consnames, varnamessize, consnamessize, nvarnames, nconsnames); 3834 3835 if( retcode == SCIP_PLUGINNOTFOUND ) 3836 retcode = SCIP_READERROR; 3837 3838 if( retcode == SCIP_NOFILE || retcode == SCIP_READERROR ) 3839 return retcode; 3840 3841 SCIP_CALL( retcode ); 3842 3843 *result = SCIP_SUCCESS; 3844 3845 return SCIP_OKAY; 3846 } 3847 3848 3849 /** writes problem to file */ 3850 SCIP_RETCODE SCIPwriteMps( 3851 SCIP* scip, /**< SCIP data structure */ 3852 SCIP_READER* reader, /**< the file reader itself */ 3853 FILE* file, /**< output file, or NULL if standard output should be used */ 3854 const char* name, /**< problem name */ 3855 SCIP_Bool transformed, /**< TRUE iff problem is the transformed problem */ 3856 SCIP_OBJSENSE objsense, /**< objective sense */ 3857 SCIP_Real objscale, /**< scalar applied to objective function; external objective value is 3858 * extobj = objsense * objscale * (intobj + objoffset) */ 3859 SCIP_Real objoffset, /**< objective offset from bound shifting and fixing */ 3860 SCIP_VAR** vars, /**< array with active variables ordered binary, integer, implicit, continuous */ 3861 int nvars, /**< number of active variables in the problem */ 3862 int nbinvars, /**< number of binary variables */ 3863 int nintvars, /**< number of general integer variables */ 3864 int nimplvars, /**< number of implicit integer variables */ 3865 int ncontvars, /**< number of continuous variables */ 3866 SCIP_VAR** fixedvars, /**< array with fixed and aggregated variables */ 3867 int nfixedvars, /**< number of fixed and aggregated variables in the problem */ 3868 SCIP_CONS** conss, /**< array with constraints of the problem */ 3869 int nconss, /**< number of constraints in the problem */ 3870 SCIP_RESULT* result /**< pointer to store the result of the file writing call */ 3871 ) 3872 { 3873 SCIP_READERDATA* readerdata; 3874 int naddrows; 3875 int faulty = 0; 3876 int c; 3877 int v; 3878 int k; 3879 char* namestr; 3880 3881 SCIP_CONS* cons = NULL; 3882 const char* consname; 3883 const char** consnames; 3884 3885 SCIP_CONSHDLR* conshdlr; 3886 const char* conshdlrname; 3887 3888 SCIP_Real lhs; 3889 SCIP_Real rhs; 3890 SCIP_Real* rhss; 3891 SCIP_Real value; 3892 3893 SCIP_VAR* var = NULL; 3894 const char* varname; 3895 const char** varnames; 3896 3897 char valuestr[MPS_MAX_VALUELEN] = { '\0' }; 3898 3899 SCIP_CONS** consIndicator; 3900 SCIP_CONS** consSOS1; 3901 SCIP_CONS** consSOS2; 3902 SCIP_CONS** consQuadratic; 3903 int nConsIndicator; 3904 int nConsSOS1; 3905 int nConsSOS2; 3906 int nConsQuadratic; 3907 3908 SCIP_HASHMAP* varnameHashmap; /* hash map from SCIP_VAR* to variable name */ 3909 SPARSEMATRIX* matrix; 3910 3911 SCIP_VAR** aggvars; 3912 int naggvars = 0; 3913 int saggvars; 3914 SCIP_HASHTABLE* varFixedHash; 3915 SCIP_HASHTABLE* indicatorSlackHash; 3916 3917 SCIP_VAR** fixvars = NULL; 3918 int nfixvars = 0; 3919 3920 SCIP_VAR** consvars; 3921 int nconsvars; 3922 SCIP_Real* vals; 3923 SCIP_Longint* weights; 3924 3925 SCIP_Bool needRANGES; 3926 unsigned int maxnamelen; 3927 3928 SCIP_Bool error; 3929 3930 assert(reader != NULL); 3931 assert(strcmp(SCIPreaderGetName(reader), READER_NAME) == 0); 3932 assert(scip != NULL); 3933 assert(result != NULL); 3934 3935 needRANGES = FALSE; 3936 maxnamelen = 0; 3937 nConsSOS1 = 0; 3938 nConsSOS2 = 0; 3939 nConsQuadratic = 0; 3940 nConsIndicator = 0; 3941 3942 /* check if the constraint names are too long and build the constraint names */ 3943 SCIP_CALL( checkConsnames(scip, conss, nconss, transformed, &maxnamelen, &consnames, &error) ); 3944 if( error ) 3945 { 3946 /* call writing with generic names */ 3947 if( transformed ) 3948 { 3949 SCIPwarningMessage(scip, "write transformed problem with generic variable and constraint names\n"); 3950 SCIP_CALL( SCIPprintTransProblem(scip, file, "mps", TRUE) ); 3951 } 3952 else 3953 { 3954 SCIPwarningMessage(scip, "write original problem with generic variable and constraint names\n"); 3955 SCIP_CALL( SCIPprintOrigProblem(scip, file, "mps", TRUE) ); 3956 } 3957 *result = SCIP_SUCCESS; 3958 3959 return SCIP_OKAY; 3960 } 3961 3962 /* check if the variable names are not too long and build the "variable" -> "variable name" hash map */ 3963 SCIP_CALL( checkVarnames(scip, vars, nvars, &maxnamelen, &varnames, &varnameHashmap) ); 3964 3965 /* collect SOS, quadratic, and indicator constraints in array for later output */ 3966 SCIP_CALL( SCIPallocBufferArray(scip, &consSOS1, nconss) ); 3967 SCIP_CALL( SCIPallocBufferArray(scip, &consSOS2, nconss) ); 3968 SCIP_CALL( SCIPallocBufferArray(scip, &consQuadratic, nconss) ); 3969 SCIP_CALL( SCIPallocBufferArray(scip, &consIndicator, nconss) ); 3970 3971 /* nfixedvars counts all variables with status SCIP_VARSTATUS_FIXED, SCIP_VARSTATUS_AGGREGATED, SCIP_VARSTATUS_MULTAGGR, but not SCIP_VARSTATUS_NEGATED */ 3972 saggvars = nfixedvars; 3973 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &aggvars, saggvars) ); 3974 3975 /* create hashtable for storing aggregated variables */ 3976 if( nfixedvars > 0 ) 3977 { 3978 SCIP_CALL( SCIPhashtableCreate(&varFixedHash, SCIPblkmem(scip), nfixedvars, hashGetKeyVar, hashKeyEqVar, hashKeyValVar, NULL) ); 3979 } 3980 else 3981 varFixedHash = NULL; 3982 3983 if( nvars > 0 ) 3984 { 3985 SCIP_CALL( SCIPhashtableCreate(&indicatorSlackHash, SCIPblkmem(scip), nvars, hashGetKeyVar, hashKeyEqVar, hashKeyValVar, NULL) ); 3986 } 3987 else 3988 indicatorSlackHash = NULL; 3989 3990 /* initialize sparse matrix */ 3991 SCIP_CALL( initializeMatrix(scip, &matrix, (nvars * 2 + nfixedvars)) ); 3992 assert( matrix->sentries >= nvars ); 3993 3994 readerdata = SCIPreaderGetData(reader); 3995 assert(readerdata != NULL); 3996 3997 naddrows = 0; 3998 3999 /* determine and-constraints and printing format to resize necessary arrays */ 4000 if( readerdata->linearizeands ) 4001 { 4002 SCIP_CONSHDLR* andconshdlr = SCIPfindConshdlr(scip, "and"); 4003 4004 if( andconshdlr != NULL ) 4005 { 4006 /* need to check for and-constraints, note that in the original problem you cannot get the number of 4007 * and-constraints by one call */ 4008 for( c = nconss - 1; c >= 0; --c ) 4009 { 4010 conshdlr = SCIPconsGetHdlr(conss[c]); 4011 assert(conshdlr != NULL); 4012 4013 conshdlrname = SCIPconshdlrGetName(conshdlr); 4014 4015 if( strcmp(conshdlrname, "and") == 0 ) 4016 { 4017 if( readerdata->aggrlinearizationands ) 4018 ++naddrows; 4019 else 4020 naddrows += SCIPgetNVarsAnd(scip, conss[c]); 4021 } 4022 } 4023 assert(naddrows >= 0); 4024 4025 if( naddrows > 0 ) 4026 { 4027 /* resize consnames vector */ 4028 SCIP_CALL( SCIPreallocBufferArray(scip, &consnames, nconss + naddrows) ); 4029 } 4030 } 4031 } 4032 4033 /* initialize rhs vector */ 4034 SCIP_CALL( SCIPallocBufferArray(scip, &rhss, nconss + naddrows) ); 4035 4036 /* print statistics as comment to file stream */ 4037 SCIPinfoMessage(scip, file, "* SCIP STATISTICS\n"); 4038 SCIPinfoMessage(scip, file, "* Problem name : %s\n", name); 4039 SCIPinfoMessage(scip, file, "* Variables : %d (%d binary, %d integer, %d implicit integer, %d continuous)\n", 4040 nvars, nbinvars, nintvars, nimplvars, ncontvars); 4041 SCIPinfoMessage(scip, file, "* Constraints : %d\n", nconss); 4042 4043 /* print NAME of the problem */ 4044 SCIPinfoMessage(scip, file, "%-14s%s\n", "NAME", name); 4045 4046 /* print OBJSENSE of the problem */ 4047 SCIPinfoMessage(scip, file, "OBJSENSE\n"); 4048 SCIPinfoMessage(scip, file, "%s\n", objsense == SCIP_OBJSENSE_MAXIMIZE ? " MAX" : " MIN"); 4049 4050 /* start ROWS section */ 4051 SCIPinfoMessage(scip, file, "ROWS\n"); 4052 4053 /* print row type for the objective function */ 4054 printStart(scip, file, "N", "Obj", -1); 4055 SCIPinfoMessage(scip, file, "\n"); 4056 4057 /* first fill the matrix with the objective coefficients */ 4058 for( v = 0; v < nvars; ++v ) 4059 { 4060 /* take care of the objective entry */ 4061 var = vars[v]; 4062 value = SCIPvarGetObj(var); 4063 4064 /* we also want to add integer variables to the columns section, even if the objective value is 0, because it 4065 * might happen that they only exist in non-linear constraints, which leads to no other line in the column section 4066 * and therefore do not mark the variable as an integer 4067 */ 4068 if( !SCIPisZero(scip, value) || SCIPvarGetType(var) < SCIP_VARTYPE_IMPLINT 4069 || ((SCIPvarGetNLocksDownType(var, SCIP_LOCKTYPE_MODEL) == 0) 4070 && (SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL) == 0)) ) 4071 { 4072 assert( matrix->nentries < matrix->sentries ); 4073 4074 matrix->values[matrix->nentries] = objscale * value; 4075 matrix->columns[matrix->nentries] = var; 4076 matrix->rows[matrix->nentries] = "Obj"; 4077 matrix->nentries++; 4078 } 4079 } 4080 4081 /* loop over all constraints */ 4082 k = nconss; 4083 for( c = 0; c < nconss; ++c ) 4084 { 4085 cons = conss[c]; 4086 assert( cons != NULL); 4087 4088 /* in case the transformed problems is written only constraint are posted which are enabled in the current node; 4089 * the conss array should only contain relevant constraints 4090 */ 4091 assert( !transformed || SCIPconsIsEnabled(cons) ); 4092 4093 conshdlr = SCIPconsGetHdlr(cons); 4094 assert( conshdlr != NULL ); 4095 4096 conshdlrname = SCIPconshdlrGetName(conshdlr); 4097 4098 /* construct constraint name */ 4099 consname = consnames[c]; 4100 4101 /* init rhs value to infinity (would then ignored) */ 4102 rhss[c] = SCIPinfinity(scip); 4103 4104 if( strcmp(conshdlrname, "linear") == 0 ) 4105 { 4106 lhs = SCIPgetLhsLinear(scip, cons); 4107 rhs = SCIPgetRhsLinear(scip, cons); 4108 4109 /* there is nothing to do if the left hand side is minus infinity and the right side is infinity */ 4110 if( !SCIPisInfinity(scip, -lhs) || !SCIPisInfinity(scip, rhs) ) 4111 { 4112 if( !SCIPisInfinity(scip, -lhs) && !SCIPisInfinity(scip, rhs) && !SCIPisEQ(scip, lhs, rhs) ) 4113 needRANGES = TRUE; 4114 4115 /* print row entry */ 4116 printRowType(scip, file, lhs, rhs, consname); 4117 4118 if( SCIPisInfinity(scip, rhs) ) 4119 rhss[c] = lhs; 4120 else 4121 rhss[c] = rhs; 4122 4123 assert( !SCIPisInfinity(scip, rhss[c]) ); 4124 4125 /* compute column entries */ 4126 SCIP_CALL( getLinearCoeffs(scip, consname, SCIPgetVarsLinear(scip, cons), SCIPgetValsLinear(scip, cons), 4127 SCIPgetNVarsLinear(scip, cons), transformed, matrix, &rhss[c]) ); 4128 } 4129 } 4130 else if( strcmp(conshdlrname, "setppc") == 0 ) 4131 { 4132 /* print row entry */ 4133 switch( SCIPgetTypeSetppc(scip, cons) ) 4134 { 4135 case SCIP_SETPPCTYPE_PARTITIONING : 4136 printRowType(scip, file, 1.0, 1.0, consname); 4137 break; 4138 case SCIP_SETPPCTYPE_PACKING : 4139 printRowType(scip, file, -SCIPinfinity(scip), 1.0, consname); 4140 break; 4141 case SCIP_SETPPCTYPE_COVERING : 4142 printRowType(scip, file, 1.0, SCIPinfinity(scip), consname); 4143 break; 4144 } 4145 4146 rhss[c] = 1.0; 4147 4148 /* compute column entries */ 4149 SCIP_CALL( getLinearCoeffs(scip, consname, SCIPgetVarsSetppc(scip, cons), NULL, SCIPgetNVarsSetppc(scip, cons), transformed, matrix, &rhss[c]) ); 4150 } 4151 else if( strcmp(conshdlrname, "logicor") == 0 ) 4152 { 4153 /* print row entry */ 4154 printRowType(scip, file, 1.0, SCIPinfinity(scip), consname); 4155 4156 rhss[c] = 1.0; 4157 4158 /* compute column entries */ 4159 SCIP_CALL( getLinearCoeffs(scip, consname, SCIPgetVarsLogicor(scip, cons), NULL, SCIPgetNVarsLogicor(scip, cons), transformed, matrix, &rhss[c]) ); 4160 } 4161 else if( strcmp(conshdlrname, "knapsack") == 0 ) 4162 { 4163 int i; 4164 4165 /* print row entry */ 4166 printRowType(scip, file, -SCIPinfinity(scip), (SCIP_Real) SCIPgetCapacityKnapsack(scip, cons), consname); 4167 4168 nconsvars = SCIPgetNVarsKnapsack(scip, cons); 4169 weights = SCIPgetWeightsKnapsack(scip, cons); 4170 4171 /* copy Longint array to SCIP_Real array */ 4172 SCIP_CALL( SCIPallocBufferArray(scip, &vals, nconsvars ) ); 4173 for( i = 0; i < nconsvars; ++i ) 4174 vals[i] = (SCIP_Real)weights[i]; 4175 4176 rhss[c] = (SCIP_Real) SCIPgetCapacityKnapsack(scip, cons); 4177 4178 /* compute column entries */ 4179 SCIP_CALL( getLinearCoeffs(scip, consname, SCIPgetVarsKnapsack(scip, cons), vals, nconsvars, transformed, matrix, &rhss[c]) ); 4180 4181 SCIPfreeBufferArray(scip, &vals); 4182 } 4183 else if( strcmp(conshdlrname, "varbound") == 0 ) 4184 { 4185 lhs = SCIPgetLhsVarbound(scip, cons); 4186 rhs = SCIPgetRhsVarbound(scip, cons); 4187 4188 /* there is nothing to do if the left hand side is minus infinity and the right side is infinity */ 4189 if( !SCIPisInfinity(scip, -lhs) || !SCIPisInfinity(scip, rhs) ) 4190 { 4191 if( !SCIPisInfinity(scip, -lhs) && !SCIPisInfinity(scip, rhs) && !SCIPisEQ(scip, lhs, rhs) ) 4192 needRANGES = TRUE; 4193 4194 /* print row entry */ 4195 printRowType(scip, file, lhs, rhs, consname); 4196 4197 /* allocate memory */ 4198 SCIP_CALL( SCIPallocBufferArray(scip, &consvars, 2) ); 4199 SCIP_CALL( SCIPallocBufferArray(scip, &vals, 2) ); 4200 4201 consvars[0] = SCIPgetVarVarbound(scip, cons); 4202 consvars[1] = SCIPgetVbdvarVarbound(scip, cons); 4203 4204 vals[0] = 1.0; 4205 vals[1] = SCIPgetVbdcoefVarbound(scip, cons); 4206 4207 if( SCIPisInfinity(scip, rhs) ) 4208 rhss[c] = lhs; 4209 else 4210 rhss[c] = rhs; 4211 4212 assert( !SCIPisInfinity(scip, rhss[c]) ); 4213 4214 /* compute column entries */ 4215 SCIP_CALL( getLinearCoeffs(scip, consname, consvars, vals, 2, transformed, matrix, &rhss[c]) ); 4216 4217 SCIPfreeBufferArray(scip, &vals); 4218 SCIPfreeBufferArray(scip, &consvars); 4219 } 4220 } 4221 else if( strcmp(conshdlrname, "indicator") == 0 ) 4222 { 4223 SCIP_VAR* slackvar; 4224 SCIP_VAR* binvar; 4225 4226 /* store slack variable in hash */ 4227 slackvar = SCIPgetSlackVarIndicator(cons); 4228 assert( slackvar != NULL ); 4229 assert( indicatorSlackHash != NULL ); 4230 assert( !SCIPhashtableExists(indicatorSlackHash, (void*) slackvar) ); 4231 SCIP_CALL( SCIPhashtableInsert(indicatorSlackHash, (void*) slackvar) ); 4232 4233 /* if slackvariable is aggregated, we store it in the list of aggregated variables */ 4234 if ( SCIPvarGetStatus(slackvar) == SCIP_VARSTATUS_AGGREGATED ) 4235 { 4236 SCIP_CALL( collectAggregatedVars(scip, &slackvar, 1, &aggvars, &naggvars, &saggvars, varFixedHash) ); 4237 } 4238 4239 /* store aggregated variables */ 4240 binvar = SCIPgetBinaryVarIndicator(cons); 4241 if( SCIPvarIsNegated(binvar) ) 4242 binvar = SCIPvarGetNegatedVar(binvar); 4243 assert( binvar != NULL ); 4244 SCIP_CALL( collectAggregatedVars(scip, &binvar, 1, &aggvars, &naggvars, &saggvars, varFixedHash) ); 4245 4246 /* indicator constraint do not have a right hand side; mark this with SCIPinfinity(scip) */ 4247 rhss[c] = SCIPinfinity(scip); 4248 4249 /* store constraint */ 4250 consIndicator[nConsIndicator++] = cons; 4251 continue; 4252 } 4253 else if( strcmp(conshdlrname, "SOS1") == 0 ) 4254 { 4255 /* store constraint */ 4256 consSOS1[nConsSOS1++] = cons; 4257 4258 /* check for aggregated variables in SOS1 constraints for later output 4259 * of aggregations as linear constraints */ 4260 consvars = SCIPgetVarsSOS1(scip, cons); 4261 nconsvars = SCIPgetNVarsSOS1(scip, cons); 4262 4263 /* SOS constraint do not have a right hand side; mark this with SCIPinfinity(scip) */ 4264 rhss[c] = SCIPinfinity(scip); 4265 4266 SCIP_CALL( collectAggregatedVars(scip, consvars, nconsvars, &aggvars, &naggvars, &saggvars, varFixedHash) ); 4267 } 4268 else if( strcmp(conshdlrname, "SOS2") == 0 ) 4269 { 4270 /* store constraint */ 4271 consSOS2[nConsSOS2++] = cons; 4272 4273 /* check for aggregated variables in SOS2 constraints for later output aggregations as linear constraints */ 4274 consvars = SCIPgetVarsSOS2(scip, cons); 4275 nconsvars = SCIPgetNVarsSOS2(scip, cons); 4276 4277 /* SOS constraint do not have a right hand side; mark this with SCIPinfinity(scip) */ 4278 rhss[c] = SCIPinfinity(scip); 4279 4280 SCIP_CALL( collectAggregatedVars(scip, consvars, nconsvars, &aggvars, &naggvars, &saggvars, varFixedHash) ); 4281 } 4282 else if( strcmp(conshdlrname, "nonlinear") == 0 ) 4283 { 4284 SCIP_EXPR* expr; 4285 SCIP_VAR** quadvars; 4286 SCIP_Real* quadvarlincoefs; 4287 SCIP_Real* lincoefs; 4288 SCIP_Real constant; 4289 SCIP_EXPR** linexprs; 4290 SCIP_Bool isquadratic; 4291 int nquadexprs; 4292 int nlinexprs; 4293 int j; 4294 4295 /* check if it is a quadratic constraint */ 4296 SCIP_CALL( SCIPcheckQuadraticNonlinear(scip, cons, &isquadratic) ); 4297 if( !isquadratic ) 4298 { 4299 /* unknown constraint type; mark this with SCIPinfinity(scip) */ 4300 rhss[c] = SCIPinfinity(scip); 4301 4302 SCIPwarningMessage(scip, "constraint handler <%s> cannot print requested format\n", conshdlrname ); 4303 continue; 4304 } 4305 4306 /* store constraint */ 4307 consQuadratic[nConsQuadratic++] = cons; 4308 4309 expr = SCIPgetExprNonlinear(cons); 4310 4311 /* collect linear coefficients of quadratic part */ 4312 SCIPexprGetQuadraticData(expr, &constant, &nlinexprs, &linexprs, &lincoefs, &nquadexprs, NULL, NULL, 4313 NULL); 4314 4315 SCIP_CALL( SCIPallocBufferArray(scip, &quadvars, nquadexprs) ); 4316 SCIP_CALL( SCIPallocBufferArray(scip, &quadvarlincoefs, nquadexprs) ); 4317 for( j = 0; j < nquadexprs; ++j ) 4318 { 4319 SCIP_EXPR* qexpr; 4320 4321 SCIPexprGetQuadraticQuadTerm(expr, j, &qexpr, &quadvarlincoefs[j], NULL, NULL, NULL, NULL); 4322 4323 assert(SCIPisExprVar(scip, qexpr)); 4324 quadvars[j] = SCIPgetVarExprVar(qexpr); 4325 } 4326 4327 lhs = SCIPgetLhsNonlinear(cons); 4328 rhs = SCIPgetRhsNonlinear(cons); 4329 4330 /* correct side by constant */ 4331 lhs -= SCIPisInfinity(scip, -lhs) ? 0.0 : constant; 4332 rhs -= SCIPisInfinity(scip, rhs) ? 0.0 : constant; 4333 4334 /* there is nothing to do if the left hand side is minus infinity and the right side is infinity */ 4335 if( !SCIPisInfinity(scip, -lhs) || !SCIPisInfinity(scip, rhs) ) 4336 { 4337 SCIP_VAR** linvars; 4338 4339 if( !SCIPisInfinity(scip, -lhs) && !SCIPisInfinity(scip, rhs) && !SCIPisEQ(scip, lhs, rhs) ) 4340 needRANGES = TRUE; 4341 4342 /* print row entry */ 4343 printRowType(scip, file, lhs, rhs, consname); 4344 4345 if( SCIPisInfinity(scip, rhs) ) 4346 rhss[c] = lhs; 4347 else 4348 rhss[c] = rhs; 4349 4350 assert( !SCIPisInfinity(scip, rhss[c]) ); 4351 4352 /* get linear vars */ 4353 SCIP_CALL( SCIPallocBufferArray(scip, &linvars, nlinexprs) ); 4354 for( j = 0; j < nlinexprs; ++j ) 4355 linvars[j] = SCIPgetVarExprVar(linexprs[j]); 4356 4357 /* compute column entries for linear part */ 4358 SCIP_CALL( getLinearCoeffs(scip, consname, linvars, lincoefs, nlinexprs, transformed, matrix, &rhss[c]) ); 4359 4360 /* compute column entries for linear part in quadratic part */ 4361 SCIP_CALL( getLinearCoeffs(scip, consname, quadvars, quadvarlincoefs, nquadexprs, transformed, matrix, 4362 &rhss[c]) ); 4363 4364 SCIPfreeBufferArray(scip, &linvars); 4365 } 4366 4367 /* check for aggregated variables in quadratic part of quadratic constraints for later output of 4368 * aggregations as linear constraints */ 4369 consvars = quadvars; 4370 nconsvars = nquadexprs; 4371 4372 SCIP_CALL( collectAggregatedVars(scip, consvars, nconsvars, &aggvars, &naggvars, &saggvars, varFixedHash) ); 4373 4374 SCIPfreeBufferArray(scip, &quadvars); 4375 SCIPfreeBufferArray(scip, &quadvarlincoefs); 4376 } 4377 else if( strcmp(conshdlrname, "and") == 0 ) 4378 { 4379 if( readerdata->linearizeands ) 4380 { 4381 SCIP_VAR** rowvars; 4382 SCIP_VAR** operands; 4383 SCIP_VAR* resultant; 4384 SCIP_Real* rowvals; 4385 char* rowname; 4386 int nrowvars; 4387 int l; 4388 int n; 4389 4390 nrowvars = SCIPgetNVarsAnd(scip, cons); 4391 operands = SCIPgetVarsAnd(scip, cons); 4392 resultant = SCIPgetResultantAnd(scip, cons); 4393 4394 /* allocate buffer array */ 4395 SCIP_CALL( SCIPallocBufferArray(scip, &rowvars, nrowvars + 1) ); 4396 SCIP_CALL( SCIPallocBufferArray(scip, &rowvals, nrowvars + 1) ); 4397 4398 /* get length of constraint name */ 4399 l = (int) strlen(consname); 4400 4401 /* the tight relaxtion, number of and-constraint operands rows */ 4402 if( !readerdata->aggrlinearizationands ) 4403 { 4404 rowvars[0] = resultant; 4405 rowvals[0] = 1.0; 4406 rowvals[1] = -1.0; 4407 4408 /* compute maximal length for rowname */ 4409 /* coverity[negative_returns] */ 4410 n = (int) log10((double)nrowvars) + 1 + l; 4411 4412 /* assure maximal allowed value */ 4413 if( n >= MPS_MAX_NAMELEN ) 4414 n = MPS_MAX_NAMELEN - 1; 4415 4416 /* update maxnamelen */ 4417 maxnamelen = MAX(maxnamelen, (unsigned int) n); 4418 4419 /* print operator rows */ 4420 for( v = 0; v < nrowvars; ++v ) 4421 { 4422 /* compute maximal length for rowname */ 4423 if( v == 0 ) 4424 n = 2; 4425 else 4426 n = (int) log10((double)v) + 2; 4427 n += l; 4428 4429 /* assure maximal allowed value */ 4430 if( n >= MPS_MAX_NAMELEN ) 4431 { 4432 n = MPS_MAX_NAMELEN - 1; 4433 ++faulty; 4434 } 4435 4436 /* need memory for additional row */ 4437 SCIP_CALL( SCIPallocBufferArray(scip, &rowname, n + 1) ); 4438 4439 assert(k < nconss + naddrows); 4440 consnames[k] = rowname; 4441 4442 (void) SCIPsnprintf(rowname, n + 1, "%s_%d", consname, v); 4443 rowvars[1] = operands[v]; 4444 4445 /* print row entry */ 4446 printRowType(scip, file, -SCIPinfinity(scip), 0.0, rowname); 4447 4448 rhss[k] = 0.0; 4449 4450 /* compute column entries */ 4451 SCIP_CALL( getLinearCoeffs(scip, rowname, rowvars, rowvals, 2, transformed, matrix, &rhss[k]) ); 4452 ++k; 4453 } 4454 } 4455 4456 /* prepare for next row */ 4457 for( v = nrowvars - 1; v >= 0; --v ) 4458 { 4459 rowvars[v] = operands[v]; 4460 rowvals[v] = -1.0; 4461 } 4462 4463 rowvars[nrowvars] = resultant; 4464 4465 /* the weak relaxtion, only one constraint */ 4466 if( readerdata->aggrlinearizationands ) 4467 { 4468 /* compute maximal length for rowname */ 4469 n = l + 3; 4470 4471 /* assure maximal allowed value */ 4472 if( n >= MPS_MAX_NAMELEN ) 4473 { 4474 n = MPS_MAX_NAMELEN - 1; 4475 ++faulty; 4476 } 4477 4478 /* update maxnamelen */ 4479 maxnamelen = MAX(maxnamelen, (unsigned int) n); 4480 4481 /* need memory for additional row */ 4482 SCIP_CALL( SCIPallocBufferArray(scip, &rowname, n + 1) ); 4483 4484 assert(k < nconss + naddrows); 4485 consnames[k] = rowname; 4486 4487 /* adjust rowname of constraint */ 4488 (void) SCIPsnprintf(rowname, n + 1, "%s_op", consname); 4489 4490 rowvals[nrowvars] = (SCIP_Real) nrowvars; 4491 4492 /* print row entry */ 4493 printRowType(scip, file, -SCIPinfinity(scip), 0.0, rowname); 4494 4495 rhss[k] = 0.0; 4496 4497 /* compute column entries */ 4498 SCIP_CALL( getLinearCoeffs(scip, rowname, rowvars, rowvals, nrowvars + 1, transformed, matrix, &rhss[k]) ); 4499 4500 SCIPdebugMsg(scip, "%g, %g\n", rowvals[1], rhss[k]); 4501 ++k; 4502 } 4503 4504 rowvals[nrowvars] = 1.0; 4505 4506 /* print row entry */ 4507 printRowType(scip, file, -nrowvars + 1.0, SCIPinfinity(scip), consname); 4508 4509 rhss[c] = -nrowvars + 1.0; 4510 4511 /* compute column entries */ 4512 SCIP_CALL( getLinearCoeffs(scip, consname, rowvars, rowvals, nrowvars + 1, transformed, matrix, &rhss[c]) ); 4513 4514 /* free buffer array */ 4515 SCIPfreeBufferArray(scip, &rowvals); 4516 SCIPfreeBufferArray(scip, &rowvars); 4517 } 4518 else 4519 { 4520 /* and constraint printing not enabled; mark this with SCIPinfinity(scip) */ 4521 rhss[c] = SCIPinfinity(scip); 4522 4523 SCIPwarningMessage(scip, "change parameter \"reading/" READER_NAME "/linearize-and-constraints\" to TRUE to print and-constraints\n"); 4524 } 4525 } 4526 else 4527 { 4528 /* unknown constraint type; mark this with SCIPinfinity(scip) */ 4529 rhss[c] = SCIPinfinity(scip); 4530 4531 SCIPwarningMessage(scip, "constraint handler <%s> cannot print requested format\n", conshdlrname ); 4532 } 4533 } 4534 4535 if( faulty > 0 ) 4536 { 4537 SCIPwarningMessage(scip, "there are %d and-constraint-rownames which have to be cut down to %d characters; MPS file might be corrupted\n", 4538 faulty, MPS_MAX_NAMELEN - 1); 4539 } 4540 4541 /* free hash table */ 4542 if( varFixedHash != NULL ) 4543 SCIPhashtableFree(&varFixedHash); 4544 4545 if( indicatorSlackHash != NULL && nConsIndicator == 0 ) 4546 { 4547 SCIPhashtableFree(&indicatorSlackHash); 4548 assert( indicatorSlackHash == NULL ); 4549 } 4550 4551 if( naggvars > 0 ) 4552 { 4553 /* construct variables name of the needed aggregated variables and the constraint names for the aggregation constraints */ 4554 4555 /* realloc memory */ 4556 SCIP_CALL( SCIPreallocBufferArray(scip, &consnames, nconss + naddrows + naggvars) ); 4557 SCIP_CALL( SCIPreallocBufferArray(scip, &rhss, nconss + naddrows + naggvars) ); 4558 SCIP_CALL( SCIPreallocBufferArray(scip, &varnames, nvars + naggvars) ); 4559 4560 for( c = 0; c < naggvars; ++c ) 4561 { 4562 size_t l; 4563 4564 /* create variable name */ 4565 var = aggvars[c]; 4566 4567 l = strlen(SCIPvarGetName(var)); 4568 if( l >= MPS_MAX_NAMELEN ) 4569 maxnamelen = MPS_MAX_NAMELEN - 1; 4570 else 4571 maxnamelen = MAX(maxnamelen, (unsigned int) l); 4572 4573 SCIP_CALL( SCIPallocBufferArray(scip, &namestr, MPS_MAX_NAMELEN) ); 4574 (void) SCIPsnprintf(namestr, MPS_MAX_NAMELEN, "%s", SCIPvarGetName(var) ); 4575 4576 /* insert variable with variable name into hash map */ 4577 varnames[nvars + c] = namestr; 4578 assert( !SCIPhashmapExists(varnameHashmap, var) ); 4579 SCIP_CALL( SCIPhashmapInsert(varnameHashmap, var, (void*) namestr) ); 4580 4581 /* output row type (it is an equation) */ 4582 SCIP_CALL( SCIPallocBufferArray(scip, &namestr, MPS_MAX_NAMELEN) ); /* note that namestr above is freed via varnames */ 4583 (void) SCIPsnprintf(namestr, MPS_MAX_NAMELEN, "aggr_%s", SCIPvarGetName(var)); 4584 printRowType(scip, file, 1.0, 1.0, namestr); 4585 4586 l = strlen(namestr); 4587 maxnamelen = MAX(maxnamelen, (unsigned int) l); 4588 consnames[nconss + naddrows + c] = namestr; 4589 rhss[nconss + naddrows + c] = 0.0; 4590 4591 /* compute column entries */ 4592 SCIP_CALL( getLinearCoeffs(scip, namestr, &(aggvars[c]), NULL, 1, transformed, matrix, &rhss[nconss + naddrows + c]) ); 4593 4594 /* add the aggregated variables to the sparse matrix */ 4595 SCIP_CALL( checkSparseMatrixCapacity(scip, matrix, 1) ); 4596 matrix->values[matrix->nentries] = -1.0; 4597 matrix->columns[matrix->nentries] = aggvars[c]; 4598 matrix->rows[matrix->nentries] = namestr; 4599 matrix->nentries++; 4600 } 4601 } 4602 4603 /* collect also fixed variables, because they might not be removed from all constraints */ 4604 /* @todo only collect fixed variables in the non-linear constraint types, where they (could not be)/(were not) removed */ 4605 if( nfixedvars > 0 ) 4606 { 4607 int startpos = nvars + naggvars; 4608 /* construct variables name of fixed variables */ 4609 4610 /* realloc memory */ 4611 SCIP_CALL( SCIPreallocBufferArray(scip, &varnames, startpos + nfixedvars) ); 4612 4613 /* allocate memory for fixed variables */ 4614 SCIP_CALL( SCIPallocBufferArray(scip, &fixvars, nfixedvars) ); 4615 4616 for( v = nfixedvars - 1; v >= 0; --v ) 4617 { 4618 /* create variable name */ 4619 var = fixedvars[v]; 4620 4621 if( SCIPvarGetStatus(var) == SCIP_VARSTATUS_FIXED ) 4622 { 4623 size_t l; 4624 l = strlen(SCIPvarGetName(var)); 4625 if( l >= MPS_MAX_NAMELEN ) 4626 maxnamelen = MPS_MAX_NAMELEN - 1; 4627 else 4628 maxnamelen = MAX(maxnamelen, (unsigned int) l); 4629 4630 SCIP_CALL( SCIPallocBufferArray(scip, &namestr, MPS_MAX_NAMELEN) ); 4631 (void) SCIPsnprintf(namestr, MPS_MAX_NAMELEN, "%s", SCIPvarGetName(var) ); 4632 4633 varnames[startpos + nfixvars] = namestr; 4634 fixvars[nfixvars] = var; 4635 ++nfixvars; 4636 4637 /* insert variable with variable name into hash map */ 4638 assert(!SCIPhashmapExists(varnameHashmap, var)); 4639 SCIP_CALL( SCIPhashmapInsert(varnameHashmap, var, (void*) namestr) ); 4640 4641 /* add the fixed variables to the sparse matrix, needed for columns section */ 4642 SCIP_CALL( checkSparseMatrixCapacity(scip, matrix, 1) ); 4643 matrix->values[matrix->nentries] = 0.0; 4644 matrix->columns[matrix->nentries] = var; 4645 matrix->rows[matrix->nentries] = "Obj"; 4646 matrix->nentries++; 4647 } 4648 } 4649 } 4650 4651 /* output COLUMNS section */ 4652 printColumnSection(scip, file, matrix, varnameHashmap, indicatorSlackHash, maxnamelen); 4653 4654 /* output RHS section */ 4655 printRhsSection(scip, file, nconss + naddrows +naggvars, consnames, rhss, maxnamelen, objscale * objoffset); 4656 4657 /* output RANGES section */ 4658 if( needRANGES ) 4659 printRangeSection(scip, file, conss, nconss, consnames, transformed, maxnamelen); 4660 4661 /* output BOUNDS section */ 4662 printBoundSection(scip, file, vars, nvars, aggvars, naggvars, fixvars, nfixvars, transformed, varnames, indicatorSlackHash, maxnamelen); 4663 4664 if( nfixedvars > 0 ) 4665 { 4666 SCIPfreeBufferArray(scip, &fixvars); 4667 } 4668 4669 /* print SOS section */ 4670 if( nConsSOS1 > 0 || nConsSOS2 > 0 ) 4671 { 4672 SCIP_Real* sosweights; 4673 4674 SCIPinfoMessage(scip, file, "SOS\n"); 4675 SCIPdebugMsg(scip, "start printing SOS section\n"); 4676 4677 SCIP_CALL( SCIPallocBufferArray(scip, &namestr, MPS_MAX_NAMELEN) ); 4678 4679 /* first output SOS1 constraints */ 4680 for( c = 0; c < nConsSOS1; ++c ) 4681 { 4682 cons = consSOS1[c]; 4683 consvars = SCIPgetVarsSOS1(scip, cons); 4684 nconsvars = SCIPgetNVarsSOS1(scip, cons); 4685 sosweights = SCIPgetWeightsSOS1(scip, cons); 4686 (void) SCIPsnprintf(namestr, MPS_MAX_NAMELEN, "%s", SCIPconsGetName(cons) ); 4687 4688 printStart(scip, file, "S1", namestr, -1); 4689 SCIPinfoMessage(scip, file, "\n"); 4690 4691 for( v = 0; v < nconsvars; ++v ) 4692 { 4693 /* get variable name */ 4694 assert ( SCIPhashmapExists(varnameHashmap, consvars[v]) ); 4695 varname = (const char*) SCIPhashmapGetImage(varnameHashmap, consvars[v]); 4696 4697 printStart(scip, file, "", varname, (int) maxnamelen); 4698 4699 if( sosweights != NULL ) 4700 (void) SCIPsnprintf(valuestr, MPS_MAX_VALUELEN, "%25.15g", sosweights[v]); 4701 else 4702 (void) SCIPsnprintf(valuestr, MPS_MAX_VALUELEN, "%25d ", v); 4703 4704 SCIPinfoMessage(scip, file, "%25s\n", valuestr); 4705 } 4706 } 4707 4708 /* next output SOS2 constraints */ 4709 for( c = 0; c < nConsSOS2; ++c ) 4710 { 4711 cons = consSOS2[c]; 4712 consvars = SCIPgetVarsSOS2(scip, cons); 4713 nconsvars = SCIPgetNVarsSOS2(scip, cons); 4714 sosweights = SCIPgetWeightsSOS2(scip, cons); 4715 (void) SCIPsnprintf(namestr, MPS_MAX_NAMELEN, "%s", SCIPconsGetName(cons) ); 4716 4717 printStart(scip, file, "S2", namestr, -1); 4718 SCIPinfoMessage(scip, file, "\n"); 4719 4720 for( v = 0; v < nconsvars; ++v ) 4721 { 4722 /* get variable name */ 4723 assert ( SCIPhashmapExists(varnameHashmap, consvars[v]) ); 4724 varname = (const char*) SCIPhashmapGetImage(varnameHashmap, consvars[v]); 4725 4726 printStart(scip, file, "", varname, (int) maxnamelen); 4727 4728 if( sosweights != NULL ) 4729 (void) SCIPsnprintf(valuestr, MPS_MAX_VALUELEN, "%25.15g", sosweights[v]); 4730 else 4731 (void) SCIPsnprintf(valuestr, MPS_MAX_VALUELEN, "%25d ", v); 4732 4733 SCIPinfoMessage(scip, file, "%25s\n", valuestr); 4734 } 4735 } 4736 SCIPfreeBufferArray(scip, &namestr); 4737 } 4738 4739 /* print QCMATRIX sections for quadratic constraints 4740 * in difference to a quadratic term in the objective function, the quadratic part is not divided by 2 here 4741 */ 4742 if( nConsQuadratic > 0 ) 4743 { 4744 const char* varname2; 4745 int nbilin; 4746 4747 SCIPdebugMsg(scip, "start printing QCMATRIX sections for quadratic constraints\n"); 4748 SCIP_CALL( SCIPallocBufferArray(scip, &namestr, MPS_MAX_NAMELEN) ); 4749 4750 for( c = 0; c < nConsQuadratic; ++c ) 4751 { 4752 SCIP_EXPR* expr; 4753 4754 cons = consQuadratic[c]; 4755 expr = SCIPgetExprNonlinear(cons); 4756 4757 SCIPexprGetQuadraticData(expr, NULL, NULL, NULL, NULL, &nconsvars, &nbilin, NULL, NULL); 4758 4759 (void) SCIPsnprintf(namestr, MPS_MAX_NAMELEN, "%s", SCIPconsGetName(cons) ); 4760 4761 SCIPinfoMessage(scip, file, "QCMATRIX %s\n", namestr); 4762 4763 /* print x^2 terms */ 4764 for( v = 0; v < nconsvars; ++v ) 4765 { 4766 SCIP_EXPR* qexpr; 4767 SCIP_VAR* qvar; 4768 SCIP_Real sqrcoef; 4769 4770 SCIPexprGetQuadraticQuadTerm(expr, v, &qexpr, NULL, &sqrcoef, NULL, NULL, NULL); 4771 if( sqrcoef == 0.0 ) 4772 continue; 4773 4774 assert(SCIPisExprVar(scip, qexpr)); 4775 qvar = SCIPgetVarExprVar(qexpr); 4776 4777 /* get variable name */ 4778 assert(SCIPhashmapExists(varnameHashmap, qvar)); 4779 varname = (const char*) SCIPhashmapGetImage(varnameHashmap, qvar); 4780 4781 /* get coefficient as string */ 4782 (void) SCIPsnprintf(valuestr, MPS_MAX_VALUELEN, "%25.15g", sqrcoef); 4783 4784 /* print "x x coeff" line */ 4785 printStart(scip, file, "", varname, (int) maxnamelen); 4786 printRecord(scip, file, varname, valuestr, maxnamelen); 4787 SCIPinfoMessage(scip, file, "\n"); 4788 } 4789 4790 /* print bilinear terms; CPLEX format expects a symmetric matrix with all coefficients specified, 4791 * i.e., we have to split bilinear coefficients into two off diagonal elements */ 4792 for( v = 0; v < nbilin; ++v ) 4793 { 4794 SCIP_EXPR* expr1; 4795 SCIP_EXPR* expr2; 4796 SCIP_VAR* var1; 4797 SCIP_VAR* var2; 4798 SCIP_Real coef; 4799 4800 SCIPexprGetQuadraticBilinTerm(expr, v, &expr1, &expr2, &coef, NULL, NULL); 4801 assert(SCIPisExprVar(scip, expr1)); 4802 assert(SCIPisExprVar(scip, expr2)); 4803 4804 if( coef == 0.0 ) 4805 continue; 4806 4807 var1 = SCIPgetVarExprVar(expr1); 4808 var2 = SCIPgetVarExprVar(expr2); 4809 4810 /* get name of first variable */ 4811 assert ( SCIPhashmapExists(varnameHashmap, var1) ); 4812 varname = (const char*) SCIPhashmapGetImage(varnameHashmap, var1); 4813 4814 /* get name of second variable */ 4815 assert ( SCIPhashmapExists(varnameHashmap, var2) ); 4816 varname2 = (const char*) SCIPhashmapGetImage(varnameHashmap, var2); 4817 4818 /* get coefficient as string */ 4819 (void) SCIPsnprintf(valuestr, MPS_MAX_VALUELEN, "%25.15g", 0.5*coef); 4820 4821 /* print "x y coeff/2" line */ 4822 printStart(scip, file, "", varname, (int) maxnamelen); 4823 printRecord(scip, file, varname2, valuestr, maxnamelen); 4824 SCIPinfoMessage(scip, file, "\n"); 4825 4826 /* print "y x coeff/2" line */ 4827 printStart(scip, file, "", varname2, (int) maxnamelen); 4828 printRecord(scip, file, varname, valuestr, maxnamelen); 4829 SCIPinfoMessage(scip, file, "\n"); 4830 } 4831 } 4832 4833 SCIPfreeBufferArray(scip, &namestr); 4834 } 4835 4836 /* print indicator section */ 4837 if( nConsIndicator > 0 ) 4838 { 4839 SCIP_CALL( SCIPallocBufferArray(scip, &namestr, MPS_MAX_NAMELEN) ); 4840 4841 SCIPinfoMessage(scip, file, "INDICATORS\n"); 4842 SCIPdebugMsg(scip, "start printing INDICATOR section\n"); 4843 4844 /* output each indicator constraint */ 4845 for( c = 0; c < nConsIndicator; ++c ) 4846 { 4847 SCIP_CONS* lincons; 4848 SCIP_VAR* slackvar; 4849 SCIP_VAR* binvar; 4850 4851 cons = consIndicator[c]; 4852 binvar = SCIPgetBinaryVarIndicator(cons); 4853 lincons = SCIPgetLinearConsIndicator(cons); 4854 slackvar = SCIPgetSlackVarIndicator(cons); 4855 4856 /* linvars always contains slack variable, thus nlinvars >= 1 */ 4857 if( SCIPgetNVarsLinear(scip, lincons) <= 1 || SCIPconsIsDeleted(lincons) ) 4858 continue; 4859 4860 /* create variable and value strings */ 4861 if( SCIPvarIsNegated(binvar) ) 4862 { 4863 (void) SCIPsnprintf(valuestr, MPS_MAX_VALUELEN, "%25d", 0); 4864 assert( SCIPvarGetNegatedVar(binvar) != NULL ); 4865 assert( SCIPhashmapExists(varnameHashmap, SCIPvarGetNegatedVar(binvar)) ); 4866 varname = (const char*) SCIPhashmapGetImage(varnameHashmap, SCIPvarGetNegatedVar(binvar)); 4867 } 4868 else 4869 { 4870 (void) SCIPsnprintf(valuestr, MPS_MAX_VALUELEN, "%25d", 1); 4871 assert ( SCIPhashmapExists(varnameHashmap, binvar) ); 4872 varname = (const char*) SCIPhashmapGetImage(varnameHashmap, binvar); 4873 } 4874 4875 /* write records */ 4876 if ( SCIPvarGetStatus(slackvar) == SCIP_VARSTATUS_AGGREGATED ) 4877 { 4878 /* for aggregated variables output name of aggregating constraint */ 4879 (void) SCIPsnprintf(namestr, MPS_MAX_NAMELEN, "aggr_%s", SCIPvarGetName(slackvar)); 4880 printStart(scip, file, "IF", namestr, (int) maxnamelen); 4881 printRecord(scip, file, varname, valuestr, maxnamelen); 4882 SCIPinfoMessage(scip, file, "\n"); 4883 } 4884 else 4885 { 4886 printStart(scip, file, "IF", SCIPconsGetName(lincons), (int) maxnamelen); 4887 printRecord(scip, file, varname, valuestr, maxnamelen); 4888 SCIPinfoMessage(scip, file, "\n"); 4889 } 4890 } 4891 SCIPfreeBufferArray(scip, &namestr); 4892 } 4893 4894 /* free matrix data structure */ 4895 freeMatrix(scip, matrix); 4896 4897 /* free slackvar hashtable */ 4898 if( indicatorSlackHash != NULL ) 4899 SCIPhashtableFree(&indicatorSlackHash); 4900 4901 /* free variable hashmap */ 4902 SCIPhashmapFree(&varnameHashmap); 4903 4904 SCIPfreeBlockMemoryArray(scip, &aggvars, saggvars); 4905 SCIPfreeBufferArray(scip, &rhss); 4906 4907 /* free buffer arrays for SOS1, SOS2, and quadratic */ 4908 SCIPfreeBufferArray(scip, &consIndicator); 4909 SCIPfreeBufferArray(scip, &consQuadratic); 4910 SCIPfreeBufferArray(scip, &consSOS2); 4911 SCIPfreeBufferArray(scip, &consSOS1); 4912 4913 /* free variable and constraint name array */ 4914 for( v = nvars + naggvars + nfixvars - 1; v >= 0; --v ) 4915 SCIPfreeBufferArray(scip, &varnames[v]); 4916 SCIPfreeBufferArray(scip, &varnames); 4917 4918 for( c = nconss + naddrows + naggvars - 1; c >= 0; --c ) 4919 SCIPfreeBufferArray(scip, &consnames[c]); 4920 SCIPfreeBufferArray(scip, &consnames); 4921 4922 /* print end of data line */ 4923 SCIPinfoMessage(scip, file, "ENDATA"); 4924 4925 *result = SCIP_SUCCESS; 4926 4927 return SCIP_OKAY; 4928 } 4929