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 lp.c 26 * @ingroup OTHER_CFILES 27 * @brief LP management methods and data structures 28 * @author Tobias Achterberg 29 * @author Timo Berthold 30 * @author Marc Pfetsch 31 * @author Kati Wolter 32 * @author Gerald Gamrath 33 * 34 * In LP management, we have to differ between the current LP and the SCIP_LP 35 * stored in the LP solver. All LP methods affect the current LP only. 36 * Before solving the current LP with the LP solver or setting an LP state, 37 * the LP solvers data has to be updated to the current LP with a call to 38 * lpFlush(). 39 */ 40 41 /*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/ 42 43 44 #include "lpi/lpi.h" 45 #include "scip/clock.h" 46 #include "scip/cons.h" 47 #include "scip/event.h" 48 #include "scip/intervalarith.h" 49 #include "scip/lp.h" 50 #include "scip/misc.h" 51 #include "scip/prob.h" 52 #include "scip/pub_lp.h" 53 #include "scip/pub_message.h" 54 #include "scip/pub_misc.h" 55 #include "scip/pub_misc_sort.h" 56 #include "scip/pub_var.h" 57 #include "scip/set.h" 58 #include "scip/sol.h" 59 #include "scip/solve.h" 60 #include "scip/stat.h" 61 #include "scip/struct_event.h" 62 #include "scip/struct_lp.h" 63 #include "scip/struct_prob.h" 64 #include "scip/struct_set.h" 65 #include "scip/struct_stat.h" 66 #include "scip/struct_var.h" 67 #include "scip/var.h" 68 #include <string.h> 69 70 71 /* activate this to use the row activities as given by the LPI instead of recalculating 72 * using the LP solver activity is potentially faster, but may not be consistent with the SCIP_ROW calculations 73 * see also #2594 for more details on possible trouble 74 */ 75 /* #define SCIP_USE_LPSOLVER_ACTIVITY */ 76 77 /* 78 * debug messages 79 */ 80 81 #ifdef SCIP_DEBUG 82 /** method is to print in row in case SCIP_DEBUG is defined */ 83 static 84 void debugRowPrint( 85 SCIP_SET* set, /**< global SCIP settings */ 86 SCIP_ROW* row /**< LP row */ 87 ) 88 { 89 int i; 90 91 assert(row != NULL); 92 93 /* print row name */ 94 if( row->name != NULL && row->name[0] != '\0' ) 95 { 96 SCIPsetDebugMsgPrint(set, "%s: ", row->name); 97 } 98 99 /* print left hand side */ 100 SCIPsetDebugMsgPrint(set, "%.15g <= ", row->lhs); 101 102 /* print coefficients */ 103 if( row->len == 0 ) 104 { 105 SCIPsetDebugMsgPrint(set, "0 "); 106 } 107 for( i = 0; i < row->len; ++i ) 108 { 109 assert(row->cols[i] != NULL); 110 assert(row->cols[i]->var != NULL); 111 assert(SCIPvarGetName(row->cols[i]->var) != NULL); 112 assert(SCIPvarGetStatus(row->cols[i]->var) == SCIP_VARSTATUS_COLUMN); 113 SCIPsetDebugMsgPrint(set, "%+.15g<%s> ", row->vals[i], SCIPvarGetName(row->cols[i]->var)); 114 } 115 116 /* print constant */ 117 if( REALABS(row->constant) > SCIP_DEFAULT_EPSILON ) 118 { 119 SCIPsetDebugMsgPrint(set, "%+.15g ", row->constant); 120 } 121 122 /* print right hand side */ 123 SCIPsetDebugMsgPrint(set, "<= %.15g\n", row->rhs); 124 } 125 #else 126 #define debugRowPrint(x,y) /**/ 127 #endif 128 129 #ifdef SCIP_DEBUG 130 /** method to output column if SCIP_DEBUG is define */ 131 static 132 void debugColPrint( 133 SCIP_SET* set, /**< global SCIP settings */ 134 SCIP_COL* col /**< LP column */ 135 ) 136 { 137 int r; 138 139 assert(col != NULL); 140 assert(col->var != NULL); 141 142 /* print bounds */ 143 SCIPsetDebugMsgPrint(set, "(obj: %.15g) [%.15g,%.15g], ", col->obj, col->lb, col->ub); 144 145 /* print coefficients */ 146 if( col->len == 0 ) 147 { 148 SCIPsetDebugMsgPrint(set, "<empty>"); 149 } 150 for( r = 0; r < col->len; ++r ) 151 { 152 assert(col->rows[r] != NULL); 153 assert(col->rows[r]->name != NULL); 154 SCIPsetDebugMsgPrint(set, "%+.15g<%s> ", col->vals[r], col->rows[r]->name); 155 } 156 SCIPsetDebugMsgPrint(set, "\n"); 157 } 158 #else 159 #define debugColPrint(x,y) /**/ 160 #endif 161 162 /* 163 * memory growing methods for dynamically allocated arrays 164 */ 165 166 /** ensures, that chgcols array can store at least num entries */ 167 static 168 SCIP_RETCODE ensureChgcolsSize( 169 SCIP_LP* lp, /**< current LP data */ 170 SCIP_SET* set, /**< global SCIP settings */ 171 int num /**< minimum number of entries to store */ 172 ) 173 { 174 assert(lp->nchgcols <= lp->chgcolssize); 175 176 if( num > lp->chgcolssize ) 177 { 178 int newsize; 179 180 newsize = SCIPsetCalcMemGrowSize(set, num); 181 SCIP_ALLOC( BMSreallocMemoryArray(&lp->chgcols, newsize) ); 182 lp->chgcolssize = newsize; 183 } 184 assert(num <= lp->chgcolssize); 185 186 return SCIP_OKAY; 187 } 188 189 /** ensures, that chgrows array can store at least num entries */ 190 static 191 SCIP_RETCODE ensureChgrowsSize( 192 SCIP_LP* lp, /**< current LP data */ 193 SCIP_SET* set, /**< global SCIP settings */ 194 int num /**< minimum number of entries to store */ 195 ) 196 { 197 assert(lp->nchgrows <= lp->chgrowssize); 198 199 if( num > lp->chgrowssize ) 200 { 201 int newsize; 202 203 newsize = SCIPsetCalcMemGrowSize(set, num); 204 SCIP_ALLOC( BMSreallocMemoryArray(&lp->chgrows, newsize) ); 205 lp->chgrowssize = newsize; 206 } 207 assert(num <= lp->chgrowssize); 208 209 return SCIP_OKAY; 210 } 211 212 /** ensures, that lpicols array can store at least num entries */ 213 static 214 SCIP_RETCODE ensureLpicolsSize( 215 SCIP_LP* lp, /**< current LP data */ 216 SCIP_SET* set, /**< global SCIP settings */ 217 int num /**< minimum number of entries to store */ 218 ) 219 { 220 assert(lp->nlpicols <= lp->lpicolssize); 221 222 if( num > lp->lpicolssize ) 223 { 224 int newsize; 225 226 newsize = SCIPsetCalcMemGrowSize(set, num); 227 SCIP_ALLOC( BMSreallocMemoryArray(&lp->lpicols, newsize) ); 228 lp->lpicolssize = newsize; 229 } 230 assert(num <= lp->lpicolssize); 231 232 return SCIP_OKAY; 233 } 234 235 /** ensures, that lpirows array can store at least num entries */ 236 static 237 SCIP_RETCODE ensureLpirowsSize( 238 SCIP_LP* lp, /**< current LP data */ 239 SCIP_SET* set, /**< global SCIP settings */ 240 int num /**< minimum number of entries to store */ 241 ) 242 { 243 assert(lp->nlpirows <= lp->lpirowssize); 244 245 if( num > lp->lpirowssize ) 246 { 247 int newsize; 248 249 newsize = SCIPsetCalcMemGrowSize(set, num); 250 SCIP_ALLOC( BMSreallocMemoryArray(&lp->lpirows, newsize) ); 251 lp->lpirowssize = newsize; 252 } 253 assert(num <= lp->lpirowssize); 254 255 return SCIP_OKAY; 256 } 257 258 /** ensures, that cols array can store at least num entries */ 259 static 260 SCIP_RETCODE ensureColsSize( 261 SCIP_LP* lp, /**< current LP data */ 262 SCIP_SET* set, /**< global SCIP settings */ 263 int num /**< minimum number of entries to store */ 264 ) 265 { 266 assert(lp->ncols <= lp->colssize); 267 268 if( num > lp->colssize ) 269 { 270 int newsize; 271 272 newsize = SCIPsetCalcMemGrowSize(set, num); 273 SCIP_ALLOC( BMSreallocMemoryArray(&lp->cols, newsize) ); 274 lp->colssize = newsize; 275 } 276 assert(num <= lp->colssize); 277 278 return SCIP_OKAY; 279 } 280 281 /** ensures, that soldirection array can store at least num entries */ 282 static 283 SCIP_RETCODE ensureSoldirectionSize( 284 SCIP_LP* lp, /**< current LP data */ 285 int num /**< minimum number of entries to store */ 286 ) 287 { 288 if( num > lp->soldirectionsize ) 289 { 290 BMSfreeMemoryArrayNull(&lp->soldirection); 291 SCIP_ALLOC( BMSallocMemoryArray(&lp->soldirection, num) ); 292 293 lp->soldirectionsize = num; 294 } 295 296 assert(num <= lp->soldirectionsize); 297 298 return SCIP_OKAY; 299 } 300 301 /** ensures, that lazy cols array can store at least num entries */ 302 static 303 SCIP_RETCODE ensureLazycolsSize( 304 SCIP_LP* lp, /**< current LP data */ 305 SCIP_SET* set, /**< global SCIP settings */ 306 int num /**< minimum number of entries to store */ 307 ) 308 { 309 assert(lp->nlazycols <= lp->lazycolssize); 310 311 if( num > lp->lazycolssize ) 312 { 313 int newsize; 314 315 newsize = SCIPsetCalcMemGrowSize(set, num); 316 SCIP_ALLOC( BMSreallocMemoryArray(&lp->lazycols, newsize) ); 317 lp->lazycolssize = newsize; 318 } 319 assert(num <= lp->lazycolssize); 320 321 return SCIP_OKAY; 322 } 323 324 /** ensures, that rows array can store at least num entries */ 325 static 326 SCIP_RETCODE ensureRowsSize( 327 SCIP_LP* lp, /**< current LP data */ 328 SCIP_SET* set, /**< global SCIP settings */ 329 int num /**< minimum number of entries to store */ 330 ) 331 { 332 assert(lp->nrows <= lp->rowssize); 333 334 if( num > lp->rowssize ) 335 { 336 int newsize; 337 338 newsize = SCIPsetCalcMemGrowSize(set, num); 339 SCIP_ALLOC( BMSreallocMemoryArray(&lp->rows, newsize) ); 340 lp->rowssize = newsize; 341 } 342 assert(num <= lp->rowssize); 343 344 return SCIP_OKAY; 345 } 346 347 /** ensures, that row array of column can store at least num entries */ 348 static 349 SCIP_RETCODE colEnsureSize( 350 SCIP_COL* col, /**< LP column */ 351 BMS_BLKMEM* blkmem, /**< block memory */ 352 SCIP_SET* set, /**< global SCIP settings */ 353 int num /**< minimum number of entries to store */ 354 ) 355 { 356 assert(col != NULL); 357 assert(col->len <= col->size); 358 359 if( num > col->size ) 360 { 361 int newsize; 362 363 newsize = SCIPsetCalcMemGrowSize(set, num); 364 SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &col->rows, col->size, newsize) ); 365 SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &col->vals, col->size, newsize) ); 366 SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &col->linkpos, col->size, newsize) ); 367 col->size = newsize; 368 } 369 assert(num <= col->size); 370 371 return SCIP_OKAY; 372 } 373 374 /** save current LP values dependent on the solution */ 375 static 376 SCIP_RETCODE lpStoreSolVals( 377 SCIP_LP* lp, /**< LP data */ 378 SCIP_STAT* stat, /**< problem statistics */ 379 BMS_BLKMEM* blkmem /**< block memory */ 380 ) 381 { 382 SCIP_LPSOLVALS* storedsolvals; 383 384 assert(lp != NULL); 385 assert(stat != NULL); 386 assert(blkmem != NULL); 387 388 /* allocate memory for storage */ 389 if( lp->storedsolvals == NULL ) 390 { 391 SCIP_ALLOC( BMSallocMemory(&lp->storedsolvals) ); 392 } 393 storedsolvals = lp->storedsolvals; 394 395 /* store values */ 396 storedsolvals->lpsolstat = lp->lpsolstat; 397 storedsolvals->lpobjval = lp->lpobjval; 398 storedsolvals->primalfeasible = lp->primalfeasible; 399 storedsolvals->primalchecked = lp->primalchecked; 400 storedsolvals->dualfeasible = lp->dualfeasible; 401 storedsolvals->dualchecked = lp->dualchecked; 402 storedsolvals->solisbasic = lp->solisbasic; 403 storedsolvals->lpissolved = lp->solved; 404 405 return SCIP_OKAY; 406 } 407 408 /** restore LP solution values in column */ 409 static 410 SCIP_RETCODE lpRestoreSolVals( 411 SCIP_LP* lp, /**< LP data */ 412 BMS_BLKMEM* blkmem, /**< block memory */ 413 SCIP_Longint validlp /**< number of lp for which restored values are valid */ 414 ) 415 { 416 SCIP_LPSOLVALS* storedsolvals; 417 418 assert(lp != NULL); 419 assert(blkmem != NULL); 420 421 /* if stored values are available, restore them */ 422 storedsolvals = lp->storedsolvals; 423 if( storedsolvals != NULL ) 424 { 425 lp->solved = storedsolvals->lpissolved; 426 lp->validsollp = validlp; 427 428 lp->lpsolstat = storedsolvals->lpsolstat; 429 lp->lpobjval = storedsolvals->lpobjval; 430 lp->primalfeasible = storedsolvals->primalfeasible; 431 lp->primalchecked = storedsolvals->primalchecked; 432 lp->dualfeasible = storedsolvals->dualfeasible; 433 lp->dualchecked = storedsolvals->dualchecked; 434 lp->solisbasic = storedsolvals->solisbasic; 435 436 /* solution values are stored only for LPs solved to optimality or unboundedness */ 437 assert(lp->lpsolstat == SCIP_LPSOLSTAT_OPTIMAL || 438 lp->lpsolstat == SCIP_LPSOLSTAT_UNBOUNDEDRAY || 439 lp->storedsolvals->lpsolstat == SCIP_LPSOLSTAT_OBJLIMIT || 440 lp->storedsolvals->lpsolstat == SCIP_LPSOLSTAT_ITERLIMIT || 441 lp->storedsolvals->lpsolstat == SCIP_LPSOLSTAT_TIMELIMIT || 442 lp->storedsolvals->lpsolstat == SCIP_LPSOLSTAT_INFEASIBLE || 443 lp->validsollp == -1); 444 } 445 /* no values available, mark LP as unsolved */ 446 else 447 { 448 lp->solved = FALSE; 449 lp->validsollp = -1; 450 451 lp->lpsolstat = SCIP_LPSOLSTAT_NOTSOLVED; 452 lp->lpobjval = SCIP_INVALID; 453 lp->primalfeasible = FALSE; 454 lp->primalchecked = FALSE; 455 lp->dualfeasible = FALSE; 456 lp->dualchecked = FALSE; 457 lp->solisbasic = FALSE; 458 lp->validfarkaslp = -1; 459 } 460 461 lp->validdegeneracylp = -1; 462 463 /* intentionally keep storage space allocated */ 464 465 return SCIP_OKAY; 466 } 467 468 /** save current LP solution values stored in each column */ 469 static 470 SCIP_RETCODE colStoreSolVals( 471 SCIP_COL* col, /**< LP column */ 472 BMS_BLKMEM* blkmem /**< block memory */ 473 ) 474 { 475 SCIP_COLSOLVALS* storedsolvals; 476 477 assert(col != NULL); 478 assert(blkmem != NULL); 479 480 /* allocate memory for storage */ 481 if( col->storedsolvals == NULL ) 482 { 483 SCIP_ALLOC( BMSallocBlockMemory(blkmem, &col->storedsolvals) ); 484 } 485 storedsolvals = col->storedsolvals; 486 487 /* store values */ 488 storedsolvals->primsol = col->primsol; 489 storedsolvals->redcost = col->redcost; 490 storedsolvals->basisstatus = col->basisstatus; /*lint !e641 !e732*/ 491 492 return SCIP_OKAY; 493 } 494 495 /** restore LP solution values in column */ 496 static 497 SCIP_RETCODE colRestoreSolVals( 498 SCIP_COL* col, /**< LP column */ 499 BMS_BLKMEM* blkmem, /**< block memory */ 500 SCIP_Longint validlp, /**< number of lp for which restored values are valid */ 501 SCIP_Bool freebuffer /**< should buffer for LP solution values be freed? */ 502 ) 503 { 504 SCIP_COLSOLVALS* storedsolvals; 505 506 assert(col != NULL); 507 assert(blkmem != NULL); 508 509 /* if stored values are available, restore them */ 510 storedsolvals = col->storedsolvals; 511 if( storedsolvals != NULL ) 512 { 513 col->primsol = storedsolvals->primsol; 514 col->redcost = storedsolvals->redcost; 515 col->validredcostlp = validlp; 516 col->basisstatus = storedsolvals->basisstatus; /*lint !e641 !e732*/ 517 518 /* we do not save the farkas coefficient, since it can be recomputed; thus, we invalidate it here */ 519 col->validfarkaslp = -1; 520 } 521 /* if the column was created after performing the storage (possibly during probing), we treat it as implicitly zero; 522 * we make sure to invalidate the reduced cost and farkas coefficient, which are not available 523 */ 524 else 525 { 526 col->primsol = 0.0; 527 col->validredcostlp = -1; 528 col->validfarkaslp = -1; 529 col->basisstatus = SCIP_BASESTAT_ZERO; /*lint !e641*/ 530 } 531 532 /* free memory */ 533 if( freebuffer ) 534 { 535 BMSfreeBlockMemoryNull(blkmem, &col->storedsolvals); 536 assert(col->storedsolvals == NULL); 537 } 538 539 return SCIP_OKAY; 540 } 541 542 /** save current LP solution values stored in each column */ 543 static 544 SCIP_RETCODE rowStoreSolVals( 545 SCIP_ROW* row, /**< LP row */ 546 BMS_BLKMEM* blkmem, /**< block memory */ 547 SCIP_Bool infeasible /**< is the solution infeasible? */ 548 ) 549 { 550 SCIP_ROWSOLVALS* storedsolvals; 551 552 assert(row != NULL); 553 assert(blkmem != NULL); 554 555 /* allocate memory for storage */ 556 if( row->storedsolvals == NULL ) 557 { 558 SCIP_ALLOC( BMSallocBlockMemory(blkmem, &row->storedsolvals) ); 559 } 560 storedsolvals = row->storedsolvals; 561 562 /* store values */ 563 if ( infeasible ) 564 { 565 storedsolvals->dualsol = row->dualfarkas; 566 storedsolvals->activity = SCIP_INVALID; 567 storedsolvals->basisstatus = SCIP_BASESTAT_BASIC; /*lint !e641*/ 568 } 569 else 570 { 571 storedsolvals->dualsol = row->dualsol; 572 storedsolvals->activity = row->activity; 573 storedsolvals->basisstatus = row->basisstatus; /*lint !e641 !e732*/ 574 } 575 576 return SCIP_OKAY; 577 } 578 579 /** restore LP solution values in row */ 580 static 581 SCIP_RETCODE rowRestoreSolVals( 582 SCIP_ROW* row, /**< LP column */ 583 BMS_BLKMEM* blkmem, /**< block memory */ 584 SCIP_Longint validlp, /**< number of lp for which restored values are valid */ 585 SCIP_Bool freebuffer, /**< should buffer for LP solution values be freed? */ 586 SCIP_Bool infeasible /**< is the solution infeasible? */ 587 ) 588 { 589 SCIP_ROWSOLVALS* storedsolvals; 590 591 assert(row != NULL); 592 assert(blkmem != NULL); 593 594 /* if stored values are available, restore them */ 595 storedsolvals = row->storedsolvals; 596 if( storedsolvals != NULL ) 597 { 598 if ( infeasible ) 599 row->dualfarkas = storedsolvals->dualsol; 600 else 601 row->dualsol = storedsolvals->dualsol; 602 row->activity = storedsolvals->activity; 603 row->validactivitylp = validlp; 604 row->basisstatus = storedsolvals->basisstatus; /*lint !e641 !e732*/ 605 } 606 /* if the row was created after performing the storage (possibly during probing), we treat it as basic; 607 * we make sure to invalidate the reduced cost and farkas coefficient, which are not available 608 */ 609 else 610 { 611 row->dualsol = 0.0; 612 row->dualfarkas = 0.0; 613 row->activity = SCIP_INVALID; 614 row->validactivitylp = -1; 615 row->basisstatus = SCIP_BASESTAT_BASIC; /*lint !e641*/ 616 } 617 618 /* free memory */ 619 if( freebuffer ) 620 { 621 BMSfreeBlockMemoryNull(blkmem, &row->storedsolvals); 622 assert(row->storedsolvals == NULL); 623 } 624 625 return SCIP_OKAY; 626 } 627 628 /** ensures, that column array of row can store at least num entries */ 629 SCIP_RETCODE SCIProwEnsureSize( 630 SCIP_ROW* row, /**< LP row */ 631 BMS_BLKMEM* blkmem, /**< block memory */ 632 SCIP_SET* set, /**< global SCIP settings */ 633 int num /**< minimum number of entries to store */ 634 ) 635 { 636 assert(row != NULL); 637 assert(row->len <= row->size); 638 639 if( num > row->size ) 640 { 641 int newsize; 642 643 newsize = SCIPsetCalcMemGrowSize(set, num); 644 SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &row->cols, row->size, newsize) ); 645 SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &row->cols_index, row->size, newsize) ); 646 SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &row->vals, row->size, newsize) ); 647 SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &row->linkpos, row->size, newsize) ); 648 row->size = newsize; 649 } 650 assert(num <= row->size); 651 652 return SCIP_OKAY; 653 } 654 655 656 #ifdef SCIP_MORE_DEBUG /* enable this to check the sortings within rows (for debugging, very slow!) */ 657 static SCIP_Bool msgdisp_checkrow = FALSE; 658 659 static 660 void checkRow( 661 SCIP_ROW* row 662 ) 663 { 664 int i; 665 666 if( !msgdisp_checkrow ) 667 { 668 printf("LP ROW CHECKING ACTIVATED! THIS IS VERY SLOW!\n"); 669 msgdisp_checkrow = TRUE; 670 } 671 672 /* validate sorting of LP part of row */ 673 if( row->lpcolssorted && row->nlpcols > 0) 674 { 675 assert(row->cols_index[0] == row->cols[0]->index); 676 for( i = 1; i < row->nlpcols; ++i ) 677 { 678 assert(row->cols_index[i] == row->cols[i]->index); 679 assert(row->cols_index[i] >= row->cols_index[i-1]); 680 } 681 } 682 683 /* validate sorting of non-LP part of row */ 684 if( row->nonlpcolssorted && row->len > row->nlpcols ) 685 { 686 assert(row->cols_index[row->nlpcols] == row->cols[row->nlpcols]->index); 687 for( i = row->nlpcols + 1; i < row->len; ++i ) 688 { 689 assert(row->cols_index[i] == row->cols[i]->index); 690 assert(row->cols_index[i] >= row->cols_index[i-1]); 691 } 692 } 693 } 694 #else 695 #define checkRow(row) /**/ 696 #endif 697 698 #ifdef SCIP_MORE_DEBUG /* enable this to check norms of rows (for debugging, very slow!) */ 699 static 700 void checkRowSqrnorm( 701 SCIP_ROW* row 702 ) 703 { 704 SCIP_COL** cols; 705 SCIP_Real sqrnorm; 706 int c; 707 708 cols = row->cols; 709 assert(cols != NULL || row->len == 0); 710 711 sqrnorm = 0.0; 712 713 for( c = row->len - 1; c >= 0; --c ) 714 { 715 if( cols[c]->lppos >= 0 ) 716 sqrnorm += SQR(row->vals[c]); 717 } 718 719 assert(ABS(sqrnorm - row->sqrnorm) < 1e-06 * MAX(1.0,sqrnorm)); 720 } 721 722 static 723 void checkRowSumnorm( 724 SCIP_ROW* row 725 ) 726 { 727 SCIP_COL** cols; 728 SCIP_Real sumnorm; 729 int c; 730 731 cols = row->cols; 732 assert(cols != NULL || row->len == 0); 733 734 sumnorm = 0.0; 735 736 for( c = row->len - 1; c >= 0; --c ) 737 { 738 if( cols[c]->lppos >= 0 ) 739 sumnorm += REALABS(row->vals[c]); 740 } 741 742 assert(ABS(sumnorm - row->sumnorm) < 1e-06 * MAX(1.0,sumnorm)); 743 } 744 745 static 746 void checkRowObjprod( 747 SCIP_ROW* row 748 ) 749 { 750 SCIP_COL** cols; 751 SCIP_Real objprod; 752 int c; 753 754 cols = row->cols; 755 assert(cols != NULL || row->len == 0); 756 757 objprod = 0.0; 758 759 for( c = row->len - 1; c >= 0; --c ) 760 { 761 if( cols[c]->lppos >= 0 ) 762 objprod += row->vals[c] * cols[c]->unchangedobj; 763 } 764 765 assert(ABS(objprod - row->objprod) < 1e-06 * MAX(1.0,objprod)); 766 } 767 #else 768 #define checkRowSqrnorm(row) /**/ 769 #define checkRowSumnorm(row) /**/ 770 #define checkRowObjprod(row) /**/ 771 #endif 772 773 /* 774 * Local methods for pseudo and loose objective values 775 */ 776 777 /* recompute the loose objective value from scratch, if it was marked to be unreliable before */ 778 static 779 void recomputeLooseObjectiveValue( 780 SCIP_LP* lp, /**< current LP data */ 781 SCIP_SET* set, /**< global SCIP settings */ 782 SCIP_PROB* prob /**< problem data */ 783 ) 784 { 785 SCIP_VAR** vars; 786 SCIP_Real obj; 787 int nvars; 788 int v; 789 790 assert(lp != NULL); 791 assert(set != NULL); 792 assert(prob != NULL); 793 assert(!lp->looseobjvalid); 794 795 vars = prob->vars; 796 nvars = prob->nvars; 797 lp->looseobjval = 0.0; 798 799 /* iterate over all variables in the problem */ 800 for( v = 0; v < nvars; ++v ) 801 { 802 if( SCIPvarGetStatus(vars[v]) == SCIP_VARSTATUS_LOOSE ) 803 { 804 obj = SCIPvarGetObj(vars[v]); 805 806 /* we are only interested in variables with a finite impact, because the infinity counters should be correct */ 807 if( SCIPsetIsPositive(set, obj) && !SCIPsetIsInfinity(set, -SCIPvarGetLbLocal(vars[v])) ) 808 lp->looseobjval += obj * SCIPvarGetLbLocal(vars[v]); 809 else if( SCIPsetIsNegative(set, obj) && !SCIPsetIsInfinity(set, SCIPvarGetUbLocal(vars[v])) ) 810 lp->looseobjval += obj * SCIPvarGetUbLocal(vars[v]); 811 } 812 } 813 814 /* the recomputed value is reliable */ 815 lp->rellooseobjval = lp->looseobjval; 816 lp->looseobjvalid = TRUE; 817 } 818 819 /* recompute the pseudo solution value from scratch, if it was marked to be unreliable before */ 820 static 821 void recomputePseudoObjectiveValue( 822 SCIP_LP* lp, /**< current LP data */ 823 SCIP_SET* set, /**< global SCIP settings */ 824 SCIP_PROB* prob /**< problem data */ 825 ) 826 { 827 SCIP_VAR** vars; 828 int nvars; 829 int v; 830 831 assert(lp != NULL); 832 assert(set != NULL); 833 assert(prob != NULL); 834 assert(!lp->pseudoobjvalid); 835 836 vars = prob->vars; 837 nvars = prob->nvars; 838 lp->pseudoobjval = 0.0; 839 840 /* iterate over all variables in the problem */ 841 for( v = 0; v < nvars; ++v ) 842 { 843 /* we are only interested in variables with a finite impact, because the infinity counters should be correct */ 844 if( SCIPsetIsPositive(set, SCIPvarGetObj(vars[v])) && 845 !SCIPsetIsInfinity(set, -SCIPvarGetLbLocal(vars[v])) ) 846 { 847 lp->pseudoobjval += SCIPvarGetObj(vars[v]) * SCIPvarGetLbLocal(vars[v]); 848 } 849 else if( SCIPsetIsNegative(set, SCIPvarGetObj(vars[v])) && 850 !SCIPsetIsInfinity(set, SCIPvarGetUbLocal(vars[v])) ) 851 { 852 lp->pseudoobjval += SCIPvarGetObj(vars[v]) * SCIPvarGetUbLocal(vars[v]); 853 } 854 } 855 856 /* the recomputed value is reliable */ 857 lp->relpseudoobjval = lp->pseudoobjval; 858 lp->pseudoobjvalid = TRUE; 859 } 860 861 /* recompute the global pseudo solution value from scratch, if it was marked to be unreliable before */ 862 static 863 void recomputeGlbPseudoObjectiveValue( 864 SCIP_LP* lp, /**< current LP data */ 865 SCIP_SET* set, /**< global SCIP settings */ 866 SCIP_PROB* prob /**< problem data */ 867 ) 868 { 869 SCIP_VAR** vars; 870 int nvars; 871 int v; 872 873 assert(lp != NULL); 874 assert(set != NULL); 875 assert(prob != NULL); 876 assert(!lp->glbpseudoobjvalid); 877 878 vars = prob->vars; 879 nvars = prob->nvars; 880 lp->glbpseudoobjval = 0.0; 881 882 /* iterate over all variables in the problem */ 883 for( v = 0; v < nvars; ++v ) 884 { 885 /* we are only interested in variables with a finite impact, because the infinity counters should be correct */ 886 if( SCIPsetIsPositive(set, SCIPvarGetObj(vars[v])) && 887 !SCIPsetIsInfinity(set, -SCIPvarGetLbGlobal(vars[v])) ) 888 { 889 lp->glbpseudoobjval += SCIPvarGetObj(vars[v]) * SCIPvarGetLbGlobal(vars[v]); 890 } 891 else if( SCIPsetIsNegative(set, SCIPvarGetObj(vars[v])) && 892 !SCIPsetIsInfinity(set, SCIPvarGetUbGlobal(vars[v])) ) 893 { 894 lp->glbpseudoobjval += SCIPvarGetObj(vars[v]) * SCIPvarGetUbGlobal(vars[v]); 895 } 896 } 897 898 /* the recomputed value is reliable */ 899 lp->relglbpseudoobjval = lp->glbpseudoobjval; 900 lp->glbpseudoobjvalid = TRUE; 901 } 902 903 /** gets finite part of objective value of current LP that results from LOOSE variables only */ 904 static 905 SCIP_Real getFiniteLooseObjval( 906 SCIP_LP* lp, /**< current LP data */ 907 SCIP_SET* set, /**< global SCIP settings */ 908 SCIP_PROB* prob /**< problem data */ 909 ) 910 { 911 assert(lp != NULL); 912 assert(set != NULL); 913 assert(prob != NULL); 914 assert((lp->nloosevars > 0) || (lp->looseobjvalinf == 0 && lp->looseobjval == 0.0)); 915 assert(lp->flushed); 916 assert(lp->looseobjvalinf == 0); 917 918 /* recalculate the loose objective value, if needed */ 919 if( !lp->looseobjvalid ) 920 recomputeLooseObjectiveValue(lp, set, prob); 921 922 return lp->looseobjval; 923 } 924 925 /** gets finite part of pseudo objective value of current LP */ 926 static 927 SCIP_Real getFinitePseudoObjval( 928 SCIP_LP* lp, /**< current LP data */ 929 SCIP_SET* set, /**< global SCIP settings */ 930 SCIP_PROB* prob /**< problem data */ 931 ) 932 { 933 assert(lp != NULL); 934 assert(set != NULL); 935 assert(prob != NULL); 936 937 /* recalculate the pseudo objective value, if needed */ 938 if( !lp->pseudoobjvalid ) 939 recomputePseudoObjectiveValue(lp, set, prob); 940 941 return lp->pseudoobjval; 942 } 943 944 /* 945 * Sorting and searching rows and columns 946 */ 947 948 949 /** comparison method for sorting rows by non-decreasing index */ 950 SCIP_DECL_SORTPTRCOMP(SCIProwComp) 951 { 952 assert(elem1 != NULL); 953 assert(elem2 != NULL); 954 955 if( ((SCIP_ROW*)elem1)->index < ((SCIP_ROW*)elem2)->index ) 956 return -1; 957 else if( ((SCIP_ROW*)elem1)->index > ((SCIP_ROW*)elem2)->index ) 958 return +1; 959 else 960 { 961 assert(SCIProwGetIndex((SCIP_ROW*)(elem1)) == SCIProwGetIndex(((SCIP_ROW*)elem2))); 962 return 0; 963 } 964 } 965 966 967 /** sorts column entries of linked rows currently in the LP such that lower row indices precede higher ones */ 968 static 969 void colSortLP( 970 SCIP_COL* col /**< column to be sorted */ 971 ) 972 { 973 int i; 974 975 assert(col != NULL); 976 977 /* check, if column is already sorted in the LP part */ 978 if( col->lprowssorted ) 979 return; 980 981 /* sort coefficients */ 982 SCIPsortPtrRealInt((void**)col->rows, col->vals, col->linkpos, SCIProwComp, col->nlprows ); 983 984 /* update links */ 985 for( i = 0; i < col->nlprows; ++i ) 986 { 987 if( col->linkpos[i] >= 0 ) 988 { 989 assert(col->rows[i]->cols[col->linkpos[i]] == col); 990 assert(col->rows[i]->linkpos[col->linkpos[i]] >= 0); 991 col->rows[i]->linkpos[col->linkpos[i]] = i; 992 } 993 } 994 995 col->lprowssorted = TRUE; 996 } 997 998 /** sorts column entries of unlinked rows or rows currently not in the LP such that lower row indices precede higher 999 * ones 1000 */ 1001 static 1002 void colSortNonLP( 1003 SCIP_COL* col /**< column to be sorted */ 1004 ) 1005 { 1006 int i; 1007 1008 assert(col != NULL); 1009 1010 /* check, if column is already sorted in the non-LP part */ 1011 if( col->nonlprowssorted ) 1012 return; 1013 1014 /* sort coefficients */ 1015 SCIPsortPtrRealInt((void**)(&(col->rows[col->nlprows])), &(col->vals[col->nlprows]), &(col->linkpos[col->nlprows]), SCIProwComp, col->len - col->nlprows); 1016 1017 /* update links */ 1018 for( i = col->nlprows; i < col->len; ++i ) 1019 { 1020 if( col->linkpos[i] >= 0 ) 1021 { 1022 assert(col->rows[i]->cols[col->linkpos[i]] == col); 1023 assert(col->rows[i]->linkpos[col->linkpos[i]] >= 0); 1024 col->rows[i]->linkpos[col->linkpos[i]] = i; 1025 } 1026 } 1027 1028 col->nonlprowssorted = TRUE; 1029 } 1030 1031 /** sorts row entries of linked columns currently in the LP such that lower column indices precede higher ones */ 1032 static 1033 void rowSortLP( 1034 SCIP_ROW* row /**< row to be sorted */ 1035 ) 1036 { 1037 int i; 1038 1039 assert(row != NULL); 1040 1041 /* check, if row is already sorted in the LP part, or if the sorting should be delayed */ 1042 if( row->lpcolssorted || row->delaysort ) 1043 return; 1044 1045 /* sort coefficients */ 1046 SCIPsortIntPtrIntReal(row->cols_index, (void**)row->cols, row->linkpos, row->vals, row->nlpcols); 1047 1048 /* update links */ 1049 for( i = 0; i < row->nlpcols; ++i ) 1050 { 1051 if( row->linkpos[i] >= 0 ) 1052 { 1053 assert(row->cols[i]->rows[row->linkpos[i]] == row); 1054 assert(row->cols[i]->linkpos[row->linkpos[i]] >= 0); 1055 row->cols[i]->linkpos[row->linkpos[i]] = i; 1056 } 1057 } 1058 1059 row->lpcolssorted = TRUE; 1060 } 1061 1062 /** sorts row entries of unlinked columns or columns currently not in the LP such that lower column indices precede 1063 * higher ones 1064 */ 1065 static 1066 void rowSortNonLP( 1067 SCIP_ROW* row /**< row to be sorted */ 1068 ) 1069 { 1070 int i; 1071 1072 assert(row != NULL); 1073 1074 checkRow(row); 1075 1076 /* check, if row is already sorted in the non-LP part, or if the sorting should be delayed */ 1077 if( row->nonlpcolssorted || row->delaysort ) 1078 return; 1079 1080 /* sort coefficients */ 1081 SCIPsortIntPtrIntReal(&(row->cols_index[row->nlpcols]), (void**)(&(row->cols[row->nlpcols])), &(row->linkpos[row->nlpcols]), &(row->vals[row->nlpcols]), row->len - row->nlpcols); 1082 1083 /* update links */ 1084 for( i = row->nlpcols; i < row->len; ++i ) 1085 { 1086 if( row->linkpos[i] >= 0 ) 1087 { 1088 assert(row->cols[i]->rows[row->linkpos[i]] == row); 1089 assert(row->cols[i]->linkpos[row->linkpos[i]] >= 0); 1090 row->cols[i]->linkpos[row->linkpos[i]] = i; 1091 } 1092 } 1093 1094 checkRow(row); 1095 1096 row->nonlpcolssorted = TRUE; 1097 } 1098 1099 /** searches coefficient in part of the column, returns position in col vector or -1 if not found */ 1100 static 1101 int colSearchCoefPart( 1102 SCIP_COL* col, /**< column to be searched in */ 1103 const SCIP_ROW* row, /**< coefficient to be searched for */ 1104 int minpos, /**< first position of search range */ 1105 int maxpos /**< last position of search range */ 1106 ) 1107 { 1108 int pos; 1109 int idx; 1110 int searchidx; 1111 1112 assert(col != NULL); 1113 assert(row != NULL); 1114 1115 /* binary search */ 1116 searchidx = row->index; 1117 while(minpos <= maxpos) 1118 { 1119 pos = (minpos + maxpos)/2; 1120 assert(0 <= pos && pos < col->len); 1121 assert(col->rows[pos] != NULL); 1122 assert((pos < col->nlprows) == (col->rows[pos]->lppos >= 0 && col->linkpos[pos] >= 0)); 1123 idx = col->rows[pos]->index; 1124 if( searchidx == idx ) 1125 return pos; 1126 else if( searchidx < idx ) 1127 maxpos = pos-1; 1128 else 1129 minpos = pos+1; 1130 } 1131 1132 return -1; 1133 } 1134 1135 /** searches coefficient in column, returns position in col vector or -1 if not found */ 1136 static 1137 int colSearchCoef( 1138 SCIP_COL* col, /**< column to be searched in */ 1139 const SCIP_ROW* row /**< coefficient to be searched for */ 1140 ) 1141 { 1142 int pos; 1143 1144 assert(col != NULL); 1145 assert(row != NULL); 1146 1147 pos = -1; 1148 1149 /* search in the linked LP rows */ 1150 if( row->lppos >= 0 ) 1151 { 1152 /* column has to be sorted, such that binary search works */ 1153 colSortLP(col); 1154 assert(col->lprowssorted); 1155 1156 pos = colSearchCoefPart(col, row, 0, col->nlprows-1); 1157 if( pos >= 0 ) 1158 return pos; 1159 } 1160 1161 /* search in the non-LP/unlinked rows */ 1162 if( row->lppos == -1 || col->nunlinked > 0 ) 1163 { 1164 /* column has to be sorted, such that binary search works */ 1165 colSortNonLP(col); 1166 assert(col->nonlprowssorted); 1167 1168 pos = colSearchCoefPart(col, row, col->nlprows, col->len-1); 1169 } 1170 1171 return pos; 1172 } 1173 1174 /** searches coefficient in part of the row, returns position in col vector or -1 if not found */ 1175 static 1176 int rowSearchCoefPart( 1177 SCIP_ROW* row, /**< row to be searched in */ 1178 const SCIP_COL* col, /**< coefficient to be searched for */ 1179 int minpos, /**< first position of search range */ 1180 int maxpos /**< last position of search range */ 1181 ) 1182 { 1183 int pos; 1184 int idx; 1185 int searchidx; 1186 1187 assert(row != NULL); 1188 assert(col != NULL); 1189 1190 /* binary search */ 1191 searchidx = col->index; 1192 while(minpos <= maxpos) 1193 { 1194 pos = (minpos + maxpos)/2; 1195 assert(0 <= pos && pos < row->len); 1196 assert(row->cols[pos] != NULL); 1197 assert((pos < row->nlpcols) == (row->cols[pos]->lppos >= 0 && row->linkpos[pos] >= 0)); 1198 assert(row->cols_index[pos] == row->cols[pos]->index); 1199 idx = row->cols_index[pos]; 1200 if( searchidx == idx ) 1201 return pos; 1202 else if( searchidx < idx ) 1203 maxpos = pos-1; 1204 else 1205 minpos = pos+1; 1206 } 1207 1208 return -1; 1209 } 1210 1211 /** searches coefficient in row, returns position in row vector or -1 if not found; 1212 * if the sorting of the row is delayed, returns -1 1213 */ 1214 static 1215 int rowSearchCoef( 1216 SCIP_ROW* row, /**< row to be searched in */ 1217 const SCIP_COL* col /**< coefficient to be searched for */ 1218 ) 1219 { 1220 int pos; 1221 1222 assert(row != NULL); 1223 assert(col != NULL); 1224 1225 if( row->delaysort ) 1226 return -1; 1227 1228 pos = -1; 1229 1230 /* search in the linked LP columns */ 1231 if( col->lppos >= 0 ) 1232 { 1233 /* row has to be sorted, such that binary search works */ 1234 rowSortLP(row); 1235 assert(row->lpcolssorted); 1236 1237 pos = rowSearchCoefPart(row, col, 0, row->nlpcols-1); 1238 } 1239 1240 /* search in the non-LP/unlinked columns */ 1241 if( pos == -1 && (col->lppos == -1 || row->nunlinked > 0) ) 1242 { 1243 /* row has to be sorted, such that binary search works */ 1244 rowSortNonLP(row); 1245 assert(row->nonlpcolssorted); 1246 1247 pos = rowSearchCoefPart(row, col, row->nlpcols, row->len-1); 1248 } 1249 1250 #ifndef NDEBUG 1251 /* validate result */ 1252 assert(-1 <= pos && pos < row->len); 1253 if( pos >= 0 ) 1254 assert(row->cols[pos] == col); 1255 else 1256 { 1257 int i; 1258 for( i = 0; i < row->len; ++i ) 1259 assert(row->cols[i] != col); 1260 } 1261 #endif 1262 1263 return pos; 1264 } 1265 1266 /** moves a coefficient in a column to a different place, and updates all corresponding data structures */ 1267 static 1268 void colMoveCoef( 1269 SCIP_COL* col, /**< LP column */ 1270 int oldpos, /**< old position of coefficient */ 1271 int newpos /**< new position of coefficient */ 1272 ) 1273 { 1274 assert(col != NULL); 1275 assert(0 <= oldpos && oldpos < col->len); 1276 assert(0 <= newpos && newpos < col->len); 1277 assert(col->rows[oldpos] != NULL); 1278 1279 if( oldpos == newpos ) 1280 return; 1281 1282 col->rows[newpos] = col->rows[oldpos]; 1283 col->vals[newpos] = col->vals[oldpos]; 1284 col->linkpos[newpos] = col->linkpos[oldpos]; 1285 1286 /* update link position in row */ 1287 if( col->linkpos[newpos] >= 0 ) 1288 { 1289 assert(col->rows[newpos]->cols[col->linkpos[newpos]] == col); 1290 assert(col->rows[newpos]->linkpos[col->linkpos[newpos]] == oldpos); 1291 1292 col->rows[newpos]->linkpos[col->linkpos[newpos]] = newpos; 1293 } 1294 1295 /* update sorted flags */ 1296 if( col->rows[newpos]->lppos >= 0 && col->linkpos[newpos] >= 0 ) 1297 col->lprowssorted = FALSE; 1298 else 1299 col->nonlprowssorted = FALSE; 1300 } 1301 1302 /** swaps two coefficients in a column, and updates all corresponding data structures */ 1303 static 1304 void colSwapCoefs( 1305 SCIP_COL* col, /**< LP column */ 1306 int pos1, /**< position of first coefficient */ 1307 int pos2 /**< position of second coefficient */ 1308 ) 1309 { 1310 SCIP_ROW* tmprow; 1311 SCIP_Real tmpval; 1312 int tmplinkpos; 1313 1314 assert(col != NULL); 1315 assert(0 <= pos1 && pos1 < col->len); 1316 assert(0 <= pos2 && pos2 < col->len); 1317 assert(col->rows[pos1] != NULL); 1318 1319 if( pos1 == pos2 ) 1320 return; 1321 1322 /* swap coefficients */ 1323 tmprow = col->rows[pos2]; 1324 tmpval = col->vals[pos2]; 1325 tmplinkpos = col->linkpos[pos2]; 1326 1327 col->rows[pos2] = col->rows[pos1]; 1328 col->vals[pos2] = col->vals[pos1]; 1329 col->linkpos[pos2] = col->linkpos[pos1]; 1330 1331 col->rows[pos1] = tmprow; 1332 col->vals[pos1] = tmpval; 1333 col->linkpos[pos1] = tmplinkpos; 1334 1335 /* update link position in rows */ 1336 if( col->linkpos[pos1] >= 0 ) 1337 { 1338 assert(col->rows[pos1]->cols[col->linkpos[pos1]] == col); 1339 assert(col->rows[pos1]->linkpos[col->linkpos[pos1]] == pos2); 1340 1341 col->rows[pos1]->linkpos[col->linkpos[pos1]] = pos1; 1342 } 1343 if( col->linkpos[pos2] >= 0 ) 1344 { 1345 assert(col->rows[pos2]->cols[col->linkpos[pos2]] == col); 1346 assert(col->rows[pos2]->linkpos[col->linkpos[pos2]] == pos1); 1347 1348 col->rows[pos2]->linkpos[col->linkpos[pos2]] = pos2; 1349 } 1350 1351 /* update sorted flags */ 1352 if( col->rows[pos1]->lppos >= 0 && col->linkpos[pos1] >= 0 ) 1353 col->lprowssorted = FALSE; 1354 else 1355 col->nonlprowssorted = FALSE; 1356 if( col->rows[pos2]->lppos >= 0 && col->linkpos[pos2] >= 0 ) 1357 col->lprowssorted = FALSE; 1358 else 1359 col->nonlprowssorted = FALSE; 1360 } 1361 1362 /** moves a coefficient in a row to a different place, and updates all corresponding data structures */ 1363 static 1364 void rowMoveCoef( 1365 SCIP_ROW* row, /**< LP row */ 1366 int oldpos, /**< old position of coefficient */ 1367 int newpos /**< new position of coefficient */ 1368 ) 1369 { 1370 assert(row != NULL); 1371 assert(0 <= oldpos && oldpos < row->len); 1372 assert(0 <= newpos && newpos < row->len); 1373 assert(row->cols[oldpos] != NULL); 1374 1375 if( oldpos == newpos ) 1376 return; 1377 1378 row->cols[newpos] = row->cols[oldpos]; 1379 row->cols_index[newpos] = row->cols_index[oldpos]; 1380 row->vals[newpos] = row->vals[oldpos]; 1381 row->linkpos[newpos] = row->linkpos[oldpos]; 1382 1383 /* update link position in column */ 1384 if( row->linkpos[newpos] >= 0 ) 1385 { 1386 assert(row->cols[newpos]->rows[row->linkpos[newpos]] == row); 1387 assert(row->cols[newpos]->linkpos[row->linkpos[newpos]] == oldpos); 1388 1389 row->cols[newpos]->linkpos[row->linkpos[newpos]] = newpos; 1390 } 1391 1392 /* update sorted flags */ 1393 if( row->cols[newpos]->lppos >= 0 && row->linkpos[newpos] >= 0 ) 1394 row->lpcolssorted = FALSE; 1395 else 1396 row->nonlpcolssorted = FALSE; 1397 } 1398 1399 /** swaps two coefficients in a row, and updates all corresponding data structures */ 1400 static 1401 void rowSwapCoefs( 1402 SCIP_ROW* row, /**< LP row */ 1403 int pos1, /**< position of first coefficient */ 1404 int pos2 /**< position of second coefficient */ 1405 ) 1406 { 1407 SCIP_COL* tmpcol; 1408 SCIP_Real tmpval; 1409 int tmpindex; 1410 int tmplinkpos; 1411 1412 assert(row != NULL); 1413 assert(0 <= pos1 && pos1 < row->len); 1414 assert(0 <= pos2 && pos2 < row->len); 1415 assert(row->cols[pos1] != NULL); 1416 assert(row->cols[pos1]->index == row->cols_index[pos1]); 1417 1418 if( pos1 == pos2 ) 1419 return; 1420 1421 /* swap coefficients */ 1422 tmpcol = row->cols[pos2]; 1423 tmpindex = row->cols_index[pos2]; 1424 tmpval = row->vals[pos2]; 1425 tmplinkpos = row->linkpos[pos2]; 1426 1427 row->cols[pos2] = row->cols[pos1]; 1428 row->cols_index[pos2] = row->cols_index[pos1]; 1429 row->vals[pos2] = row->vals[pos1]; 1430 row->linkpos[pos2] = row->linkpos[pos1]; 1431 1432 row->cols[pos1] = tmpcol; 1433 row->cols_index[pos1] = tmpindex; 1434 row->vals[pos1] = tmpval; 1435 row->linkpos[pos1] = tmplinkpos; 1436 1437 /* update link position in columns */ 1438 if( row->linkpos[pos1] >= 0 ) 1439 { 1440 assert(row->cols[pos1]->rows[row->linkpos[pos1]] == row); 1441 assert(row->cols[pos1]->linkpos[row->linkpos[pos1]] == pos2); 1442 1443 row->cols[pos1]->linkpos[row->linkpos[pos1]] = pos1; 1444 } 1445 if( row->linkpos[pos2] >= 0 ) 1446 { 1447 assert(row->cols[pos2]->rows[row->linkpos[pos2]] == row); 1448 assert(row->cols[pos2]->linkpos[row->linkpos[pos2]] == pos1); 1449 1450 row->cols[pos2]->linkpos[row->linkpos[pos2]] = pos2; 1451 } 1452 1453 /* update sorted flags */ 1454 if( row->cols[pos1]->lppos >= 0 && row->linkpos[pos1] >= 0 ) 1455 row->lpcolssorted = FALSE; 1456 else 1457 row->nonlpcolssorted = FALSE; 1458 if( row->cols[pos2]->lppos >= 0 && row->linkpos[pos2] >= 0 ) 1459 row->lpcolssorted = FALSE; 1460 else 1461 row->nonlpcolssorted = FALSE; 1462 } 1463 1464 /** issues a ROWCOEFCHANGED event on the given row */ 1465 static 1466 SCIP_RETCODE rowEventCoefChanged( 1467 SCIP_ROW* row, /**< row which coefficient has changed */ 1468 BMS_BLKMEM* blkmem, /**< block memory */ 1469 SCIP_SET* set, /**< global SCIP settings */ 1470 SCIP_EVENTQUEUE* eventqueue, /**< event queue */ 1471 SCIP_COL* col, /**< the column which coefficient has changed */ 1472 SCIP_Real oldval, /**< old value of the coefficient */ 1473 SCIP_Real newval /**< new value of the coefficient */ 1474 ) 1475 { 1476 assert(row != NULL); 1477 assert(row->eventfilter != NULL); 1478 assert(col != NULL); 1479 1480 /* check, if the row is being tracked for coefficient changes 1481 * if so, issue ROWCOEFCHANGED event 1482 */ 1483 if( (row->eventfilter->len > 0 && (row->eventfilter->eventmask & SCIP_EVENTTYPE_ROWCOEFCHANGED) != 0) ) 1484 { 1485 SCIP_EVENT* event; 1486 1487 SCIP_CALL( SCIPeventCreateRowCoefChanged(&event, blkmem, row, col, oldval, newval) ); 1488 SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, NULL, NULL, row->eventfilter, &event) ); 1489 } 1490 1491 return SCIP_OKAY; 1492 } 1493 1494 /** issues a ROWCONSTCHANGED event on the given row */ 1495 static 1496 SCIP_RETCODE rowEventConstantChanged( 1497 SCIP_ROW* row, /**< row which coefficient has changed */ 1498 BMS_BLKMEM* blkmem, /**< block memory */ 1499 SCIP_SET* set, /**< global SCIP settings */ 1500 SCIP_EVENTQUEUE* eventqueue, /**< event queue */ 1501 SCIP_Real oldval, /**< old value of the constant */ 1502 SCIP_Real newval /**< new value of the constant */ 1503 ) 1504 { 1505 assert(row != NULL); 1506 assert(row->eventfilter != NULL); 1507 1508 /* check, if the row is being tracked for coefficient changes 1509 * if so, issue ROWCONSTCHANGED event 1510 */ 1511 if( (row->eventfilter->len > 0 && (row->eventfilter->eventmask & SCIP_EVENTTYPE_ROWCONSTCHANGED)) ) 1512 { 1513 SCIP_EVENT* event; 1514 1515 SCIP_CALL( SCIPeventCreateRowConstChanged(&event, blkmem, row, oldval, newval) ); 1516 SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, NULL, NULL, row->eventfilter, &event) ); 1517 } 1518 1519 return SCIP_OKAY; 1520 } 1521 1522 /** issues a ROWSIDECHANGED event on the given row */ 1523 static 1524 SCIP_RETCODE rowEventSideChanged( 1525 SCIP_ROW* row, /**< row which coefficient has changed */ 1526 BMS_BLKMEM* blkmem, /**< block memory */ 1527 SCIP_SET* set, /**< global SCIP settings */ 1528 SCIP_EVENTQUEUE* eventqueue, /**< event queue */ 1529 SCIP_SIDETYPE side, /**< the side that has changed */ 1530 SCIP_Real oldval, /**< old value of side */ 1531 SCIP_Real newval /**< new value of side */ 1532 ) 1533 { 1534 assert(row != NULL); 1535 assert(row->eventfilter != NULL); 1536 1537 /* check, if the row is being tracked for coefficient changes 1538 * if so, issue ROWSIDECHANGED event 1539 */ 1540 if( (row->eventfilter->len > 0 && !(row->eventfilter->eventmask & SCIP_EVENTTYPE_ROWSIDECHANGED)) ) 1541 { 1542 SCIP_EVENT* event; 1543 1544 SCIP_CALL( SCIPeventCreateRowSideChanged(&event, blkmem, row, side, oldval, newval) ); 1545 SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, NULL, NULL, row->eventfilter, &event) ); 1546 } 1547 1548 return SCIP_OKAY; 1549 } 1550 1551 #ifdef SCIP_MORE_DEBUG /* enable this to check links between columns and rows in LP data structure (for debugging, very slow!) */ 1552 1553 #ifdef NDEBUG 1554 #define ASSERT(x) do { if( !(x) ) abort(); } while( FALSE ) 1555 #else 1556 #define ASSERT(x) assert(x) 1557 #endif 1558 1559 static SCIP_Bool msgdisp_checklinks = FALSE; 1560 1561 1562 static 1563 void checkLinks( 1564 SCIP_LP* lp /**< current LP data */ 1565 ) 1566 { 1567 SCIP_COL* col; 1568 SCIP_ROW* row; 1569 int i; 1570 int j; 1571 1572 ASSERT(lp != NULL); 1573 1574 if( !msgdisp_checklinks ) 1575 { 1576 printf("LP LINK CHECKING ACTIVATED! THIS IS VERY SLOW!\n"); 1577 msgdisp_checklinks = TRUE; 1578 } 1579 1580 for( i = 0; i < lp->ncols; ++i ) 1581 { 1582 col = lp->cols[i]; 1583 ASSERT(col != NULL); 1584 ASSERT(!lp->flushed || col->lppos >= 0 || col->primsol == 0.0); 1585 ASSERT(!lp->flushed || col->lppos >= 0 || col->farkascoef == 0.0); 1586 ASSERT(col->nlprows <= col->len); 1587 ASSERT(col->lppos == -1 || col->lppos >= lp->lpifirstchgcol || col->nunlinked == 0); 1588 1589 for( j = 0; j < col->len; ++j ) 1590 { 1591 row = col->rows[j]; 1592 ASSERT(row != NULL); 1593 ASSERT(!lp->flushed || col->lppos == -1 || col->linkpos[j] >= 0); 1594 ASSERT(col->linkpos[j] == -1 || row->cols[col->linkpos[j]] == col); 1595 ASSERT(col->linkpos[j] == -1 || EPSEQ(row->vals[col->linkpos[j]], col->vals[j], 1e-6)); 1596 ASSERT((j < col->nlprows) == (col->linkpos[j] >= 0 && row->lppos >= 0)); 1597 } 1598 } 1599 1600 for( i = 0; i < lp->nrows; ++i ) 1601 { 1602 row = lp->rows[i]; 1603 ASSERT(row != NULL); 1604 ASSERT(!lp->flushed || row->lppos >= 0 || row->dualsol == 0.0); 1605 ASSERT(!lp->flushed || row->lppos >= 0 || row->dualfarkas == 0.0); 1606 ASSERT(row->nlpcols <= row->len); 1607 ASSERT(row->lppos == -1 || row->lppos >= lp->lpifirstchgrow || row->nunlinked == 0); 1608 1609 for( j = 0; j < row->len; ++j ) 1610 { 1611 col = row->cols[j]; 1612 ASSERT(col != NULL); 1613 ASSERT(!lp->flushed || row->lppos == -1 || row->linkpos[j] >= 0); 1614 ASSERT(row->linkpos[j] == -1 || col->rows[row->linkpos[j]] == row); 1615 ASSERT(row->linkpos[j] == -1 || EPSEQ(col->vals[row->linkpos[j]], row->vals[j], 1e-6)); 1616 ASSERT((j < row->nlpcols) == (row->linkpos[j] >= 0 && col->lppos >= 0)); 1617 } 1618 } 1619 } 1620 1621 #undef ASSERT 1622 1623 #else 1624 #define checkLinks(lp) /**/ 1625 #endif 1626 1627 /* 1628 * Changing announcements 1629 */ 1630 1631 /** announces, that the given coefficient in the constraint matrix changed */ 1632 static 1633 void coefChanged( 1634 SCIP_ROW* row, /**< LP row */ 1635 SCIP_COL* col, /**< LP col */ 1636 SCIP_LP* lp /**< current LP data */ 1637 ) 1638 { 1639 assert(row != NULL); 1640 assert(col != NULL); 1641 assert(lp != NULL); 1642 1643 if( row->lpipos >= 0 && col->lpipos >= 0 ) 1644 { 1645 assert(row->lpipos < lp->nlpirows); 1646 assert(col->lpipos < lp->nlpicols); 1647 1648 /* we have to remember the change only in the row or in the column, 1649 * because the readdition of one vector would change the other automatically. 1650 */ 1651 if( row->lpipos >= lp->lpifirstchgrow ) 1652 row->coefchanged = TRUE; 1653 else if( col->lpipos >= lp->lpifirstchgcol ) 1654 col->coefchanged = TRUE; 1655 else if( lp->lpifirstchgrow - row->lpipos <= lp->lpifirstchgcol - col->lpipos ) 1656 { 1657 row->coefchanged = TRUE; 1658 lp->lpifirstchgrow = row->lpipos; 1659 } 1660 else 1661 { 1662 col->coefchanged = TRUE; 1663 lp->lpifirstchgcol = col->lpipos; 1664 } 1665 1666 /* mark the current LP unflushed */ 1667 lp->flushed = FALSE; 1668 } 1669 1670 row->pseudoactivity = SCIP_INVALID; 1671 row->minactivity = SCIP_INVALID; 1672 row->maxactivity = SCIP_INVALID; 1673 row->validpsactivitydomchg = -1; 1674 row->validactivitybdsdomchg = -1; 1675 } 1676 1677 1678 1679 /* 1680 * local column changing methods 1681 */ 1682 1683 /* forward declaration for colAddCoef() */ 1684 static 1685 SCIP_RETCODE rowAddCoef( 1686 SCIP_ROW* row, /**< LP row */ 1687 BMS_BLKMEM* blkmem, /**< block memory */ 1688 SCIP_SET* set, /**< global SCIP settings */ 1689 SCIP_EVENTQUEUE* eventqueue, /**< event queue */ 1690 SCIP_LP* lp, /**< current LP data */ 1691 SCIP_COL* col, /**< LP column */ 1692 SCIP_Real val, /**< value of coefficient */ 1693 int linkpos /**< position of row in the column's row array, or -1 */ 1694 ); 1695 1696 /** adds a previously non existing coefficient to an LP column */ 1697 static 1698 SCIP_RETCODE colAddCoef( 1699 SCIP_COL* col, /**< LP column */ 1700 BMS_BLKMEM* blkmem, /**< block memory */ 1701 SCIP_SET* set, /**< global SCIP settings */ 1702 SCIP_EVENTQUEUE* eventqueue, /**< event queue */ 1703 SCIP_LP* lp, /**< current LP data */ 1704 SCIP_ROW* row, /**< LP row */ 1705 SCIP_Real val, /**< value of coefficient */ 1706 int linkpos /**< position of column in the row's col array, or -1 */ 1707 ) 1708 { 1709 int pos; 1710 1711 assert(blkmem != NULL); 1712 assert(col != NULL); 1713 assert(col->nlprows <= col->len); 1714 assert(col->var != NULL); 1715 assert(row != NULL); 1716 assert(!SCIPsetIsZero(set, val)); 1717 /*assert(colSearchCoef(col, row) == -1);*/ /* this assert would lead to slight differences in the solution process */ 1718 1719 SCIP_CALL( colEnsureSize(col, blkmem, set, col->len+1) ); 1720 assert(col->rows != NULL); 1721 assert(col->vals != NULL); 1722 assert(col->linkpos != NULL); 1723 1724 pos = col->len; 1725 col->len++; 1726 1727 /* if the row is in current LP and is linked to the column, we have to insert it at the end of the linked LP rows 1728 * part of the column's arrays 1729 */ 1730 if( row->lppos >= 0 && linkpos >= 0 ) 1731 { 1732 /* move the first non-LP/not linked row to the end */ 1733 if( col->nlprows < pos ) 1734 { 1735 colMoveCoef(col, col->nlprows, pos); 1736 pos = col->nlprows; 1737 } 1738 col->nlprows++; 1739 } 1740 1741 /* in case the coefficient is integral w.r.t. numerics we explicitly round the coefficient to an integral value */ 1742 val = SCIPsetIsIntegral(set, val) ? SCIPsetRound(set, val) : val; 1743 1744 /* insert the row at the correct position and update the links */ 1745 col->rows[pos] = row; 1746 col->vals[pos] = val; 1747 col->linkpos[pos] = linkpos; 1748 if( linkpos == -1 ) 1749 { 1750 col->nunlinked++; 1751 1752 /* if the column is in current LP, we have to link it to the row, because otherwise, the primal information 1753 * of the row is not complete 1754 */ 1755 if( col->lppos >= 0 ) 1756 { 1757 /* this call might swap the current row with the first non-LP/not linked row, s.t. insertion position 1758 * has to be updated 1759 */ 1760 SCIP_CALL( rowAddCoef(row, blkmem, set, eventqueue, lp, col, val, pos) ); 1761 if( row->lppos >= 0 ) 1762 pos = col->nlprows-1; 1763 linkpos = col->linkpos[pos]; 1764 1765 assert(0 <= linkpos && linkpos < row->len); 1766 assert(row->cols[linkpos] == col); 1767 assert(col->rows[pos] == row); 1768 assert(col->rows[pos]->cols[col->linkpos[pos]] == col); 1769 assert(col->rows[pos]->linkpos[col->linkpos[pos]] == pos); 1770 } 1771 } 1772 else 1773 { 1774 assert(row->linkpos[linkpos] == -1); 1775 assert(row->nunlinked > 0); 1776 row->linkpos[linkpos] = pos; 1777 row->nunlinked--; 1778 1779 /* if the column is in current LP, now both conditions, row->cols[linkpos]->lppos >= 0 and row->linkpos[linkpos] >= 0 1780 * hold, so we have to move the column to the linked LP-cols part of the row's cols array 1781 */ 1782 if( col->lppos >= 0 ) 1783 { 1784 row->nlpcols++; 1785 rowSwapCoefs(row, linkpos, row->nlpcols-1); 1786 1787 /* if no swap was necessary, mark nonlpcols to be unsorted */ 1788 if( linkpos == row->nlpcols-1 ) 1789 row->lpcolssorted = FALSE; 1790 } 1791 } 1792 1793 /* update the sorted flags */ 1794 if( row->lppos >= 0 && linkpos >= 0 ) 1795 { 1796 assert(col->nlprows >= 1); 1797 assert(col->rows[col->nlprows-1] == row); 1798 if( col->nlprows > 1 ) 1799 col->lprowssorted = col->lprowssorted && (col->rows[col->nlprows-2]->index < row->index); 1800 } 1801 else 1802 { 1803 assert(col->len - col->nlprows >= 1); 1804 assert(col->rows[col->len-1] == row); 1805 if( col->len - col->nlprows > 1 ) 1806 col->nonlprowssorted = col->nonlprowssorted && (col->rows[col->len-2]->index < row->index); 1807 } 1808 1809 coefChanged(row, col, lp); 1810 1811 SCIPsetDebugMsg(set, "added coefficient %g * <%s> at position %d (%d/%d) to column <%s> (nunlinked=%d)\n", 1812 val, row->name, pos, col->nlprows, col->len, SCIPvarGetName(col->var), col->nunlinked); 1813 1814 return SCIP_OKAY; 1815 } 1816 1817 /** deletes coefficient at given position from column */ 1818 static 1819 SCIP_RETCODE colDelCoefPos( 1820 SCIP_COL* col, /**< column to be changed */ 1821 SCIP_SET* set, /**< global SCIP settings */ 1822 SCIP_LP* lp, /**< current LP data */ 1823 int pos /**< position in column vector to delete */ 1824 ) 1825 { 1826 SCIP_ROW* row; 1827 1828 assert(col != NULL); 1829 assert(col->var != NULL); 1830 assert(set != NULL); 1831 assert(0 <= pos && pos < col->len); 1832 assert(col->rows[pos] != NULL); 1833 assert(col->linkpos[pos] == -1 || col->rows[pos]->cols[col->linkpos[pos]] == col); 1834 assert((pos < col->nlprows) == (col->linkpos[pos] >= 0 && col->rows[pos]->lppos >= 0)); 1835 1836 row = col->rows[pos]; 1837 assert((row->lppos >= 0) == (pos < col->nlprows)); 1838 1839 /*SCIPsetDebugMsg(set, "deleting coefficient %g * <%s> at position %d from column <%s>\n", 1840 col->vals[pos], row->name, pos, SCIPvarGetName(col->var));*/ 1841 1842 if( col->linkpos[pos] == -1 ) 1843 col->nunlinked--; 1844 1845 /* if row is a linked LP row, move last linked LP coefficient to position of empty slot (deleted coefficient) */ 1846 if( pos < col->nlprows ) 1847 { 1848 colMoveCoef(col, col->nlprows-1, pos); 1849 col->nlprows--; 1850 pos = col->nlprows; 1851 } 1852 1853 /* move last coefficient to position of empty slot */ 1854 colMoveCoef(col, col->len-1, pos); 1855 col->len--; 1856 1857 coefChanged(row, col, lp); 1858 1859 return SCIP_OKAY; 1860 } 1861 1862 /** changes a coefficient at given position of an LP column */ 1863 static 1864 SCIP_RETCODE colChgCoefPos( 1865 SCIP_COL* col, /**< LP column */ 1866 SCIP_SET* set, /**< global SCIP settings */ 1867 SCIP_LP* lp, /**< current LP data */ 1868 int pos, /**< position in column vector to change */ 1869 SCIP_Real val /**< value of coefficient */ 1870 ) 1871 { 1872 assert(col != NULL); 1873 assert(col->var != NULL); 1874 assert(0 <= pos && pos < col->len); 1875 assert(col->rows[pos] != NULL); 1876 assert(col->linkpos[pos] == -1 || col->rows[pos]->cols[col->linkpos[pos]] == col); 1877 1878 /*debugMsg(scip, "changing coefficient %g * <%s> at position %d of column <%s> to %g\n", 1879 col->vals[pos], col->rows[pos]->name, pos, SCIPvarGetName(col->var), val);*/ 1880 1881 /* in case the coefficient is integral w.r.t. numerics we explicitly round the coefficient to an integral value */ 1882 val = SCIPsetIsIntegral(set, val) ? SCIPsetRound(set, val) : val; 1883 1884 if( SCIPsetIsZero(set, val) ) 1885 { 1886 /* delete existing coefficient */ 1887 SCIP_CALL( colDelCoefPos(col, set, lp, pos) ); 1888 } 1889 else if( !SCIPsetIsEQ(set, col->vals[pos], val) ) 1890 { 1891 /* change existing coefficient */ 1892 col->vals[pos] = val; 1893 coefChanged(col->rows[pos], col, lp); 1894 } 1895 1896 return SCIP_OKAY; 1897 } 1898 1899 1900 1901 1902 /* 1903 * local row changing methods 1904 */ 1905 1906 /** update row norms after addition of coefficient */ 1907 static 1908 void rowAddNorms( 1909 SCIP_ROW* row, /**< LP row */ 1910 SCIP_SET* set, /**< global SCIP settings */ 1911 SCIP_COL* col, /**< column of added coefficient */ 1912 SCIP_Real val, /**< value of added coefficient */ 1913 SCIP_Bool updateidxvals /**< update min/max idx and min/max val? */ 1914 ) 1915 { 1916 SCIP_Real absval; 1917 1918 assert(row != NULL); 1919 assert(row->nummaxval >= 0); 1920 assert(row->numminval >= 0); 1921 assert(set != NULL); 1922 assert(col != NULL); 1923 1924 absval = REALABS(val); 1925 assert(!SCIPsetIsZero(set, absval)); 1926 1927 /* Euclidean norm, sum norm, and objective function scalar product only take LP columns into account */ 1928 if( col->lppos >= 0 ) 1929 { 1930 /* update squared Euclidean norm and sum norm */ 1931 row->sqrnorm += SQR(absval); 1932 row->sumnorm += absval; 1933 1934 /* update objective function scalar product */ 1935 row->objprod += val * col->unchangedobj; 1936 } 1937 1938 if( updateidxvals ) 1939 { 1940 /* update min/maxidx */ 1941 row->minidx = MIN(row->minidx, col->index); 1942 row->maxidx = MAX(row->maxidx, col->index); 1943 1944 /* update maximal and minimal non-zero value */ 1945 if( row->nummaxval > 0 ) 1946 { 1947 if( SCIPsetIsGT(set, absval, row->maxval) ) 1948 { 1949 row->maxval = absval; 1950 row->nummaxval = 1; 1951 } 1952 else if( SCIPsetIsGE(set, absval, row->maxval) ) 1953 { 1954 /* make sure the maxval is always exactly the same */ 1955 row->maxval = MAX(absval, row->maxval); 1956 row->nummaxval++; 1957 } 1958 } 1959 if( row->numminval > 0 ) 1960 { 1961 if( SCIPsetIsLT(set, absval, row->minval) ) 1962 { 1963 row->minval = absval; 1964 row->numminval = 1; 1965 } 1966 else if( SCIPsetIsLE(set, absval, row->minval) ) 1967 { 1968 /* make sure the minval is always exactly the same */ 1969 row->minval = MIN(absval, row->minval); 1970 row->numminval++; 1971 } 1972 } 1973 } 1974 else 1975 { 1976 assert(row->minidx <= col->index); 1977 assert(row->maxidx >= col->index); 1978 assert(row->numminval <= 0 || absval >= row->minval); 1979 assert(row->nummaxval <= 0 || absval <= row->maxval); 1980 } 1981 } 1982 1983 /** update row norms after deletion of coefficient */ 1984 static 1985 void rowDelNorms( 1986 SCIP_ROW* row, /**< LP row */ 1987 SCIP_SET* set, /**< global SCIP settings */ 1988 SCIP_COL* col, /**< column of deleted coefficient */ 1989 SCIP_Real val, /**< value of deleted coefficient */ 1990 SCIP_Bool forcenormupdate, /**< should the norms be updated even if lppos of column is -1? */ 1991 SCIP_Bool updateindex, /**< should the minimal/maximal column index of row be updated? */ 1992 SCIP_Bool updateval /**< should the minimal/maximal value of row be updated? */ 1993 ) 1994 { 1995 SCIP_Real absval; 1996 1997 assert(row != NULL); 1998 assert(row->nummaxval >= 0); 1999 assert(row->numminval >= 0); 2000 assert(set != NULL); 2001 assert(col != NULL); 2002 2003 absval = REALABS(val); 2004 assert(!SCIPsetIsZero(set, absval)); 2005 assert(row->nummaxval == 0 || row->maxval >= absval); 2006 assert(row->numminval == 0 || row->minval <= absval); 2007 2008 /* update min/maxidx validity */ 2009 if( updateindex && (col->index == row->minidx || col->index == row->maxidx) ) 2010 row->validminmaxidx = FALSE; 2011 2012 /* Euclidean norm, sum norm, and objective function scalar product only take LP columns into account */ 2013 if( forcenormupdate || col->lppos >= 0 ) 2014 { 2015 /* update squared Euclidean norm and sum norm */ 2016 row->sqrnorm -= SQR(absval); 2017 row->sqrnorm = MAX(row->sqrnorm, 0.0); 2018 row->sumnorm -= absval; 2019 row->sumnorm = MAX(row->sumnorm, 0.0); 2020 2021 /* update objective function scalar product */ 2022 row->objprod -= val * col->unchangedobj; 2023 } 2024 2025 if( updateval ) 2026 { 2027 /* update maximal and minimal non-zero value */ 2028 if( row->nummaxval > 0 ) 2029 { 2030 if( SCIPsetIsGE(set, absval, row->maxval) ) 2031 row->nummaxval--; 2032 } 2033 if( row->numminval > 0 ) 2034 { 2035 if( SCIPsetIsLE(set, absval, row->minval) ) 2036 row->numminval--; 2037 } 2038 } 2039 } 2040 2041 /** adds a previously non existing coefficient to an LP row */ 2042 static 2043 SCIP_RETCODE rowAddCoef( 2044 SCIP_ROW* row, /**< LP row */ 2045 BMS_BLKMEM* blkmem, /**< block memory */ 2046 SCIP_SET* set, /**< global SCIP settings */ 2047 SCIP_EVENTQUEUE* eventqueue, /**< event queue */ 2048 SCIP_LP* lp, /**< current LP data */ 2049 SCIP_COL* col, /**< LP column */ 2050 SCIP_Real val, /**< value of coefficient */ 2051 int linkpos /**< position of row in the column's row array, or -1 */ 2052 ) 2053 { 2054 int pos; 2055 2056 assert(row != NULL); 2057 assert(row->nlpcols <= row->len); 2058 assert(blkmem != NULL); 2059 assert(col != NULL); 2060 assert(col->var != NULL); 2061 assert(col->var_probindex == SCIPvarGetProbindex(col->var)); 2062 assert(!SCIPsetIsZero(set, val)); 2063 /*assert(rowSearchCoef(row, col) == -1);*/ /* this assert would lead to slight differences in the solution process */ 2064 2065 if( row->nlocks > 0 ) 2066 { 2067 SCIPerrorMessage("cannot add a coefficient to the locked unmodifiable row <%s>\n", row->name); 2068 return SCIP_INVALIDDATA; 2069 } 2070 2071 SCIP_CALL( SCIProwEnsureSize(row, blkmem, set, row->len+1) ); 2072 assert(row->cols != NULL); 2073 assert(row->vals != NULL); 2074 2075 pos = row->len; 2076 row->len++; 2077 2078 /* if the column is in current LP and is linked to the row, we have to insert it at the end of the linked LP columns 2079 * part of the row's arrays 2080 */ 2081 if( col->lppos >= 0 && linkpos >= 0 ) 2082 { 2083 /* move the first non-LP/not linked column to the end */ 2084 if( row->nlpcols < pos ) 2085 { 2086 rowMoveCoef(row, row->nlpcols, pos); 2087 pos = row->nlpcols; 2088 } 2089 row->nlpcols++; 2090 } 2091 2092 /* in case the coefficient is integral w.r.t. numerics we explicitly round the coefficient to an integral value */ 2093 val = SCIPsetIsIntegral(set, val) ? SCIPsetRound(set, val) : val; 2094 2095 /* insert the column at the correct position and update the links */ 2096 row->cols[pos] = col; 2097 row->cols_index[pos] = col->index; 2098 row->vals[pos] = val; 2099 row->linkpos[pos] = linkpos; 2100 row->integral = row->integral && SCIPcolIsIntegral(col) && SCIPsetIsIntegral(set, val); 2101 if( linkpos == -1 ) 2102 { 2103 row->nunlinked++; 2104 2105 /* if the row is in current LP, we have to link it to the column, because otherwise, the dual information 2106 * of the column is not complete 2107 */ 2108 if( row->lppos >= 0 ) 2109 { 2110 /* this call might swap the current column with the first non-LP/not linked column, s.t. insertion position 2111 * has to be updated 2112 */ 2113 SCIP_CALL( colAddCoef(col, blkmem, set, eventqueue, lp, row, val, pos) ); 2114 if( col->lppos >= 0 ) 2115 pos = row->nlpcols-1; 2116 linkpos = row->linkpos[pos]; 2117 2118 assert(0 <= linkpos && linkpos < col->len); 2119 assert(col->rows[linkpos] == row); 2120 assert(row->cols[pos] == col); 2121 assert(row->cols[pos]->rows[row->linkpos[pos]] == row); 2122 assert(row->cols[pos]->linkpos[row->linkpos[pos]] == pos); 2123 } 2124 } 2125 else 2126 { 2127 assert(col->linkpos[linkpos] == -1); 2128 assert(col->nunlinked > 0); 2129 col->linkpos[linkpos] = pos; 2130 col->nunlinked--; 2131 2132 /* if the row is in current LP, now both conditions, col->rows[linkpos]->lppos >= 0 and col->linkpos[linkpos] >= 0 2133 * hold, so we have to move the row to the linked LP-rows part of the column's rows array 2134 */ 2135 if( row->lppos >= 0 ) 2136 { 2137 col->nlprows++; 2138 colSwapCoefs(col, linkpos, col->nlprows-1); 2139 2140 /* if no swap was necessary, mark lprows to be unsorted */ 2141 if( linkpos == col->nlprows-1 ) 2142 col->lprowssorted = FALSE; 2143 } 2144 } 2145 2146 /* update the sorted flags */ 2147 if( col->lppos >= 0 && linkpos >= 0 ) 2148 { 2149 assert(row->nlpcols >= 1); 2150 assert(row->cols[row->nlpcols-1] == col); 2151 if( row->nlpcols > 1 ) 2152 { 2153 assert(row->cols_index[row->nlpcols-2] == row->cols[row->nlpcols-2]->index); 2154 row->lpcolssorted = row->lpcolssorted && (row->cols_index[row->nlpcols-2] < col->index); 2155 } 2156 } 2157 else 2158 { 2159 assert(row->len - row->nlpcols >= 1); 2160 assert(row->cols[row->len-1] == col); 2161 if( row->len - row->nlpcols > 1 ) 2162 { 2163 assert(row->cols_index[row->len-2] == row->cols[row->len-2]->index); 2164 row->nonlpcolssorted = row->nonlpcolssorted && (row->cols_index[row->len-2] < col->index); 2165 } 2166 } 2167 2168 /* update row norm */ 2169 rowAddNorms(row, set, col, val, TRUE); 2170 2171 coefChanged(row, col, lp); 2172 2173 SCIPsetDebugMsg(set, "added coefficient %g * <%s> at position %d (%d/%d) to row <%s> (nunlinked=%d)\n", 2174 val, SCIPvarGetName(col->var), pos, row->nlpcols, row->len, row->name, row->nunlinked); 2175 2176 /* issue row coefficient changed event */ 2177 SCIP_CALL( rowEventCoefChanged(row, blkmem, set, eventqueue, col, 0.0, val) ); 2178 2179 return SCIP_OKAY; 2180 } 2181 2182 /** deletes coefficient at given position from row */ 2183 static 2184 SCIP_RETCODE rowDelCoefPos( 2185 SCIP_ROW* row, /**< row to be changed */ 2186 BMS_BLKMEM* blkmem, /**< block memory */ 2187 SCIP_SET* set, /**< global SCIP settings */ 2188 SCIP_EVENTQUEUE* eventqueue, /**< event queue */ 2189 SCIP_LP* lp, /**< current LP data */ 2190 int pos /**< position in row vector to delete */ 2191 ) 2192 { 2193 SCIP_COL* col; 2194 SCIP_Real val; 2195 2196 assert(row != NULL); 2197 assert(set != NULL); 2198 assert(0 <= pos && pos < row->len); 2199 assert(row->cols[pos] != NULL); 2200 assert((pos < row->nlpcols) == (row->linkpos[pos] >= 0 && row->cols[pos]->lppos >= 0)); 2201 2202 col = row->cols[pos]; 2203 val = row->vals[pos]; 2204 assert((pos < row->nlpcols) == (col->lppos >= 0 && row->linkpos[pos] >= 0)); 2205 2206 /*SCIPsetDebugMsg(set, "deleting coefficient %g * <%s> at position %d from row <%s>\n", 2207 val, SCIPvarGetName(col->var), pos, row->name);*/ 2208 2209 if( row->nlocks > 0 ) 2210 { 2211 SCIPerrorMessage("cannot delete a coefficient from the locked unmodifiable row <%s>\n", row->name); 2212 return SCIP_INVALIDDATA; 2213 } 2214 2215 if( row->linkpos[pos] == -1 ) 2216 row->nunlinked--; 2217 2218 /* if column is a linked LP column, move last linked LP coefficient to position of empty slot (deleted coefficient) */ 2219 if( pos < row->nlpcols ) 2220 { 2221 rowMoveCoef(row, row->nlpcols-1, pos); 2222 assert(!row->lpcolssorted); 2223 row->nlpcols--; 2224 pos = row->nlpcols; 2225 } 2226 2227 /* move last coefficient to position of empty slot */ 2228 rowMoveCoef(row, row->len-1, pos); 2229 row->len--; 2230 2231 /* update norms */ 2232 rowDelNorms(row, set, col, val, FALSE, TRUE, TRUE); 2233 2234 coefChanged(row, col, lp); 2235 2236 /* issue row coefficient changed event */ 2237 SCIP_CALL( rowEventCoefChanged(row, blkmem, set, eventqueue, col, val, 0.0) ); 2238 2239 return SCIP_OKAY; 2240 } 2241 2242 /** changes a coefficient at given position of an LP row */ 2243 static 2244 SCIP_RETCODE rowChgCoefPos( 2245 SCIP_ROW* row, /**< LP row */ 2246 BMS_BLKMEM* blkmem, /**< block memory */ 2247 SCIP_SET* set, /**< global SCIP settings */ 2248 SCIP_EVENTQUEUE* eventqueue, /**< event queue */ 2249 SCIP_LP* lp, /**< current LP data */ 2250 int pos, /**< position in row vector to change */ 2251 SCIP_Real val /**< value of coefficient */ 2252 ) 2253 { 2254 SCIP_COL* col; 2255 2256 assert(row != NULL); 2257 assert(0 <= pos && pos < row->len); 2258 2259 /*SCIPsetDebugMsg(set, "changing coefficient %g * <%s> at position %d of row <%s> to %g\n", 2260 row->vals[pos], SCIPvarGetName(row->cols[pos]->var), pos, row->name, val);*/ 2261 2262 if( row->nlocks > 0 ) 2263 { 2264 SCIPerrorMessage("cannot change a coefficient of the locked unmodifiable row <%s>\n", row->name); 2265 return SCIP_INVALIDDATA; 2266 } 2267 2268 /* in case the coefficient is integral w.r.t. numerics we explicitly round the coefficient to an integral value */ 2269 val = SCIPsetIsIntegral(set, val) ? SCIPsetRound(set, val) : val; 2270 col = row->cols[pos]; 2271 assert(row->cols[pos] != NULL); 2272 2273 if( SCIPsetIsZero(set, val) ) 2274 { 2275 /* delete existing coefficient */ 2276 SCIP_CALL( rowDelCoefPos(row, blkmem, set, eventqueue, lp, pos) ); 2277 } 2278 else if( !SCIPsetIsEQ(set, row->vals[pos], val) ) 2279 { 2280 SCIP_Real oldval; 2281 2282 oldval = row->vals[pos]; 2283 2284 /* change existing coefficient */ 2285 rowDelNorms(row, set, col, row->vals[pos], FALSE, FALSE, TRUE); 2286 row->vals[pos] = val; 2287 row->integral = row->integral && SCIPcolIsIntegral(col) && SCIPsetIsIntegral(set, val); 2288 rowAddNorms(row, set, col, row->vals[pos], TRUE); 2289 coefChanged(row, col, lp); 2290 2291 /* issue row coefficient changed event */ 2292 SCIP_CALL( rowEventCoefChanged(row, blkmem, set, eventqueue, col, oldval, val) ); 2293 } 2294 2295 return SCIP_OKAY; 2296 } 2297 2298 /** notifies LP row, that its sides were changed */ 2299 static 2300 SCIP_RETCODE rowSideChanged( 2301 SCIP_ROW* row, /**< LP row */ 2302 SCIP_SET* set, /**< global SCIP settings */ 2303 SCIP_LP* lp, /**< current LP data */ 2304 SCIP_SIDETYPE sidetype /**< type of side: left or right hand side */ 2305 ) 2306 { 2307 assert(row != NULL); 2308 assert(lp != NULL); 2309 2310 if( row->lpipos >= 0 ) 2311 { 2312 /* insert row in the chgrows list (if not already there) */ 2313 if( !row->lhschanged && !row->rhschanged ) 2314 { 2315 SCIP_CALL( ensureChgrowsSize(lp, set, lp->nchgrows+1) ); 2316 lp->chgrows[lp->nchgrows] = row; 2317 lp->nchgrows++; 2318 } 2319 2320 /* mark side change in the row */ 2321 switch( sidetype ) 2322 { 2323 case SCIP_SIDETYPE_LEFT: 2324 row->lhschanged = TRUE; 2325 break; 2326 case SCIP_SIDETYPE_RIGHT: 2327 row->rhschanged = TRUE; 2328 break; 2329 default: 2330 SCIPerrorMessage("unknown row side type\n"); 2331 SCIPABORT(); 2332 return SCIP_INVALIDDATA; /*lint !e527*/ 2333 } 2334 2335 /* mark the current LP unflushed */ 2336 lp->flushed = FALSE; 2337 2338 assert(lp->nchgrows > 0); 2339 } 2340 2341 return SCIP_OKAY; 2342 } 2343 2344 2345 2346 2347 /* 2348 * double linked coefficient matrix methods 2349 */ 2350 2351 /** insert column coefficients in corresponding rows */ 2352 SCIP_RETCODE colLink( 2353 SCIP_COL* col, /**< column data */ 2354 BMS_BLKMEM* blkmem, /**< block memory */ 2355 SCIP_SET* set, /**< global SCIP settings */ 2356 SCIP_EVENTQUEUE* eventqueue, /**< event queue */ 2357 SCIP_LP* lp /**< current LP data */ 2358 ) 2359 { 2360 int i; 2361 2362 assert(col != NULL); 2363 assert(col->var != NULL); 2364 assert(blkmem != NULL); 2365 assert(set != NULL); 2366 assert(lp != NULL); 2367 2368 if( col->nunlinked > 0 ) 2369 { 2370 SCIPsetDebugMsg(set, "linking column <%s>\n", SCIPvarGetName(col->var)); 2371 2372 /* unlinked rows can only be in the non-LP/unlinked rows part of the rows array */ 2373 for( i = col->nlprows; i < col->len; ++i ) 2374 { 2375 assert(!SCIPsetIsZero(set, col->vals[i])); 2376 if( col->linkpos[i] == -1 ) 2377 { 2378 /* this call might swap the current row with the first non-LP/not linked row, but this is of no harm */ 2379 SCIP_CALL( rowAddCoef(col->rows[i], blkmem, set, eventqueue, lp, col, col->vals[i], i) ); 2380 } 2381 assert(col->rows[i]->cols[col->linkpos[i]] == col); 2382 assert(col->rows[i]->linkpos[col->linkpos[i]] == i); 2383 assert(col->nlprows == 0 || col->rows[col->nlprows-1]->cols[col->linkpos[col->nlprows-1]] == col); 2384 assert(col->nlprows == 0 || col->rows[col->nlprows-1]->linkpos[col->linkpos[col->nlprows-1]] == col->nlprows-1); 2385 } 2386 } 2387 assert(col->nunlinked == 0); 2388 2389 checkLinks(lp); 2390 2391 return SCIP_OKAY; 2392 } 2393 2394 /** removes column coefficients from corresponding rows */ 2395 SCIP_RETCODE colUnlink( 2396 SCIP_COL* col, /**< column data */ 2397 BMS_BLKMEM* blkmem, /**< block memory */ 2398 SCIP_SET* set, /**< global SCIP settings */ 2399 SCIP_EVENTQUEUE* eventqueue, /**< event queue */ 2400 SCIP_LP* lp /**< current LP data */ 2401 ) 2402 { 2403 int i; 2404 2405 assert(col != NULL); 2406 assert(col->var != NULL); 2407 assert(blkmem != NULL); 2408 assert(set != NULL); 2409 assert(lp != NULL); 2410 2411 if( col->nunlinked < col->len ) 2412 { 2413 SCIPsetDebugMsg(set, "unlinking column <%s>\n", SCIPvarGetName(col->var)); 2414 for( i = 0; i < col->len; ++i ) 2415 { 2416 if( col->linkpos[i] >= 0 ) 2417 { 2418 assert(col->rows[i]->cols[col->linkpos[i]] == col); 2419 SCIP_CALL( rowDelCoefPos(col->rows[i], blkmem, set, eventqueue, lp, col->linkpos[i]) ); 2420 col->linkpos[i] = -1; 2421 col->nunlinked++; 2422 } 2423 } 2424 } 2425 assert(col->nunlinked == col->len); 2426 2427 checkLinks(lp); 2428 2429 return SCIP_OKAY; 2430 } 2431 2432 /** insert row coefficients in corresponding columns */ 2433 SCIP_RETCODE rowLink( 2434 SCIP_ROW* row, /**< row data */ 2435 BMS_BLKMEM* blkmem, /**< block memory */ 2436 SCIP_SET* set, /**< global SCIP settings */ 2437 SCIP_EVENTQUEUE* eventqueue, /**< event queue */ 2438 SCIP_LP* lp /**< current LP data */ 2439 ) 2440 { 2441 int i; 2442 2443 assert(row != NULL); 2444 assert(blkmem != NULL); 2445 assert(set != NULL); 2446 assert(lp != NULL); 2447 2448 if( row->nunlinked > 0 ) 2449 { 2450 SCIPsetDebugMsg(set, "linking row <%s>\n", row->name); 2451 2452 /* unlinked columns can only be in the non-LP/unlinked columns part of the cols array */ 2453 for( i = row->nlpcols; i < row->len; ++i ) 2454 { 2455 assert(!SCIPsetIsZero(set, row->vals[i])); 2456 if( row->linkpos[i] == -1 ) 2457 { 2458 /* this call might swap the current column with the first non-LP/not linked column, but this is of no harm */ 2459 SCIP_CALL( colAddCoef(row->cols[i], blkmem, set, eventqueue, lp, row, row->vals[i], i) ); 2460 } 2461 assert(row->cols[i]->rows[row->linkpos[i]] == row); 2462 assert(row->cols[i]->linkpos[row->linkpos[i]] == i); 2463 assert(row->nlpcols == 0 || row->cols[row->nlpcols-1]->rows[row->linkpos[row->nlpcols-1]] == row); 2464 assert(row->nlpcols == 0 || row->cols[row->nlpcols-1]->linkpos[row->linkpos[row->nlpcols-1]] == row->nlpcols-1); 2465 } 2466 } 2467 assert(row->nunlinked == 0); 2468 2469 checkLinks(lp); 2470 2471 return SCIP_OKAY; 2472 } 2473 2474 /** removes row coefficients from corresponding columns */ 2475 SCIP_RETCODE rowUnlink( 2476 SCIP_ROW* row, /**< row data */ 2477 SCIP_SET* set, /**< global SCIP settings */ 2478 SCIP_LP* lp /**< current LP data */ 2479 ) 2480 { 2481 int i; 2482 2483 assert(row != NULL); 2484 assert(set != NULL); 2485 assert(lp != NULL); 2486 2487 if( row->nunlinked < row->len ) 2488 { 2489 SCIPsetDebugMsg(set, "unlinking row <%s>\n", row->name); 2490 for( i = 0; i < row->len; ++i ) 2491 { 2492 if( row->linkpos[i] >= 0 ) 2493 { 2494 assert(row->cols[i]->rows[row->linkpos[i]] == row); 2495 SCIP_CALL( colDelCoefPos(row->cols[i], set, lp, row->linkpos[i]) ); 2496 row->nunlinked++; 2497 } 2498 } 2499 } 2500 assert(row->nunlinked == row->len); 2501 2502 return SCIP_OKAY; 2503 } 2504 2505 2506 2507 2508 /* 2509 * local LP parameter methods 2510 */ 2511 2512 /** sets parameter of type int in LP solver, ignoring unknown parameters */ 2513 static 2514 SCIP_RETCODE lpSetIntpar( 2515 SCIP_LP* lp, /**< current LP data */ 2516 SCIP_LPPARAM lpparam, /**< LP parameter */ 2517 int value, /**< value to set parameter to */ 2518 SCIP_Bool* success /**< pointer to store whether the parameter was successfully changed */ 2519 ) 2520 { 2521 SCIP_RETCODE retcode; 2522 2523 assert(lp != NULL); 2524 assert(success != NULL); 2525 2526 retcode = SCIPlpiSetIntpar(lp->lpi, lpparam, value); 2527 2528 /* check, if parameter is unknown */ 2529 if( retcode == SCIP_PARAMETERUNKNOWN ) 2530 { 2531 *success = FALSE; 2532 return SCIP_OKAY; 2533 } 2534 *success = TRUE; 2535 2536 return retcode; 2537 } 2538 2539 /** sets parameter of type SCIP_Bool in LP solver, ignoring unknown parameters */ 2540 static 2541 SCIP_RETCODE lpSetBoolpar( 2542 SCIP_LP* lp, /**< current LP data */ 2543 SCIP_LPPARAM lpparam, /**< LP parameter */ 2544 SCIP_Bool value, /**< value to set parameter to */ 2545 SCIP_Bool* success /**< pointer to store whether the parameter was successfully changed */ 2546 ) 2547 { 2548 return lpSetIntpar(lp, lpparam, (int)value, success); 2549 } 2550 2551 /** sets parameter of type SCIP_Real in LP solver, ignoring unknown parameters */ 2552 static 2553 SCIP_RETCODE lpSetRealpar( 2554 SCIP_LP* lp, /**< current LP data */ 2555 SCIP_LPPARAM lpparam, /**< LP parameter */ 2556 SCIP_Real value, /**< value to set parameter to */ 2557 SCIP_Bool* success /**< pointer to store whether the parameter was successfully changed */ 2558 ) 2559 { 2560 SCIP_RETCODE retcode; 2561 2562 assert(lp != NULL); 2563 assert(success != NULL); 2564 2565 retcode = SCIPlpiSetRealpar(lp->lpi, lpparam, value); 2566 2567 /* check, if parameter is unknown */ 2568 if( retcode == SCIP_PARAMETERUNKNOWN ) 2569 { 2570 *success = FALSE; 2571 return SCIP_OKAY; 2572 } 2573 *success = TRUE; 2574 2575 return retcode; 2576 } 2577 2578 #ifndef NDEBUG 2579 /** checks, that parameter of type int in LP solver has the given value, ignoring unknown parameters */ 2580 static 2581 SCIP_RETCODE lpCheckIntpar( 2582 SCIP_LP* lp, /**< current LP data */ 2583 SCIP_LPPARAM lpparam, /**< LP parameter */ 2584 int value /**< value parameter should have */ 2585 ) 2586 { 2587 SCIP_RETCODE retcode; 2588 int lpivalue; 2589 2590 assert(lp != NULL); 2591 2592 retcode = SCIPlpiGetIntpar(lp->lpi, lpparam, &lpivalue); 2593 2594 /* ignore unknown parameter error */ 2595 if( retcode == SCIP_PARAMETERUNKNOWN ) 2596 return SCIP_OKAY; 2597 2598 /* check value */ 2599 assert(lpivalue == value); 2600 2601 return retcode; 2602 } 2603 2604 /** checks, that parameter of type SCIP_Bool in LP solver has the given value, ignoring unknown parameters */ 2605 static 2606 SCIP_RETCODE lpCheckBoolpar( 2607 SCIP_LP* lp, /**< current LP data */ 2608 SCIP_LPPARAM lpparam, /**< LP parameter */ 2609 SCIP_Bool value /**< value parameter should have */ 2610 ) 2611 { 2612 return lpCheckIntpar(lp, lpparam, (int)value); 2613 } 2614 2615 /** checks, that parameter of type SCIP_Real in LP solver has the given value, ignoring unknown parameters */ 2616 static 2617 SCIP_RETCODE lpCheckRealpar( 2618 SCIP_LP* lp, /**< current LP data */ 2619 SCIP_LPPARAM lpparam, /**< LP parameter */ 2620 SCIP_Real value /**< value parameter should have */ 2621 ) 2622 { 2623 SCIP_RETCODE retcode; 2624 SCIP_Real lpivalue; 2625 2626 assert(lp != NULL); 2627 2628 retcode = SCIPlpiGetRealpar(lp->lpi, lpparam, &lpivalue); 2629 2630 /* ignore unknown parameter error */ 2631 if( retcode == SCIP_PARAMETERUNKNOWN ) 2632 return SCIP_OKAY; 2633 2634 /* check value */ 2635 assert(lpivalue == value); /*lint !e777*/ 2636 2637 return retcode; 2638 } 2639 #else 2640 #define lpCheckIntpar(lp, lpparam, value) SCIP_OKAY 2641 #define lpCheckBoolpar(lp, lpparam, value) SCIP_OKAY 2642 #define lpCheckRealpar(lp, lpparam, value) SCIP_OKAY 2643 #endif 2644 2645 /** should the objective limit of the LP solver be disabled */ 2646 #define lpCutoffDisabled(set,prob) (set->lp_disablecutoff == 1 || ((set->nactivepricers > 0 || !SCIPprobAllColsInLP(prob, set, lp)) && set->lp_disablecutoff == 2)) 2647 2648 /** sets the objective limit of the LP solver 2649 * 2650 * Note that we are always minimizing. 2651 */ 2652 static 2653 SCIP_RETCODE lpSetObjlim( 2654 SCIP_LP* lp, /**< current LP data */ 2655 SCIP_SET* set, /**< global SCIP settings */ 2656 SCIP_PROB* prob, /**< problem data */ 2657 SCIP_Real objlim, /**< new objective limit */ 2658 SCIP_Bool* success /**< pointer to store whether the parameter was actually changed */ 2659 ) 2660 { 2661 assert(lp != NULL); 2662 assert(set != NULL); 2663 assert(success != NULL); 2664 2665 *success = FALSE; 2666 2667 /* We disabled the objective limit in the LP solver or we want so solve exactly and thus cannot rely on the LP 2668 * solver's objective limit handling, so we make sure that the objective limit is inactive (infinity). */ 2669 if( lpCutoffDisabled(set, prob) || set->misc_exactsolve ) 2670 objlim = SCIPlpiInfinity(lp->lpi); 2671 2672 /* convert SCIP infinity value to lp-solver infinity value if necessary */ 2673 if( SCIPsetIsInfinity(set, objlim) ) 2674 objlim = SCIPlpiInfinity(lp->lpi); 2675 2676 SCIP_CALL( lpCheckRealpar(lp, SCIP_LPPAR_OBJLIM, lp->lpiobjlim) ); 2677 2678 if( objlim != lp->lpiobjlim ) /*lint !e777*/ 2679 { 2680 SCIP_CALL( lpSetRealpar(lp, SCIP_LPPAR_OBJLIM, objlim, success) ); 2681 if( *success ) 2682 { 2683 SCIP_Real actualobjlim; 2684 2685 /* check whether the parameter was actually changed or already was at the boundary of the LP solver's parameter range */ 2686 SCIP_CALL( SCIPlpiGetRealpar(lp->lpi, SCIP_LPPAR_OBJLIM, &actualobjlim) ); 2687 if( actualobjlim != lp->lpiobjlim ) /*lint !e777*/ 2688 { 2689 /* mark the current solution invalid */ 2690 lp->solved = FALSE; 2691 lp->primalfeasible = FALSE; 2692 lp->primalchecked = FALSE; 2693 lp->lpobjval = SCIP_INVALID; 2694 lp->lpsolstat = SCIP_LPSOLSTAT_NOTSOLVED; 2695 } 2696 lp->lpiobjlim = actualobjlim; 2697 } 2698 } 2699 2700 return SCIP_OKAY; 2701 } 2702 2703 /** sets the feasibility tolerance of the LP solver */ 2704 static 2705 SCIP_RETCODE lpSetFeastol( 2706 SCIP_LP* lp, /**< current LP data */ 2707 SCIP_Real feastol, /**< new feasibility tolerance */ 2708 SCIP_Bool* success /**< pointer to store whether the parameter was actually changed */ 2709 ) 2710 { 2711 assert(lp != NULL); 2712 assert(feastol >= 0.0); 2713 assert(success != NULL); 2714 2715 SCIP_CALL( lpCheckRealpar(lp, SCIP_LPPAR_FEASTOL, lp->lpifeastol) ); 2716 2717 if( feastol != lp->lpifeastol ) /*lint !e777*/ 2718 { 2719 SCIP_CALL( lpSetRealpar(lp, SCIP_LPPAR_FEASTOL, feastol, success) ); 2720 if( *success ) 2721 { 2722 SCIP_Real actualfeastol; 2723 2724 /* check whether the parameter was actually changed or already was at the boundary of the LP solver's parameter range */ 2725 SCIP_CALL( SCIPlpiGetRealpar(lp->lpi, SCIP_LPPAR_FEASTOL, &actualfeastol) ); 2726 if( lp->nrows > 0 && actualfeastol < lp->lpifeastol ) 2727 { 2728 /* mark the current solution invalid */ 2729 lp->solved = FALSE; 2730 lp->primalfeasible = FALSE; 2731 lp->primalchecked = FALSE; 2732 lp->lpobjval = SCIP_INVALID; 2733 lp->lpsolstat = SCIP_LPSOLSTAT_NOTSOLVED; 2734 } 2735 else 2736 *success = FALSE; 2737 lp->lpifeastol = actualfeastol; 2738 } 2739 } 2740 else 2741 *success = FALSE; 2742 2743 return SCIP_OKAY; 2744 } 2745 2746 /** sets the reduced costs feasibility tolerance of the LP solver */ 2747 static 2748 SCIP_RETCODE lpSetDualfeastol( 2749 SCIP_LP* lp, /**< current LP data */ 2750 SCIP_Real dualfeastol, /**< new reduced costs feasibility tolerance */ 2751 SCIP_Bool* success /**< pointer to store whether the parameter was actually changed */ 2752 ) 2753 { 2754 assert(lp != NULL); 2755 assert(dualfeastol >= 0.0); 2756 assert(success != NULL); 2757 2758 SCIP_CALL( lpCheckRealpar(lp, SCIP_LPPAR_DUALFEASTOL, lp->lpidualfeastol) ); 2759 2760 if( dualfeastol != lp->lpidualfeastol ) /*lint !e777*/ 2761 { 2762 SCIP_CALL( lpSetRealpar(lp, SCIP_LPPAR_DUALFEASTOL, dualfeastol, success) ); 2763 if( *success ) 2764 { 2765 SCIP_Real actualdualfeastol; 2766 2767 /* check whether the parameter was actually changed or already was at the boundary of the LP solver's parameter range */ 2768 SCIP_CALL( SCIPlpiGetRealpar(lp->lpi, SCIP_LPPAR_DUALFEASTOL, &actualdualfeastol) ); 2769 if( lp->nrows > 0 && actualdualfeastol < lp->lpidualfeastol ) 2770 { 2771 /* mark the current solution invalid */ 2772 lp->solved = FALSE; 2773 lp->dualfeasible = FALSE; 2774 lp->dualchecked = FALSE; 2775 lp->lpobjval = SCIP_INVALID; 2776 lp->lpsolstat = SCIP_LPSOLSTAT_NOTSOLVED; 2777 } 2778 else 2779 *success = FALSE; 2780 lp->lpidualfeastol = actualdualfeastol; 2781 } 2782 } 2783 else 2784 *success = FALSE; 2785 2786 return SCIP_OKAY; 2787 } 2788 2789 /** sets the convergence tolerance used in barrier algorithm of the LP solver */ 2790 static 2791 SCIP_RETCODE lpSetBarrierconvtol( 2792 SCIP_LP* lp, /**< current LP data */ 2793 SCIP_Real barrierconvtol, /**< new convergence tolerance used in barrier algorithm */ 2794 SCIP_Bool* success /**< pointer to store whether the parameter was actually changed */ 2795 ) 2796 { 2797 assert(lp != NULL); 2798 assert(barrierconvtol >= 0.0); 2799 assert(success != NULL); 2800 2801 SCIP_CALL( lpCheckRealpar(lp, SCIP_LPPAR_BARRIERCONVTOL, lp->lpibarrierconvtol) ); 2802 2803 if( barrierconvtol != lp->lpibarrierconvtol ) /*lint !e777*/ 2804 { 2805 SCIP_CALL( lpSetRealpar(lp, SCIP_LPPAR_BARRIERCONVTOL, barrierconvtol, success) ); 2806 if( *success ) 2807 { 2808 SCIP_Real actualbarrierconvtol; 2809 2810 /* check whether the parameter was actually changed or already was at the boundary of the LP solver's parameter range */ 2811 SCIP_CALL( SCIPlpiGetRealpar(lp->lpi, SCIP_LPPAR_BARRIERCONVTOL, &actualbarrierconvtol) ); 2812 if( lp->nrows > 0 && actualbarrierconvtol < lp->lpibarrierconvtol 2813 && (lp->lastlpalgo == SCIP_LPALGO_BARRIER || lp->lastlpalgo == SCIP_LPALGO_BARRIERCROSSOVER) ) 2814 { 2815 /* mark the current solution invalid */ 2816 lp->solved = FALSE; 2817 lp->dualfeasible = FALSE; 2818 lp->dualchecked = FALSE; 2819 lp->lpobjval = SCIP_INVALID; 2820 lp->lpsolstat = SCIP_LPSOLSTAT_NOTSOLVED; 2821 } 2822 else 2823 *success = FALSE; 2824 lp->lpibarrierconvtol = actualbarrierconvtol; 2825 } 2826 } 2827 else 2828 *success = FALSE; 2829 2830 return SCIP_OKAY; 2831 } 2832 2833 /** sets the FROMSCRATCH setting of the LP solver */ 2834 static 2835 SCIP_RETCODE lpSetFromscratch( 2836 SCIP_LP* lp, /**< current LP data */ 2837 SCIP_Bool fromscratch, /**< new FROMSCRATCH setting */ 2838 SCIP_Bool* success /**< pointer to store whether the parameter was successfully changed */ 2839 ) 2840 { 2841 assert(lp != NULL); 2842 assert(success != NULL); 2843 2844 SCIP_CALL( lpCheckBoolpar(lp, SCIP_LPPAR_FROMSCRATCH, lp->lpifromscratch) ); 2845 2846 if( fromscratch != lp->lpifromscratch ) 2847 { 2848 SCIP_CALL( lpSetBoolpar(lp, SCIP_LPPAR_FROMSCRATCH, fromscratch, success) ); 2849 if( *success ) 2850 lp->lpifromscratch = fromscratch; 2851 } 2852 else 2853 *success = FALSE; 2854 2855 return SCIP_OKAY; 2856 } 2857 2858 /** sets the FASTMIP setting of the LP solver */ 2859 static 2860 SCIP_RETCODE lpSetFastmip( 2861 SCIP_LP* lp, /**< current LP data */ 2862 int fastmip, /**< new FASTMIP setting */ 2863 SCIP_Bool* success /**< pointer to store whether the parameter was successfully changed */ 2864 ) 2865 { 2866 assert(lp != NULL); 2867 assert(success != NULL); 2868 assert(0 <= fastmip && fastmip <= 1); 2869 2870 SCIP_CALL( lpCheckIntpar(lp, SCIP_LPPAR_FASTMIP, lp->lpifastmip) ); 2871 2872 if( fastmip != lp->lpifastmip ) 2873 { 2874 SCIP_CALL( lpSetIntpar(lp, SCIP_LPPAR_FASTMIP, fastmip, success) ); 2875 if( *success ) 2876 { 2877 lp->lpifastmip = fastmip; 2878 lp->solved = FALSE; 2879 /* We might only set lp->solved to false if fastmip is turned off, since the latter should be the more 2880 * demanding setting; however, in the current code, this should have not effect. */ 2881 } 2882 } 2883 else 2884 *success = FALSE; 2885 2886 return SCIP_OKAY; 2887 } 2888 2889 /** sets the SCALING setting of the LP solver */ 2890 static 2891 SCIP_RETCODE lpSetScaling( 2892 SCIP_LP* lp, /**< current LP data */ 2893 int scaling, /**< new SCALING setting */ 2894 SCIP_Bool* success /**< pointer to store whether the parameter was successfully changed */ 2895 ) 2896 { 2897 assert(lp != NULL); 2898 assert(success != NULL); 2899 2900 SCIP_CALL( lpCheckIntpar(lp, SCIP_LPPAR_SCALING, lp->lpiscaling) ); 2901 2902 if( scaling != lp->lpiscaling ) 2903 { 2904 SCIP_CALL( lpSetIntpar(lp, SCIP_LPPAR_SCALING, scaling, success) ); 2905 if( *success ) 2906 lp->lpiscaling = scaling; 2907 } 2908 else 2909 *success = FALSE; 2910 2911 return SCIP_OKAY; 2912 } 2913 2914 /** sets the number of THREADS of the LP solver */ 2915 static 2916 SCIP_RETCODE lpSetThreads( 2917 SCIP_LP* lp, /**< current LP data */ 2918 int threads, /**< new number of threads used to solve the LP */ 2919 SCIP_Bool* success /**< pointer to store whether the parameter was successfully changed */ 2920 ) 2921 { 2922 assert(lp != NULL); 2923 assert(success != NULL); 2924 2925 SCIP_CALL( lpCheckIntpar(lp, SCIP_LPPAR_THREADS, lp->lpithreads) ); 2926 2927 if( threads != lp->lpithreads ) 2928 { 2929 SCIP_CALL( lpSetIntpar(lp, SCIP_LPPAR_THREADS, threads, success) ); 2930 if( *success ) 2931 lp->lpithreads = threads; 2932 } 2933 else 2934 *success = FALSE; 2935 2936 return SCIP_OKAY; 2937 } 2938 2939 /** sets the PRESOLVING setting of the LP solver */ 2940 static 2941 SCIP_RETCODE lpSetPresolving( 2942 SCIP_LP* lp, /**< current LP data */ 2943 SCIP_Bool presolving, /**< new PRESOLVING setting */ 2944 SCIP_Bool* success /**< pointer to store whether the parameter was successfully changed */ 2945 ) 2946 { 2947 assert(lp != NULL); 2948 assert(success != NULL); 2949 2950 SCIP_CALL( lpCheckBoolpar(lp, SCIP_LPPAR_PRESOLVING, lp->lpipresolving) ); 2951 2952 if( presolving != lp->lpipresolving ) 2953 { 2954 SCIP_CALL( lpSetBoolpar(lp, SCIP_LPPAR_PRESOLVING, presolving, success) ); 2955 if( *success ) 2956 lp->lpipresolving = presolving; 2957 } 2958 else 2959 *success = FALSE; 2960 2961 return SCIP_OKAY; 2962 } 2963 2964 /** sets the ROWREPSWITCH setting of the LP solver */ 2965 static 2966 SCIP_RETCODE lpSetRowrepswitch( 2967 SCIP_LP* lp, /**< current LP data */ 2968 SCIP_Real rowrepswitch, /**< new ROWREPSWITCH value */ 2969 SCIP_Bool* success /**< pointer to store whether the parameter was successfully changed */ 2970 ) 2971 { 2972 assert(lp != NULL); 2973 assert(success != NULL); 2974 2975 SCIP_CALL( lpCheckRealpar(lp, SCIP_LPPAR_ROWREPSWITCH, lp->lpirowrepswitch) ); 2976 2977 if( rowrepswitch != lp->lpirowrepswitch ) /*lint !e777*/ 2978 { 2979 SCIP_CALL( lpSetRealpar(lp, SCIP_LPPAR_ROWREPSWITCH, rowrepswitch, success) ); 2980 if( *success ) 2981 lp->lpirowrepswitch = rowrepswitch; 2982 } 2983 else 2984 *success = FALSE; 2985 2986 return SCIP_OKAY; 2987 } 2988 2989 /** sets the iteration limit of the LP solver */ 2990 static 2991 SCIP_RETCODE lpSetIterationLimit( 2992 SCIP_LP* lp, /**< current LP data */ 2993 int itlim /**< maximal number of LP iterations to perform, or -1 for no limit */ 2994 ) 2995 { 2996 SCIP_Bool success; 2997 2998 assert(lp != NULL); 2999 assert(itlim >= -1); 3000 3001 if( itlim == -1 ) 3002 itlim = INT_MAX; 3003 3004 SCIP_CALL( lpCheckIntpar(lp, SCIP_LPPAR_LPITLIM, lp->lpiitlim) ); 3005 3006 if( itlim != lp->lpiitlim ) 3007 { 3008 SCIP_CALL( lpSetIntpar(lp, SCIP_LPPAR_LPITLIM, itlim, &success) ); 3009 if( success ) 3010 { 3011 if( itlim > lp->lpiitlim ) 3012 { 3013 /* mark the current solution invalid */ 3014 lp->solved = FALSE; 3015 lp->lpobjval = SCIP_INVALID; 3016 lp->lpsolstat = SCIP_LPSOLSTAT_NOTSOLVED; 3017 } 3018 lp->lpiitlim = itlim; 3019 } 3020 } 3021 3022 return SCIP_OKAY; 3023 } 3024 3025 /** sets the pricing strategy of the LP solver */ 3026 static 3027 SCIP_RETCODE lpSetPricing( 3028 SCIP_LP* lp, /**< current LP data */ 3029 SCIP_PRICING pricing /**< pricing strategy */ 3030 ) 3031 { 3032 SCIP_Bool success; 3033 3034 assert(lp != NULL); 3035 3036 SCIP_CALL( lpCheckIntpar(lp, SCIP_LPPAR_PRICING, (int)lp->lpipricing) ); 3037 3038 if( pricing != lp->lpipricing ) 3039 { 3040 SCIP_CALL( lpSetIntpar(lp, SCIP_LPPAR_PRICING, (int)pricing, &success) ); 3041 if( success ) 3042 lp->lpipricing = pricing; 3043 } 3044 3045 return SCIP_OKAY; 3046 } 3047 3048 /** sets the pricing strategy of the LP solver (given the character representation of the strategy) */ 3049 static 3050 SCIP_RETCODE lpSetPricingChar( 3051 SCIP_LP* lp, /**< current LP data */ 3052 char pricingchar /**< character representing the pricing strategy */ 3053 ) 3054 { 3055 SCIP_PRICING pricing; 3056 3057 switch( pricingchar ) 3058 { 3059 case 'l': 3060 pricing = SCIP_PRICING_LPIDEFAULT; 3061 break; 3062 case 'a': 3063 pricing = SCIP_PRICING_AUTO; 3064 break; 3065 case 'f': 3066 pricing = SCIP_PRICING_FULL; 3067 break; 3068 case 'p': 3069 pricing = SCIP_PRICING_PARTIAL; 3070 break; 3071 case 's': 3072 pricing = SCIP_PRICING_STEEP; 3073 break; 3074 case 'q': 3075 pricing = SCIP_PRICING_STEEPQSTART; 3076 break; 3077 case 'd': 3078 pricing = SCIP_PRICING_DEVEX; 3079 break; 3080 default: 3081 SCIPerrorMessage("invalid LP pricing parameter <%c>\n", pricingchar); 3082 return SCIP_INVALIDDATA; 3083 } 3084 3085 SCIP_CALL( lpSetPricing(lp, pricing) ); 3086 3087 return SCIP_OKAY; 3088 } 3089 3090 /** sets the verbosity of the LP solver */ 3091 static 3092 SCIP_RETCODE lpSetLPInfo( 3093 SCIP_LP* lp, /**< current LP data */ 3094 SCIP_Bool lpinfo /**< should the LP solver display status messages? */ 3095 ) 3096 { 3097 SCIP_Bool success; 3098 3099 assert(lp != NULL); 3100 3101 SCIP_CALL( lpCheckBoolpar(lp, SCIP_LPPAR_LPINFO, lp->lpilpinfo) ); 3102 3103 if( lpinfo != lp->lpilpinfo ) 3104 { 3105 SCIP_CALL( lpSetBoolpar(lp, SCIP_LPPAR_LPINFO, lpinfo, &success) ); 3106 if( success ) 3107 lp->lpilpinfo = lpinfo; 3108 } 3109 3110 return SCIP_OKAY; 3111 } 3112 3113 /** sets the CONDITIONLIMIT setting of the LP solver */ 3114 static 3115 SCIP_RETCODE lpSetConditionLimit( 3116 SCIP_LP* lp, /**< current LP data */ 3117 SCIP_Real condlimit, /**< new CONDITIONLIMIT value */ 3118 SCIP_Bool* success /**< pointer to store whether the parameter was successfully changed */ 3119 ) 3120 { 3121 assert(lp != NULL); 3122 assert(success != NULL); 3123 3124 SCIP_CALL( lpCheckRealpar(lp, SCIP_LPPAR_CONDITIONLIMIT, lp->lpiconditionlimit) ); 3125 3126 if( condlimit != lp->lpiconditionlimit ) /*lint !e777*/ 3127 { 3128 SCIP_CALL( lpSetRealpar(lp, SCIP_LPPAR_CONDITIONLIMIT, condlimit, success) ); 3129 if( *success ) 3130 lp->lpiconditionlimit = condlimit; 3131 } 3132 else 3133 *success = FALSE; 3134 3135 return SCIP_OKAY; 3136 } 3137 3138 /** sets the MARKOWITZ setting of the LP solver */ 3139 static 3140 SCIP_RETCODE lpSetMarkowitz( 3141 SCIP_LP* lp, /**< current LP data */ 3142 SCIP_Real threshhold, /**< new MARKOWITZ value */ 3143 SCIP_Bool* success /**< pointer to store whether the parameter was successfully changed */ 3144 ) 3145 { 3146 assert(lp != NULL); 3147 assert(success != NULL); 3148 3149 SCIP_CALL( lpCheckRealpar(lp, SCIP_LPPAR_MARKOWITZ, lp->lpimarkowitz) ); 3150 3151 if( threshhold != lp->lpimarkowitz ) /*lint !e777*/ 3152 { 3153 SCIP_CALL( lpSetRealpar(lp, SCIP_LPPAR_MARKOWITZ, threshhold, success) ); 3154 if( *success ) 3155 lp->lpimarkowitz = threshhold; 3156 } 3157 else 3158 *success = FALSE; 3159 3160 return SCIP_OKAY; 3161 } 3162 3163 /** sets the type of timer of the LP solver */ 3164 static 3165 SCIP_RETCODE lpSetTiming( 3166 SCIP_LP* lp, /**< current LP data */ 3167 SCIP_CLOCKTYPE timing, /**< new timing value */ 3168 SCIP_Bool enabled, /**< is timing enabled? */ 3169 SCIP_Bool* success /**< pointer to store whether the parameter was successfully changed */ 3170 ) 3171 { 3172 int lptiming; 3173 3174 assert(lp != NULL); 3175 assert(success != NULL); 3176 assert((int) SCIP_CLOCKTYPE_CPU == 1 && (int) SCIP_CLOCKTYPE_WALL == 2); /*lint !e506*//*lint !e1564*/ 3177 3178 SCIP_CALL( lpCheckIntpar(lp, SCIP_LPPAR_TIMING, lp->lpitiming) ); 3179 3180 if( !enabled ) 3181 lptiming = 0; 3182 else 3183 lptiming = (int) timing; 3184 3185 if( lptiming != lp->lpitiming ) /*lint !e777*/ 3186 { 3187 SCIP_CALL( lpSetIntpar(lp, SCIP_LPPAR_TIMING, lptiming, success) ); 3188 if( *success ) 3189 lp->lpitiming = lptiming; 3190 } 3191 else 3192 *success = FALSE; 3193 3194 return SCIP_OKAY; 3195 } 3196 3197 /** sets the initial random seed of the LP solver */ 3198 static 3199 SCIP_RETCODE lpSetRandomseed( 3200 SCIP_LP* lp, /**< current LP data */ 3201 int randomseed, /**< new initial random seed */ 3202 SCIP_Bool* success /**< pointer to store whether the parameter was successfully changed */ 3203 ) 3204 { 3205 assert(lp != NULL); 3206 assert(success != NULL); 3207 3208 /* we don't check this parameter because SoPlex will always return its current random seed, not the initial one */ 3209 3210 if( randomseed == 0 ) 3211 { 3212 lp->lpirandomseed = randomseed; 3213 *success = TRUE; 3214 } 3215 else if( randomseed != lp->lpirandomseed ) /*lint !e777*/ 3216 { 3217 SCIP_CALL( lpSetIntpar(lp, SCIP_LPPAR_RANDOMSEED, randomseed, success) ); 3218 if( *success ) 3219 lp->lpirandomseed = randomseed; 3220 } 3221 else 3222 *success = FALSE; 3223 3224 return SCIP_OKAY; 3225 } 3226 3227 /** sets the LP solution polishing method */ 3228 static 3229 SCIP_RETCODE lpSetSolutionPolishing( 3230 SCIP_LP* lp, /**< current LP data */ 3231 SCIP_Bool polishing, /**< LP solution polishing activated (0: disabled, 1: enabled) */ 3232 SCIP_Bool* success /**< pointer to store whether the parameter was successfully changed */ 3233 ) 3234 { 3235 assert(lp != NULL); 3236 assert(success != NULL); 3237 3238 if( polishing != lp->lpisolutionpolishing ) 3239 { 3240 SCIP_CALL( lpSetIntpar(lp, SCIP_LPPAR_POLISHING, (polishing ? 1 : 0), success) ); 3241 if( *success ) 3242 lp->lpisolutionpolishing = polishing; 3243 } 3244 else 3245 *success = FALSE; 3246 3247 return SCIP_OKAY; 3248 } 3249 3250 /** sets the LP refactorization interval */ 3251 static 3252 SCIP_RETCODE lpSetRefactorInterval( 3253 SCIP_LP* lp, /**< current LP data */ 3254 int refactor, /**< LP refactorization interval (0: automatic) */ 3255 SCIP_Bool* success /**< pointer to store whether the parameter was successfully changed */ 3256 ) 3257 { 3258 assert(lp != NULL); 3259 assert(success != NULL); 3260 3261 if( refactor != lp->lpirefactorinterval ) 3262 { 3263 SCIP_CALL( lpSetIntpar(lp, SCIP_LPPAR_REFACTOR, refactor, success) ); 3264 if( *success ) 3265 lp->lpirefactorinterval = refactor; 3266 } 3267 else 3268 *success = FALSE; 3269 3270 return SCIP_OKAY; 3271 } 3272 3273 3274 /* 3275 * Column methods 3276 */ 3277 3278 /** creates an LP column */ 3279 SCIP_RETCODE SCIPcolCreate( 3280 SCIP_COL** col, /**< pointer to column data */ 3281 BMS_BLKMEM* blkmem, /**< block memory */ 3282 SCIP_SET* set, /**< global SCIP settings */ 3283 SCIP_STAT* stat, /**< problem statistics */ 3284 SCIP_VAR* var, /**< variable, this column represents */ 3285 int len, /**< number of nonzeros in the column */ 3286 SCIP_ROW** rows, /**< array with rows of column entries */ 3287 SCIP_Real* vals, /**< array with coefficients of column entries */ 3288 SCIP_Bool removable /**< should the column be removed from the LP due to aging or cleanup? */ 3289 ) 3290 { 3291 int i; 3292 3293 assert(col != NULL); 3294 assert(blkmem != NULL); 3295 assert(set != NULL); 3296 assert(stat != NULL); 3297 assert(var != NULL); 3298 assert(len >= 0); 3299 assert(len == 0 || (rows != NULL && vals != NULL)); 3300 3301 SCIP_ALLOC( BMSallocBlockMemory(blkmem, col) ); 3302 3303 if( len > 0 ) 3304 { 3305 SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &(*col)->rows, rows, len) ); 3306 SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &(*col)->vals, vals, len) ); 3307 SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &(*col)->linkpos, len) ); 3308 3309 for( i = 0; i < len; ++i ) 3310 { 3311 assert(rows[i] != NULL); 3312 assert(!SCIPsetIsZero(set, vals[i])); 3313 (*col)->linkpos[i] = -1; 3314 } 3315 } 3316 else 3317 { 3318 (*col)->rows = NULL; 3319 (*col)->vals = NULL; 3320 (*col)->linkpos = NULL; 3321 } 3322 3323 (*col)->var = var; 3324 (*col)->obj = SCIPvarGetObj(var); 3325 (*col)->unchangedobj = SCIPvarGetUnchangedObj(var); 3326 (*col)->lb = SCIPvarGetLbLocal(var); 3327 (*col)->ub = SCIPvarGetUbLocal(var); 3328 (*col)->flushedobj = 0.0; 3329 (*col)->flushedlb = 0.0; 3330 (*col)->flushedub = 0.0; 3331 (*col)->index = stat->ncolidx; 3332 SCIPstatIncrement(stat, set, ncolidx); 3333 (*col)->size = len; 3334 (*col)->len = len; 3335 (*col)->nlprows = 0; 3336 (*col)->nunlinked = len; 3337 (*col)->lppos = -1; 3338 (*col)->lpipos = -1; 3339 (*col)->lpdepth = -1; 3340 (*col)->primsol = 0.0; 3341 (*col)->redcost = SCIP_INVALID; 3342 (*col)->farkascoef = SCIP_INVALID; 3343 (*col)->minprimsol = (*col)->ub; 3344 (*col)->maxprimsol = (*col)->lb; 3345 (*col)->sbdown = SCIP_INVALID; 3346 (*col)->sbup = SCIP_INVALID; 3347 (*col)->sbsolval = SCIP_INVALID; 3348 (*col)->sblpobjval = SCIP_INVALID; 3349 (*col)->sbnode = -1; 3350 (*col)->validredcostlp = -1; 3351 (*col)->validfarkaslp = -1; 3352 (*col)->validsblp = -1; 3353 (*col)->sbitlim = -1; 3354 (*col)->nsbcalls = 0; 3355 (*col)->age = 0; 3356 (*col)->obsoletenode = -1; 3357 (*col)->var_probindex = SCIPvarGetProbindex(var); 3358 (*col)->basisstatus = SCIP_BASESTAT_ZERO; /*lint !e641*/ 3359 (*col)->lprowssorted = TRUE; 3360 (*col)->nonlprowssorted = (len <= 1); 3361 (*col)->objchanged = FALSE; 3362 (*col)->lbchanged = FALSE; 3363 (*col)->ubchanged = FALSE; 3364 (*col)->coefchanged = FALSE; 3365 (*col)->integral = SCIPvarIsIntegral(var); 3366 (*col)->removable = removable; 3367 (*col)->sbdownvalid = FALSE; 3368 (*col)->sbupvalid = FALSE; 3369 (*col)->lazylb = SCIPvarGetLbLazy(var); 3370 (*col)->lazyub = SCIPvarGetUbLazy(var); 3371 (*col)->storedsolvals = NULL; 3372 3373 return SCIP_OKAY; 3374 } 3375 3376 /** frees an LP column */ 3377 SCIP_RETCODE SCIPcolFree( 3378 SCIP_COL** col, /**< pointer to LP column */ 3379 BMS_BLKMEM* blkmem, /**< block memory */ 3380 SCIP_SET* set, /**< global SCIP settings */ 3381 SCIP_EVENTQUEUE* eventqueue, /**< event queue */ 3382 SCIP_LP* lp /**< current LP data */ 3383 ) 3384 { 3385 assert(blkmem != NULL); 3386 assert(col != NULL); 3387 assert(*col != NULL); 3388 assert((*col)->var != NULL); 3389 assert(SCIPvarGetStatus((*col)->var) == SCIP_VARSTATUS_COLUMN); 3390 assert(&(*col)->var->data.col == col); /* SCIPcolFree() has to be called from SCIPvarFree() */ 3391 assert((*col)->lppos == -1); 3392 assert((*col)->lpipos == -1); 3393 3394 /* remove column indices from corresponding rows */ 3395 SCIP_CALL( colUnlink(*col, blkmem, set, eventqueue, lp) ); 3396 3397 BMSfreeBlockMemoryNull(blkmem, &(*col)->storedsolvals); 3398 BMSfreeBlockMemoryArrayNull(blkmem, &(*col)->rows, (*col)->size); 3399 BMSfreeBlockMemoryArrayNull(blkmem, &(*col)->vals, (*col)->size); 3400 BMSfreeBlockMemoryArrayNull(blkmem, &(*col)->linkpos, (*col)->size); 3401 BMSfreeBlockMemory(blkmem, col); 3402 3403 return SCIP_OKAY; 3404 } 3405 3406 /** output column to file stream */ 3407 void SCIPcolPrint( 3408 SCIP_COL* col, /**< LP column */ 3409 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */ 3410 FILE* file /**< output file (or NULL for standard output) */ 3411 ) 3412 { 3413 int r; 3414 3415 assert(col != NULL); 3416 assert(col->var != NULL); 3417 3418 /* print bounds */ 3419 SCIPmessageFPrintInfo(messagehdlr, file, "(obj: %.15g) [%.15g,%.15g], ", col->obj, col->lb, col->ub); 3420 3421 /* print coefficients */ 3422 if( col->len == 0 ) 3423 SCIPmessageFPrintInfo(messagehdlr, file, "<empty>"); 3424 for( r = 0; r < col->len; ++r ) 3425 { 3426 assert(col->rows[r] != NULL); 3427 assert(col->rows[r]->name != NULL); 3428 SCIPmessageFPrintInfo(messagehdlr, file, "%+.15g<%s> ", col->vals[r], col->rows[r]->name); 3429 } 3430 SCIPmessageFPrintInfo(messagehdlr, file, "\n"); 3431 } 3432 3433 /** sorts column entries such that LP rows precede non-LP rows and inside both parts lower row indices precede higher ones 3434 */ 3435 void SCIPcolSort( 3436 SCIP_COL* col /**< column to be sorted */ 3437 ) 3438 { 3439 /* sort LP rows */ 3440 colSortLP(col); 3441 3442 /* sort non-LP rows */ 3443 colSortNonLP(col); 3444 } 3445 3446 /** adds a previously non existing coefficient to an LP column */ 3447 SCIP_RETCODE SCIPcolAddCoef( 3448 SCIP_COL* col, /**< LP column */ 3449 BMS_BLKMEM* blkmem, /**< block memory */ 3450 SCIP_SET* set, /**< global SCIP settings */ 3451 SCIP_EVENTQUEUE* eventqueue, /**< event queue */ 3452 SCIP_LP* lp, /**< current LP data */ 3453 SCIP_ROW* row, /**< LP row */ 3454 SCIP_Real val /**< value of coefficient */ 3455 ) 3456 { 3457 assert(lp != NULL); 3458 assert(!lp->diving); 3459 3460 SCIP_CALL( colAddCoef(col, blkmem, set, eventqueue, lp, row, val, -1) ); 3461 3462 checkLinks(lp); 3463 3464 return SCIP_OKAY; 3465 } 3466 3467 /** deletes existing coefficient from column */ 3468 SCIP_RETCODE SCIPcolDelCoef( 3469 SCIP_COL* col, /**< column to be changed */ 3470 BMS_BLKMEM* blkmem, /**< block memory */ 3471 SCIP_SET* set, /**< global SCIP settings */ 3472 SCIP_EVENTQUEUE* eventqueue, /**< event queue */ 3473 SCIP_LP* lp, /**< current LP data */ 3474 SCIP_ROW* row /**< coefficient to be deleted */ 3475 ) 3476 { 3477 int pos; 3478 3479 assert(col != NULL); 3480 assert(col->var != NULL); 3481 assert(lp != NULL); 3482 assert(!lp->diving); 3483 assert(row != NULL); 3484 3485 /* search the position of the row in the column's row vector */ 3486 pos = colSearchCoef(col, row); 3487 if( pos == -1 ) 3488 { 3489 SCIPerrorMessage("coefficient for row <%s> doesn't exist in column <%s>\n", row->name, SCIPvarGetName(col->var)); 3490 return SCIP_INVALIDDATA; 3491 } 3492 assert(0 <= pos && pos < col->len); 3493 assert(col->rows[pos] == row); 3494 3495 /* if row knows of the column, remove the column from the row's col vector */ 3496 if( col->linkpos[pos] >= 0 ) 3497 { 3498 assert(row->cols[col->linkpos[pos]] == col); 3499 assert(row->cols_index[col->linkpos[pos]] == col->index); 3500 assert(SCIPsetIsEQ(set, row->vals[col->linkpos[pos]], col->vals[pos])); 3501 SCIP_CALL( rowDelCoefPos(row, blkmem, set, eventqueue, lp, col->linkpos[pos]) ); 3502 } 3503 3504 /* delete the row from the column's row vector */ 3505 SCIP_CALL( colDelCoefPos(col, set, lp, pos) ); 3506 3507 checkLinks(lp); 3508 3509 return SCIP_OKAY; 3510 } 3511 3512 /** changes or adds a coefficient to an LP column */ 3513 SCIP_RETCODE SCIPcolChgCoef( 3514 SCIP_COL* col, /**< LP column */ 3515 BMS_BLKMEM* blkmem, /**< block memory */ 3516 SCIP_SET* set, /**< global SCIP settings */ 3517 SCIP_EVENTQUEUE* eventqueue, /**< event queue */ 3518 SCIP_LP* lp, /**< current LP data */ 3519 SCIP_ROW* row, /**< LP row */ 3520 SCIP_Real val /**< value of coefficient */ 3521 ) 3522 { 3523 int pos; 3524 3525 assert(col != NULL); 3526 assert(lp != NULL); 3527 assert(!lp->diving); 3528 assert(row != NULL); 3529 3530 /* search the position of the row in the column's row vector */ 3531 pos = colSearchCoef(col, row); 3532 3533 /* check, if row already exists in the column's row vector */ 3534 if( pos == -1 ) 3535 { 3536 /* add previously not existing coefficient */ 3537 SCIP_CALL( colAddCoef(col, blkmem, set, eventqueue, lp, row, val, -1) ); 3538 } 3539 else 3540 { 3541 /* modify already existing coefficient */ 3542 assert(0 <= pos && pos < col->len); 3543 assert(col->rows[pos] == row); 3544 3545 /* if row knows of the column, change the corresponding coefficient in the row */ 3546 if( col->linkpos[pos] >= 0 ) 3547 { 3548 assert(row->cols[col->linkpos[pos]] == col); 3549 assert(row->cols_index[col->linkpos[pos]] == col->index); 3550 assert(SCIPsetIsEQ(set, row->vals[col->linkpos[pos]], col->vals[pos])); 3551 SCIP_CALL( rowChgCoefPos(row, blkmem, set, eventqueue, lp, col->linkpos[pos], val) ); 3552 } 3553 3554 /* change the coefficient in the column */ 3555 SCIP_CALL( colChgCoefPos(col, set, lp, pos, val) ); 3556 } 3557 3558 checkLinks(lp); 3559 3560 return SCIP_OKAY; 3561 } 3562 3563 /** increases value of an existing or non-existing coefficient in an LP column */ 3564 SCIP_RETCODE SCIPcolIncCoef( 3565 SCIP_COL* col, /**< LP column */ 3566 BMS_BLKMEM* blkmem, /**< block memory */ 3567 SCIP_SET* set, /**< global SCIP settings */ 3568 SCIP_EVENTQUEUE* eventqueue, /**< event queue */ 3569 SCIP_LP* lp, /**< current LP data */ 3570 SCIP_ROW* row, /**< LP row */ 3571 SCIP_Real incval /**< value to add to the coefficient */ 3572 ) 3573 { 3574 int pos; 3575 3576 assert(col != NULL); 3577 assert(lp != NULL); 3578 assert(!lp->diving); 3579 assert(row != NULL); 3580 3581 if( SCIPsetIsZero(set, incval) ) 3582 return SCIP_OKAY; 3583 3584 /* search the position of the row in the column's row vector */ 3585 pos = colSearchCoef(col, row); 3586 3587 /* check, if row already exists in the column's row vector */ 3588 if( pos == -1 ) 3589 { 3590 /* add previously not existing coefficient */ 3591 SCIP_CALL( colAddCoef(col, blkmem, set, eventqueue, lp, row, incval, -1) ); 3592 } 3593 else 3594 { 3595 /* modify already existing coefficient */ 3596 assert(0 <= pos && pos < col->len); 3597 assert(col->rows[pos] == row); 3598 3599 /* if row knows of the column, change the corresponding coefficient in the row */ 3600 if( col->linkpos[pos] >= 0 ) 3601 { 3602 assert(row->cols[col->linkpos[pos]] == col); 3603 assert(row->cols_index[col->linkpos[pos]] == col->index); 3604 assert(SCIPsetIsEQ(set, row->vals[col->linkpos[pos]], col->vals[pos])); 3605 SCIP_CALL( rowChgCoefPos(row, blkmem, set, eventqueue, lp, col->linkpos[pos], col->vals[pos] + incval) ); 3606 } 3607 3608 /* change the coefficient in the column */ 3609 SCIP_CALL( colChgCoefPos(col, set, lp, pos, col->vals[pos] + incval) ); 3610 } 3611 3612 checkLinks(lp); 3613 3614 return SCIP_OKAY; 3615 } 3616 3617 /** insert column in the chgcols list (if not already there) */ 3618 static 3619 SCIP_RETCODE insertColChgcols( 3620 SCIP_COL* col, /**< LP column to change */ 3621 SCIP_SET* set, /**< global SCIP settings */ 3622 SCIP_LP* lp /**< current LP data */ 3623 ) 3624 { 3625 if( !col->objchanged && !col->lbchanged && !col->ubchanged ) 3626 { 3627 SCIP_CALL( ensureChgcolsSize(lp, set, lp->nchgcols+1) ); 3628 lp->chgcols[lp->nchgcols] = col; 3629 lp->nchgcols++; 3630 } 3631 3632 /* mark the current LP unflushed */ 3633 lp->flushed = FALSE; 3634 3635 return SCIP_OKAY; 3636 } 3637 3638 /** Is the new value reliable or may we have cancellation? 3639 * 3640 * @note: Here we only consider cancellations which can occur during decreasing the oldvalue to newvalue; not the 3641 * cancellations which can occur during increasing the oldvalue to the newvalue 3642 */ 3643 static 3644 SCIP_Bool isNewValueUnreliable( 3645 SCIP_SET* set, /**< global SCIP settings */ 3646 SCIP_Real newvalue, /**< new value */ 3647 SCIP_Real oldvalue /**< old reliable value */ 3648 ) 3649 { 3650 SCIP_Real quotient; 3651 3652 assert(set != NULL); 3653 assert(oldvalue != SCIP_INVALID); /*lint !e777*/ 3654 3655 quotient = (REALABS(newvalue)+1.0) / (REALABS(oldvalue) + 1.0); 3656 3657 return SCIPsetIsZero(set, quotient); 3658 } 3659 3660 /** update norms of objective function vector */ 3661 static 3662 void lpUpdateObjNorms( 3663 SCIP_LP* lp, /**< current LP data */ 3664 SCIP_SET* set, /**< global SCIP settings */ 3665 SCIP_Real oldobj, /**< old objective value of variable */ 3666 SCIP_Real newobj /**< new objective value of variable */ 3667 ) 3668 { 3669 if( REALABS(newobj) != REALABS(oldobj) ) /*lint !e777*/ 3670 { 3671 if( !lp->objsqrnormunreliable ) 3672 { 3673 SCIP_Real oldvalue; 3674 3675 oldvalue = lp->objsqrnorm; 3676 lp->objsqrnorm += SQR(newobj) - SQR(oldobj); 3677 3678 /* due to numerical cancellations, we recalculate lp->objsqrnorm using all variables */ 3679 if( SCIPsetIsLT(set, lp->objsqrnorm, 0.0) || isNewValueUnreliable(set, lp->objsqrnorm, oldvalue) ) 3680 lp->objsqrnormunreliable = TRUE; 3681 else 3682 { 3683 assert(SCIPsetIsGE(set, lp->objsqrnorm, 0.0)); 3684 3685 /* due to numerical troubles it still can appear that lp->objsqrnorm is a little bit smaller than 0 */ 3686 lp->objsqrnorm = MAX(lp->objsqrnorm, 0.0); 3687 3688 assert(lp->objsqrnorm >= 0.0); 3689 } 3690 } 3691 3692 lp->objsumnorm += REALABS(newobj) - REALABS(oldobj); 3693 lp->objsumnorm = MAX(lp->objsumnorm, 0.0); 3694 } 3695 } 3696 3697 /** changes objective value of column */ 3698 SCIP_RETCODE SCIPcolChgObj( 3699 SCIP_COL* col, /**< LP column to change */ 3700 SCIP_SET* set, /**< global SCIP settings */ 3701 SCIP_LP* lp, /**< current LP data */ 3702 SCIP_Real newobj /**< new objective value */ 3703 ) 3704 { 3705 assert(col != NULL); 3706 assert(col->var != NULL); 3707 assert(SCIPvarGetStatus(col->var) == SCIP_VARSTATUS_COLUMN); 3708 assert(SCIPvarGetCol(col->var) == col); 3709 assert(lp != NULL); 3710 3711 SCIPsetDebugMsg(set, "changing objective value of column <%s> from %f to %f\n", SCIPvarGetName(col->var), col->obj, newobj); 3712 3713 /* only add actual changes */ 3714 if( !SCIPsetIsEQ(set, col->obj, newobj) ) 3715 { 3716 /* only variables with a real position in the LPI can be inserted */ 3717 if( col->lpipos >= 0 ) 3718 { 3719 /* insert column in the chgcols list (if not already there) */ 3720 SCIP_CALL( insertColChgcols(col, set, lp) ); 3721 3722 /* mark objective value change in the column */ 3723 col->objchanged = TRUE; 3724 3725 assert(lp->nchgcols > 0); 3726 } 3727 /* in any case, when the sign of the objective (and thereby the best bound) changes, the variable has to enter the 3728 * LP and the LP has to be flushed 3729 */ 3730 else if( (col->obj < 0.0 && newobj >= 0.0 && SCIPsetIsZero(set, col->ub)) 3731 || (col->obj >= 0.0 && newobj < 0.0 && SCIPsetIsZero(set, col->lb)) ) 3732 { 3733 /* mark the LP unflushed */ 3734 lp->flushed = FALSE; 3735 } 3736 } 3737 3738 /* store new objective function value */ 3739 col->obj = newobj; 3740 3741 /* update original objective value, as long as we are not in diving or probing and changed objective values */ 3742 if( !lp->divingobjchg ) 3743 { 3744 SCIP_Real oldobj = col->unchangedobj; 3745 3746 assert(SCIPsetIsEQ(set, newobj, SCIPvarGetUnchangedObj(col->var))); 3747 col->unchangedobj = newobj; 3748 3749 /* update the objective function vector norms */ 3750 lpUpdateObjNorms(lp, set, oldobj, newobj); 3751 } 3752 3753 return SCIP_OKAY; 3754 } 3755 3756 /** changes lower bound of column */ 3757 SCIP_RETCODE SCIPcolChgLb( 3758 SCIP_COL* col, /**< LP column to change */ 3759 SCIP_SET* set, /**< global SCIP settings */ 3760 SCIP_LP* lp, /**< current LP data */ 3761 SCIP_Real newlb /**< new lower bound value */ 3762 ) 3763 { 3764 assert(col != NULL); 3765 assert(col->var != NULL); 3766 assert(SCIPvarGetStatus(col->var) == SCIP_VARSTATUS_COLUMN); 3767 assert(SCIPvarGetCol(col->var) == col); 3768 assert(lp != NULL); 3769 3770 SCIPsetDebugMsg(set, "changing lower bound of column <%s> from %f to %f\n", SCIPvarGetName(col->var), col->lb, newlb); 3771 3772 /* only add actual changes */ 3773 if( !SCIPsetIsEQ(set, col->lb, newlb) ) 3774 { 3775 /* only variables with a real position in the LPI can be inserted */ 3776 if( col->lpipos >= 0 ) 3777 { 3778 /* insert column in the chgcols list (if not already there) */ 3779 SCIP_CALL( insertColChgcols(col, set, lp) ); 3780 3781 /* mark bound change in the column */ 3782 col->lbchanged = TRUE; 3783 3784 assert(lp->nchgcols > 0); 3785 } 3786 /* in any case, when the best bound is zero and gets changed, the variable has to enter the LP and the LP has to be 3787 * flushed 3788 */ 3789 else if( col->obj >= 0.0 && SCIPsetIsZero(set, col->lb) ) 3790 { 3791 /* mark the LP unflushed */ 3792 lp->flushed = FALSE; 3793 } 3794 } 3795 3796 col->lb = newlb; 3797 3798 return SCIP_OKAY; 3799 } 3800 3801 /** changes upper bound of column */ 3802 SCIP_RETCODE SCIPcolChgUb( 3803 SCIP_COL* col, /**< LP column to change */ 3804 SCIP_SET* set, /**< global SCIP settings */ 3805 SCIP_LP* lp, /**< current LP data */ 3806 SCIP_Real newub /**< new upper bound value */ 3807 ) 3808 { 3809 assert(col != NULL); 3810 assert(col->var != NULL); 3811 assert(SCIPvarGetStatus(col->var) == SCIP_VARSTATUS_COLUMN); 3812 assert(SCIPvarGetCol(col->var) == col); 3813 assert(lp != NULL); 3814 3815 SCIPsetDebugMsg(set, "changing upper bound of column <%s> from %f to %f\n", SCIPvarGetName(col->var), col->ub, newub); 3816 3817 /* only add actual changes */ 3818 if( !SCIPsetIsEQ(set, col->ub, newub) ) 3819 { 3820 /* only variables with a real position in the LPI can be inserted */ 3821 if( col->lpipos >= 0 ) 3822 { 3823 /* insert column in the chgcols list (if not already there) */ 3824 SCIP_CALL( insertColChgcols(col, set, lp) ); 3825 3826 /* mark bound change in the column */ 3827 col->ubchanged = TRUE; 3828 3829 assert(lp->nchgcols > 0); 3830 } 3831 /* in any case, when the best bound is zero and gets changed, the variable has to enter the LP and the LP has to be 3832 * flushed 3833 */ 3834 else if( col->obj < 0.0 && SCIPsetIsZero(set, col->ub) ) 3835 { 3836 /* mark the LP unflushed */ 3837 lp->flushed = FALSE; 3838 } 3839 } 3840 3841 col->ub = newub; 3842 3843 return SCIP_OKAY; 3844 } 3845 3846 /** calculates the reduced costs of a column using the given dual solution vector */ 3847 SCIP_Real SCIPcolCalcRedcost( 3848 SCIP_COL* col, /**< LP column */ 3849 SCIP_Real* dualsol /**< dual solution vector for current LP rows */ 3850 ) 3851 { 3852 SCIP_ROW* row; 3853 SCIP_Real redcost; 3854 int i; 3855 3856 assert(col != NULL); 3857 assert(SCIPvarGetStatus(col->var) == SCIP_VARSTATUS_COLUMN); 3858 assert(SCIPvarGetCol(col->var) == col); 3859 assert(dualsol != NULL); 3860 3861 redcost = col->obj; 3862 for( i = 0; i < col->nlprows; ++i ) 3863 { 3864 row = col->rows[i]; 3865 assert(row != NULL); 3866 assert(row->lppos >= 0); 3867 redcost -= col->vals[i] * dualsol[row->lppos]; 3868 } 3869 3870 if( col->nunlinked > 0 ) 3871 { 3872 for( i = col->nlprows; i < col->len; ++i ) 3873 { 3874 row = col->rows[i]; 3875 assert(row != NULL); 3876 assert(row->lppos == -1 || col->linkpos[i] == -1); 3877 if( row->lppos >= 0 ) 3878 redcost -= col->vals[i] * dualsol[row->lppos]; 3879 } 3880 } 3881 #ifndef NDEBUG 3882 else 3883 { 3884 for( i = col->nlprows; i < col->len; ++i ) 3885 { 3886 row = col->rows[i]; 3887 assert(row != NULL); 3888 assert(row->lppos == -1); 3889 assert(col->linkpos[i] >= 0); 3890 } 3891 } 3892 #endif 3893 3894 return redcost; 3895 } 3896 3897 /** calculates the reduced costs of a column using the dual solution stored in the rows */ 3898 static 3899 SCIP_Real colCalcInternalRedcost( 3900 SCIP_COL* col /**< LP column */ 3901 ) 3902 { 3903 SCIP_ROW* row; 3904 SCIP_Real redcost; 3905 int i; 3906 3907 assert(col != NULL); 3908 assert(SCIPvarGetStatus(col->var) == SCIP_VARSTATUS_COLUMN); 3909 assert(SCIPvarGetCol(col->var) == col); 3910 3911 redcost = col->obj; 3912 for( i = 0; i < col->nlprows; ++i ) 3913 { 3914 row = col->rows[i]; 3915 assert(row != NULL); 3916 assert(row->dualsol != SCIP_INVALID); /*lint !e777*/ 3917 assert(row->lppos >= 0); 3918 assert(col->linkpos[i] >= 0); 3919 redcost -= col->vals[i] * row->dualsol; 3920 } 3921 3922 if( col->nunlinked > 0 ) 3923 { 3924 for( i = col->nlprows; i < col->len; ++i ) 3925 { 3926 row = col->rows[i]; 3927 assert(row != NULL); 3928 assert(row->lppos >= 0 || row->dualsol == 0.0); 3929 assert(row->lppos == -1 || col->linkpos[i] == -1); 3930 if( row->lppos >= 0 ) 3931 redcost -= col->vals[i] * row->dualsol; 3932 } 3933 } 3934 #ifndef NDEBUG 3935 else 3936 { 3937 for( i = col->nlprows; i < col->len; ++i ) 3938 { 3939 row = col->rows[i]; 3940 assert(row != NULL); 3941 assert(row->dualsol == 0.0); 3942 assert(row->lppos == -1); 3943 assert(col->linkpos[i] >= 0); 3944 } 3945 } 3946 #endif 3947 3948 return redcost; 3949 } 3950 3951 /** gets the reduced costs of a column in last LP or after recalculation */ 3952 SCIP_Real SCIPcolGetRedcost( 3953 SCIP_COL* col, /**< LP column */ 3954 SCIP_STAT* stat, /**< problem statistics */ 3955 SCIP_LP* lp /**< current LP data */ 3956 ) 3957 { 3958 assert(col != NULL); 3959 assert(stat != NULL); 3960 assert(lp != NULL); 3961 assert(col->validredcostlp <= stat->lpcount); 3962 assert(lp->validsollp == stat->lpcount); 3963 3964 if( col->validredcostlp < stat->lpcount ) 3965 { 3966 col->redcost = colCalcInternalRedcost(col); 3967 col->validredcostlp = stat->lpcount; 3968 } 3969 assert(col->validredcostlp == stat->lpcount); 3970 assert(col->redcost != SCIP_INVALID); /*lint !e777*/ 3971 3972 return col->redcost; 3973 } 3974 3975 /** gets the feasibility of (the dual row of) a column in last LP or after recalculation */ 3976 SCIP_Real SCIPcolGetFeasibility( 3977 SCIP_COL* col, /**< LP column */ 3978 SCIP_SET* set, /**< global SCIP settings */ 3979 SCIP_STAT* stat, /**< problem statistics */ 3980 SCIP_LP* lp /**< current LP data */ 3981 ) 3982 { 3983 assert(col != NULL); 3984 assert(set != NULL); 3985 assert(stat != NULL); 3986 assert(lp != NULL); 3987 assert(lp->validsollp == stat->lpcount); 3988 3989 /* A column's reduced cost is defined as 3990 * redcost = obj - activity, activity = y^T * col. (activity = obj - redcost) 3991 * The activity is equal to the activity of the corresponding row in the dual LP. 3992 * The column's feasibility is the feasibility of the corresponding row in the dual LP. 3993 * The sides of the dual row depend on the bounds of the column: 3994 * - lb == ub : dual row is a free row with infinite sides 3995 * - 0 <= lb < ub: activity <= obj => 0 <= redcost 3996 * - lb < 0 < ub: obj <= activity <= obj => 0 <= redcost <= 0 3997 * - lb < ub <= 0: obj <= activity => redcost <= 0 3998 */ 3999 if( SCIPsetIsEQ(set, col->lb, col->ub) ) 4000 { 4001 /* dual row is free */ 4002 return SCIPsetInfinity(set); 4003 } 4004 else 4005 { 4006 SCIP_Real redcost; 4007 4008 /* calculate reduced costs */ 4009 redcost = SCIPcolGetRedcost(col, stat, lp); 4010 4011 if( !SCIPsetIsNegative(set, col->lb) ) 4012 { 4013 /* dual row is activity <= obj <=> redcost >= 0 */ 4014 return redcost; 4015 } 4016 else if( SCIPsetIsPositive(set, col->ub) ) 4017 { 4018 /* dual row is activity == obj <=> redcost == 0 */ 4019 return -REALABS(redcost); 4020 } 4021 else 4022 { 4023 /* dual row is activity >= obj <=> redcost <= 0 */ 4024 return -redcost; 4025 } 4026 } 4027 } 4028 4029 /** calculates the Farkas coefficient y^T A_i of a column i using the given dual Farkas vector y */ 4030 SCIP_Real SCIPcolCalcFarkasCoef( 4031 SCIP_COL* col, /**< LP column */ 4032 SCIP_Real* dualfarkas /**< dense dual Farkas vector for current LP rows */ 4033 ) 4034 { 4035 SCIP_ROW* row; 4036 SCIP_Real farkas; 4037 int i; 4038 4039 assert(col != NULL); 4040 assert(SCIPvarGetStatus(col->var) == SCIP_VARSTATUS_COLUMN); 4041 assert(SCIPvarGetCol(col->var) == col); 4042 assert(dualfarkas != NULL); 4043 4044 farkas = 0.0; 4045 for( i = 0; i < col->nlprows; ++i ) 4046 { 4047 row = col->rows[i]; 4048 assert(row != NULL); 4049 assert(row->lppos >= 0); 4050 farkas += col->vals[i] * dualfarkas[row->lppos]; 4051 } 4052 4053 if( col->nunlinked > 0 ) 4054 { 4055 for( i = col->nlprows; i < col->len; ++i ) 4056 { 4057 row = col->rows[i]; 4058 assert(row != NULL); 4059 assert(row->lppos == -1 || col->linkpos[i] == -1); 4060 if( row->lppos >= 0 ) 4061 farkas += col->vals[i] * dualfarkas[row->lppos]; 4062 } 4063 } 4064 #ifndef NDEBUG 4065 else 4066 { 4067 for( i = col->nlprows; i < col->len; ++i ) 4068 { 4069 row = col->rows[i]; 4070 assert(row != NULL); 4071 assert(row->lppos == -1); 4072 assert(col->linkpos[i] >= 0); 4073 } 4074 } 4075 #endif 4076 4077 return farkas; 4078 } 4079 4080 /** gets the Farkas coefficient y^T A_i of a column i in last LP (which must be infeasible) */ 4081 static 4082 SCIP_Real colCalcInternalFarkasCoef( 4083 SCIP_COL* col /**< LP column */ 4084 ) 4085 { 4086 SCIP_ROW* row; 4087 SCIP_Real farkas; 4088 int i; 4089 4090 assert(col != NULL); 4091 assert(SCIPvarGetStatus(col->var) == SCIP_VARSTATUS_COLUMN); 4092 assert(SCIPvarGetCol(col->var) == col); 4093 4094 farkas = 0.0; 4095 for( i = 0; i < col->nlprows; ++i ) 4096 { 4097 row = col->rows[i]; 4098 assert(row != NULL); 4099 assert(row->dualfarkas != SCIP_INVALID); /*lint !e777*/ 4100 assert(row->lppos >= 0); 4101 assert(col->linkpos[i] >= 0); 4102 farkas += col->vals[i] * row->dualfarkas; 4103 } 4104 4105 if( col->nunlinked > 0 ) 4106 { 4107 for( i = col->nlprows; i < col->len; ++i ) 4108 { 4109 row = col->rows[i]; 4110 assert(row != NULL); 4111 assert(row->lppos >= 0 || row->dualfarkas == 0.0); 4112 assert(row->lppos == -1 || col->linkpos[i] == -1); 4113 if( row->lppos >= 0 ) 4114 farkas += col->vals[i] * row->dualfarkas; 4115 } 4116 } 4117 #ifndef NDEBUG 4118 else 4119 { 4120 for( i = col->nlprows; i < col->len; ++i ) 4121 { 4122 row = col->rows[i]; 4123 assert(row != NULL); 4124 assert(row->dualfarkas == 0.0); 4125 assert(row->lppos == -1); 4126 assert(col->linkpos[i] >= 0); 4127 } 4128 } 4129 #endif 4130 4131 return farkas; 4132 } 4133 4134 /** gets the Farkas coefficient of a column in last LP (which must be infeasible) */ 4135 SCIP_Real SCIPcolGetFarkasCoef( 4136 SCIP_COL* col, /**< LP column */ 4137 SCIP_STAT* stat, /**< problem statistics */ 4138 SCIP_LP* lp /**< current LP data */ 4139 ) 4140 { 4141 assert(col != NULL); 4142 assert(stat != NULL); 4143 assert(lp != NULL); 4144 assert(col->validfarkaslp <= stat->lpcount); 4145 assert(lp->validfarkaslp == stat->lpcount); 4146 4147 if( col->validfarkaslp < stat->lpcount ) 4148 { 4149 col->farkascoef = colCalcInternalFarkasCoef(col); 4150 col->validfarkaslp = stat->lpcount; 4151 } 4152 assert(col->validfarkaslp == stat->lpcount); 4153 assert(col->farkascoef != SCIP_INVALID); /*lint !e777*/ 4154 4155 return col->farkascoef; 4156 } 4157 4158 /** gets the Farkas value of a column in last LP (which must be infeasible), i.e. the Farkas coefficient y^T A_i times 4159 * the best bound for this coefficient, i.e. max{y^T A_i x_i | lb <= x_i <= ub} 4160 */ 4161 SCIP_Real SCIPcolGetFarkasValue( 4162 SCIP_COL* col, /**< LP column */ 4163 SCIP_STAT* stat, /**< problem statistics */ 4164 SCIP_LP* lp /**< current LP data */ 4165 ) 4166 { 4167 SCIP_Real farkascoef; 4168 4169 assert(col != NULL); 4170 4171 farkascoef = SCIPcolGetFarkasCoef(col, stat, lp); 4172 4173 if( farkascoef > 0.0 ) 4174 return col->ub * farkascoef; 4175 else 4176 return col->lb * farkascoef; 4177 } 4178 4179 /** start strong branching - call before any strong branching */ 4180 SCIP_RETCODE SCIPlpStartStrongbranch( 4181 SCIP_LP* lp /**< LP data */ 4182 ) 4183 { 4184 assert(lp != NULL); 4185 assert(!lp->strongbranching); 4186 4187 lp->strongbranching = TRUE; 4188 SCIPdebugMessage("starting strong branching ...\n"); 4189 SCIP_CALL( SCIPlpiStartStrongbranch(lp->lpi) ); 4190 4191 return SCIP_OKAY; 4192 } 4193 4194 /** end strong branching - call after any strong branching */ 4195 SCIP_RETCODE SCIPlpEndStrongbranch( 4196 SCIP_LP* lp /**< LP data */ 4197 ) 4198 { 4199 assert(lp != NULL); 4200 assert(lp->strongbranching); 4201 4202 lp->strongbranching = FALSE; 4203 SCIPdebugMessage("ending strong branching ...\n"); 4204 SCIP_CALL( SCIPlpiEndStrongbranch(lp->lpi) ); 4205 4206 return SCIP_OKAY; 4207 } 4208 4209 /** sets strong branching information for a column variable */ 4210 void SCIPcolSetStrongbranchData( 4211 SCIP_COL* col, /**< LP column */ 4212 SCIP_SET* set, /**< global SCIP settings */ 4213 SCIP_STAT* stat, /**< dynamic problem statistics */ 4214 SCIP_LP* lp, /**< LP data */ 4215 SCIP_Real lpobjval, /**< objective value of the current LP */ 4216 SCIP_Real primsol, /**< primal solution value of the column in the current LP */ 4217 SCIP_Real sbdown, /**< dual bound after branching column down */ 4218 SCIP_Real sbup, /**< dual bound after branching column up */ 4219 SCIP_Bool sbdownvalid, /**< is the returned down value a valid dual bound? */ 4220 SCIP_Bool sbupvalid, /**< is the returned up value a valid dual bound? */ 4221 SCIP_Longint iter, /**< total number of strong branching iterations */ 4222 int itlim /**< iteration limit applied to the strong branching call */ 4223 ) 4224 { 4225 assert(col != NULL); 4226 assert(col->var != NULL); 4227 assert(SCIPcolIsIntegral(col)); 4228 assert(SCIPvarIsIntegral(col->var)); 4229 assert(SCIPvarGetStatus(col->var) == SCIP_VARSTATUS_COLUMN); 4230 assert(SCIPvarGetCol(col->var) == col); 4231 assert(col->lpipos >= 0); 4232 assert(col->lppos >= 0); 4233 assert(set != NULL); 4234 assert(stat != NULL); 4235 assert(lp != NULL); 4236 assert(lp->strongbranchprobing); 4237 assert(col->lppos < lp->ncols); 4238 assert(lp->cols[col->lppos] == col); 4239 assert(itlim >= 1); 4240 4241 col->sblpobjval = lpobjval; 4242 col->sbsolval = primsol; 4243 col->validsblp = stat->nlps; 4244 col->sbnode = stat->nnodes; 4245 4246 col->sbitlim = itlim; 4247 col->nsbcalls++; 4248 4249 col->sbdown = MIN(sbdown, lp->cutoffbound); 4250 col->sbup = MIN(sbup, lp->cutoffbound); 4251 col->sbdownvalid = sbdownvalid; 4252 col->sbupvalid = sbupvalid; 4253 4254 SCIPstatIncrement(stat, set, nstrongbranchs); 4255 SCIPstatAdd(stat, set, nsblpiterations, iter); 4256 if( stat->nnodes == 1 ) 4257 { 4258 SCIPstatIncrement(stat, set, nrootstrongbranchs); 4259 SCIPstatAdd(stat, set, nrootsblpiterations, iter); 4260 } 4261 } 4262 4263 /** invalidates strong branching information for a column variable */ 4264 void SCIPcolInvalidateStrongbranchData( 4265 SCIP_COL* col, /**< LP column */ 4266 SCIP_SET* set, /**< global SCIP settings */ 4267 SCIP_STAT* stat, /**< dynamic problem statistics */ 4268 SCIP_LP* lp /**< LP data */ 4269 ) 4270 { 4271 assert(col != NULL); 4272 assert(col->var != NULL); 4273 assert(SCIPcolIsIntegral(col)); 4274 assert(SCIPvarIsIntegral(col->var)); 4275 assert(SCIPvarGetStatus(col->var) == SCIP_VARSTATUS_COLUMN); 4276 assert(SCIPvarGetCol(col->var) == col); 4277 assert(col->lpipos >= 0); 4278 assert(col->lppos >= 0); 4279 assert(set != NULL); 4280 assert(stat != NULL); 4281 assert(lp != NULL); 4282 assert(lp->strongbranchprobing); 4283 assert(col->lppos < lp->ncols); 4284 assert(lp->cols[col->lppos] == col); 4285 4286 col->sbdown = SCIP_INVALID; 4287 col->sbup = SCIP_INVALID; 4288 col->sbdownvalid = FALSE; 4289 col->sbupvalid = FALSE; 4290 col->validsblp = -1; 4291 col->sbsolval = SCIP_INVALID; 4292 col->sblpobjval = SCIP_INVALID; 4293 col->sbnode = -1; 4294 col->sbitlim = -1; 4295 } 4296 4297 4298 /** gets strong branching information on a column variable */ 4299 SCIP_RETCODE SCIPcolGetStrongbranch( 4300 SCIP_COL* col, /**< LP column */ 4301 SCIP_Bool integral, /**< should integral strong branching be performed? */ 4302 SCIP_SET* set, /**< global SCIP settings */ 4303 SCIP_STAT* stat, /**< dynamic problem statistics */ 4304 SCIP_PROB* prob, /**< problem data */ 4305 SCIP_LP* lp, /**< LP data */ 4306 int itlim, /**< iteration limit for strong branchings */ 4307 SCIP_Bool updatecol, /**< should col be updated, or should it stay in its current state ? */ 4308 SCIP_Bool updatestat, /**< should stat be updated, or should it stay in its current state ? */ 4309 SCIP_Real* down, /**< stores dual bound after branching column down */ 4310 SCIP_Real* up, /**< stores dual bound after branching column up */ 4311 SCIP_Bool* downvalid, /**< stores whether the returned down value is a valid dual bound, or NULL; 4312 * otherwise, it can only be used as an estimate value */ 4313 SCIP_Bool* upvalid, /**< stores whether the returned up value is a valid dual bound, or NULL; 4314 * otherwise, it can only be used as an estimate value */ 4315 SCIP_Bool* lperror /**< pointer to store whether an unresolved LP error occurred */ 4316 ) 4317 { 4318 SCIP_Real sbdown; 4319 SCIP_Real sbup; 4320 SCIP_Bool sbdownvalid; 4321 SCIP_Bool sbupvalid; 4322 SCIP_Longint validsblp; 4323 SCIP_Real sbsolval; 4324 SCIP_Real sblpobjval; 4325 SCIP_Longint sbnode; 4326 int sbitlim; 4327 int nsbcalls; 4328 4329 assert(col != NULL); 4330 assert(col->var != NULL); 4331 assert(SCIPcolIsIntegral(col)); 4332 assert(SCIPvarIsIntegral(col->var)); 4333 assert(SCIPvarGetStatus(col->var) == SCIP_VARSTATUS_COLUMN); 4334 assert(SCIPvarGetCol(col->var) == col); 4335 assert(col->primsol != SCIP_INVALID); /*lint !e777*/ 4336 assert(col->lpipos >= 0); 4337 assert(col->lppos >= 0); 4338 assert(set != NULL); 4339 assert(stat != NULL); 4340 assert(lp != NULL); 4341 assert(lp->flushed); 4342 assert(lp->solved); 4343 assert(lp->strongbranching); 4344 assert(lp->lpsolstat == SCIP_LPSOLSTAT_OPTIMAL); 4345 assert(lp->validsollp == stat->lpcount); 4346 assert(col->lppos < lp->ncols); 4347 assert(lp->cols[col->lppos] == col); 4348 assert(itlim >= 1); 4349 /* assert(down != NULL); 4350 * assert(up != NULL); temporary hack for cloud branching 4351 */ 4352 assert(lperror != NULL); 4353 4354 *lperror = FALSE; 4355 4356 sbdown = col->sbdown; 4357 sbup = col->sbup; 4358 sbdownvalid = col->sbdownvalid; 4359 sbupvalid = col->sbupvalid; 4360 sbitlim = col->sbitlim; 4361 nsbcalls = col->nsbcalls; 4362 4363 validsblp = stat->nlps; 4364 sbsolval = col->primsol; 4365 sblpobjval = SCIPlpGetObjval(lp, set, prob); 4366 sbnode = stat->nnodes; 4367 assert(integral || !SCIPsetIsFeasIntegral(set, col->primsol)); 4368 4369 /* if a loose variables has an infinite best bound, the LP bound is -infinity and no gain can be achieved */ 4370 if( lp->looseobjvalinf > 0 ) 4371 { 4372 sbdown = -SCIPsetInfinity(set); 4373 sbup = -SCIPsetInfinity(set); 4374 sbdownvalid = FALSE; 4375 sbupvalid = FALSE; 4376 } 4377 else 4378 { 4379 SCIP_RETCODE retcode; 4380 int iter; 4381 4382 SCIPsetDebugMsg(set, "performing strong branching on variable <%s>(%g) with %d iterations\n", 4383 SCIPvarGetName(col->var), col->primsol, itlim); 4384 4385 /* start timing */ 4386 SCIPclockStart(stat->strongbranchtime, set); 4387 4388 /* call LPI strong branching */ 4389 sbitlim = itlim; 4390 nsbcalls++; 4391 4392 sbdown = lp->lpobjval; 4393 sbup = lp->lpobjval; 4394 4395 if( integral ) 4396 retcode = SCIPlpiStrongbranchInt(lp->lpi, col->lpipos, col->primsol, itlim, down == NULL ? NULL : &sbdown, up == NULL ? NULL : &sbup, &sbdownvalid, &sbupvalid, &iter); 4397 else 4398 { 4399 assert( ! SCIPsetIsIntegral(set, col->primsol) ); 4400 retcode = SCIPlpiStrongbranchFrac(lp->lpi, col->lpipos, col->primsol, itlim, down == NULL ? NULL : &sbdown, up == NULL ? NULL : &sbup, &sbdownvalid, &sbupvalid, &iter); 4401 } 4402 4403 /* check return code for errors */ 4404 if( retcode == SCIP_LPERROR ) 4405 { 4406 *lperror = TRUE; 4407 sbdown = SCIP_INVALID; 4408 sbup = SCIP_INVALID; 4409 sbdownvalid = FALSE; 4410 sbupvalid = FALSE; 4411 validsblp = -1; 4412 sbsolval = SCIP_INVALID; 4413 sblpobjval = SCIP_INVALID; 4414 sbnode = -1; 4415 } 4416 else 4417 { 4418 SCIP_Real looseobjval; 4419 4420 *lperror = FALSE; 4421 SCIP_CALL( retcode ); 4422 4423 looseobjval = getFiniteLooseObjval(lp, set, prob); 4424 sbdown = MIN(sbdown + looseobjval, lp->cutoffbound); 4425 sbup = MIN(sbup + looseobjval, lp->cutoffbound); 4426 4427 /* update strong branching statistics */ 4428 if( updatestat ) 4429 { 4430 if( iter == -1 ) 4431 { 4432 /* calculate average iteration number */ 4433 iter = stat->ndualresolvelps > 0 ? (int)(2*stat->ndualresolvelpiterations / stat->ndualresolvelps) 4434 : stat->nduallps > 0 ? (int)((stat->nduallpiterations / stat->nduallps) / 5) 4435 : stat->nprimalresolvelps > 0 ? (int)(2*stat->nprimalresolvelpiterations / stat->nprimalresolvelps) 4436 : stat->nprimallps > 0 ? (int)((stat->nprimallpiterations / stat->nprimallps) / 5) 4437 : 0; 4438 if( iter/2 >= itlim ) 4439 iter = 2*itlim; 4440 } 4441 SCIPstatIncrement(stat, set, nstrongbranchs); 4442 SCIPstatAdd(stat, set, nsblpiterations, iter); 4443 if( stat->nnodes == 1 ) 4444 { 4445 SCIPstatIncrement(stat, set, nrootstrongbranchs); 4446 SCIPstatAdd(stat, set, nrootsblpiterations, iter); 4447 } 4448 } 4449 } 4450 4451 /* stop timing */ 4452 SCIPclockStop(stat->strongbranchtime, set); 4453 } 4454 assert(*lperror || sbdown != SCIP_INVALID); /*lint !e777*/ 4455 assert(*lperror || sbup != SCIP_INVALID); /*lint !e777*/ 4456 4457 if( down != NULL) 4458 *down = sbdown; 4459 if( up != NULL ) 4460 *up = sbup; 4461 if( downvalid != NULL ) 4462 *downvalid = sbdownvalid; 4463 if( upvalid != NULL ) 4464 *upvalid = sbupvalid; 4465 4466 if( updatecol ) 4467 { 4468 col->sbdown = sbdown; 4469 col->sbup = sbup; 4470 col->sbdownvalid = sbdownvalid; 4471 col->sbupvalid = sbupvalid; 4472 col->validsblp = validsblp; 4473 col->sbsolval = sbsolval; 4474 col->sblpobjval = sblpobjval; 4475 col->sbnode = sbnode; 4476 col->sbitlim = sbitlim; 4477 col->nsbcalls = nsbcalls; 4478 } 4479 4480 return SCIP_OKAY; 4481 } 4482 4483 /** gets strong branching information on column variables */ 4484 SCIP_RETCODE SCIPcolGetStrongbranches( 4485 SCIP_COL** cols, /**< LP columns */ 4486 int ncols, /**< number of columns */ 4487 SCIP_Bool integral, /**< should integral strong branching be performed? */ 4488 SCIP_SET* set, /**< global SCIP settings */ 4489 SCIP_STAT* stat, /**< dynamic problem statistics */ 4490 SCIP_PROB* prob, /**< problem data */ 4491 SCIP_LP* lp, /**< LP data */ 4492 int itlim, /**< iteration limit for strong branchings */ 4493 SCIP_Real* down, /**< stores dual bounds after branching columns down */ 4494 SCIP_Real* up, /**< stores dual bounds after branching columns up */ 4495 SCIP_Bool* downvalid, /**< stores whether the returned down values are valid dual bounds, or NULL; 4496 * otherwise, they can only be used as an estimate value */ 4497 SCIP_Bool* upvalid, /**< stores whether the returned up values are valid dual bounds, or NULL; 4498 * otherwise, they can only be used as an estimate value */ 4499 SCIP_Bool* lperror /**< pointer to store whether an unresolved LP error occurred */ 4500 ) 4501 { 4502 SCIP_RETCODE retcode; 4503 SCIP_Real* sbdown; 4504 SCIP_Real* sbup; 4505 SCIP_Bool* sbdownvalid; 4506 SCIP_Bool* sbupvalid; 4507 SCIP_Real* primsols; 4508 SCIP_COL** subcols; 4509 int* lpipos; 4510 int* subidx; 4511 int nsubcols; 4512 int iter; 4513 int j; 4514 4515 assert(cols != NULL); 4516 assert(set != NULL); 4517 assert(stat != NULL); 4518 assert(lp != NULL); 4519 assert(lp->flushed); 4520 assert(lp->solved); 4521 assert(lp->lpsolstat == SCIP_LPSOLSTAT_OPTIMAL); 4522 assert(lp->validsollp == stat->lpcount); 4523 assert(itlim >= 1); 4524 assert(down != NULL); 4525 assert(up != NULL); 4526 assert(lperror != NULL); 4527 4528 *lperror = FALSE; 4529 4530 if ( ncols <= 0 ) 4531 return SCIP_OKAY; 4532 4533 /* start timing */ 4534 SCIPclockStart(stat->strongbranchtime, set); 4535 4536 /* initialize storage */ 4537 SCIP_CALL( SCIPsetAllocBufferArray(set, &subcols, ncols) ); 4538 SCIP_CALL( SCIPsetAllocBufferArray(set, &subidx, ncols) ); 4539 SCIP_CALL( SCIPsetAllocBufferArray(set, &lpipos, ncols) ); 4540 SCIP_CALL( SCIPsetAllocBufferArray(set, &primsols, ncols) ); 4541 SCIP_CALL( SCIPsetAllocBufferArray(set, &sbdown, ncols) ); 4542 SCIP_CALL( SCIPsetAllocBufferArray(set, &sbup, ncols) ); 4543 SCIP_CALL( SCIPsetAllocBufferArray(set, &sbdownvalid, ncols) ); 4544 SCIP_CALL( SCIPsetAllocBufferArray(set, &sbupvalid, ncols) ); 4545 4546 nsubcols = 0; 4547 for( j = 0; j < ncols; ++j ) 4548 { 4549 SCIP_COL* col; 4550 col = cols[j]; 4551 4552 assert(col->lppos < lp->ncols); 4553 assert(lp->cols[col->lppos] == col); 4554 assert(SCIPcolIsIntegral(col)); 4555 assert(SCIPvarIsIntegral(col->var)); 4556 assert(SCIPvarGetStatus(col->var) == SCIP_VARSTATUS_COLUMN); 4557 assert(SCIPvarGetCol(col->var) == col); 4558 assert(col->primsol != SCIP_INVALID); /*lint !e777*/ 4559 assert(col->lpipos >= 0); 4560 assert(col->lppos >= 0); 4561 4562 col->validsblp = stat->nlps; 4563 col->sbsolval = col->primsol; 4564 col->sblpobjval = SCIPlpGetObjval(lp, set, prob); 4565 col->sbnode = stat->nnodes; 4566 assert(!SCIPsetIsFeasIntegral(set, col->primsol)); 4567 4568 /* if a loose variables has an infinite best bound, the LP bound is -infinity and no gain can be achieved */ 4569 if( lp->looseobjvalinf > 0 ) 4570 { 4571 /* directly set up column and result vectors*/ 4572 col->sbdown = -SCIPsetInfinity(set); 4573 col->sbup = -SCIPsetInfinity(set); 4574 col->sbdownvalid = FALSE; 4575 col->sbupvalid = FALSE; 4576 down[j] = col->sbdown; 4577 up[j] = col->sbup; 4578 if( downvalid != NULL ) 4579 downvalid[j] = col->sbdownvalid; 4580 if( upvalid != NULL ) 4581 upvalid[j] = col->sbupvalid; 4582 } 4583 else 4584 { 4585 col->sbitlim = itlim; 4586 col->nsbcalls++; 4587 4588 lpipos[nsubcols] = col->lpipos; 4589 primsols[nsubcols] = col->primsol; 4590 assert( integral || ! SCIPsetIsFeasIntegral(set, col->primsol) ); 4591 subidx[nsubcols] = j; 4592 subcols[nsubcols++] = col; 4593 } 4594 } 4595 4596 SCIPsetDebugMsg(set, "performing strong branching on %d variables with %d iterations\n", ncols, itlim); 4597 4598 /* call LPI strong branching */ 4599 if ( integral ) 4600 retcode = SCIPlpiStrongbranchesInt(lp->lpi, lpipos, nsubcols, primsols, itlim, sbdown, sbup, sbdownvalid, sbupvalid, &iter); 4601 else 4602 retcode = SCIPlpiStrongbranchesFrac(lp->lpi, lpipos, nsubcols, primsols, itlim, sbdown, sbup, sbdownvalid, sbupvalid, &iter); 4603 4604 /* check return code for errors */ 4605 if( retcode == SCIP_LPERROR ) 4606 { 4607 *lperror = TRUE; 4608 4609 for( j = 0; j < nsubcols; ++j ) 4610 { 4611 SCIP_COL* col; 4612 int idx; 4613 4614 col = subcols[j]; 4615 idx = subidx[j]; 4616 4617 col->sbdown = SCIP_INVALID; 4618 col->sbup = SCIP_INVALID; 4619 col->sbdownvalid = FALSE; 4620 col->sbupvalid = FALSE; 4621 col->validsblp = -1; 4622 col->sbsolval = SCIP_INVALID; 4623 col->sblpobjval = SCIP_INVALID; 4624 col->sbnode = -1; 4625 4626 down[idx] = col->sbdown; 4627 up[idx] = col->sbup; 4628 if( downvalid != NULL ) 4629 downvalid[idx] = col->sbdownvalid; 4630 if( upvalid != NULL ) 4631 upvalid[idx] = col->sbupvalid; 4632 } 4633 } 4634 else 4635 { 4636 SCIP_Real looseobjval; 4637 4638 *lperror = FALSE; 4639 SCIP_CALL( retcode ); 4640 4641 looseobjval = getFiniteLooseObjval(lp, set, prob); 4642 4643 for( j = 0; j < nsubcols; ++j ) 4644 { 4645 SCIP_COL* col; 4646 int idx; 4647 4648 col = subcols[j]; 4649 idx = subidx[j]; 4650 4651 assert( col->sbdown != SCIP_INVALID); /*lint !e777*/ 4652 assert( col->sbup != SCIP_INVALID); /*lint !e777*/ 4653 4654 col->sbdown = MIN(sbdown[j] + looseobjval, lp->cutoffbound); 4655 col->sbup = MIN(sbup[j] + looseobjval, lp->cutoffbound); 4656 col->sbdownvalid = sbdownvalid[j]; 4657 col->sbupvalid = sbupvalid[j]; 4658 4659 down[idx] = col->sbdown; 4660 up[idx] = col->sbup; 4661 if( downvalid != NULL ) 4662 downvalid[idx] = col->sbdownvalid; 4663 if( upvalid != NULL ) 4664 upvalid[idx] = col->sbupvalid; 4665 } 4666 4667 /* update strong branching statistics */ 4668 if( iter == -1 ) 4669 { 4670 /* calculate average iteration number */ 4671 iter = stat->ndualresolvelps > 0 ? (int)(2*stat->ndualresolvelpiterations / stat->ndualresolvelps) 4672 : stat->nduallps > 0 ? (int)((stat->nduallpiterations / stat->nduallps) / 5) 4673 : stat->nprimalresolvelps > 0 ? (int)(2*stat->nprimalresolvelpiterations / stat->nprimalresolvelps) 4674 : stat->nprimallps > 0 ? (int)((stat->nprimallpiterations / stat->nprimallps) / 5) 4675 : 0; 4676 if( iter/2 >= itlim ) 4677 iter = 2*itlim; 4678 } 4679 SCIPstatAdd(stat, set, nstrongbranchs, ncols); 4680 SCIPstatAdd(stat, set, nsblpiterations, iter); 4681 if( stat->nnodes == 1 ) 4682 { 4683 SCIPstatAdd(stat, set, nrootstrongbranchs, ncols); 4684 SCIPstatAdd(stat, set, nrootsblpiterations, iter); 4685 } 4686 } 4687 4688 SCIPsetFreeBufferArray(set, &sbupvalid); 4689 SCIPsetFreeBufferArray(set, &sbdownvalid); 4690 SCIPsetFreeBufferArray(set, &sbup); 4691 SCIPsetFreeBufferArray(set, &sbdown); 4692 SCIPsetFreeBufferArray(set, &primsols); 4693 SCIPsetFreeBufferArray(set, &lpipos); 4694 SCIPsetFreeBufferArray(set, &subidx); 4695 SCIPsetFreeBufferArray(set, &subcols); 4696 4697 /* stop timing */ 4698 SCIPclockStop(stat->strongbranchtime, set); 4699 4700 return SCIP_OKAY; 4701 } 4702 4703 /** gets last strong branching information available for a column variable; 4704 * returns values of SCIP_INVALID, if strong branching was not yet called on the given column; 4705 * keep in mind, that the returned old values may have nothing to do with the current LP solution 4706 */ 4707 void SCIPcolGetStrongbranchLast( 4708 SCIP_COL* col, /**< LP column */ 4709 SCIP_Real* down, /**< stores dual bound after branching column down, or NULL */ 4710 SCIP_Real* up, /**< stores dual bound after branching column up, or NULL */ 4711 SCIP_Bool* downvalid, /**< stores whether the returned down value is a valid dual bound, or NULL; 4712 * otherwise, it can only be used as an estimate value */ 4713 SCIP_Bool* upvalid, /**< stores whether the returned up value is a valid dual bound, or NULL; 4714 * otherwise, it can only be used as an estimate value */ 4715 SCIP_Real* solval, /**< stores LP solution value of column at last strong branching call, or NULL */ 4716 SCIP_Real* lpobjval /**< stores LP objective value at last strong branching call, or NULL */ 4717 ) 4718 { 4719 assert(col != NULL); 4720 4721 if( down != NULL ) 4722 *down = col->sbdown; 4723 if( up != NULL ) 4724 *up = col->sbup; 4725 if( downvalid != NULL ) 4726 *downvalid = col->sbdownvalid; 4727 if( upvalid != NULL ) 4728 *upvalid = col->sbupvalid; 4729 if( solval != NULL ) 4730 *solval = col->sbsolval; 4731 if( lpobjval != NULL ) 4732 *lpobjval = col->sblpobjval; 4733 } 4734 4735 /** if strong branching was already applied on the column at the current node, returns the number of LPs solved after 4736 * the LP where the strong branching on this column was applied; 4737 * if strong branching was not yet applied on the column at the current node, returns INT_MAX 4738 */ 4739 SCIP_Longint SCIPcolGetStrongbranchLPAge( 4740 SCIP_COL* col, /**< LP column */ 4741 SCIP_STAT* stat /**< dynamic problem statistics */ 4742 ) 4743 { 4744 assert(col != NULL); 4745 assert(stat != NULL); 4746 4747 return (col->sbnode != stat->nnodes ? SCIP_LONGINT_MAX : stat->nlps - col->validsblp); 4748 } 4749 4750 /** marks a column to be not removable from the LP in the current node because it became obsolete */ 4751 void SCIPcolMarkNotRemovableLocal( 4752 SCIP_COL* col, /**< LP column */ 4753 SCIP_STAT* stat /**< problem statistics */ 4754 ) 4755 { 4756 assert(col != NULL); 4757 assert(stat != NULL); 4758 assert(stat->nnodes > 0); 4759 4760 /* lpRemoveObsoleteCols() does not remove a column if the node number stored in obsoletenode equals the current node number */ 4761 col->obsoletenode = stat->nnodes; 4762 } 4763 4764 4765 /* 4766 * Row methods 4767 */ 4768 4769 /** calculates row norms and min/maxidx from scratch, and checks for sorting */ 4770 static 4771 void rowCalcNorms( 4772 SCIP_ROW* row, /**< LP row */ 4773 SCIP_SET* set /**< global SCIP settings */ 4774 ) 4775 { 4776 int i; 4777 4778 assert(row != NULL); 4779 assert(set != NULL); 4780 4781 row->sqrnorm = 0.0; 4782 row->sumnorm = 0.0; 4783 row->objprod = 0.0; 4784 row->maxval = 0.0; 4785 row->nummaxval = 1; 4786 row->minval = SCIPsetInfinity(set); 4787 row->numminval = 1; 4788 row->minidx = INT_MAX; 4789 row->maxidx = INT_MIN; 4790 row->validminmaxidx = TRUE; 4791 row->lpcolssorted = TRUE; 4792 row->nonlpcolssorted = TRUE; 4793 4794 /* check, if row is sorted 4795 * calculate sqrnorm, sumnorm, maxval, minval, minidx, and maxidx 4796 */ 4797 for( i = 0; i < row->nlpcols; ++i ) 4798 { 4799 assert(row->cols[i] != NULL); 4800 assert(!SCIPsetIsZero(set, row->vals[i])); 4801 assert(row->cols[i]->lppos >= 0); 4802 assert(row->linkpos[i] >= 0); 4803 assert(row->cols[i]->index == row->cols_index[i]); 4804 4805 rowAddNorms(row, set, row->cols[i], row->vals[i], TRUE); 4806 if( i > 0 ) 4807 { 4808 assert(row->cols[i-1]->index == row->cols_index[i-1]); 4809 row->lpcolssorted = row->lpcolssorted && (row->cols_index[i-1] < row->cols_index[i]); 4810 } 4811 } 4812 for( i = row->nlpcols; i < row->len; ++i ) 4813 { 4814 assert(row->cols[i] != NULL); 4815 assert(!SCIPsetIsZero(set, row->vals[i])); 4816 assert(row->cols[i]->lppos == -1 || row->linkpos[i] == -1); 4817 assert(row->cols[i]->index == row->cols_index[i]); 4818 4819 rowAddNorms(row, set, row->cols[i], row->vals[i], TRUE); 4820 if( i > row->nlpcols ) 4821 { 4822 assert(row->cols[i-1]->index == row->cols_index[i-1]); 4823 row->nonlpcolssorted = row->nonlpcolssorted && (row->cols_index[i-1] < row->cols_index[i]); 4824 } 4825 } 4826 } 4827 4828 /** calculates min/maxval and min/maxidx from scratch */ 4829 static 4830 void rowCalcIdxsAndVals( 4831 SCIP_ROW* row, /**< LP row */ 4832 SCIP_SET* set /**< global SCIP settings */ 4833 ) 4834 { 4835 SCIP_COL* col; 4836 SCIP_Real absval; 4837 int i; 4838 4839 assert(row != NULL); 4840 assert(set != NULL); 4841 4842 row->maxval = 0.0; 4843 row->nummaxval = 1; 4844 row->numintcols = 0; 4845 row->minval = SCIPsetInfinity(set); 4846 row->numminval = 1; 4847 row->minidx = INT_MAX; 4848 row->maxidx = INT_MIN; 4849 row->validminmaxidx = TRUE; 4850 4851 /* calculate maxval, minval, minidx, and maxidx */ 4852 for( i = 0; i < row->len; ++i ) 4853 { 4854 col = row->cols[i]; 4855 assert(col != NULL); 4856 assert(!SCIPsetIsZero(set, row->vals[i])); 4857 4858 absval = REALABS(row->vals[i]); 4859 assert(!SCIPsetIsZero(set, absval)); 4860 4861 /* update min/maxidx */ 4862 row->minidx = MIN(row->minidx, col->index); 4863 row->maxidx = MAX(row->maxidx, col->index); 4864 row->numintcols += SCIPcolIsIntegral(col); /*lint !e713*/ 4865 4866 /* update maximal and minimal non-zero value */ 4867 if( row->nummaxval > 0 ) 4868 { 4869 if( SCIPsetIsGT(set, absval, row->maxval) ) 4870 { 4871 row->maxval = absval; 4872 row->nummaxval = 1; 4873 } 4874 else if( SCIPsetIsGE(set, absval, row->maxval) ) 4875 { 4876 /* make sure the maxval is always exactly the same */ 4877 row->maxval = MAX(absval, row->maxval); 4878 row->nummaxval++; 4879 } 4880 } 4881 if( row->numminval > 0 ) 4882 { 4883 if( SCIPsetIsLT(set, absval, row->minval) ) 4884 { 4885 row->minval = absval; 4886 row->numminval = 1; 4887 } 4888 else if( SCIPsetIsLE(set, absval, row->minval) ) 4889 { 4890 /* make sure the minval is always exactly the same */ 4891 row->minval = MIN(absval, row->minval); 4892 row->numminval++; 4893 } 4894 } 4895 } 4896 } 4897 4898 /** checks, whether the given scalar scales the given value to an integral number with error in the given bounds */ 4899 static 4900 SCIP_Bool isIntegralScalar( 4901 SCIP_Real val, /**< value that should be scaled to an integral value */ 4902 SCIP_Real scalar, /**< scalar that should be tried */ 4903 SCIP_Real mindelta, /**< minimal relative allowed difference of scaled coefficient s*c and integral i */ 4904 SCIP_Real maxdelta, /**< maximal relative allowed difference of scaled coefficient s*c and integral i */ 4905 SCIP_Real* intval /**< pointer to store the scaled integral value, or NULL */ 4906 ) 4907 { 4908 SCIP_Real sval; 4909 SCIP_Real downval; 4910 SCIP_Real upval; 4911 4912 assert(mindelta <= 0.0); 4913 assert(maxdelta >= 0.0); 4914 4915 sval = val * scalar; 4916 downval = floor(sval); 4917 upval = ceil(sval); 4918 4919 if( SCIPrelDiff(sval, downval) <= maxdelta ) 4920 { 4921 if( intval != NULL ) 4922 *intval = downval; 4923 return TRUE; 4924 } 4925 else if( SCIPrelDiff(sval, upval) >= mindelta ) 4926 { 4927 if( intval != NULL ) 4928 *intval = upval; 4929 return TRUE; 4930 } 4931 4932 return FALSE; 4933 } 4934 4935 /** scales row with given factor, and rounds coefficients to integers if close enough; 4936 * the constant is automatically moved to the sides; 4937 * if the row's activity is proven to be integral, the sides are automatically rounded to the next integer 4938 */ 4939 static 4940 SCIP_RETCODE rowScale( 4941 SCIP_ROW* row, /**< LP row */ 4942 BMS_BLKMEM* blkmem, /**< block memory */ 4943 SCIP_SET* set, /**< global SCIP settings */ 4944 SCIP_EVENTQUEUE* eventqueue, /**< event queue */ 4945 SCIP_STAT* stat, /**< problem statistics */ 4946 SCIP_LP* lp, /**< current LP data */ 4947 SCIP_Real scaleval, /**< value to scale row with */ 4948 SCIP_Bool integralcontvars, /**< should the coefficients of the continuous variables also be made integral, 4949 * if they are close to integral values? */ 4950 SCIP_Real minrounddelta, /**< minimal relative difference of scaled coefficient s*c and integral i, 4951 * upto which the integral is used instead of the scaled real coefficient */ 4952 SCIP_Real maxrounddelta /**< maximal relative difference of scaled coefficient s*c and integral i 4953 * upto which the integral is used instead of the scaled real coefficient */ 4954 ) 4955 { 4956 SCIP_COL* col; 4957 SCIP_Real val; 4958 SCIP_Real newval; 4959 SCIP_Real intval; 4960 SCIP_Real mindelta; 4961 SCIP_Real maxdelta; 4962 SCIP_Real lb; 4963 SCIP_Real ub; 4964 SCIP_Bool mindeltainf; 4965 SCIP_Bool maxdeltainf; 4966 int oldlen; 4967 int c; 4968 4969 assert(row != NULL); 4970 assert(row->len == 0 || row->cols != NULL); 4971 assert(row->len == 0 || row->vals != NULL); 4972 assert(SCIPsetIsPositive(set, scaleval)); 4973 assert(-1.0 < minrounddelta && minrounddelta <= 0.0); 4974 assert(0.0 <= maxrounddelta && maxrounddelta < 1.0); 4975 4976 SCIPsetDebugMsg(set, "scale row <%s> with %g (tolerance=[%g,%g])\n", row->name, scaleval, minrounddelta, maxrounddelta); 4977 4978 mindelta = 0.0; 4979 maxdelta = 0.0; 4980 mindeltainf = FALSE; 4981 maxdeltainf = FALSE; 4982 oldlen = row->len; 4983 4984 /* scale the row coefficients, thereby recalculating whether the row's activity is always integral; 4985 * if the row coefficients are rounded to the nearest integer value, calculate the maximal activity difference, 4986 * this rounding can lead to 4987 */ 4988 row->integral = TRUE; 4989 4990 c = 0; 4991 while( c < row->len ) 4992 { 4993 col = row->cols[c]; 4994 val = row->vals[c]; 4995 assert(!SCIPsetIsZero(set, val)); 4996 4997 /* get local or global bounds for column, depending on the local or global feasibility of the row */ 4998 if( row->local ) 4999 { 5000 lb = col->lb; 5001 ub = col->ub; 5002 } 5003 else 5004 { 5005 lb = SCIPvarGetLbGlobal(col->var); 5006 ub = SCIPvarGetUbGlobal(col->var); 5007 } 5008 5009 /* calculate scaled coefficient */ 5010 newval = val * scaleval; 5011 if( (integralcontvars || SCIPcolIsIntegral(col) || SCIPsetIsIntegral(set, newval)) 5012 && isIntegralScalar(val, scaleval, minrounddelta, maxrounddelta, &intval) ) 5013 { 5014 if( !SCIPsetIsEQ(set, intval, newval) ) 5015 { 5016 if( intval < newval ) 5017 { 5018 mindelta += (intval - newval)*ub; 5019 maxdelta += (intval - newval)*lb; 5020 mindeltainf = mindeltainf || SCIPsetIsInfinity(set, ub); 5021 maxdeltainf = maxdeltainf || SCIPsetIsInfinity(set, -lb); 5022 } 5023 else 5024 { 5025 mindelta += (intval - newval)*lb; 5026 maxdelta += (intval - newval)*ub; 5027 mindeltainf = mindeltainf || SCIPsetIsInfinity(set, -lb); 5028 maxdeltainf = maxdeltainf || SCIPsetIsInfinity(set, ub); 5029 } 5030 } 5031 newval = intval; 5032 } 5033 5034 if( !SCIPsetIsEQ(set, val, newval) ) 5035 { 5036 /* if column knows of the row, change the corresponding coefficient in the column */ 5037 if( row->linkpos[c] >= 0 ) 5038 { 5039 assert(col->rows[row->linkpos[c]] == row); 5040 assert(SCIPsetIsEQ(set, col->vals[row->linkpos[c]], row->vals[c])); 5041 SCIP_CALL( colChgCoefPos(col, set, lp, row->linkpos[c], newval) ); 5042 } 5043 5044 /* change the coefficient in the row, and update the norms and integrality status */ 5045 SCIP_CALL( rowChgCoefPos(row, blkmem, set, eventqueue, lp, c, newval) ); 5046 5047 /* current coefficient has been deleted from the row because it was almost zero */ 5048 if( oldlen != row->len ) 5049 { 5050 assert(row->len == oldlen - 1); 5051 c--; 5052 oldlen = row->len; 5053 } 5054 } 5055 else 5056 row->integral = row->integral && SCIPcolIsIntegral(col) && SCIPsetIsIntegral(set, val); 5057 5058 ++c; 5059 } 5060 5061 /* scale the row sides, and move the constant to the sides; relax the sides with accumulated delta in order 5062 * to not destroy feasibility due to rounding 5063 */ 5064 /**@todo ensure that returned cut does not have infinite lhs and rhs */ 5065 if( !SCIPsetIsInfinity(set, -row->lhs) ) 5066 { 5067 if( mindeltainf ) 5068 newval = -SCIPsetInfinity(set); 5069 else 5070 { 5071 newval = (row->lhs - row->constant) * scaleval + mindelta; 5072 if( SCIPsetIsIntegral(set, newval) || (row->integral && !row->modifiable) ) 5073 newval = SCIPsetSumCeil(set, newval); 5074 } 5075 SCIP_CALL( SCIProwChgLhs(row, blkmem, set, eventqueue, lp, newval) ); 5076 } 5077 if( !SCIPsetIsInfinity(set, row->rhs) ) 5078 { 5079 if( maxdeltainf ) 5080 newval = SCIPsetInfinity(set); 5081 else 5082 { 5083 newval = (row->rhs - row->constant) * scaleval + maxdelta; 5084 if( SCIPsetIsIntegral(set, newval) || (row->integral && !row->modifiable) ) 5085 newval = SCIPsetSumFloor(set, newval); 5086 } 5087 SCIP_CALL( SCIProwChgRhs(row, blkmem, set, eventqueue, lp, newval) ); 5088 } 5089 5090 /* clear the row constant */ 5091 SCIP_CALL( SCIProwChgConstant(row, blkmem, set, stat, eventqueue, lp, 0.0) ); 5092 5093 SCIPsetDebugMsg(set, "scaled row <%s> (integral: %u)\n", row->name, row->integral); 5094 debugRowPrint(set, row); 5095 5096 #ifdef SCIP_DEBUG 5097 /* check integrality status of row */ 5098 for( c = 0; c < row->len && SCIPcolIsIntegral(row->cols[c]) && SCIPsetIsIntegral(set, row->vals[c]); ++c ) 5099 {} 5100 assert(row->integral == (c == row->len)); 5101 #endif 5102 5103 /* invalid the activity */ 5104 row->validactivitylp = -1; 5105 5106 return SCIP_OKAY; 5107 } 5108 5109 /** creates and captures an LP row */ 5110 SCIP_RETCODE SCIProwCreate( 5111 SCIP_ROW** row, /**< pointer to LP row data */ 5112 BMS_BLKMEM* blkmem, /**< block memory */ 5113 SCIP_SET* set, /**< global SCIP settings */ 5114 SCIP_STAT* stat, /**< problem statistics */ 5115 const char* name, /**< name of row */ 5116 int len, /**< number of nonzeros in the row */ 5117 SCIP_COL** cols, /**< array with columns of row entries */ 5118 SCIP_Real* vals, /**< array with coefficients of row entries */ 5119 SCIP_Real lhs, /**< left hand side of row */ 5120 SCIP_Real rhs, /**< right hand side of row */ 5121 SCIP_ROWORIGINTYPE origintype, /**< type of origin of row */ 5122 void* origin, /**< pointer to constraint handler or separator who created the row (NULL if unkown) */ 5123 SCIP_Bool local, /**< is row only valid locally? */ 5124 SCIP_Bool modifiable, /**< is row modifiable during node processing (subject to column generation)? */ 5125 SCIP_Bool removable /**< should the row be removed from the LP due to aging or cleanup? */ 5126 ) 5127 { 5128 assert(row != NULL); 5129 assert(blkmem != NULL); 5130 assert(stat != NULL); 5131 assert(len >= 0); 5132 assert(len == 0 || (cols != NULL && vals != NULL)); 5133 /* note, that the assert tries to avoid numerical troubles in the LP solver. 5134 * in case, for example, lhs > rhs but they are equal with tolerances, one could pass lhs=rhs=lhs+rhs/2 to 5135 * SCIProwCreate() (see cons_linear.c: detectRedundantConstraints()) 5136 */ 5137 assert(lhs <= rhs); 5138 5139 SCIP_ALLOC( BMSallocBlockMemory(blkmem, row) ); 5140 5141 (*row)->integral = TRUE; 5142 if( len > 0 ) 5143 { 5144 SCIP_VAR* var; 5145 int i; 5146 5147 SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &(*row)->cols, cols, len) ); 5148 SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &(*row)->vals, vals, len) ); 5149 SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &(*row)->cols_index, len) ); 5150 SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &(*row)->linkpos, len) ); 5151 5152 for( i = 0; i < len; ++i ) 5153 { 5154 assert(cols[i] != NULL); 5155 assert(!SCIPsetIsZero(set, vals[i])); 5156 5157 var = cols[i]->var; 5158 (*row)->cols_index[i] = cols[i]->index; 5159 (*row)->linkpos[i] = -1; 5160 if( SCIPsetIsIntegral(set, (*row)->vals[i]) ) 5161 { 5162 (*row)->vals[i] = SCIPsetRound(set, (*row)->vals[i]); 5163 (*row)->integral = (*row)->integral && SCIPvarIsIntegral(var); 5164 } 5165 else 5166 { 5167 (*row)->integral = FALSE; 5168 } 5169 } 5170 } 5171 else 5172 { 5173 (*row)->cols = NULL; 5174 (*row)->cols_index = NULL; 5175 (*row)->vals = NULL; 5176 (*row)->linkpos = NULL; 5177 } 5178 5179 SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &(*row)->name, name, strlen(name)+1) ); 5180 (*row)->constant = 0.0; 5181 (*row)->lhs = lhs; 5182 (*row)->rhs = rhs; 5183 (*row)->flushedlhs = -SCIPsetInfinity(set); 5184 (*row)->flushedrhs = SCIPsetInfinity(set); 5185 (*row)->sqrnorm = 0.0; 5186 (*row)->sumnorm = 0.0; 5187 (*row)->objprod = 0.0; 5188 (*row)->maxval = 0.0; 5189 (*row)->minval = SCIPsetInfinity(set); 5190 (*row)->dualsol = 0.0; 5191 (*row)->activity = SCIP_INVALID; 5192 (*row)->dualfarkas = 0.0; 5193 (*row)->pseudoactivity = SCIP_INVALID; 5194 (*row)->minactivity = SCIP_INVALID; 5195 (*row)->maxactivity = SCIP_INVALID; 5196 (*row)->origin = origin; 5197 (*row)->eventfilter = NULL; 5198 (*row)->index = stat->nrowidx; 5199 SCIPstatIncrement(stat, set, nrowidx); 5200 (*row)->size = len; 5201 (*row)->len = len; 5202 (*row)->nlpcols = 0; 5203 (*row)->nunlinked = len; 5204 (*row)->nuses = 0; 5205 (*row)->lppos = -1; 5206 (*row)->lpipos = -1; 5207 (*row)->lpdepth = -1; 5208 (*row)->minidx = INT_MAX; 5209 (*row)->maxidx = INT_MIN; 5210 (*row)->nummaxval = 0; 5211 (*row)->numminval = 0; 5212 (*row)->numintcols = -1; 5213 (*row)->validactivitylp = -1; 5214 (*row)->validpsactivitydomchg = -1; 5215 (*row)->validactivitybdsdomchg = -1; 5216 (*row)->nlpsaftercreation = 0L; 5217 (*row)->activeinlpcounter = 0L; 5218 (*row)->age = 0; 5219 (*row)->rank = 0; 5220 (*row)->obsoletenode = -1; 5221 (*row)->fromcutpool = FALSE; 5222 (*row)->basisstatus = SCIP_BASESTAT_BASIC; /*lint !e641*/ 5223 (*row)->lpcolssorted = TRUE; 5224 (*row)->nonlpcolssorted = (len <= 1); 5225 (*row)->delaysort = FALSE; 5226 (*row)->validminmaxidx = FALSE; 5227 (*row)->lhschanged = FALSE; 5228 (*row)->rhschanged = FALSE; 5229 (*row)->coefchanged = FALSE; 5230 (*row)->local = local; 5231 (*row)->modifiable = modifiable; 5232 (*row)->nlocks = 0; 5233 (*row)->origintype = origintype; /*lint !e641*/ 5234 (*row)->removable = removable; 5235 (*row)->inglobalcutpool = FALSE; 5236 (*row)->storedsolvals = NULL; 5237 5238 /* calculate row norms and min/maxidx, and check if row is sorted */ 5239 rowCalcNorms(*row, set); 5240 5241 /* capture the row */ 5242 SCIProwCapture(*row); 5243 5244 /* create event filter */ 5245 SCIP_CALL( SCIPeventfilterCreate(&(*row)->eventfilter, blkmem) ); 5246 5247 /* capture origin constraint if available */ 5248 if( origintype == SCIP_ROWORIGINTYPE_CONS ) 5249 { 5250 SCIP_CONS* cons = (SCIP_CONS*) origin; 5251 assert(cons != NULL); 5252 SCIPconsCapture(cons); 5253 } 5254 5255 return SCIP_OKAY; 5256 } /*lint !e715*/ 5257 5258 /** frees an LP row */ 5259 SCIP_RETCODE SCIProwFree( 5260 SCIP_ROW** row, /**< pointer to LP row */ 5261 BMS_BLKMEM* blkmem, /**< block memory */ 5262 SCIP_SET* set, /**< global SCIP settings */ 5263 SCIP_LP* lp /**< current LP data */ 5264 ) 5265 { 5266 assert(blkmem != NULL); 5267 assert(row != NULL); 5268 assert(*row != NULL); 5269 assert((*row)->nuses == 0); 5270 assert((*row)->lppos == -1); 5271 assert((*row)->eventfilter != NULL); 5272 5273 /* release constraint that has been used for creating the row */ 5274 if( (SCIP_ROWORIGINTYPE) (*row)->origintype == SCIP_ROWORIGINTYPE_CONS ) 5275 { 5276 SCIP_CONS* cons = (SCIP_CONS*) (*row)->origin; 5277 assert(cons != NULL); 5278 SCIP_CALL( SCIPconsRelease(&cons, blkmem, set) ); 5279 } 5280 5281 /* remove column indices from corresponding rows */ 5282 SCIP_CALL( rowUnlink(*row, set, lp) ); 5283 5284 /* free event filter */ 5285 SCIP_CALL( SCIPeventfilterFree(&(*row)->eventfilter, blkmem, set) ); 5286 5287 BMSfreeBlockMemoryNull(blkmem, &(*row)->storedsolvals); 5288 BMSfreeBlockMemoryArray(blkmem, &(*row)->name, strlen((*row)->name)+1); 5289 BMSfreeBlockMemoryArrayNull(blkmem, &(*row)->cols, (*row)->size); 5290 BMSfreeBlockMemoryArrayNull(blkmem, &(*row)->cols_index, (*row)->size); 5291 BMSfreeBlockMemoryArrayNull(blkmem, &(*row)->vals, (*row)->size); 5292 BMSfreeBlockMemoryArrayNull(blkmem, &(*row)->linkpos, (*row)->size); 5293 BMSfreeBlockMemory(blkmem, row); 5294 5295 return SCIP_OKAY; 5296 } 5297 5298 /** output row to file stream */ 5299 void SCIProwPrint( 5300 SCIP_ROW* row, /**< LP row */ 5301 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */ 5302 FILE* file /**< output file (or NULL for standard output) */ 5303 ) 5304 { 5305 int i; 5306 5307 assert(row != NULL); 5308 5309 /* print row name */ 5310 if( row->name != NULL && row->name[0] != '\0' ) 5311 { 5312 SCIPmessageFPrintInfo(messagehdlr, file, "%s: ", row->name); 5313 } 5314 5315 /* print left hand side */ 5316 SCIPmessageFPrintInfo(messagehdlr, file, "%.15g <= ", row->lhs); 5317 5318 /* print coefficients */ 5319 if( row->len == 0 ) 5320 SCIPmessageFPrintInfo(messagehdlr, file, "0 "); 5321 for( i = 0; i < row->len; ++i ) 5322 { 5323 assert(row->cols[i] != NULL); 5324 assert(row->cols[i]->var != NULL); 5325 assert(SCIPvarGetName(row->cols[i]->var) != NULL); 5326 assert(SCIPvarGetStatus(row->cols[i]->var) == SCIP_VARSTATUS_COLUMN); 5327 SCIPmessageFPrintInfo(messagehdlr, file, "%+.15g<%s> ", row->vals[i], SCIPvarGetName(row->cols[i]->var)); 5328 } 5329 5330 /* print constant */ 5331 if( REALABS(row->constant) > SCIP_DEFAULT_EPSILON ) 5332 SCIPmessageFPrintInfo(messagehdlr, file, "%+.15g ", row->constant); 5333 5334 /* print right hand side */ 5335 SCIPmessageFPrintInfo(messagehdlr, file, "<= %.15g\n", row->rhs); 5336 } 5337 5338 /** increases usage counter of LP row */ 5339 void SCIProwCapture( 5340 SCIP_ROW* row /**< LP row */ 5341 ) 5342 { 5343 assert(row != NULL); 5344 assert(row->nuses >= 0); 5345 assert(row->nlocks <= (unsigned int)(row->nuses)); /*lint !e574*/ 5346 5347 SCIPdebugMessage("capture row <%s> with nuses=%d and nlocks=%u\n", row->name, row->nuses, row->nlocks); 5348 row->nuses++; 5349 } 5350 5351 /** decreases usage counter of LP row, and frees memory if necessary */ 5352 SCIP_RETCODE SCIProwRelease( 5353 SCIP_ROW** row, /**< pointer to LP row */ 5354 BMS_BLKMEM* blkmem, /**< block memory */ 5355 SCIP_SET* set, /**< global SCIP settings */ 5356 SCIP_LP* lp /**< current LP data */ 5357 ) 5358 { 5359 assert(blkmem != NULL); 5360 assert(row != NULL); 5361 assert(*row != NULL); 5362 assert((*row)->nuses >= 1); 5363 assert((*row)->nlocks < (unsigned int)((*row)->nuses)); /*lint !e574*/ 5364 5365 SCIPsetDebugMsg(set, "release row <%s> with nuses=%d and nlocks=%u\n", (*row)->name, (*row)->nuses, (*row)->nlocks); 5366 (*row)->nuses--; 5367 if( (*row)->nuses == 0 ) 5368 { 5369 SCIP_CALL( SCIProwFree(row, blkmem, set, lp) ); 5370 } 5371 5372 *row = NULL; 5373 5374 return SCIP_OKAY; 5375 } 5376 5377 /** locks an unmodifiable row, which forbids further changes; has no effect on modifiable rows */ 5378 void SCIProwLock( 5379 SCIP_ROW* row /**< LP row */ 5380 ) 5381 { 5382 assert(row != NULL); 5383 5384 /* check, if row is modifiable */ 5385 if( !row->modifiable ) 5386 { 5387 SCIPdebugMessage("lock row <%s> with nuses=%d and nlocks=%u\n", row->name, row->nuses, row->nlocks); 5388 row->nlocks++; 5389 } 5390 } 5391 5392 /** unlocks a lock of an unmodifiable row; a row with no sealed lock may be modified; has no effect on modifiable rows */ 5393 void SCIProwUnlock( 5394 SCIP_ROW* row /**< LP row */ 5395 ) 5396 { 5397 assert(row != NULL); 5398 5399 /* check, if row is modifiable */ 5400 if( !row->modifiable ) 5401 { 5402 SCIPdebugMessage("unlock row <%s> with nuses=%d and nlocks=%u\n", row->name, row->nuses, row->nlocks); 5403 assert(row->nlocks > 0); 5404 row->nlocks--; 5405 } 5406 } 5407 5408 /** adds a previously non existing coefficient to an LP row */ 5409 SCIP_RETCODE SCIProwAddCoef( 5410 SCIP_ROW* row, /**< LP row */ 5411 BMS_BLKMEM* blkmem, /**< block memory */ 5412 SCIP_SET* set, /**< global SCIP settings */ 5413 SCIP_EVENTQUEUE* eventqueue, /**< event queue */ 5414 SCIP_LP* lp, /**< current LP data */ 5415 SCIP_COL* col, /**< LP column */ 5416 SCIP_Real val /**< value of coefficient */ 5417 ) 5418 { 5419 assert(lp != NULL); 5420 assert(!lp->diving || row->lppos == -1); 5421 5422 SCIP_CALL( rowAddCoef(row, blkmem, set, eventqueue, lp, col, val, -1) ); 5423 5424 checkLinks(lp); 5425 5426 return SCIP_OKAY; 5427 } 5428 5429 /** deletes coefficient from row */ 5430 SCIP_RETCODE SCIProwDelCoef( 5431 SCIP_ROW* row, /**< row to be changed */ 5432 BMS_BLKMEM* blkmem, /**< block memory */ 5433 SCIP_SET* set, /**< global SCIP settings */ 5434 SCIP_EVENTQUEUE* eventqueue, /**< event queue */ 5435 SCIP_LP* lp, /**< current LP data */ 5436 SCIP_COL* col /**< coefficient to be deleted */ 5437 ) 5438 { 5439 int pos; 5440 5441 assert(row != NULL); 5442 assert(!row->delaysort); 5443 assert(lp != NULL); 5444 assert(!lp->diving || row->lppos == -1); 5445 assert(col != NULL); 5446 assert(col->var != NULL); 5447 5448 /* search the position of the column in the row's col vector */ 5449 pos = rowSearchCoef(row, col); 5450 if( pos == -1 ) 5451 { 5452 SCIPerrorMessage("coefficient for column <%s> doesn't exist in row <%s>\n", SCIPvarGetName(col->var), row->name); 5453 return SCIP_INVALIDDATA; 5454 } 5455 assert(0 <= pos && pos < row->len); 5456 assert(row->cols[pos] == col); 5457 assert(row->cols_index[pos] == col->index); 5458 5459 /* if column knows of the row, remove the row from the column's row vector */ 5460 if( row->linkpos[pos] >= 0 ) 5461 { 5462 assert(col->rows[row->linkpos[pos]] == row); 5463 assert(SCIPsetIsEQ(set, col->vals[row->linkpos[pos]], row->vals[pos])); 5464 SCIP_CALL( colDelCoefPos(col, set, lp, row->linkpos[pos]) ); 5465 } 5466 5467 /* delete the column from the row's col vector */ 5468 SCIP_CALL( rowDelCoefPos(row, blkmem, set, eventqueue, lp, pos) ); 5469 5470 checkLinks(lp); 5471 5472 return SCIP_OKAY; 5473 } 5474 5475 /** changes or adds a coefficient to an LP row */ 5476 SCIP_RETCODE SCIProwChgCoef( 5477 SCIP_ROW* row, /**< LP row */ 5478 BMS_BLKMEM* blkmem, /**< block memory */ 5479 SCIP_SET* set, /**< global SCIP settings */ 5480 SCIP_EVENTQUEUE* eventqueue, /**< event queue */ 5481 SCIP_LP* lp, /**< current LP data */ 5482 SCIP_COL* col, /**< LP column */ 5483 SCIP_Real val /**< value of coefficient */ 5484 ) 5485 { 5486 int pos; 5487 5488 assert(row != NULL); 5489 assert(!row->delaysort); 5490 assert(lp != NULL); 5491 assert(!lp->diving || row->lppos == -1); 5492 assert(col != NULL); 5493 5494 /* search the position of the column in the row's col vector */ 5495 pos = rowSearchCoef(row, col); 5496 5497 /* check, if column already exists in the row's col vector */ 5498 if( pos == -1 ) 5499 { 5500 /* add previously not existing coefficient */ 5501 SCIP_CALL( rowAddCoef(row, blkmem, set, eventqueue, lp, col, val, -1) ); 5502 } 5503 else 5504 { 5505 /* modify already existing coefficient */ 5506 assert(0 <= pos && pos < row->len); 5507 assert(row->cols[pos] == col); 5508 assert(row->cols_index[pos] == col->index); 5509 5510 /* if column knows of the row, change the corresponding coefficient in the column */ 5511 if( row->linkpos[pos] >= 0 ) 5512 { 5513 assert(col->rows[row->linkpos[pos]] == row); 5514 assert(SCIPsetIsEQ(set, col->vals[row->linkpos[pos]], row->vals[pos])); 5515 SCIP_CALL( colChgCoefPos(col, set, lp, row->linkpos[pos], val) ); 5516 } 5517 5518 /* change the coefficient in the row */ 5519 SCIP_CALL( rowChgCoefPos(row, blkmem, set, eventqueue, lp, pos, val) ); 5520 } 5521 5522 checkLinks(lp); 5523 5524 return SCIP_OKAY; 5525 } 5526 5527 /** increases value of an existing or non-existing coefficient in an LP row */ 5528 SCIP_RETCODE SCIProwIncCoef( 5529 SCIP_ROW* row, /**< LP row */ 5530 BMS_BLKMEM* blkmem, /**< block memory */ 5531 SCIP_SET* set, /**< global SCIP settings */ 5532 SCIP_EVENTQUEUE* eventqueue, /**< event queue */ 5533 SCIP_LP* lp, /**< current LP data */ 5534 SCIP_COL* col, /**< LP column */ 5535 SCIP_Real incval /**< value to add to the coefficient */ 5536 ) 5537 { 5538 int pos; 5539 5540 assert(row != NULL); 5541 assert(lp != NULL); 5542 assert(!lp->diving || row->lppos == -1); 5543 assert(col != NULL); 5544 5545 if( SCIPsetIsZero(set, incval) ) 5546 return SCIP_OKAY; 5547 5548 /* search the position of the column in the row's col vector */ 5549 pos = rowSearchCoef(row, col); 5550 5551 /* check, if column already exists in the row's col vector */ 5552 if( pos == -1 ) 5553 { 5554 /* coefficient doesn't exist, or sorting is delayed: add coefficient to the end of the row's arrays */ 5555 SCIP_CALL( rowAddCoef(row, blkmem, set, eventqueue, lp, col, incval, -1) ); 5556 } 5557 else 5558 { 5559 /* modify already existing coefficient */ 5560 assert(0 <= pos && pos < row->len); 5561 assert(row->cols[pos] == col); 5562 assert(row->cols_index[pos] == col->index); 5563 5564 /* if column knows of the row, change the corresponding coefficient in the column */ 5565 if( row->linkpos[pos] >= 0 ) 5566 { 5567 assert(col->rows[row->linkpos[pos]] == row); 5568 assert(SCIPsetIsEQ(set, col->vals[row->linkpos[pos]], row->vals[pos])); 5569 SCIP_CALL( colChgCoefPos(col, set, lp, row->linkpos[pos], row->vals[pos] + incval) ); 5570 } 5571 5572 /* change the coefficient in the row */ 5573 SCIP_CALL( rowChgCoefPos(row, blkmem, set, eventqueue, lp, pos, row->vals[pos] + incval) ); 5574 } 5575 5576 checkLinks(lp); 5577 5578 /* invalid the activity */ 5579 row->validactivitylp = -1; 5580 5581 return SCIP_OKAY; 5582 } 5583 5584 /** changes constant value of a row */ 5585 SCIP_RETCODE SCIProwChgConstant( 5586 SCIP_ROW* row, /**< LP row */ 5587 BMS_BLKMEM* blkmem, /**< block memory */ 5588 SCIP_SET* set, /**< global SCIP settings */ 5589 SCIP_STAT* stat, /**< problem statistics */ 5590 SCIP_EVENTQUEUE* eventqueue, /**< event queue */ 5591 SCIP_LP* lp, /**< current LP data */ 5592 SCIP_Real constant /**< new constant value */ 5593 ) 5594 { 5595 assert(row != NULL); 5596 assert(row->lhs <= row->rhs); 5597 assert(!SCIPsetIsInfinity(set, REALABS(constant))); 5598 assert(stat != NULL); 5599 assert(lp != NULL); 5600 assert(!lp->diving || row->lppos == -1); 5601 5602 if( !SCIPsetIsEQ(set, constant, row->constant) ) 5603 { 5604 SCIP_Real oldconstant; 5605 5606 if( row->validpsactivitydomchg == stat->domchgcount ) 5607 { 5608 assert(row->pseudoactivity != SCIP_INVALID); /*lint !e777*/ 5609 row->pseudoactivity += constant - row->constant; 5610 } 5611 if( row->validactivitybdsdomchg == stat->domchgcount ) 5612 { 5613 assert(row->minactivity != SCIP_INVALID); /*lint !e777*/ 5614 assert(row->maxactivity != SCIP_INVALID); /*lint !e777*/ 5615 row->minactivity += constant - row->constant; 5616 row->maxactivity += constant - row->constant; 5617 } 5618 5619 if( !SCIPsetIsInfinity(set, -row->lhs) ) 5620 { 5621 SCIP_CALL( rowSideChanged(row, set, lp, SCIP_SIDETYPE_LEFT) ); 5622 } 5623 if( !SCIPsetIsInfinity(set, row->rhs) ) 5624 { 5625 SCIP_CALL( rowSideChanged(row, set, lp, SCIP_SIDETYPE_RIGHT) ); 5626 } 5627 5628 oldconstant = row->constant; 5629 5630 row->constant = constant; 5631 5632 /* issue row constant changed event */ 5633 SCIP_CALL( rowEventConstantChanged(row, blkmem, set, eventqueue, oldconstant, constant) ); 5634 } 5635 5636 return SCIP_OKAY; 5637 } 5638 5639 /** add constant value to a row */ 5640 SCIP_RETCODE SCIProwAddConstant( 5641 SCIP_ROW* row, /**< LP row */ 5642 BMS_BLKMEM* blkmem, /**< block memory */ 5643 SCIP_SET* set, /**< global SCIP settings */ 5644 SCIP_STAT* stat, /**< problem statistics */ 5645 SCIP_EVENTQUEUE* eventqueue, /**< event queue */ 5646 SCIP_LP* lp, /**< current LP data */ 5647 SCIP_Real addval /**< constant value to add to the row */ 5648 ) 5649 { 5650 assert(row != NULL); 5651 assert(row->lhs <= row->rhs); 5652 assert(!SCIPsetIsInfinity(set, REALABS(addval))); 5653 assert(stat != NULL); 5654 assert(lp != NULL); 5655 assert(!lp->diving || row->lppos == -1); 5656 5657 if( !SCIPsetIsZero(set, addval) ) 5658 { 5659 SCIP_CALL( SCIProwChgConstant(row, blkmem, set, stat, eventqueue, lp, row->constant + addval) ); 5660 } 5661 5662 return SCIP_OKAY; 5663 } 5664 5665 /** changes left hand side of LP row */ 5666 SCIP_RETCODE SCIProwChgLhs( 5667 SCIP_ROW* row, /**< LP row */ 5668 BMS_BLKMEM* blkmem, /**< block memory */ 5669 SCIP_SET* set, /**< global SCIP settings */ 5670 SCIP_EVENTQUEUE* eventqueue, /**< event queue */ 5671 SCIP_LP* lp, /**< current LP data */ 5672 SCIP_Real lhs /**< new left hand side */ 5673 ) 5674 { 5675 assert(row != NULL); 5676 assert(lp != NULL); 5677 5678 if( !SCIPsetIsEQ(set, row->lhs, lhs) ) 5679 { 5680 SCIP_Real oldlhs; 5681 5682 oldlhs = row->lhs; 5683 5684 row->lhs = lhs; 5685 SCIP_CALL( rowSideChanged(row, set, lp, SCIP_SIDETYPE_LEFT) ); 5686 5687 if( !lp->diving ) 5688 { 5689 /* issue row side changed event */ 5690 SCIP_CALL( rowEventSideChanged(row, blkmem, set, eventqueue, SCIP_SIDETYPE_LEFT, oldlhs, lhs) ); 5691 } 5692 } 5693 5694 return SCIP_OKAY; 5695 } 5696 5697 /** changes right hand side of LP row */ 5698 SCIP_RETCODE SCIProwChgRhs( 5699 SCIP_ROW* row, /**< LP row */ 5700 BMS_BLKMEM* blkmem, /**< block memory */ 5701 SCIP_SET* set, /**< global SCIP settings */ 5702 SCIP_EVENTQUEUE* eventqueue, /**< event queue */ 5703 SCIP_LP* lp, /**< current LP data */ 5704 SCIP_Real rhs /**< new right hand side */ 5705 ) 5706 { 5707 assert(row != NULL); 5708 assert(lp != NULL); 5709 5710 if( !SCIPsetIsEQ(set, row->rhs, rhs) ) 5711 { 5712 SCIP_Real oldrhs; 5713 5714 oldrhs = row->rhs; 5715 5716 row->rhs = rhs; 5717 SCIP_CALL( rowSideChanged(row, set, lp, SCIP_SIDETYPE_RIGHT) ); 5718 5719 if( !lp->diving ) 5720 { 5721 /* issue row side changed event */ 5722 SCIP_CALL( rowEventSideChanged(row, blkmem, set, eventqueue, SCIP_SIDETYPE_RIGHT, oldrhs, rhs) ); 5723 } 5724 } 5725 5726 return SCIP_OKAY; 5727 } 5728 5729 /** changes the local flag of LP row */ 5730 SCIP_RETCODE SCIProwChgLocal( 5731 SCIP_ROW* row, /**< LP row */ 5732 SCIP_Bool local /**< new value for local flag */ 5733 ) 5734 { 5735 assert(row != NULL); 5736 5737 row->local = local; 5738 5739 return SCIP_OKAY; 5740 } 5741 5742 /** additional scalars that are tried in integrality scaling */ 5743 static const SCIP_Real scalars[] = {3.0, 5.0, 7.0, 9.0, 11.0, 13.0, 15.0, 17.0, 19.0}; 5744 static const int nscalars = 9; 5745 5746 /** tries to find a value, such that all row coefficients, if scaled with this value become integral */ 5747 SCIP_RETCODE SCIProwCalcIntegralScalar( 5748 SCIP_ROW* row, /**< LP row */ 5749 SCIP_SET* set, /**< global SCIP settings */ 5750 SCIP_Real mindelta, /**< minimal relative allowed difference of scaled coefficient s*c and integral i */ 5751 SCIP_Real maxdelta, /**< maximal relative allowed difference of scaled coefficient s*c and integral i */ 5752 SCIP_Longint maxdnom, /**< maximal denominator allowed in rational numbers */ 5753 SCIP_Real maxscale, /**< maximal allowed scalar */ 5754 SCIP_Bool usecontvars, /**< should the coefficients of the continuous variables also be made integral? */ 5755 SCIP_Real* intscalar, /**< pointer to store scalar that would make the coefficients integral, or NULL */ 5756 SCIP_Bool* success /**< stores whether returned value is valid */ 5757 ) 5758 { 5759 #ifndef NDEBUG 5760 SCIP_COL* col; 5761 #endif 5762 SCIP_Longint gcd; 5763 SCIP_Longint scm; 5764 SCIP_Longint nominator; 5765 SCIP_Longint denominator; 5766 SCIP_Real val; 5767 SCIP_Real absval; 5768 SCIP_Real minval; 5769 SCIP_Real scaleval; 5770 SCIP_Real twomultval; 5771 SCIP_Bool scalable; 5772 SCIP_Bool twomult; 5773 SCIP_Bool rational; 5774 int c; 5775 int s; 5776 5777 /**@todo call misc.c:SCIPcalcIntegralScalar() instead - if usecontvars == FALSE, filter the integer variables first */ 5778 assert(row != NULL); 5779 assert(row->len == 0 || row->cols != NULL); 5780 assert(row->len == 0 || row->cols_index != NULL); 5781 assert(row->len == 0 || row->vals != NULL); 5782 assert(maxdnom >= 1); 5783 assert(mindelta < 0.0); 5784 assert(maxdelta > 0.0); 5785 assert(success != NULL); 5786 5787 SCIPsetDebugMsg(set, "trying to find rational representation for row <%s> (contvars: %u)\n", SCIProwGetName(row), usecontvars); 5788 SCIPdebug( val = 0; ); /* avoid warning "val might be used uninitialized; see SCIPdebugMessage lastval=%g below */ 5789 5790 if( intscalar != NULL ) 5791 *intscalar = SCIP_INVALID; 5792 *success = FALSE; 5793 5794 /* get minimal absolute non-zero value */ 5795 minval = SCIP_REAL_MAX; 5796 for( c = 0; c < row->len; ++c ) 5797 { 5798 #ifndef NDEBUG 5799 col = row->cols[c]; 5800 assert(col != NULL); 5801 assert(col->var != NULL); 5802 assert(SCIPvarGetStatus(col->var) == SCIP_VARSTATUS_COLUMN); 5803 assert(SCIPvarGetCol(col->var) == col); 5804 #endif 5805 val = row->vals[c]; 5806 assert(!SCIPsetIsZero(set, val)); 5807 5808 if( val < mindelta || val > maxdelta ) 5809 { 5810 absval = REALABS(val); 5811 minval = MIN(minval, absval); 5812 } 5813 } 5814 if( minval == SCIP_REAL_MAX ) /*lint !e777*/ 5815 { 5816 /* all coefficients are zero (inside tolerances) */ 5817 if( intscalar != NULL ) 5818 *intscalar = 1.0; 5819 *success = TRUE; 5820 SCIPsetDebugMsg(set, " -> all values are zero (inside tolerances)\n"); 5821 5822 return SCIP_OKAY; 5823 } 5824 assert(minval > MIN(-mindelta, maxdelta)); 5825 assert(SCIPsetIsPositive(set, minval)); 5826 assert(!SCIPsetIsInfinity(set, minval)); 5827 5828 /* try, if row coefficients can be made integral by multiplying them with the reciprocal of the smallest coefficient 5829 * and a power of 2 5830 */ 5831 scaleval = 1.0/minval; 5832 scalable = (scaleval <= maxscale); 5833 for( c = 0; c < row->len && scalable; ++c ) 5834 { 5835 /* don't look at continuous variables, if we don't have to */ 5836 if( !usecontvars && !SCIPcolIsIntegral(row->cols[c]) ) 5837 continue; 5838 5839 /* check, if the coefficient can be scaled with a simple scalar */ 5840 val = row->vals[c]; 5841 absval = REALABS(val); 5842 while( scaleval <= maxscale 5843 && (absval * scaleval < 0.5 || !isIntegralScalar(val, scaleval, mindelta, maxdelta, NULL)) ) 5844 { 5845 for( s = 0; s < nscalars; ++s ) 5846 { 5847 if( isIntegralScalar(val, scaleval * scalars[s], mindelta, maxdelta, NULL) ) 5848 { 5849 scaleval *= scalars[s]; 5850 break; 5851 } 5852 } 5853 if( s >= nscalars ) 5854 scaleval *= 2.0; 5855 } 5856 scalable = (scaleval <= maxscale); 5857 SCIPsetDebugMsg(set, " -> val=%g, scaleval=%g, val*scaleval=%g, scalable=%u\n", val, scaleval, val*scaleval, scalable); 5858 } 5859 if( scalable ) 5860 { 5861 /* make row coefficients integral by dividing them by the smallest coefficient 5862 * (and multiplying them with a power of 2) 5863 */ 5864 assert(scaleval <= maxscale); 5865 if( intscalar != NULL ) 5866 *intscalar = scaleval; 5867 *success = TRUE; 5868 SCIPsetDebugMsg(set, " -> integrality can be achieved by scaling with %g (minval=%g)\n", scaleval, minval); 5869 5870 return SCIP_OKAY; 5871 } 5872 5873 /* try, if row coefficients can be made integral by multiplying them by a power of 2 */ 5874 twomultval = 1.0; 5875 twomult = (twomultval <= maxscale); 5876 for( c = 0; c < row->len && twomult; ++c ) 5877 { 5878 /* don't look at continuous variables, if we don't have to */ 5879 if( !usecontvars && !SCIPcolIsIntegral(row->cols[c]) ) 5880 continue; 5881 5882 /* check, if the coefficient can be scaled with a simple scalar */ 5883 val = row->vals[c]; 5884 absval = REALABS(val); 5885 while( twomultval <= maxscale 5886 && (absval * twomultval < 0.5 || !isIntegralScalar(val, twomultval, mindelta, maxdelta, NULL)) ) 5887 { 5888 for( s = 0; s < nscalars; ++s ) 5889 { 5890 if( isIntegralScalar(val, twomultval * scalars[s], mindelta, maxdelta, NULL) ) 5891 { 5892 twomultval *= scalars[s]; 5893 break; 5894 } 5895 } 5896 if( s >= nscalars ) 5897 twomultval *= 2.0; 5898 } 5899 twomult = (twomultval <= maxscale); 5900 SCIPsetDebugMsg(set, " -> val=%g, twomult=%g, val*twomult=%g, twomultable=%u\n", 5901 val, twomultval, val*twomultval, twomult); 5902 } 5903 if( twomult ) 5904 { 5905 /* make row coefficients integral by multiplying them with a power of 2 */ 5906 assert(twomultval <= maxscale); 5907 if( intscalar != NULL ) 5908 *intscalar = twomultval; 5909 *success = TRUE; 5910 SCIPsetDebugMsg(set, " -> integrality can be achieved by scaling with %g (power of 2)\n", twomultval); 5911 5912 return SCIP_OKAY; 5913 } 5914 5915 /* convert each coefficient into a rational number, calculate the greatest common divisor of the numerators 5916 * and the smallest common multiple of the denominators 5917 */ 5918 gcd = 1; 5919 scm = 1; 5920 rational = (maxdnom > 1); 5921 5922 /* first coefficient (to initialize gcd) */ 5923 for( c = 0; c < row->len && rational; ++c ) 5924 { 5925 if( usecontvars || SCIPcolIsIntegral(row->cols[c]) ) 5926 { 5927 val = row->vals[c]; 5928 rational = SCIPrealToRational(val, mindelta, maxdelta, maxdnom, &nominator, &denominator); 5929 if( rational && nominator != 0 ) 5930 { 5931 assert(denominator > 0); 5932 gcd = ABS(nominator); 5933 scm = denominator; 5934 rational = ((SCIP_Real)scm/(SCIP_Real)gcd <= maxscale); 5935 SCIPsetDebugMsg(set, " -> first rational: val: %g == %" SCIP_LONGINT_FORMAT "/%" SCIP_LONGINT_FORMAT ", gcd=%" SCIP_LONGINT_FORMAT ", scm=%" SCIP_LONGINT_FORMAT ", rational=%u\n", 5936 val, nominator, denominator, gcd, scm, rational); 5937 break; 5938 } 5939 } 5940 } 5941 5942 /* remaining coefficients */ 5943 for( ++c; c < row->len && rational; ++c ) 5944 { 5945 if( usecontvars || SCIPcolIsIntegral(row->cols[c]) ) 5946 { 5947 val = row->vals[c]; 5948 rational = SCIPrealToRational(val, mindelta, maxdelta, maxdnom, &nominator, &denominator); 5949 if( rational && nominator != 0 ) 5950 { 5951 assert(denominator > 0); 5952 gcd = SCIPcalcGreComDiv(gcd, ABS(nominator)); 5953 scm *= denominator / SCIPcalcGreComDiv(scm, denominator); 5954 rational = ((SCIP_Real)scm/(SCIP_Real)gcd <= maxscale); 5955 SCIPsetDebugMsg(set, " -> next rational : val: %g == %" SCIP_LONGINT_FORMAT "/%" SCIP_LONGINT_FORMAT ", gcd=%" SCIP_LONGINT_FORMAT ", scm=%" SCIP_LONGINT_FORMAT ", rational=%u\n", 5956 val, nominator, denominator, gcd, scm, rational); 5957 } 5958 } 5959 } 5960 5961 if( rational ) 5962 { 5963 /* make row coefficients integral by multiplying them with the smallest common multiple of the denominators */ 5964 assert((SCIP_Real)scm/(SCIP_Real)gcd <= maxscale); 5965 if( intscalar != NULL ) 5966 *intscalar = (SCIP_Real)scm/(SCIP_Real)gcd; 5967 *success = TRUE; 5968 SCIPsetDebugMsg(set, " -> integrality can be achieved by scaling with %g (rational:%" SCIP_LONGINT_FORMAT "/%" SCIP_LONGINT_FORMAT ")\n", 5969 (SCIP_Real)scm/(SCIP_Real)gcd, scm, gcd); 5970 } 5971 else 5972 { 5973 assert(!(*success)); 5974 SCIPsetDebugMsg(set, " -> rationalizing failed: gcd=%" SCIP_LONGINT_FORMAT ", scm=%" SCIP_LONGINT_FORMAT ", lastval=%g\n", gcd, scm, val); /*lint !e771*/ 5975 } 5976 5977 return SCIP_OKAY; 5978 } 5979 5980 /** tries to scale row, s.t. all coefficients become integral */ 5981 SCIP_RETCODE SCIProwMakeIntegral( 5982 SCIP_ROW* row, /**< LP row */ 5983 BMS_BLKMEM* blkmem, /**< block memory */ 5984 SCIP_SET* set, /**< global SCIP settings */ 5985 SCIP_EVENTQUEUE* eventqueue, /**< event queue */ 5986 SCIP_STAT* stat, /**< problem statistics */ 5987 SCIP_LP* lp, /**< current LP data */ 5988 SCIP_Real mindelta, /**< minimal relative allowed difference of scaled coefficient s*c and integral i */ 5989 SCIP_Real maxdelta, /**< maximal relative allowed difference of scaled coefficient s*c and integral i */ 5990 SCIP_Longint maxdnom, /**< maximal denominator allowed in rational numbers */ 5991 SCIP_Real maxscale, /**< maximal value to scale row with */ 5992 SCIP_Bool usecontvars, /**< should the coefficients of the continuous variables also be made integral? */ 5993 SCIP_Bool* success /**< stores whether row could be made rational */ 5994 ) 5995 { 5996 SCIP_Real intscalar; 5997 5998 assert(success != NULL); 5999 6000 /* calculate scalar to make coefficients integral */ 6001 SCIP_CALL( SCIProwCalcIntegralScalar(row, set, mindelta, maxdelta, maxdnom, maxscale, usecontvars, 6002 &intscalar, success) ); 6003 6004 if( *success ) 6005 { 6006 /* scale the row */ 6007 SCIP_CALL( rowScale(row, blkmem, set, eventqueue, stat, lp, intscalar, usecontvars, mindelta, maxdelta) ); 6008 } 6009 6010 return SCIP_OKAY; 6011 } 6012 6013 /** sorts row entries such that LP columns precede non-LP columns and inside both parts lower column indices precede 6014 * higher ones 6015 */ 6016 void SCIProwSort( 6017 SCIP_ROW* row /**< row to be sorted */ 6018 ) 6019 { 6020 assert(row != NULL); 6021 6022 /* sort LP columns */ 6023 rowSortLP(row); 6024 6025 /* sort non-LP columns */ 6026 rowSortNonLP(row); 6027 6028 #ifdef SCIP_MORE_DEBUG 6029 /* check the sorting */ 6030 { 6031 int c; 6032 if( !row->delaysort ) 6033 { 6034 for( c = 1; c < row->nlpcols; ++c ) 6035 assert(row->cols[c]->index >= row->cols[c-1]->index); 6036 for( c = row->nlpcols + 1; c < row->len; ++c ) 6037 assert(row->cols[c]->index >= row->cols[c-1]->index); 6038 } 6039 } 6040 #endif 6041 } 6042 6043 /** sorts row, and merges equal column entries (resulting from lazy sorting and adding) into a single entry; removes 6044 * zero entries from row 6045 * the row must not be linked to the columns; otherwise, we would need to update the columns as 6046 * well, which is too expensive 6047 */ 6048 static 6049 void rowMerge( 6050 SCIP_ROW* row, /**< row to be sorted */ 6051 SCIP_SET* set /**< global SCIP settings */ 6052 ) 6053 { 6054 assert(row != NULL); 6055 assert(!row->delaysort); 6056 assert(row->nunlinked == row->len); 6057 assert(row->nlpcols == 0); 6058 6059 SCIPsetDebugMsg(set, "merging row <%s>\n", row->name); 6060 6061 /* do nothing on empty rows; if row is sorted, nothing has to be done */ 6062 if( row->len > 0 && (!row->lpcolssorted || !row->nonlpcolssorted) ) 6063 { 6064 SCIP_COL** cols; 6065 int* cols_index; 6066 SCIP_Real* vals; 6067 int s; 6068 int t; 6069 6070 /* make sure, the row is sorted */ 6071 SCIProwSort(row); 6072 assert(row->lpcolssorted); 6073 assert(row->nonlpcolssorted); 6074 6075 /* merge equal columns, thereby recalculating whether the row's activity is always integral */ 6076 cols = row->cols; 6077 cols_index = row->cols_index; 6078 vals = row->vals; 6079 assert(cols != NULL); 6080 assert(cols_index != NULL); 6081 assert(vals != NULL); 6082 6083 t = 0; 6084 row->integral = TRUE; 6085 assert(!SCIPsetIsZero(set, vals[0])); 6086 assert(row->linkpos[0] == -1); 6087 6088 for( s = 1; s < row->len; ++s ) 6089 { 6090 assert(!SCIPsetIsZero(set, vals[s])); 6091 assert(row->linkpos[s] == -1); 6092 6093 if( cols[s] == cols[t] ) 6094 { 6095 /* merge entries with equal column */ 6096 vals[t] += vals[s]; 6097 } 6098 else 6099 { 6100 /* go to the next entry, overwriting current entry if coefficient is zero */ 6101 if( !SCIPsetIsZero(set, vals[t]) ) 6102 { 6103 /* in case the coefficient is integral w.r.t. numerics we explicitly round the coefficient to an integral value */ 6104 vals[t] = SCIPsetIsIntegral(set, vals[t]) ? SCIPsetRound(set, vals[t]) : vals[t]; 6105 6106 row->integral = row->integral && SCIPcolIsIntegral(cols[t]) && SCIPsetIsIntegral(set, vals[t]); 6107 t++; 6108 } 6109 cols[t] = cols[s]; 6110 cols_index[t] = cols_index[s]; 6111 vals[t] = vals[s]; 6112 } 6113 } 6114 if( !SCIPsetIsZero(set, vals[t]) ) 6115 { 6116 row->integral = row->integral && SCIPcolIsIntegral(cols[t]) && SCIPsetIsIntegral(set, vals[t]); 6117 t++; 6118 } 6119 assert(s == row->len); 6120 assert(t <= row->len); 6121 6122 row->len = t; 6123 row->nunlinked = t; 6124 6125 /* if equal entries were merged, we have to recalculate the norms, since the squared Euclidean norm is wrong */ 6126 if( t < s ) 6127 rowCalcNorms(row, set); 6128 } 6129 6130 #ifndef NDEBUG 6131 /* check for double entries */ 6132 { 6133 int i; 6134 int j; 6135 6136 for( i = 0; i < row->len; ++i ) 6137 { 6138 assert(row->cols[i] != NULL); 6139 assert(row->cols[i]->index == row->cols_index[i]); 6140 for( j = i+1; j < row->len; ++j ) 6141 assert(row->cols[i] != row->cols[j]); 6142 } 6143 } 6144 #endif 6145 } 6146 6147 /** enables delaying of row sorting */ 6148 void SCIProwDelaySort( 6149 SCIP_ROW* row /**< LP row */ 6150 ) 6151 { 6152 assert(row != NULL); 6153 assert(!row->delaysort); 6154 6155 row->delaysort = TRUE; 6156 } 6157 6158 /** disables delaying of row sorting, sorts row and merges coefficients with equal columns */ 6159 void SCIProwForceSort( 6160 SCIP_ROW* row, /**< LP row */ 6161 SCIP_SET* set /**< global SCIP settings */ 6162 ) 6163 { 6164 assert(row != NULL); 6165 assert(row->delaysort); 6166 6167 row->delaysort = FALSE; 6168 rowMerge(row, set); 6169 } 6170 6171 /** recalculates the current activity of a row */ 6172 void SCIProwRecalcLPActivity( 6173 SCIP_ROW* row, /**< LP row */ 6174 SCIP_STAT* stat /**< problem statistics */ 6175 ) 6176 { 6177 SCIP_COL* col; 6178 int c; 6179 6180 assert(row != NULL); 6181 assert(stat != NULL); 6182 6183 row->activity = row->constant; 6184 for( c = 0; c < row->nlpcols; ++c ) 6185 { 6186 col = row->cols[c]; 6187 assert(col != NULL); 6188 assert(col->primsol != SCIP_INVALID); /*lint !e777*/ 6189 assert(col->lppos >= 0); 6190 assert(row->linkpos[c] >= 0); 6191 row->activity += row->vals[c] * col->primsol; 6192 } 6193 6194 if( row->nunlinked > 0 ) 6195 { 6196 for( c = row->nlpcols; c < row->len; ++c ) 6197 { 6198 col = row->cols[c]; 6199 assert(col != NULL); 6200 assert(col->lppos >= 0 || col->primsol == 0.0); 6201 assert(col->lppos == -1 || row->linkpos[c] == -1); 6202 if( col->lppos >= 0 ) 6203 row->activity += row->vals[c] * col->primsol; 6204 } 6205 } 6206 #ifndef NDEBUG 6207 else 6208 { 6209 for( c = row->nlpcols; c < row->len; ++c ) 6210 { 6211 col = row->cols[c]; 6212 assert(col != NULL); 6213 assert(col->primsol == 0.0); 6214 assert(col->lppos == -1); 6215 assert(row->linkpos[c] >= 0); 6216 } 6217 } 6218 #endif 6219 6220 row->validactivitylp = stat->lpcount; 6221 } 6222 6223 /** returns the activity of a row in the current LP solution */ 6224 SCIP_Real SCIProwGetLPActivity( 6225 SCIP_ROW* row, /**< LP row */ 6226 SCIP_SET* set, /**< global SCIP settings */ 6227 SCIP_STAT* stat, /**< problem statistics */ 6228 SCIP_LP* lp /**< current LP data */ 6229 ) 6230 { 6231 SCIP_Real inf; 6232 SCIP_Real activity; 6233 6234 assert(row != NULL); 6235 assert(stat != NULL); 6236 assert(lp != NULL); 6237 assert(row->validactivitylp <= stat->lpcount); 6238 assert(lp->validsollp == stat->lpcount); 6239 6240 if( row->validactivitylp != stat->lpcount ) 6241 SCIProwRecalcLPActivity(row, stat); 6242 assert(row->validactivitylp == stat->lpcount); 6243 assert(row->activity != SCIP_INVALID); /*lint !e777*/ 6244 6245 activity = row->activity; 6246 inf = SCIPsetInfinity(set); 6247 activity = MAX(activity, -inf); 6248 activity = MIN(activity, +inf); 6249 6250 return activity; 6251 } 6252 6253 /** returns the feasibility of a row in the current LP solution: negative value means infeasibility */ 6254 SCIP_Real SCIProwGetLPFeasibility( 6255 SCIP_ROW* row, /**< LP row */ 6256 SCIP_SET* set, /**< global SCIP settings */ 6257 SCIP_STAT* stat, /**< problem statistics */ 6258 SCIP_LP* lp /**< current LP data */ 6259 ) 6260 { 6261 SCIP_Real activity; 6262 6263 assert(row != NULL); 6264 6265 activity = SCIProwGetLPActivity(row, set, stat, lp); 6266 6267 return MIN(row->rhs - activity, activity - row->lhs); 6268 } 6269 6270 /** returns the feasibility of a row in the relaxed solution solution: negative value means infeasibility 6271 * 6272 * @todo Implement calculation of activities similar to LPs. 6273 */ 6274 SCIP_Real SCIProwGetRelaxFeasibility( 6275 SCIP_ROW* row, /**< LP row */ 6276 SCIP_SET* set, /**< global SCIP settings */ 6277 SCIP_STAT* stat /**< problem statistics */ 6278 ) 6279 { 6280 SCIP_Real inf; 6281 SCIP_Real activity; 6282 SCIP_COL* col; 6283 int c; 6284 6285 assert( row != NULL ); 6286 assert( stat != NULL ); 6287 6288 activity = row->constant; 6289 for (c = 0; c < row->nlpcols; ++c) 6290 { 6291 col = row->cols[c]; 6292 assert( col != NULL ); 6293 assert( col->lppos >= 0 ); 6294 assert( col->var != NULL ); 6295 assert( row->linkpos[c] >= 0 ); 6296 activity += row->vals[c] * SCIPvarGetRelaxSol(col->var, set); 6297 } 6298 6299 if ( row->nunlinked > 0 ) 6300 { 6301 for (c = row->nlpcols; c < row->len; ++c) 6302 { 6303 col = row->cols[c]; 6304 assert( col != NULL ); 6305 assert( col->lppos == -1 || row->linkpos[c] == -1 ); 6306 if ( col->lppos >= 0 ) 6307 { 6308 assert( col->var != NULL ); 6309 activity += row->vals[c] * SCIPvarGetRelaxSol(col->var, set); 6310 } 6311 } 6312 } 6313 #ifndef NDEBUG 6314 else 6315 { 6316 for (c = row->nlpcols; c < row->len; ++c) 6317 { 6318 col = row->cols[c]; 6319 assert( col != NULL ); 6320 assert( col->lppos == -1 ); 6321 assert( row->linkpos[c] >= 0 ); 6322 } 6323 } 6324 #endif 6325 inf = SCIPsetInfinity(set); 6326 activity = MAX(activity, -inf); 6327 activity = MIN(activity, +inf); 6328 6329 return MIN(row->rhs - activity, activity - row->lhs); 6330 } 6331 6332 /** returns the feasibility of a row in the current NLP solution: negative value means infeasibility 6333 * 6334 * @todo Implement calculation of activities similar to LPs. 6335 */ 6336 SCIP_Real SCIProwGetNLPFeasibility( 6337 SCIP_ROW* row, /**< LP row */ 6338 SCIP_SET* set, /**< global SCIP settings */ 6339 SCIP_STAT* stat /**< problem statistics */ 6340 ) 6341 { 6342 SCIP_Real inf; 6343 SCIP_Real activity; 6344 SCIP_COL* col; 6345 int c; 6346 6347 assert( row != NULL ); 6348 assert( stat != NULL ); 6349 6350 activity = row->constant; 6351 for (c = 0; c < row->nlpcols; ++c) 6352 { 6353 col = row->cols[c]; 6354 assert( col != NULL ); 6355 assert( col->lppos >= 0 ); 6356 assert( col->var != NULL ); 6357 assert( row->linkpos[c] >= 0 ); 6358 activity += row->vals[c] * SCIPvarGetNLPSol(col->var); 6359 } 6360 6361 if ( row->nunlinked > 0 ) 6362 { 6363 for (c = row->nlpcols; c < row->len; ++c) 6364 { 6365 col = row->cols[c]; 6366 assert( col != NULL ); 6367 assert( col->lppos == -1 || row->linkpos[c] == -1 ); 6368 if ( col->lppos >= 0 ) 6369 { 6370 assert( col->var != NULL ); 6371 activity += row->vals[c] * SCIPvarGetNLPSol(col->var); 6372 } 6373 } 6374 } 6375 #ifndef NDEBUG 6376 else 6377 { 6378 for (c = row->nlpcols; c < row->len; ++c) 6379 { 6380 col = row->cols[c]; 6381 assert( col != NULL ); 6382 assert( col->lppos == -1 ); 6383 assert( row->linkpos[c] >= 0 ); 6384 } 6385 } 6386 #endif 6387 inf = SCIPsetInfinity(set); 6388 activity = MAX(activity, -inf); 6389 activity = MIN(activity, +inf); 6390 6391 return MIN(row->rhs - activity, activity - row->lhs); 6392 } 6393 6394 /** calculates the current pseudo activity of a row */ 6395 void SCIProwRecalcPseudoActivity( 6396 SCIP_ROW* row, /**< row data */ 6397 SCIP_STAT* stat /**< problem statistics */ 6398 ) 6399 { 6400 SCIP_COL* col; 6401 int i; 6402 6403 assert(row != NULL); 6404 assert(stat != NULL); 6405 6406 row->pseudoactivity = row->constant; 6407 for( i = 0; i < row->len; ++i ) 6408 { 6409 col = row->cols[i]; 6410 assert(col != NULL); 6411 assert((i < row->nlpcols) == (row->linkpos[i] >= 0 && col->lppos >= 0)); 6412 assert(col->var != NULL); 6413 assert(SCIPvarGetStatus(col->var) == SCIP_VARSTATUS_COLUMN); 6414 6415 row->pseudoactivity += SCIPcolGetBestBound(col) * row->vals[i]; 6416 } 6417 row->validpsactivitydomchg = stat->domchgcount; 6418 assert(!row->integral || EPSISINT(row->pseudoactivity - row->constant, SCIP_DEFAULT_SUMEPSILON)); 6419 } 6420 6421 /** returns the pseudo activity of a row in the current pseudo solution */ 6422 SCIP_Real SCIProwGetPseudoActivity( 6423 SCIP_ROW* row, /**< LP row */ 6424 SCIP_SET* set, /**< global SCIP settings */ 6425 SCIP_STAT* stat /**< problem statistics */ 6426 ) 6427 { 6428 SCIP_Real inf; 6429 SCIP_Real activity; 6430 6431 assert(row != NULL); 6432 assert(stat != NULL); 6433 assert(row->validpsactivitydomchg <= stat->domchgcount); 6434 6435 /* check, if pseudo activity has to be calculated */ 6436 if( row->validpsactivitydomchg != stat->domchgcount ) 6437 SCIProwRecalcPseudoActivity(row, stat); 6438 assert(row->validpsactivitydomchg == stat->domchgcount); 6439 assert(row->pseudoactivity != SCIP_INVALID); /*lint !e777*/ 6440 6441 activity = row->pseudoactivity; 6442 inf = SCIPsetInfinity(set); 6443 activity = MAX(activity, -inf); 6444 activity = MIN(activity, +inf); 6445 6446 return activity; 6447 } 6448 6449 /** returns the pseudo feasibility of a row in the current pseudo solution: negative value means infeasibility */ 6450 SCIP_Real SCIProwGetPseudoFeasibility( 6451 SCIP_ROW* row, /**< LP row */ 6452 SCIP_SET* set, /**< global SCIP settings */ 6453 SCIP_STAT* stat /**< problem statistics */ 6454 ) 6455 { 6456 SCIP_Real pseudoactivity; 6457 6458 assert(row != NULL); 6459 6460 pseudoactivity = SCIProwGetPseudoActivity(row, set, stat); 6461 6462 return MIN(row->rhs - pseudoactivity, pseudoactivity - row->lhs); 6463 } 6464 6465 /** returns the activity of a row for a given solution */ 6466 SCIP_Real SCIProwGetSolActivity( 6467 SCIP_ROW* row, /**< LP row */ 6468 SCIP_SET* set, /**< global SCIP settings */ 6469 SCIP_STAT* stat, /**< problem statistics data */ 6470 SCIP_SOL* sol /**< primal CIP solution */ 6471 ) 6472 { 6473 SCIP_COL* col; 6474 SCIP_Real inf; 6475 SCIP_Real activity; 6476 SCIP_Real solval; 6477 int i; 6478 6479 assert(row != NULL); 6480 6481 activity = row->constant; 6482 for( i = 0; i < row->len; ++i ) 6483 { 6484 col = row->cols[i]; 6485 assert(col != NULL); 6486 assert((i < row->nlpcols) == (row->linkpos[i] >= 0 && col->lppos >= 0)); 6487 solval = SCIPsolGetVal(sol, set, stat, col->var); 6488 if( solval == SCIP_UNKNOWN ) /*lint !e777*/ 6489 { 6490 if( SCIPsetIsInfinity(set, -row->lhs) ) 6491 solval = (row->vals[i] >= 0.0 ? col->lb : col->ub); 6492 else if( SCIPsetIsInfinity(set, row->rhs) ) 6493 solval = (row->vals[i] >= 0.0 ? col->ub : col->lb); 6494 else 6495 solval = (col->lb + col->ub)/2.0; 6496 } 6497 activity += row->vals[i] * solval; 6498 } 6499 6500 inf = SCIPsetInfinity(set); 6501 activity = MAX(activity, -inf); 6502 activity = MIN(activity, +inf); 6503 6504 return activity; 6505 } 6506 6507 /** returns the feasibility of a row for the given solution */ 6508 SCIP_Real SCIProwGetSolFeasibility( 6509 SCIP_ROW* row, /**< LP row */ 6510 SCIP_SET* set, /**< global SCIP settings */ 6511 SCIP_STAT* stat, /**< problem statistics data */ 6512 SCIP_SOL* sol /**< primal CIP solution */ 6513 ) 6514 { 6515 SCIP_Real activity; 6516 6517 assert(row != NULL); 6518 6519 activity = SCIProwGetSolActivity(row, set, stat, sol); 6520 6521 return MIN(row->rhs - activity, activity - row->lhs); 6522 } 6523 6524 /** calculates minimal and maximal activity of row w.r.t. the column's bounds */ 6525 static 6526 void rowCalcActivityBounds( 6527 SCIP_ROW* row, /**< row data */ 6528 SCIP_SET* set, /**< global SCIP settings */ 6529 SCIP_STAT* stat /**< problem statistics data */ 6530 ) 6531 { 6532 SCIP_COL* col; 6533 SCIP_Real val; 6534 SCIP_Bool mininfinite; 6535 SCIP_Bool maxinfinite; 6536 int i; 6537 6538 assert(row != NULL); 6539 assert(!SCIPsetIsInfinity(set, REALABS(row->constant))); 6540 assert(stat != NULL); 6541 6542 /* calculate activity bounds */ 6543 mininfinite = FALSE; 6544 maxinfinite = FALSE; 6545 row->minactivity = row->constant; 6546 row->maxactivity = row->constant; 6547 for( i = 0; i < row->len && (!mininfinite || !maxinfinite); ++i ) 6548 { 6549 col = row->cols[i]; 6550 assert(col != NULL); 6551 assert((i < row->nlpcols) == (row->linkpos[i] >= 0 && col->lppos >= 0)); 6552 val = row->vals[i]; 6553 if( val >= 0.0 ) 6554 { 6555 mininfinite = mininfinite || SCIPsetIsInfinity(set, -col->lb); 6556 maxinfinite = maxinfinite || SCIPsetIsInfinity(set, col->ub); 6557 if( !mininfinite ) 6558 row->minactivity += val * col->lb; 6559 if( !maxinfinite ) 6560 row->maxactivity += val * col->ub; 6561 } 6562 else 6563 { 6564 mininfinite = mininfinite || SCIPsetIsInfinity(set, col->ub); 6565 maxinfinite = maxinfinite || SCIPsetIsInfinity(set, -col->lb); 6566 if( !mininfinite ) 6567 row->minactivity += val * col->ub; 6568 if( !maxinfinite ) 6569 row->maxactivity += val * col->lb; 6570 } 6571 } 6572 6573 if( mininfinite ) 6574 row->minactivity = -SCIPsetInfinity(set); 6575 if( maxinfinite ) 6576 row->maxactivity = SCIPsetInfinity(set); 6577 row->validactivitybdsdomchg = stat->domchgcount; 6578 6579 #ifndef NDEBUG 6580 { 6581 SCIP_Real inttol = 1000.0*SCIPsetFeastol(set); 6582 6583 /* even if the row is integral, the bounds on the variables used for computing minimum and maximum activity might 6584 * be integral only within feasibility tolerance; this can happen, e.g., if a continuous variable is promoted to 6585 * an (implicit) integer variable and the bounds cannot be adjusted because they are minimally tighter than the 6586 * rounded bound value; hence, the activity may violate integrality; we allow 1000 times the default feasibility 6587 * tolerance as a proxy to account for the accumulation effect 6588 */ 6589 assert(!row->integral || mininfinite || REALABS(row->minactivity - row->constant) > 1.0/SCIPsetSumepsilon(set) 6590 || EPSISINT(row->minactivity - row->constant, inttol)); 6591 assert(!row->integral || maxinfinite || REALABS(row->maxactivity - row->constant) > 1.0/SCIPsetSumepsilon(set) 6592 || EPSISINT(row->maxactivity - row->constant, inttol)); 6593 } 6594 #endif 6595 } 6596 6597 /** returns the minimal activity of a row w.r.t. the columns' bounds */ 6598 SCIP_Real SCIProwGetMinActivity( 6599 SCIP_ROW* row, /**< LP row */ 6600 SCIP_SET* set, /**< global SCIP settings */ 6601 SCIP_STAT* stat /**< problem statistics data */ 6602 ) 6603 { 6604 assert(row != NULL); 6605 assert(stat != NULL); 6606 assert(row->validactivitybdsdomchg <= stat->domchgcount); 6607 6608 /* check, if activity bounds has to be calculated */ 6609 if( row->validactivitybdsdomchg != stat->domchgcount ) 6610 rowCalcActivityBounds(row, set, stat); 6611 assert(row->validactivitybdsdomchg == stat->domchgcount); 6612 assert(row->minactivity != SCIP_INVALID); /*lint !e777*/ 6613 assert(row->maxactivity != SCIP_INVALID); /*lint !e777*/ 6614 6615 return row->minactivity; 6616 } 6617 6618 /** returns the maximal activity of a row w.r.t. the columns' bounds */ 6619 SCIP_Real SCIProwGetMaxActivity( 6620 SCIP_ROW* row, /**< LP row */ 6621 SCIP_SET* set, /**< global SCIP settings */ 6622 SCIP_STAT* stat /**< problem statistics data */ 6623 ) 6624 { 6625 assert(row != NULL); 6626 assert(stat != NULL); 6627 assert(row->validactivitybdsdomchg <= stat->domchgcount); 6628 6629 /* check, if activity bounds has to be calculated */ 6630 if( row->validactivitybdsdomchg != stat->domchgcount ) 6631 rowCalcActivityBounds(row, set, stat); 6632 assert(row->validactivitybdsdomchg == stat->domchgcount); 6633 assert(row->minactivity != SCIP_INVALID); /*lint !e777*/ 6634 assert(row->maxactivity != SCIP_INVALID); /*lint !e777*/ 6635 6636 return row->maxactivity; 6637 } 6638 6639 /** returns whether the row is unmodifiable and redundant w.r.t. the columns' bounds */ 6640 SCIP_Bool SCIProwIsRedundant( 6641 SCIP_ROW* row, /**< LP row */ 6642 SCIP_SET* set, /**< global SCIP settings */ 6643 SCIP_STAT* stat /**< problem statistics data */ 6644 ) 6645 { 6646 assert(row != NULL); 6647 6648 if( row->modifiable ) 6649 return FALSE; 6650 if( !SCIPsetIsInfinity(set, -row->lhs) ) 6651 { 6652 SCIP_Real minactivity; 6653 6654 minactivity = SCIProwGetMinActivity(row, set, stat); 6655 if( SCIPsetIsFeasLT(set, minactivity, row->lhs) ) 6656 return FALSE; 6657 } 6658 if( !SCIPsetIsInfinity(set, row->rhs) ) 6659 { 6660 SCIP_Real maxactivity; 6661 6662 maxactivity = SCIProwGetMaxActivity(row, set, stat); 6663 if( SCIPsetIsFeasGT(set, maxactivity, row->rhs) ) 6664 return FALSE; 6665 } 6666 6667 return TRUE; 6668 } 6669 6670 /** gets maximal absolute value of row vector coefficients */ 6671 SCIP_Real SCIProwGetMaxval( 6672 SCIP_ROW* row, /**< LP row */ 6673 SCIP_SET* set /**< global SCIP settings */ 6674 ) 6675 { 6676 assert(row != NULL); 6677 6678 if( row->nummaxval == 0 ) 6679 rowCalcIdxsAndVals(row, set); 6680 assert(row->nummaxval > 0); 6681 assert(row->maxval >= 0.0 || row->len == 0); 6682 6683 return row->maxval; 6684 } 6685 6686 /** gets minimal absolute value of row vector's non-zero coefficients */ 6687 SCIP_Real SCIProwGetMinval( 6688 SCIP_ROW* row, /**< LP row */ 6689 SCIP_SET* set /**< global SCIP settings */ 6690 ) 6691 { 6692 assert(row != NULL); 6693 6694 if( row->numminval == 0 ) 6695 rowCalcIdxsAndVals(row, set); 6696 assert(row->numminval > 0); 6697 assert(row->minval >= 0.0 || row->len == 0); 6698 6699 return row->minval; 6700 } 6701 6702 /** gets maximal column index of row entries */ 6703 int SCIProwGetMaxidx( 6704 SCIP_ROW* row, /**< LP row */ 6705 SCIP_SET* set /**< global SCIP settings */ 6706 ) 6707 { 6708 assert(row != NULL); 6709 6710 if( row->validminmaxidx == 0 ) 6711 rowCalcIdxsAndVals(row, set); 6712 assert(row->maxidx >= 0 || row->len == 0); 6713 assert(row->validminmaxidx); 6714 6715 return row->maxidx; 6716 } 6717 6718 /** gets minimal column index of row entries */ 6719 int SCIProwGetMinidx( 6720 SCIP_ROW* row, /**< LP row */ 6721 SCIP_SET* set /**< global SCIP settings */ 6722 ) 6723 { 6724 assert(row != NULL); 6725 6726 if( row->validminmaxidx == 0 ) 6727 rowCalcIdxsAndVals(row, set); 6728 assert(row->minidx >= 0 || row->len == 0); 6729 assert(row->validminmaxidx); 6730 6731 return row->minidx; 6732 } 6733 6734 /** gets number of integral columns in row */ 6735 int SCIProwGetNumIntCols( 6736 SCIP_ROW* row, /**< LP row */ 6737 SCIP_SET* set /**< global SCIP settings */ 6738 ) 6739 { 6740 assert(row != NULL); 6741 6742 if( row->numintcols == -1 ) 6743 rowCalcIdxsAndVals(row, set); 6744 6745 assert(row->numintcols <= row->len && row->numintcols >= 0); 6746 6747 return row->numintcols; 6748 } 6749 6750 /** returns row's cutoff distance in the direction of the given primal solution */ 6751 SCIP_Real SCIProwGetLPSolCutoffDistance( 6752 SCIP_ROW* row, /**< LP row */ 6753 SCIP_SET* set, /**< global SCIP settings */ 6754 SCIP_STAT* stat, /**< problem statistics data */ 6755 SCIP_SOL* sol, /**< solution to compute direction for cutoff distance; must not be NULL */ 6756 SCIP_LP* lp /**< current LP data */ 6757 ) 6758 { 6759 SCIP_Real solcutoffdist; 6760 int k; 6761 6762 assert(sol != NULL); 6763 6764 if( lp->validsoldirlp != stat->lpcount || lp->validsoldirsol != sol ) 6765 { 6766 SCIP_Real scale = 0.0; 6767 6768 lp->validsoldirlp = stat->lpcount; 6769 lp->validsoldirsol = sol; 6770 6771 SCIP_CALL_ABORT( ensureSoldirectionSize(lp, lp->ncols) ); 6772 6773 for( k = 0; k < lp->ncols; ++k ) 6774 { 6775 assert(lp->cols[k]->lppos == k); 6776 lp->soldirection[k] = SCIPsolGetVal(sol, set, stat, lp->cols[k]->var) - lp->cols[k]->primsol; 6777 scale += SQR(lp->soldirection[k]); 6778 } 6779 6780 if( scale > 0.0 ) 6781 { 6782 scale = 1.0 / SQRT(scale); 6783 6784 for( k = 0; k < lp->ncols; ++k ) 6785 lp->soldirection[k] *= scale; 6786 } 6787 } 6788 6789 solcutoffdist = 0.0; 6790 for( k = 0; k < row->nlpcols; ++k ) 6791 solcutoffdist += row->vals[k] * lp->soldirection[row->cols[k]->lppos]; 6792 6793 for( k = row->nlpcols; k < row->len; ++k ) 6794 { 6795 if( row->cols[k]->lppos >= 0 ) 6796 solcutoffdist += row->vals[k] * lp->soldirection[row->cols[k]->lppos]; 6797 } 6798 6799 if( SCIPsetIsSumZero(set, solcutoffdist) ) 6800 solcutoffdist = set->num_sumepsilon; 6801 6802 solcutoffdist = -SCIProwGetLPFeasibility(row, set, stat, lp) / ABS(solcutoffdist); /*lint !e795*/ 6803 6804 return solcutoffdist; 6805 } 6806 6807 /** returns row's efficacy with respect to the current LP solution: e = -feasibility/norm */ 6808 SCIP_Real SCIProwGetLPEfficacy( 6809 SCIP_ROW* row, /**< LP row */ 6810 SCIP_SET* set, /**< global SCIP settings */ 6811 SCIP_STAT* stat, /**< problem statistics data */ 6812 SCIP_LP* lp /**< current LP data */ 6813 ) 6814 { 6815 SCIP_Real norm; 6816 SCIP_Real feasibility; 6817 SCIP_Real eps; 6818 6819 assert(set != NULL); 6820 6821 switch( set->sepa_efficacynorm ) 6822 { 6823 case 'e': 6824 norm = SCIProwGetNorm(row); 6825 break; 6826 case 'm': 6827 norm = SCIProwGetMaxval(row, set); 6828 break; 6829 case 's': 6830 norm = SCIProwGetSumNorm(row); 6831 break; 6832 case 'd': 6833 norm = (row->len == 0 ? 0.0 : 1.0); 6834 break; 6835 default: 6836 SCIPerrorMessage("invalid efficacy norm parameter '%c'\n", set->sepa_efficacynorm); 6837 SCIPABORT(); 6838 norm = 0.0; /*lint !e527*/ 6839 } 6840 6841 eps = SCIPsetSumepsilon(set); 6842 norm = MAX(norm, eps); 6843 feasibility = SCIProwGetLPFeasibility(row, set, stat, lp); 6844 6845 return -feasibility / norm; 6846 } 6847 6848 /** returns whether the row's efficacy with respect to the current LP solution is greater than the minimal cut efficacy */ 6849 SCIP_Bool SCIProwIsLPEfficacious( 6850 SCIP_ROW* row, /**< LP row */ 6851 SCIP_SET* set, /**< global SCIP settings */ 6852 SCIP_STAT* stat, /**< problem statistics data */ 6853 SCIP_LP* lp, /**< current LP data */ 6854 SCIP_Bool root /**< should the root's minimal cut efficacy be used? */ 6855 ) 6856 { 6857 SCIP_Real efficacy; 6858 6859 efficacy = SCIProwGetLPEfficacy(row, set, stat, lp); 6860 6861 return SCIPsetIsEfficacious(set, root, efficacy); 6862 } 6863 6864 /** returns row's efficacy with respect to the given primal solution: e = -feasibility/norm */ 6865 SCIP_Real SCIProwGetSolEfficacy( 6866 SCIP_ROW* row, /**< LP row */ 6867 SCIP_SET* set, /**< global SCIP settings */ 6868 SCIP_STAT* stat, /**< problem statistics data */ 6869 SCIP_SOL* sol /**< primal CIP solution */ 6870 ) 6871 { 6872 SCIP_Real norm; 6873 SCIP_Real feasibility; 6874 SCIP_Real eps; 6875 6876 assert(set != NULL); 6877 6878 switch( set->sepa_efficacynorm ) 6879 { 6880 case 'e': 6881 norm = SCIProwGetNorm(row); 6882 break; 6883 case 'm': 6884 norm = SCIProwGetMaxval(row, set); 6885 break; 6886 case 's': 6887 norm = SCIProwGetSumNorm(row); 6888 break; 6889 case 'd': 6890 norm = (row->len == 0 ? 0.0 : 1.0); 6891 break; 6892 default: 6893 SCIPerrorMessage("invalid efficacy norm parameter '%c'\n", set->sepa_efficacynorm); 6894 SCIPABORT(); 6895 norm = 0.0; /*lint !e527*/ 6896 } 6897 6898 eps = SCIPsetSumepsilon(set); 6899 norm = MAX(norm, eps); 6900 feasibility = SCIProwGetSolFeasibility(row, set, stat, sol); 6901 6902 return -feasibility / norm; 6903 } 6904 6905 /** returns whether the row's efficacy with respect to the given primal solution is greater than the minimal cut 6906 * efficacy 6907 */ 6908 SCIP_Bool SCIProwIsSolEfficacious( 6909 SCIP_ROW* row, /**< LP row */ 6910 SCIP_SET* set, /**< global SCIP settings */ 6911 SCIP_STAT* stat, /**< problem statistics data */ 6912 SCIP_SOL* sol, /**< primal CIP solution */ 6913 SCIP_Bool root /**< should the root's minimal cut efficacy be used? */ 6914 ) 6915 { 6916 SCIP_Real efficacy; 6917 6918 efficacy = SCIProwGetSolEfficacy(row, set, stat, sol); 6919 6920 return SCIPsetIsEfficacious(set, root, efficacy); 6921 } 6922 6923 /** returns row's efficacy with respect to the relaxed solution: e = -feasibility/norm */ 6924 SCIP_Real SCIProwGetRelaxEfficacy( 6925 SCIP_ROW* row, /**< LP row */ 6926 SCIP_SET* set, /**< global SCIP settings */ 6927 SCIP_STAT* stat /**< problem statistics data */ 6928 ) 6929 { 6930 SCIP_Real norm; 6931 SCIP_Real feasibility; 6932 SCIP_Real eps; 6933 6934 assert(set != NULL); 6935 6936 switch( set->sepa_efficacynorm ) 6937 { 6938 case 'e': 6939 norm = SCIProwGetNorm(row); 6940 break; 6941 case 'm': 6942 norm = SCIProwGetMaxval(row, set); 6943 break; 6944 case 's': 6945 norm = SCIProwGetSumNorm(row); 6946 break; 6947 case 'd': 6948 norm = (row->len == 0 ? 0.0 : 1.0); 6949 break; 6950 default: 6951 SCIPerrorMessage("invalid efficacy norm parameter '%c'\n", set->sepa_efficacynorm); 6952 SCIPABORT(); 6953 norm = 0.0; /*lint !e527*/ 6954 } 6955 6956 eps = SCIPsetSumepsilon(set); 6957 norm = MAX(norm, eps); 6958 feasibility = SCIProwGetRelaxFeasibility(row, set, stat); 6959 6960 return -feasibility / norm; 6961 } 6962 6963 /** returns row's efficacy with respect to the NLP solution: e = -feasibility/norm */ 6964 SCIP_Real SCIProwGetNLPEfficacy( 6965 SCIP_ROW* row, /**< LP row */ 6966 SCIP_SET* set, /**< global SCIP settings */ 6967 SCIP_STAT* stat /**< problem statistics data */ 6968 ) 6969 { 6970 SCIP_Real norm; 6971 SCIP_Real feasibility; 6972 SCIP_Real eps; 6973 6974 assert(set != NULL); 6975 6976 switch( set->sepa_efficacynorm ) 6977 { 6978 case 'e': 6979 norm = SCIProwGetNorm(row); 6980 break; 6981 case 'm': 6982 norm = SCIProwGetMaxval(row, set); 6983 break; 6984 case 's': 6985 norm = SCIProwGetSumNorm(row); 6986 break; 6987 case 'd': 6988 norm = (row->len == 0 ? 0.0 : 1.0); 6989 break; 6990 default: 6991 SCIPerrorMessage("invalid efficacy norm parameter '%c'\n", set->sepa_efficacynorm); 6992 SCIPABORT(); 6993 norm = 0.0; /*lint !e527*/ 6994 } 6995 6996 eps = SCIPsetSumepsilon(set); 6997 norm = MAX(norm, eps); 6998 feasibility = SCIProwGetNLPFeasibility(row, set, stat); 6999 7000 return -feasibility / norm; 7001 } 7002 7003 /** returns the scalar product of the coefficient vectors of the two given rows 7004 * 7005 * @note the scalar product is computed w.r.t. the current LP columns only 7006 * @todo also consider non-LP columns for the computation? 7007 */ 7008 SCIP_Real SCIProwGetScalarProduct( 7009 SCIP_ROW* row1, /**< first LP row */ 7010 SCIP_ROW* row2 /**< second LP row */ 7011 ) 7012 { 7013 SCIP_Real scalarprod; 7014 int* row1colsidx; 7015 int* row2colsidx; 7016 int i1; 7017 int i2; 7018 7019 assert(row1 != NULL); 7020 assert(row2 != NULL); 7021 7022 /* Sort the column indices of both rows. 7023 * 7024 * The columns in a row are divided into two parts: LP columns, which are currently in the LP and non-LP columns; 7025 * we sort the rows, but that only ensures that within these two parts, columns are sorted w.r.t. their index. 7026 * Normally, this should be suficient, because a column contained in both rows should either be one of the LP columns 7027 * for both or one of the non-LP columns for both. 7028 * However, directly after a row was created, before a row is added to the LP, the row is not linked to all its 7029 * columns and all columns are treated as non-LP columns. Moreover, for example when doing column generation, 7030 * columns can be added later and remain unlinked while all previously added columns might already be linked. 7031 * Therefore, we have to be very careful about whether we can rely on the partitioning of the variables. 7032 * 7033 * We distinguish the following cases: 7034 * 7035 * 1) both rows have no unlinked columns 7036 * -> we just check the LP partitions 7037 * 7038 * 2) exactly one row is completely unlinked, the other one is completely linked 7039 * -> we compare the non-LP (unlinked) partition with the LP partition of the other row 7040 * (thus all common LP columns are regarded) 7041 * 7042 * 3) we have unlinked and LP columns in both rows 7043 * -> we need to compare four partitions at once 7044 * 7045 * 4a) we have one row with unlinked and LP columns and the other without any unlinked columns 7046 * -> we need to compare three partitions: the LP part of the completely linked row and both partitions of the 7047 * other row 7048 * 7049 * 4b) we have one row with unlinked and LP columns and the other is completely unlinked 7050 * -> we need to compare three partitions: the complete unlinked row and both partitions of the other row 7051 * 7052 * 5) both rows are completely unlinked 7053 * -> we need to compare two partitions: both complete rows 7054 */ 7055 SCIProwSort(row1); 7056 assert(row1->lpcolssorted); 7057 assert(row1->nonlpcolssorted); 7058 SCIProwSort(row2); 7059 assert(row2->lpcolssorted); 7060 assert(row2->nonlpcolssorted); 7061 7062 assert(row1->nunlinked <= row1->len - row1->nlpcols); 7063 assert(row2->nunlinked <= row2->len - row2->nlpcols); 7064 7065 row1colsidx = row1->cols_index; 7066 row2colsidx = row2->cols_index; 7067 7068 #ifndef NDEBUG 7069 /* check that we can rely on the partition into LP columns and non-LP columns if the rows are completely linked */ 7070 if( row1->nunlinked == 0 && row2->nunlinked == 0 ) 7071 { 7072 i1 = 0; 7073 i2 = row2->nlpcols; 7074 while( i1 < row1->nlpcols && i2 < row2->len ) 7075 { 7076 assert(row1->cols[i1] != row2->cols[i2]); 7077 if( row1->cols[i1]->index < row2->cols[i2]->index ) 7078 ++i1; 7079 else 7080 { 7081 assert(row1->cols[i1]->index > row2->cols[i2]->index); 7082 ++i2; 7083 } 7084 } 7085 assert(i1 == row1->nlpcols || i2 == row2->len); 7086 7087 i1 = row1->nlpcols; 7088 i2 = 0; 7089 while( i1 < row1->len && i2 < row2->nlpcols ) 7090 { 7091 assert(row1->cols[i1] != row2->cols[i2]); 7092 if( row1->cols[i1]->index < row2->cols[i2]->index ) 7093 ++i1; 7094 else 7095 { 7096 assert(row1->cols[i1]->index > row2->cols[i2]->index); 7097 ++i2; 7098 } 7099 } 7100 assert(i1 == row1->len || i2 == row2->nlpcols); 7101 } 7102 #endif 7103 7104 /* The "easy" cases 1) and 2) */ 7105 if( (row1->nunlinked == 0 && row2->nunlinked == 0) || 7106 ((row1->nlpcols == row1->len || row1->nunlinked == row1->len) 7107 && (row2->nlpcols == row2->len || row2->nunlinked == row2->len) 7108 && (row1->nunlinked == 0 || row2->nunlinked == 0)) ) 7109 { 7110 assert(row1->nunlinked == 0 || row1->nunlinked == row1->len); 7111 assert(row2->nunlinked == 0 || row2->nunlinked == row2->len); 7112 7113 /* set the iterators to the last column we want to regard in the row: nunlinked is either 0 or row->len, 7114 * therefore, we get nlpcols if nunlinked is 0 and row->len if the row is completely unlinked 7115 */ 7116 i1 = MAX(row1->nlpcols, row1->nunlinked) - 1; 7117 i2 = MAX(row2->nlpcols, row2->nunlinked) - 1; 7118 scalarprod = 0.0; 7119 7120 /* calculate the scalar product */ 7121 while( i1 >= 0 && i2 >= 0 ) 7122 { 7123 assert(row1->cols[i1]->index == row1colsidx[i1]); 7124 assert(row2->cols[i2]->index == row2colsidx[i2]); 7125 assert((row1->cols[i1] == row2->cols[i2]) == (row1colsidx[i1] == row2colsidx[i2])); 7126 if( row1colsidx[i1] < row2colsidx[i2] ) 7127 --i2; 7128 else if( row1colsidx[i1] > row2colsidx[i2] ) 7129 --i1; 7130 else 7131 { 7132 scalarprod += row1->vals[i1] * row2->vals[i2]; 7133 --i1; 7134 --i2; 7135 } 7136 } 7137 } 7138 /* the "harder" cases 3) - 5): start with four partitions and reduce their number iteratively */ 7139 else 7140 { 7141 SCIP_Bool lpcols; 7142 int ilp1; 7143 int inlp1; 7144 int ilp2; 7145 int inlp2; 7146 int end1; 7147 int end2; 7148 7149 scalarprod = 0; 7150 ilp1 = 0; 7151 ilp2 = 0; 7152 7153 /* if a row is completely linked (case 4a), we do not have to consider its non-LP columns */ 7154 inlp1 = (row1->nunlinked > 0 ? row1->nlpcols : row1->len); 7155 inlp2 = (row2->nunlinked > 0 ? row2->nlpcols : row2->len); 7156 7157 /* handle the case of four partitions (case 3) until one partition is finished; 7158 * cases 4a), 4b), and 5) will fail the while-condition 7159 */ 7160 while( ilp1 < row1->nlpcols && inlp1 < row1->len && ilp2 < row2->nlpcols && inlp2 < row2->len ) 7161 { 7162 assert(row1->cols[ilp1]->index == row1colsidx[ilp1]); 7163 assert(row1->cols[inlp1]->index == row1colsidx[inlp1]); 7164 assert(row2->cols[ilp2]->index == row2colsidx[ilp2]); 7165 assert(row2->cols[inlp2]->index == row2colsidx[inlp2]); 7166 assert((row1->cols[ilp1] == row2->cols[ilp2]) == (row1colsidx[ilp1] == row2colsidx[ilp2])); 7167 assert((row1->cols[ilp1] == row2->cols[inlp2]) == (row1colsidx[ilp1] == row2colsidx[inlp2])); 7168 assert((row1->cols[inlp1] == row2->cols[ilp2]) == (row1colsidx[inlp1] == row2colsidx[ilp2])); 7169 assert((row1->cols[inlp1] == row2->cols[inlp2]) == (row1colsidx[inlp1] == row2colsidx[inlp2])); 7170 7171 /* rows have the same linked LP columns */ 7172 if( row1colsidx[ilp1] == row2colsidx[ilp2] ) 7173 { 7174 scalarprod += row1->vals[ilp1] * row2->vals[ilp2]; 7175 ++ilp1; 7176 ++ilp2; 7177 } 7178 /* LP column of row1 is the same as unlinked column of row2 */ 7179 else if( row1colsidx[ilp1] == row2colsidx[inlp2] ) 7180 { 7181 scalarprod += row1->vals[ilp1] * row2->vals[inlp2]; 7182 ++ilp1; 7183 ++inlp2; 7184 } 7185 /* unlinked column of row1 is the same as LP column of row2 */ 7186 else if( row1colsidx[inlp1] == row2colsidx[ilp2] ) 7187 { 7188 scalarprod += row1->vals[inlp1] * row2->vals[ilp2]; 7189 ++inlp1; 7190 ++ilp2; 7191 } 7192 /* two unlinked LP columns are the same */ 7193 else if( row1colsidx[inlp1] == row2colsidx[inlp2] && row1->cols[inlp1]->lppos >= 0 ) 7194 { 7195 scalarprod += row1->vals[inlp1] * row2->vals[inlp2]; 7196 ++inlp1; 7197 ++inlp2; 7198 } 7199 /* increase smallest counter */ 7200 else if( row1colsidx[ilp1] < row1colsidx[inlp1] ) 7201 { 7202 if( row2colsidx[ilp2] < row2colsidx[inlp2] ) 7203 { 7204 if( row1colsidx[ilp1] < row2colsidx[ilp2] ) 7205 ++ilp1; 7206 else 7207 ++ilp2; 7208 } 7209 else 7210 { 7211 if( row1colsidx[ilp1] < row2colsidx[inlp2] ) 7212 ++ilp1; 7213 else 7214 ++inlp2; 7215 } 7216 } 7217 else 7218 { 7219 if( row2colsidx[ilp2] < row2colsidx[inlp2] ) 7220 { 7221 if( row1colsidx[inlp1] < row2colsidx[ilp2] ) 7222 ++inlp1; 7223 else 7224 ++ilp2; 7225 } 7226 else 7227 { 7228 if( row1colsidx[inlp1] < row2colsidx[inlp2] ) 7229 ++inlp1; 7230 else 7231 ++inlp2; 7232 } 7233 } 7234 } 7235 7236 /* One partition was completely handled, we just have to handle the three remaining partitions: 7237 * the remaining partition of this row and the two partitions of the other row. 7238 * If necessary, we swap the partitions to ensure that row1 is the row with only one remaining partition. 7239 */ 7240 if( ilp1 != row1->nlpcols && inlp1 != row1->len ) 7241 { 7242 int tmpilp; 7243 int tmpinlp; 7244 7245 assert(ilp2 == row2->nlpcols || inlp2 == row2->len); 7246 7247 SCIPswapPointers((void**) &row1, (void**) &row2); 7248 SCIPswapPointers((void**) &row1colsidx, (void**) &row2colsidx); 7249 tmpilp = ilp1; 7250 tmpinlp = inlp1; 7251 ilp1 = ilp2; 7252 inlp1 = inlp2; 7253 ilp2 = tmpilp; 7254 inlp2 = tmpinlp; 7255 } 7256 7257 /* determine section of row 1 that we want to look at (current iterator = begin, end, LP-columns?) 7258 * -> this merges cases 4a) and 4b) 7259 */ 7260 if( ilp1 == row1->nlpcols ) 7261 { 7262 i1 = inlp1; 7263 end1 = row1->len; 7264 lpcols = FALSE; 7265 } 7266 else 7267 { 7268 assert(inlp1 == row1->len); 7269 7270 i1 = ilp1; 7271 end1 = row1->nlpcols; 7272 lpcols = TRUE; 7273 } 7274 7275 /* handle the case of three partitions (case 4) until one partition is finished, this reduces our problem to case 1), 2), or 5); 7276 * case 5) will fail the while-condition 7277 */ 7278 while( i1 < end1 && ilp2 < row2->nlpcols && inlp2 < row2->len ) 7279 { 7280 assert(row1->cols[i1]->index == row1colsidx[i1]); 7281 assert(row2->cols[ilp2]->index == row2colsidx[ilp2]); 7282 assert(row2->cols[inlp2]->index == row2colsidx[inlp2]); 7283 assert((row1->cols[i1] == row2->cols[ilp2]) == (row1colsidx[i1] == row2colsidx[ilp2])); 7284 assert((row1->cols[i1] == row2->cols[inlp2]) == (row1colsidx[i1] == row2colsidx[inlp2])); 7285 7286 /* current column in row 1 is the same as the current LP column in row 2 */ 7287 if( row1colsidx[i1] == row2colsidx[ilp2] ) 7288 { 7289 scalarprod += row1->vals[i1] * row2->vals[ilp2]; 7290 ++i1; 7291 ++ilp2; 7292 } 7293 /* linked or unlinked LP column of row1 is the same as unlinked column of row2 */ 7294 else if( row1colsidx[i1] == row2colsidx[inlp2] && (lpcols || row1->cols[i1]->lppos >= 0) ) 7295 { 7296 scalarprod += row1->vals[i1] * row2->vals[inlp2]; 7297 ++i1; 7298 ++inlp2; 7299 } 7300 /* increase smallest counter */ 7301 else if( row2colsidx[ilp2] < row2colsidx[inlp2] ) 7302 { 7303 if( row1colsidx[i1] < row2colsidx[ilp2] ) 7304 ++i1; 7305 else 7306 ++ilp2; 7307 } 7308 else 7309 { 7310 if( row1colsidx[i1] < row2colsidx[inlp2] ) 7311 ++i1; 7312 else 7313 ++inlp2; 7314 } 7315 } 7316 7317 /* if the second section of row 1 was finished, we can stop; otherwise, we have to consider the remaining parts of 7318 * the two rows 7319 */ 7320 if( i1 < end1 ) 7321 { 7322 /* determine section of row 2 that we want to look at (current iterator = begin, end, LP-columns?) */ 7323 if( ilp2 == row2->nlpcols ) 7324 { 7325 i2 = inlp2; 7326 end2 = row2->len; 7327 lpcols = FALSE; 7328 } 7329 else 7330 { 7331 assert(inlp2 == row2->len); 7332 7333 i2 = ilp2; 7334 end2 = row2->nlpcols; 7335 } 7336 7337 /* handle the case of two partitions (standard case 5, or case 1 or 2 due to partition reduction) */ 7338 while( i1 < end1 && i2 < end2 ) 7339 { 7340 assert(row1->cols[i1]->index == row1colsidx[i1]); 7341 assert(row2->cols[i2]->index == row2colsidx[i2]); 7342 assert((row1->cols[i1] == row2->cols[i2]) == (row1colsidx[i1] == row2colsidx[i2])); 7343 7344 /* linked or unlinked LP column of row1 is the same as linked or unlinked LP column of row2 */ 7345 if( row1colsidx[i1] == row2colsidx[i2] && (lpcols || row1->cols[i1]->lppos >= 0) ) 7346 { 7347 scalarprod += row1->vals[i1] * row2->vals[i2]; 7348 ++i1; 7349 ++i2; 7350 } 7351 /* increase smallest counter */ 7352 else if( row1colsidx[i1] < row2colsidx[i2] ) 7353 ++i1; 7354 else 7355 ++i2; 7356 } 7357 } 7358 } 7359 7360 return scalarprod; 7361 } 7362 7363 /** returns the discrete scalar product of the coefficient vectors of the two given rows */ 7364 static 7365 int SCIProwGetDiscreteScalarProduct( 7366 SCIP_ROW* row1, /**< first LP row */ 7367 SCIP_ROW* row2 /**< second LP row */ 7368 ) 7369 { 7370 int prod; 7371 int* row1colsidx; 7372 int* row2colsidx; 7373 int i1; 7374 int i2; 7375 7376 assert(row1 != NULL); 7377 assert(row2 != NULL); 7378 7379 /* Sort the column indices of both rows. 7380 * 7381 * The columns in a row are divided into two parts: LP columns, which are currently in the LP and non-LP columns; 7382 * we sort the rows, but that only ensures that within these two parts, columns are sorted w.r.t. their index. 7383 * Normally, this should be suficient, because a column contained in both rows should either be one of the LP columns 7384 * for both or one of the non-LP columns for both. 7385 * However, directly after a row was created, before a row is added to the LP, the row is not linked to all its 7386 * columns and all columns are treated as non-LP columns. Moreover, for example when doing column generation, 7387 * columns can be added later and remain unlinked while all previously added columns might already be linked. 7388 * Therefore, we have to be very careful about whether we can rely on the partitioning of the variables. 7389 * 7390 * We distinguish the following cases: 7391 * 7392 * 1) both rows have no unlinked columns 7393 * -> we just check the LP partitions 7394 * 7395 * 2) exactly one row is completely unlinked, the other one is completely linked 7396 * -> we compare the non-LP (unlinked) partition with the LP partition of the other row 7397 * (thus all common LP columns are regarded) 7398 * 7399 * 3) we have unlinked and LP columns in both rows 7400 * -> we need to compare four partitions at once 7401 * 7402 * 4a) we have one row with unlinked and LP columns and the other without any unlinked columns 7403 * -> we need to compare three partitions: the LP part of the completely linked row and both partitions of the 7404 * other row 7405 * 7406 * 4b) we have one row with unlinked and LP columns and the other is completely unlinked 7407 * -> we need to compare three partitions: the complete unlinked row and both partitions of the other row 7408 * 7409 * 5) both rows are completely unlinked 7410 * -> we need to compare two partitions: both complete rows 7411 */ 7412 SCIProwSort(row1); 7413 assert(row1->lpcolssorted); 7414 assert(row1->nonlpcolssorted); 7415 SCIProwSort(row2); 7416 assert(row2->lpcolssorted); 7417 assert(row2->nonlpcolssorted); 7418 7419 assert(row1->nunlinked <= row1->len - row1->nlpcols); 7420 assert(row2->nunlinked <= row2->len - row2->nlpcols); 7421 7422 row1colsidx = row1->cols_index; 7423 row2colsidx = row2->cols_index; 7424 7425 #ifndef NDEBUG 7426 /* check that we can rely on the partition into LP columns and non-LP columns if the rows are completely linked */ 7427 if( row1->nunlinked == 0 && row2->nunlinked == 0 ) 7428 { 7429 i1 = 0; 7430 i2 = row2->nlpcols; 7431 while( i1 < row1->nlpcols && i2 < row2->len ) 7432 { 7433 assert(row1->cols[i1] != row2->cols[i2]); 7434 if( row1->cols[i1]->index < row2->cols[i2]->index ) 7435 ++i1; 7436 else 7437 { 7438 assert(row1->cols[i1]->index > row2->cols[i2]->index); 7439 ++i2; 7440 } 7441 } 7442 assert(i1 == row1->nlpcols || i2 == row2->len); 7443 7444 i1 = row1->nlpcols; 7445 i2 = 0; 7446 while( i1 < row1->len && i2 < row2->nlpcols ) 7447 { 7448 assert(row1->cols[i1] != row2->cols[i2]); 7449 if( row1->cols[i1]->index < row2->cols[i2]->index ) 7450 ++i1; 7451 else 7452 { 7453 assert(row1->cols[i1]->index > row2->cols[i2]->index); 7454 ++i2; 7455 } 7456 } 7457 assert(i1 == row1->len || i2 == row2->nlpcols); 7458 } 7459 #endif 7460 7461 /* The "easy" cases 1) and 2) */ 7462 if( (row1->nunlinked == 0 && row2->nunlinked == 0) || 7463 ((row1->nlpcols == row1->len || row1->nunlinked == row1->len) 7464 && (row2->nlpcols == row2->len || row2->nunlinked == row2->len) 7465 && (row1->nunlinked == 0 || row2->nunlinked == 0)) ) 7466 { 7467 assert(row1->nunlinked == 0 || row1->nunlinked == row1->len); 7468 assert(row2->nunlinked == 0 || row2->nunlinked == row2->len); 7469 7470 /* set the iterators to the last column we want to regard in the row: nunlinked is either 0 or row->len, 7471 * therefore, we get nlpcols if nunlinked is 0 and row->len if the row is completely unlinked 7472 */ 7473 i1 = MAX(row1->nlpcols, row1->nunlinked) - 1; 7474 i2 = MAX(row2->nlpcols, row2->nunlinked) - 1; 7475 prod = 0; 7476 7477 /* calculate the scalar product */ 7478 while( i1 >= 0 && i2 >= 0 ) 7479 { 7480 assert(row1->cols[i1]->index == row1colsidx[i1]); 7481 assert(row2->cols[i2]->index == row2colsidx[i2]); 7482 assert((row1->cols[i1] == row2->cols[i2]) == (row1colsidx[i1] == row2colsidx[i2])); 7483 if( row1colsidx[i1] < row2colsidx[i2] ) 7484 --i2; 7485 else if( row1colsidx[i1] > row2colsidx[i2] ) 7486 --i1; 7487 else 7488 { 7489 ++prod; 7490 --i1; 7491 --i2; 7492 } 7493 } 7494 } 7495 /* the "harder" cases 3) - 5): start with four partitions and reduce their number iteratively */ 7496 else 7497 { 7498 SCIP_Bool lpcols; 7499 int ilp1; 7500 int inlp1; 7501 int ilp2; 7502 int inlp2; 7503 int end1; 7504 int end2; 7505 7506 prod = 0; 7507 ilp1 = 0; 7508 ilp2 = 0; 7509 7510 /* if a row is completely linked (case 4a), we do not have to consider its non-LP columns */ 7511 inlp1 = (row1->nunlinked > 0 ? row1->nlpcols : row1->len); 7512 inlp2 = (row2->nunlinked > 0 ? row2->nlpcols : row2->len); 7513 7514 /* handle the case of four partitions (case 3) until one partition is finished; 7515 * cases 4a), 4b), and 5) will fail the while-condition 7516 */ 7517 while( ilp1 < row1->nlpcols && inlp1 < row1->len && ilp2 < row2->nlpcols && inlp2 < row2->len ) 7518 { 7519 assert(row1->cols[ilp1]->index == row1colsidx[ilp1]); 7520 assert(row1->cols[inlp1]->index == row1colsidx[inlp1]); 7521 assert(row2->cols[ilp2]->index == row2colsidx[ilp2]); 7522 assert(row2->cols[inlp2]->index == row2colsidx[inlp2]); 7523 assert((row1->cols[ilp1] == row2->cols[ilp2]) == (row1colsidx[ilp1] == row2colsidx[ilp2])); 7524 assert((row1->cols[ilp1] == row2->cols[inlp2]) == (row1colsidx[ilp1] == row2colsidx[inlp2])); 7525 assert((row1->cols[inlp1] == row2->cols[ilp2]) == (row1colsidx[inlp1] == row2colsidx[ilp2])); 7526 assert((row1->cols[inlp1] == row2->cols[inlp2]) == (row1colsidx[inlp1] == row2colsidx[inlp2])); 7527 7528 /* rows have the same linked LP columns */ 7529 if( row1colsidx[ilp1] == row2colsidx[ilp2] ) 7530 { 7531 ++prod; 7532 ++ilp1; 7533 ++ilp2; 7534 } 7535 /* LP column of row1 is the same as unlinked column of row2 */ 7536 else if( row1colsidx[ilp1] == row2colsidx[inlp2] ) 7537 { 7538 ++prod; 7539 ++ilp1; 7540 ++inlp2; 7541 } 7542 /* unlinked column of row1 is the same as LP column of row2 */ 7543 else if( row1colsidx[inlp1] == row2colsidx[ilp2] ) 7544 { 7545 ++prod; 7546 ++inlp1; 7547 ++ilp2; 7548 } 7549 /* two unlinked LP columns are the same */ 7550 else if( row1colsidx[inlp1] == row2colsidx[inlp2] && row1->cols[inlp1]->lppos >= 0 ) 7551 { 7552 ++prod; 7553 ++inlp1; 7554 ++inlp2; 7555 } 7556 /* increase smallest counter */ 7557 else if( row1colsidx[ilp1] < row1colsidx[inlp1] ) 7558 { 7559 if( row2colsidx[ilp2] < row2colsidx[inlp2] ) 7560 { 7561 if( row1colsidx[ilp1] < row2colsidx[ilp2] ) 7562 ++ilp1; 7563 else 7564 ++ilp2; 7565 } 7566 else 7567 { 7568 if( row1colsidx[ilp1] < row2colsidx[inlp2] ) 7569 ++ilp1; 7570 else 7571 ++inlp2; 7572 } 7573 } 7574 else 7575 { 7576 if( row2colsidx[ilp2] < row2colsidx[inlp2] ) 7577 { 7578 if( row1colsidx[inlp1] < row2colsidx[ilp2] ) 7579 ++inlp1; 7580 else 7581 ++ilp2; 7582 } 7583 else 7584 { 7585 if( row1colsidx[inlp1] < row2colsidx[inlp2] ) 7586 ++inlp1; 7587 else 7588 ++inlp2; 7589 } 7590 } 7591 } 7592 7593 /* One partition was completely handled, we just have to handle the three remaining partitions: 7594 * the remaining partition of this row and the two partitions of the other row. 7595 * If necessary, we swap the partitions to ensure that row1 is the row with only one remaining partition. 7596 */ 7597 if( ilp1 != row1->nlpcols && inlp1 != row1->len ) 7598 { 7599 int tmpilp; 7600 int tmpinlp; 7601 7602 assert(ilp2 == row2->nlpcols || inlp2 == row2->len); 7603 7604 SCIPswapPointers((void**) &row1, (void**) &row2); 7605 SCIPswapPointers((void**) &row1colsidx, (void**) &row2colsidx); 7606 tmpilp = ilp1; 7607 tmpinlp = inlp1; 7608 ilp1 = ilp2; 7609 inlp1 = inlp2; 7610 ilp2 = tmpilp; 7611 inlp2 = tmpinlp; 7612 } 7613 7614 /* determine section of row 1 that we want to look at (current iterator = begin, end, LP-columns?) 7615 * -> this merges cases 4a) and 4b) 7616 */ 7617 if( ilp1 == row1->nlpcols ) 7618 { 7619 i1 = inlp1; 7620 end1 = row1->len; 7621 lpcols = FALSE; 7622 } 7623 else 7624 { 7625 assert(inlp1 == row1->len); 7626 7627 i1 = ilp1; 7628 end1 = row1->nlpcols; 7629 lpcols = TRUE; 7630 } 7631 7632 /* handle the case of three partitions (case 4) until one partition is finished, this reduces our problem to case 1), 2), or 5); 7633 * case 5) will fail the while-condition 7634 */ 7635 while( i1 < end1 && ilp2 < row2->nlpcols && inlp2 < row2->len ) 7636 { 7637 assert(row1->cols[i1]->index == row1colsidx[i1]); 7638 assert(row2->cols[ilp2]->index == row2colsidx[ilp2]); 7639 assert(row2->cols[inlp2]->index == row2colsidx[inlp2]); 7640 assert((row1->cols[i1] == row2->cols[ilp2]) == (row1colsidx[i1] == row2colsidx[ilp2])); 7641 assert((row1->cols[i1] == row2->cols[inlp2]) == (row1colsidx[i1] == row2colsidx[inlp2])); 7642 7643 /* current column in row 1 is the same as the current LP column in row 2 */ 7644 if( row1colsidx[i1] == row2colsidx[ilp2] ) 7645 { 7646 ++prod; 7647 ++i1; 7648 ++ilp2; 7649 } 7650 /* linked or unlinked LP column of row1 is the same as unlinked column of row2 */ 7651 else if( row1colsidx[i1] == row2colsidx[inlp2] && (lpcols || row1->cols[i1]->lppos >= 0) ) 7652 { 7653 ++prod; 7654 ++i1; 7655 ++inlp2; 7656 } 7657 /* increase smallest counter */ 7658 else if( row2colsidx[ilp2] < row2colsidx[inlp2] ) 7659 { 7660 if( row1colsidx[i1] < row2colsidx[ilp2] ) 7661 ++i1; 7662 else 7663 ++ilp2; 7664 } 7665 else 7666 { 7667 if( row1colsidx[i1] < row2colsidx[inlp2] ) 7668 ++i1; 7669 else 7670 ++inlp2; 7671 } 7672 } 7673 7674 /* if the second section of row 1 was finished, we can stop; otherwise, we have to consider the remaining parts of 7675 * the two rows 7676 */ 7677 if( i1 < end1 ) 7678 { 7679 /* determine section of row 2 that we want to look at (current iterator = begin, end, LP-columns?) */ 7680 if( ilp2 == row2->nlpcols ) 7681 { 7682 i2 = inlp2; 7683 end2 = row2->len; 7684 lpcols = FALSE; 7685 } 7686 else 7687 { 7688 assert(inlp2 == row2->len); 7689 7690 i2 = ilp2; 7691 end2 = row2->nlpcols; 7692 } 7693 7694 /* handle the case of two partitions (standard case 5, or case 1 or 2 due to partition reduction) */ 7695 while( i1 < end1 && i2 < end2 ) 7696 { 7697 assert(row1->cols[i1]->index == row1colsidx[i1]); 7698 assert(row2->cols[i2]->index == row2colsidx[i2]); 7699 assert((row1->cols[i1] == row2->cols[i2]) == (row1colsidx[i1] == row2colsidx[i2])); 7700 7701 /* linked or unlinked LP column of row1 is the same as linked or unlinked LP column of row2 */ 7702 if( row1colsidx[i1] == row2colsidx[i2] && (lpcols || row1->cols[i1]->lppos >= 0) ) 7703 { 7704 ++prod; 7705 ++i1; 7706 ++i2; 7707 } 7708 /* increase smallest counter */ 7709 else if( row1colsidx[i1] < row2colsidx[i2] ) 7710 ++i1; 7711 else 7712 ++i2; 7713 } 7714 } 7715 } 7716 7717 return prod; 7718 } 7719 7720 /** returns the degree of parallelism between the hyperplanes defined by the two row vectors v, w: 7721 * p = |v*w|/(|v|*|w|); 7722 * the hyperplanes are parallel, iff p = 1, they are orthogonal, iff p = 0 7723 */ 7724 SCIP_Real SCIProwGetParallelism( 7725 SCIP_ROW* row1, /**< first LP row */ 7726 SCIP_ROW* row2, /**< second LP row */ 7727 char orthofunc /**< function used for calc. scalar prod. ('e'uclidean, 'd'iscrete) */ 7728 ) 7729 { 7730 SCIP_Real parallelism; 7731 SCIP_Real scalarprod; 7732 7733 switch( orthofunc ) 7734 { 7735 case 'e': 7736 scalarprod = SCIProwGetScalarProduct(row1, row2); 7737 if( scalarprod == 0.0 ) 7738 { 7739 parallelism = 0.0; 7740 break; 7741 } 7742 7743 if( SCIProwGetNorm(row1) == 0.0 ) 7744 { 7745 /* In theory, this should not happen if the scalarproduct is not zero 7746 * But due to bug 520 (also issue 44), it is possible that norms are not correct. 7747 * Thus, if the norm is so bad that it is even 0, then reevaluate it here. 7748 * But as we don't have set available here, we cannot call rowCalcNorms, so do it by hand. 7749 */ 7750 int i; 7751 for( i = 0; i < row1->len; ++i ) 7752 if( row1->cols[i]->lppos >= 0 ) 7753 row1->sqrnorm += SQR(row1->vals[i]); 7754 assert(SCIProwGetNorm(row1) != 0.0); 7755 } 7756 7757 if( SCIProwGetNorm(row2) == 0.0 ) 7758 { 7759 /* same as for row1 above: reeval norms if it is 0, which is wrong */ 7760 int i; 7761 for( i = 0; i < row2->len; ++i ) 7762 if( row2->cols[i]->lppos >= 0 ) 7763 row2->sqrnorm += SQR(row2->vals[i]); 7764 assert(SCIProwGetNorm(row2) != 0.0); 7765 } 7766 7767 parallelism = REALABS(scalarprod) / (SCIProwGetNorm(row1) * SCIProwGetNorm(row2)); 7768 break; 7769 7770 case 'd': 7771 scalarprod = (SCIP_Real) SCIProwGetDiscreteScalarProduct(row1, row2); 7772 parallelism = scalarprod / (sqrt((SCIP_Real) SCIProwGetNNonz(row1)) * sqrt((SCIP_Real) SCIProwGetNNonz(row2))); 7773 break; 7774 7775 default: 7776 SCIPerrorMessage("invalid orthogonality function parameter '%c'\n", orthofunc); 7777 SCIPABORT(); 7778 parallelism = 0.0; /*lint !e527*/ 7779 } 7780 7781 return parallelism; 7782 } 7783 7784 /** returns the degree of orthogonality between the hyperplanes defined by the two row vectors v, w: 7785 * o = 1 - |v*w|/(|v|*|w|); 7786 * the hyperplanes are orthogonal, iff p = 1, they are parallel, iff p = 0 7787 */ 7788 SCIP_Real SCIProwGetOrthogonality( 7789 SCIP_ROW* row1, /**< first LP row */ 7790 SCIP_ROW* row2, /**< second LP row */ 7791 char orthofunc /**< function used for calc. scalar prod. ('e'uclidean, 'd'iscrete) */ 7792 ) 7793 { 7794 return 1.0 - SCIProwGetParallelism(row1, row2, orthofunc); 7795 } 7796 7797 /** gets parallelism of row with objective function: if the returned value is 1, the row is parallel to the objective 7798 * function, if the value is 0, it is orthogonal to the objective function 7799 */ 7800 SCIP_Real SCIProwGetObjParallelism( 7801 SCIP_ROW* row, /**< LP row */ 7802 SCIP_SET* set, /**< global SCIP settings */ 7803 SCIP_LP* lp /**< current LP data */ 7804 ) 7805 { 7806 SCIP_Real prod; 7807 SCIP_Real parallelism; 7808 7809 assert(row != NULL); 7810 assert(lp != NULL); 7811 7812 if( lp->objsqrnormunreliable ) 7813 SCIPlpRecalculateObjSqrNorm(set, lp); 7814 7815 assert(!lp->objsqrnormunreliable); 7816 assert(lp->objsqrnorm >= 0.0); 7817 7818 checkRowSqrnorm(row); 7819 checkRowObjprod(row); 7820 7821 prod = row->sqrnorm * lp->objsqrnorm; 7822 7823 parallelism = SCIPsetIsPositive(set, prod) ? REALABS(row->objprod) / SQRT(prod) : 0.0; 7824 assert(SCIPsetIsSumGE(set, parallelism, 0.0)); 7825 assert(SCIPsetIsSumLE(set, parallelism, 1.0)); 7826 parallelism = MIN(parallelism, 1.0); 7827 parallelism = MAX(parallelism, 0.0); 7828 7829 return parallelism; 7830 } 7831 7832 /** includes event handler with given data in row's event filter */ 7833 SCIP_RETCODE SCIProwCatchEvent( 7834 SCIP_ROW* row, /**< row */ 7835 BMS_BLKMEM* blkmem, /**< block memory */ 7836 SCIP_SET* set, /**< global SCIP settings */ 7837 SCIP_EVENTTYPE eventtype, /**< event type to catch */ 7838 SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */ 7839 SCIP_EVENTDATA* eventdata, /**< event data to pass to the event handler for the event processing */ 7840 int* filterpos /**< pointer to store position of event filter entry, or NULL */ 7841 ) 7842 { 7843 assert(row != NULL); 7844 assert(row->eventfilter != NULL); 7845 assert((eventtype & ~SCIP_EVENTTYPE_ROWCHANGED) == 0); 7846 assert((eventtype & SCIP_EVENTTYPE_ROWCHANGED) != 0); 7847 7848 SCIPsetDebugMsg(set, "catch event of type 0x%" SCIP_EVENTTYPE_FORMAT " of row <%s> with handler %p and data %p\n", 7849 eventtype, row->name, (void*)eventhdlr, (void*)eventdata); 7850 7851 SCIP_CALL( SCIPeventfilterAdd(row->eventfilter, blkmem, set, eventtype, eventhdlr, eventdata, filterpos) ); 7852 7853 return SCIP_OKAY; 7854 } 7855 7856 /** deletes event handler with given data from row's event filter */ 7857 SCIP_RETCODE SCIProwDropEvent( 7858 SCIP_ROW* row, /**< row */ 7859 BMS_BLKMEM* blkmem, /**< block memory */ 7860 SCIP_SET* set, /**< global SCIP settings */ 7861 SCIP_EVENTTYPE eventtype, /**< event type mask of dropped event */ 7862 SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */ 7863 SCIP_EVENTDATA* eventdata, /**< event data to pass to the event handler for the event processing */ 7864 int filterpos /**< position of event filter entry returned by SCIPvarCatchEvent(), or -1 */ 7865 ) 7866 { 7867 assert(row != NULL); 7868 assert(row->eventfilter != NULL); 7869 7870 SCIPsetDebugMsg(set, "drop event of row <%s> with handler %p and data %p\n", row->name, (void*)eventhdlr, (void*)eventdata); 7871 7872 SCIP_CALL( SCIPeventfilterDel(row->eventfilter, blkmem, set, eventtype, eventhdlr, eventdata, filterpos) ); 7873 7874 return SCIP_OKAY; 7875 } 7876 7877 /** marks a row to be not removable from the LP in the current node because it became obsolete */ 7878 void SCIProwMarkNotRemovableLocal( 7879 SCIP_ROW* row, /**< LP row */ 7880 SCIP_STAT* stat /**< problem statistics */ 7881 ) 7882 { 7883 assert(row != NULL); 7884 assert(stat != NULL); 7885 assert(stat->nnodes > 0); 7886 7887 /* lpRemoveObsoleteRows() does not remove a row if the node number stored in obsoletenode equals the current node number */ 7888 row->obsoletenode = stat->nnodes; 7889 } 7890 7891 /* 7892 * LP solver data update 7893 */ 7894 7895 /** resets column data to represent a column not in the LP solver */ 7896 static 7897 void markColDeleted( 7898 SCIP_COL* col /**< column to be marked deleted */ 7899 ) 7900 { 7901 assert(col != NULL); 7902 7903 col->lpipos = -1; 7904 col->primsol = 0.0; 7905 col->redcost = SCIP_INVALID; 7906 col->farkascoef = SCIP_INVALID; 7907 col->sbdown = SCIP_INVALID; 7908 col->sbup = SCIP_INVALID; 7909 col->sbdownvalid = FALSE; 7910 col->sbupvalid = FALSE; 7911 col->validredcostlp = -1; 7912 col->validfarkaslp = -1; 7913 col->sbitlim = -1; 7914 col->basisstatus = SCIP_BASESTAT_ZERO; /*lint !e641*/ 7915 } 7916 7917 /** applies all cached column removals to the LP solver */ 7918 static 7919 SCIP_RETCODE lpFlushDelCols( 7920 SCIP_LP* lp /**< current LP data */ 7921 ) 7922 { 7923 assert(lp != NULL); 7924 assert(lp->lpifirstchgcol <= lp->nlpicols); 7925 assert(lp->lpifirstchgcol <= lp->ncols); 7926 7927 /* find the first column to change */ 7928 while( lp->lpifirstchgcol < lp->nlpicols 7929 && lp->lpifirstchgcol < lp->ncols 7930 && lp->cols[lp->lpifirstchgcol]->lpipos == lp->lpifirstchgcol 7931 && !lp->cols[lp->lpifirstchgcol]->coefchanged ) 7932 { 7933 assert(lp->cols[lp->lpifirstchgcol] == lp->lpicols[lp->lpifirstchgcol]); 7934 lp->lpifirstchgcol++; 7935 } 7936 7937 /* shrink LP to the part which didn't change */ 7938 if( lp->lpifirstchgcol < lp->nlpicols ) 7939 { 7940 int i; 7941 7942 assert(!lp->diving); 7943 SCIPdebugMessage("flushing col deletions: shrink LP from %d to %d columns\n", lp->nlpicols, lp->lpifirstchgcol); 7944 SCIP_CALL( SCIPlpiDelCols(lp->lpi, lp->lpifirstchgcol, lp->nlpicols-1) ); 7945 for( i = lp->lpifirstchgcol; i < lp->nlpicols; ++i ) 7946 { 7947 markColDeleted(lp->lpicols[i]); 7948 } 7949 lp->nlpicols = lp->lpifirstchgcol; 7950 lp->flushdeletedcols = TRUE; 7951 lp->updateintegrality = TRUE; 7952 7953 /* mark the LP unsolved */ 7954 lp->solved = FALSE; 7955 lp->primalfeasible = FALSE; 7956 lp->primalchecked = FALSE; 7957 lp->lpobjval = SCIP_INVALID; 7958 lp->lpsolstat = SCIP_LPSOLSTAT_NOTSOLVED; 7959 } 7960 assert(lp->nlpicols == lp->lpifirstchgcol); 7961 7962 return SCIP_OKAY; 7963 } 7964 7965 /** computes for the given column the lower and upper bound that should be flushed into the LP 7966 * depending on lazy bounds and diving mode; in diving mode, lazy bounds are ignored, i.e., 7967 * the bounds are explicitly added to the LP in any case 7968 */ 7969 static 7970 void computeLPBounds( 7971 SCIP_LP* lp, /**< current LP data */ 7972 SCIP_SET* set, /**< global SCIP settings */ 7973 SCIP_COL* col, /**< column to compute bounds for */ 7974 SCIP_Real lpiinf, /**< infinity value if the LP solver */ 7975 SCIP_Real* lb, /**< pointer to store the new lower bound */ 7976 SCIP_Real* ub /**< pointer to store the new upper bound */ 7977 ) 7978 { 7979 assert(lp != NULL); 7980 assert(set != NULL); 7981 assert(col != NULL); 7982 assert(lb != NULL); 7983 assert(ub != NULL); 7984 7985 /* get the correct new lower bound: 7986 * if lazy lower bound exists and is larger than lower bound, set lower bound to infinity; 7987 * if we are in diving mode, ignore lazy bounds and always take the lower bound 7988 */ 7989 if( SCIPsetIsInfinity(set, -col->lb) || (SCIPsetIsLE(set, col->lb, col->lazylb) && !SCIPlpDiving(lp)) ) 7990 (*lb) = -lpiinf; 7991 else 7992 (*lb) = col->lb; 7993 /* get the correct new upper bound: 7994 * if lazy upper bound exists and is larger than upper bound, set upper bound to infinity; 7995 * if we are in diving mode, ignore lazy bounds and always take the upper bound 7996 */ 7997 if( SCIPsetIsInfinity(set, col->ub) || (SCIPsetIsGE(set, col->ub, col->lazyub) && !SCIPlpDiving(lp)) ) 7998 (*ub) = lpiinf; 7999 else 8000 (*ub) = col->ub; 8001 } 8002 8003 /** applies all cached column additions to the LP solver */ 8004 static 8005 SCIP_RETCODE lpFlushAddCols( 8006 SCIP_LP* lp, /**< current LP data */ 8007 BMS_BLKMEM* blkmem, /**< block memory */ 8008 SCIP_SET* set, /**< global SCIP settings */ 8009 SCIP_EVENTQUEUE* eventqueue /**< event queue */ 8010 ) 8011 { 8012 SCIP_Real* obj; 8013 SCIP_Real* lb; 8014 SCIP_Real* ub; 8015 int* beg; 8016 int* ind; 8017 SCIP_Real* val; 8018 char** name; 8019 SCIP_COL* col; 8020 SCIP_Real lpiinf; 8021 int c; 8022 int pos; 8023 int nnonz; 8024 int naddcols; 8025 int naddcoefs; 8026 int i; 8027 int lpipos; 8028 8029 assert(lp != NULL); 8030 assert(lp->lpifirstchgcol == lp->nlpicols); 8031 assert(blkmem != NULL); 8032 assert(set != NULL); 8033 8034 /* if there are no columns to add, we are ready */ 8035 if( lp->ncols == lp->nlpicols ) 8036 return SCIP_OKAY; 8037 8038 /* add the additional columns */ 8039 assert(!lp->diving); 8040 assert(lp->ncols > lp->nlpicols); 8041 SCIP_CALL( ensureLpicolsSize(lp, set, lp->ncols) ); 8042 8043 /* get the solver's infinity value */ 8044 lpiinf = SCIPlpiInfinity(lp->lpi); 8045 8046 /* count the (maximal) number of added coefficients, calculate the number of added columns */ 8047 naddcols = lp->ncols - lp->nlpicols; 8048 naddcoefs = 0; 8049 for( c = lp->nlpicols; c < lp->ncols; ++c ) 8050 naddcoefs += lp->cols[c]->len; 8051 assert(naddcols > 0); 8052 8053 /* get temporary memory for changes */ 8054 SCIP_CALL( SCIPsetAllocBufferArray(set, &obj, naddcols) ); 8055 SCIP_CALL( SCIPsetAllocBufferArray(set, &lb, naddcols) ); 8056 SCIP_CALL( SCIPsetAllocBufferArray(set, &ub, naddcols) ); 8057 SCIP_CALL( SCIPsetAllocBufferArray(set, &beg, naddcols) ); 8058 SCIP_CALL( SCIPsetAllocBufferArray(set, &ind, naddcoefs) ); 8059 SCIP_CALL( SCIPsetAllocBufferArray(set, &val, naddcoefs) ); 8060 SCIP_CALL( SCIPsetAllocBufferArray(set, &name, naddcols) ); 8061 8062 /* fill temporary memory with column data */ 8063 nnonz = 0; 8064 for( pos = 0, c = lp->nlpicols; c < lp->ncols; ++pos, ++c ) 8065 { 8066 col = lp->cols[c]; 8067 assert(col != NULL); 8068 assert(col->var != NULL); 8069 assert(SCIPvarGetStatus(col->var) == SCIP_VARSTATUS_COLUMN); 8070 assert(SCIPvarGetCol(col->var) == col); 8071 assert(col->lppos == c); 8072 assert(nnonz + col->nlprows <= naddcoefs); 8073 8074 SCIPsetDebugMsg(set, "flushing added column <%s>: ", SCIPvarGetName(col->var)); 8075 debugColPrint(set, col); 8076 8077 /* Because the column becomes a member of the LP solver, it now can take values 8078 * different from zero. That means, we have to include the column in the corresponding 8079 * row vectors. 8080 */ 8081 SCIP_CALL( colLink(col, blkmem, set, eventqueue, lp) ); 8082 8083 lp->lpicols[c] = col; 8084 col->lpipos = c; 8085 col->primsol = SCIP_INVALID; 8086 col->redcost = SCIP_INVALID; 8087 col->farkascoef = SCIP_INVALID; 8088 col->sbdown = SCIP_INVALID; 8089 col->sbup = SCIP_INVALID; 8090 col->sbdownvalid = FALSE; 8091 col->sbupvalid = FALSE; 8092 col->validredcostlp = -1; 8093 col->validfarkaslp = -1; 8094 col->sbitlim = -1; 8095 col->objchanged = FALSE; 8096 col->lbchanged = FALSE; 8097 col->ubchanged = FALSE; 8098 col->coefchanged = FALSE; 8099 obj[pos] = col->obj; 8100 8101 /* compute bounds that should be flushed into the LP (taking into account lazy bounds) */ 8102 computeLPBounds(lp, set, col, lpiinf, &(lb[pos]), &(ub[pos])); 8103 8104 beg[pos] = nnonz; 8105 name[pos] = (char*)SCIPvarGetName(col->var); 8106 8107 col->flushedobj = obj[pos]; 8108 col->flushedlb = lb[pos]; 8109 col->flushedub = ub[pos]; 8110 8111 for( i = 0; i < col->nlprows; ++i ) 8112 { 8113 assert(col->rows[i] != NULL); 8114 lpipos = col->rows[i]->lpipos; 8115 if( lpipos >= 0 ) 8116 { 8117 assert(lpipos < lp->nrows); 8118 assert(nnonz < naddcoefs); 8119 ind[nnonz] = lpipos; 8120 val[nnonz] = col->vals[i]; 8121 nnonz++; 8122 } 8123 } 8124 #ifndef NDEBUG 8125 for( i = col->nlprows; i < col->len; ++i ) 8126 { 8127 assert(col->rows[i] != NULL); 8128 assert(col->rows[i]->lpipos == -1); /* because the row deletions are already performed */ 8129 } 8130 #endif 8131 } 8132 8133 /* call LP interface */ 8134 SCIPsetDebugMsg(set, "flushing col additions: enlarge LP from %d to %d columns\n", lp->nlpicols, lp->ncols); 8135 SCIP_CALL( SCIPlpiAddCols(lp->lpi, naddcols, obj, lb, ub, name, nnonz, beg, ind, val) ); 8136 lp->nlpicols = lp->ncols; 8137 lp->lpifirstchgcol = lp->nlpicols; 8138 8139 /* free temporary memory */ 8140 SCIPsetFreeBufferArray(set, &name); 8141 SCIPsetFreeBufferArray(set, &val); 8142 SCIPsetFreeBufferArray(set, &ind); 8143 SCIPsetFreeBufferArray(set, &beg); 8144 SCIPsetFreeBufferArray(set, &ub); 8145 SCIPsetFreeBufferArray(set, &lb); 8146 SCIPsetFreeBufferArray(set, &obj); 8147 8148 lp->flushaddedcols = TRUE; 8149 lp->updateintegrality = TRUE; 8150 8151 /* mark the LP unsolved */ 8152 lp->solved = FALSE; 8153 lp->dualfeasible = FALSE; 8154 lp->dualchecked = FALSE; 8155 lp->lpobjval = SCIP_INVALID; 8156 lp->lpsolstat = SCIP_LPSOLSTAT_NOTSOLVED; 8157 8158 return SCIP_OKAY; 8159 } 8160 8161 /** resets row data to represent a row not in the LP solver */ 8162 static 8163 void markRowDeleted( 8164 SCIP_ROW* row /**< row to be marked deleted */ 8165 ) 8166 { 8167 assert(row != NULL); 8168 8169 row->lpipos = -1; 8170 row->dualsol = 0.0; 8171 row->activity = SCIP_INVALID; 8172 row->dualfarkas = 0.0; 8173 row->basisstatus = SCIP_BASESTAT_BASIC; /*lint !e641*/ 8174 row->validactivitylp = -1; 8175 } 8176 8177 /** applies all cached row removals to the LP solver */ 8178 static 8179 SCIP_RETCODE lpFlushDelRows( 8180 SCIP_LP* lp, /**< current LP data */ 8181 BMS_BLKMEM* blkmem, /**< block memory */ 8182 SCIP_SET* set /**< global SCIP settings */ 8183 ) 8184 { 8185 assert(lp != NULL); 8186 assert(lp->lpifirstchgrow <= lp->nlpirows); 8187 assert(lp->lpifirstchgrow <= lp->nrows); 8188 8189 /* find the first row to change */ 8190 while( lp->lpifirstchgrow < lp->nlpirows 8191 && lp->lpifirstchgrow < lp->nrows 8192 && lp->rows[lp->lpifirstchgrow]->lpipos == lp->lpifirstchgrow 8193 && !lp->rows[lp->lpifirstchgrow]->coefchanged ) 8194 { 8195 assert(lp->rows[lp->lpifirstchgrow] == lp->lpirows[lp->lpifirstchgrow]); 8196 lp->lpifirstchgrow++; 8197 } 8198 8199 /* shrink LP to the part which didn't change */ 8200 if( lp->lpifirstchgrow < lp->nlpirows ) 8201 { 8202 int i; 8203 8204 SCIPsetDebugMsg(set, "flushing row deletions: shrink LP from %d to %d rows\n", lp->nlpirows, lp->lpifirstchgrow); 8205 SCIP_CALL( SCIPlpiDelRows(lp->lpi, lp->lpifirstchgrow, lp->nlpirows-1) ); 8206 for( i = lp->lpifirstchgrow; i < lp->nlpirows; ++i ) 8207 { 8208 markRowDeleted(lp->lpirows[i]); 8209 SCIP_CALL( SCIProwRelease(&lp->lpirows[i], blkmem, set, lp) ); 8210 } 8211 lp->nlpirows = lp->lpifirstchgrow; 8212 lp->flushdeletedrows = TRUE; 8213 8214 /* mark the LP unsolved */ 8215 lp->solved = FALSE; 8216 lp->dualfeasible = FALSE; 8217 lp->dualchecked = FALSE; 8218 lp->lpobjval = SCIP_INVALID; 8219 lp->lpsolstat = SCIP_LPSOLSTAT_NOTSOLVED; 8220 } 8221 assert(lp->nlpirows == lp->lpifirstchgrow); 8222 8223 return SCIP_OKAY; 8224 } 8225 8226 /** applies all cached row additions and removals to the LP solver */ 8227 static 8228 SCIP_RETCODE lpFlushAddRows( 8229 SCIP_LP* lp, /**< current LP data */ 8230 BMS_BLKMEM* blkmem, /**< block memory */ 8231 SCIP_SET* set, /**< global SCIP settings */ 8232 SCIP_EVENTQUEUE* eventqueue /**< event queue */ 8233 ) 8234 { 8235 SCIP_Real* lhs; 8236 SCIP_Real* rhs; 8237 int* beg; 8238 int* ind; 8239 SCIP_Real* val; 8240 char** name; 8241 SCIP_ROW* row; 8242 SCIP_Real lpiinf; 8243 int r; 8244 int pos; 8245 int nnonz; 8246 int naddrows; 8247 int naddcoefs; 8248 int i; 8249 int lpipos; 8250 8251 assert(lp != NULL); 8252 assert(lp->lpifirstchgrow == lp->nlpirows); 8253 assert(blkmem != NULL); 8254 8255 /* if there are no rows to add, we are ready */ 8256 if( lp->nrows == lp->nlpirows ) 8257 return SCIP_OKAY; 8258 8259 /* add the additional rows */ 8260 assert(lp->nrows > lp->nlpirows); 8261 SCIP_CALL( ensureLpirowsSize(lp, set, lp->nrows) ); 8262 8263 /* get the solver's infinity value */ 8264 lpiinf = SCIPlpiInfinity(lp->lpi); 8265 8266 /* count the (maximal) number of added coefficients, calculate the number of added rows */ 8267 naddrows = lp->nrows - lp->nlpirows; 8268 naddcoefs = 0; 8269 for( r = lp->nlpirows; r < lp->nrows; ++r ) 8270 naddcoefs += lp->rows[r]->len; 8271 assert(naddrows > 0); 8272 8273 /* get temporary memory for changes */ 8274 SCIP_CALL( SCIPsetAllocBufferArray(set, &lhs, naddrows) ); 8275 SCIP_CALL( SCIPsetAllocBufferArray(set, &rhs, naddrows) ); 8276 SCIP_CALL( SCIPsetAllocBufferArray(set, &beg, naddrows) ); 8277 SCIP_CALL( SCIPsetAllocBufferArray(set, &ind, naddcoefs) ); 8278 SCIP_CALL( SCIPsetAllocBufferArray(set, &val, naddcoefs) ); 8279 SCIP_CALL( SCIPsetAllocBufferArray(set, &name, naddrows) ); 8280 8281 /* fill temporary memory with row data */ 8282 nnonz = 0; 8283 for( pos = 0, r = lp->nlpirows; r < lp->nrows; ++pos, ++r ) 8284 { 8285 row = lp->rows[r]; 8286 assert(row != NULL); 8287 assert(row->lppos == r); 8288 assert(nnonz + row->nlpcols <= naddcoefs); 8289 8290 SCIPsetDebugMsg(set, "flushing added row <%s>: ", row->name); 8291 debugRowPrint(set, row); 8292 8293 /* Because the row becomes a member of the LP solver, its dual variable now can take values 8294 * different from zero. That means, we have to include the row in the corresponding 8295 * column vectors. 8296 */ 8297 SCIP_CALL( rowLink(row, blkmem, set, eventqueue, lp) ); 8298 8299 SCIProwCapture(row); 8300 lp->lpirows[r] = row; 8301 row->lpipos = r; 8302 row->dualsol = SCIP_INVALID; 8303 row->activity = SCIP_INVALID; 8304 row->dualfarkas = SCIP_INVALID; 8305 row->validactivitylp = -1; 8306 row->lhschanged = FALSE; 8307 row->rhschanged = FALSE; 8308 row->coefchanged = FALSE; 8309 if( SCIPsetIsInfinity(set, -row->lhs) ) 8310 lhs[pos] = -lpiinf; 8311 else 8312 lhs[pos] = row->lhs - row->constant; 8313 if( SCIPsetIsInfinity(set, row->rhs) ) 8314 rhs[pos] = lpiinf; 8315 else 8316 rhs[pos] = row->rhs - row->constant; 8317 beg[pos] = nnonz; 8318 name[pos] = row->name; 8319 8320 row->flushedlhs = lhs[pos]; 8321 row->flushedrhs = rhs[pos]; 8322 8323 SCIPsetDebugMsg(set, "flushing added row (SCIP_LPI): %+g <=", lhs[pos]); 8324 for( i = 0; i < row->nlpcols; ++i ) 8325 { 8326 assert(row->cols[i] != NULL); 8327 lpipos = row->cols[i]->lpipos; 8328 if( lpipos >= 0 ) 8329 { 8330 assert(lpipos < lp->ncols); 8331 assert(nnonz < naddcoefs); 8332 SCIPsetDebugMsgPrint(set, " %+gx%d(<%s>)", row->vals[i], lpipos+1, SCIPvarGetName(row->cols[i]->var)); 8333 ind[nnonz] = lpipos; 8334 val[nnonz] = row->vals[i]; 8335 nnonz++; 8336 } 8337 } 8338 SCIPsetDebugMsgPrint(set, " <= %+g\n", rhs[pos]); 8339 #ifndef NDEBUG 8340 for( i = row->nlpcols; i < row->len; ++i ) 8341 { 8342 assert(row->cols[i] != NULL); 8343 assert(row->cols[i]->lpipos == -1); /* because the column deletions are already performed */ 8344 } 8345 #endif 8346 } 8347 8348 /* call LP interface */ 8349 SCIPsetDebugMsg(set, "flushing row additions: enlarge LP from %d to %d rows\n", lp->nlpirows, lp->nrows); 8350 SCIP_CALL( SCIPlpiAddRows(lp->lpi, naddrows, lhs, rhs, name, nnonz, beg, ind, val) ); 8351 lp->nlpirows = lp->nrows; 8352 lp->lpifirstchgrow = lp->nlpirows; 8353 8354 /* free temporary memory */ 8355 SCIPsetFreeBufferArray(set, &name); 8356 SCIPsetFreeBufferArray(set, &val); 8357 SCIPsetFreeBufferArray(set, &ind); 8358 SCIPsetFreeBufferArray(set, &beg); 8359 SCIPsetFreeBufferArray(set, &rhs); 8360 SCIPsetFreeBufferArray(set, &lhs); 8361 8362 lp->flushaddedrows = TRUE; 8363 8364 /* mark the LP unsolved */ 8365 lp->solved = FALSE; 8366 lp->primalfeasible = FALSE; 8367 lp->primalchecked = FALSE; 8368 lp->lpobjval = SCIP_INVALID; 8369 lp->lpsolstat = SCIP_LPSOLSTAT_NOTSOLVED; 8370 8371 return SCIP_OKAY; 8372 } 8373 8374 /** applies all cached column bound and objective changes to the LP */ 8375 static 8376 SCIP_RETCODE lpFlushChgCols( 8377 SCIP_LP* lp, /**< current LP data */ 8378 SCIP_SET* set /**< global SCIP settings */ 8379 ) 8380 { 8381 #ifndef NDEBUG 8382 SCIP_Bool lpinone = (strcmp( SCIPlpiGetSolverName(), "NONE") == 0); 8383 #endif 8384 SCIP_COL* col; 8385 int* objind; 8386 int* bdind; 8387 SCIP_Real* obj; 8388 SCIP_Real* lb; 8389 SCIP_Real* ub; 8390 SCIP_Real lpiinf; 8391 int nobjchg; 8392 int nbdchg; 8393 int i; 8394 8395 assert(lp != NULL); 8396 8397 if( lp->nchgcols == 0 ) 8398 return SCIP_OKAY; 8399 8400 /* get the solver's infinity value */ 8401 lpiinf = SCIPlpiInfinity(lp->lpi); 8402 8403 /* get temporary memory for changes */ 8404 SCIP_CALL( SCIPsetAllocBufferArray(set, &objind, lp->ncols) ); 8405 SCIP_CALL( SCIPsetAllocBufferArray(set, &obj, lp->ncols) ); 8406 SCIP_CALL( SCIPsetAllocBufferArray(set, &bdind, lp->ncols) ); 8407 SCIP_CALL( SCIPsetAllocBufferArray(set, &lb, lp->ncols) ); 8408 SCIP_CALL( SCIPsetAllocBufferArray(set, &ub, lp->ncols) ); 8409 8410 /* collect all cached bound and objective changes */ 8411 nobjchg = 0; 8412 nbdchg = 0; 8413 for( i = 0; i < lp->nchgcols; ++i ) 8414 { 8415 col = lp->chgcols[i]; 8416 assert(col != NULL); 8417 assert(col->var != NULL); 8418 assert(SCIPvarGetStatus(col->var) == SCIP_VARSTATUS_COLUMN); 8419 assert(SCIPvarGetCol(col->var) == col); 8420 8421 if( col->lpipos >= 0 ) 8422 { 8423 #ifndef NDEBUG 8424 /* do not check consistency of data with LPI in case of LPI=none */ 8425 if( !lpinone ) 8426 { 8427 SCIP_Real lpiobj; 8428 SCIP_Real lpilb; 8429 SCIP_Real lpiub; 8430 8431 SCIP_CALL( SCIPlpiGetObj(lp->lpi, col->lpipos, col->lpipos, &lpiobj) ); 8432 SCIP_CALL( SCIPlpiGetBounds(lp->lpi, col->lpipos, col->lpipos, &lpilb, &lpiub) ); 8433 assert(SCIPsetIsFeasEQ(set, lpiobj, col->flushedobj)); 8434 assert((SCIPsetIsInfinity(set, -lpilb) && SCIPsetIsInfinity(set, -col->flushedlb)) 8435 || (!SCIPsetIsInfinity(set, -lpilb) && !SCIPsetIsInfinity(set, -col->flushedlb) && SCIPsetIsFeasEQ(set, lpilb, col->flushedlb))); 8436 assert((SCIPsetIsInfinity(set, lpiub) && SCIPsetIsInfinity(set, col->flushedub)) 8437 || (!SCIPsetIsInfinity(set, lpiub) && !SCIPsetIsInfinity(set, col->flushedub) && SCIPsetIsFeasEQ(set, lpiub, col->flushedub))); 8438 } 8439 #endif 8440 8441 if( col->objchanged ) 8442 { 8443 SCIP_Real newobj; 8444 8445 newobj = col->obj; 8446 if( col->flushedobj != newobj ) /*lint !e777*/ 8447 { 8448 assert(nobjchg < lp->ncols); 8449 objind[nobjchg] = col->lpipos; 8450 obj[nobjchg] = newobj; 8451 nobjchg++; 8452 col->flushedobj = newobj; 8453 } 8454 col->objchanged = FALSE; 8455 } 8456 8457 if( col->lbchanged || col->ubchanged ) 8458 { 8459 SCIP_Real newlb; 8460 SCIP_Real newub; 8461 8462 /* compute bounds that should be flushed into the LP (taking into account lazy bounds) */ 8463 computeLPBounds(lp, set, col, lpiinf, &newlb, &newub); 8464 8465 if( col->flushedlb != newlb || col->flushedub != newub ) /*lint !e777*/ 8466 { 8467 assert(nbdchg < lp->ncols); 8468 bdind[nbdchg] = col->lpipos; 8469 lb[nbdchg] = newlb; 8470 ub[nbdchg] = newub; 8471 nbdchg++; 8472 col->flushedlb = newlb; 8473 col->flushedub = newub; 8474 } 8475 col->lbchanged = FALSE; 8476 col->ubchanged = FALSE; 8477 } 8478 } 8479 /* maybe lb/ub/objchanged should all be set to false when lpipos is -1 */ 8480 } 8481 8482 /* change objective values in LP */ 8483 if( nobjchg > 0 ) 8484 { 8485 SCIPsetDebugMsg(set, "flushing objective changes: change %d objective values of %d changed columns\n", nobjchg, lp->nchgcols); 8486 SCIP_CALL( SCIPlpiChgObj(lp->lpi, nobjchg, objind, obj) ); 8487 8488 /* mark the LP unsolved */ 8489 lp->solved = FALSE; 8490 lp->dualfeasible = FALSE; 8491 lp->dualchecked = FALSE; 8492 lp->lpobjval = SCIP_INVALID; 8493 lp->lpsolstat = SCIP_LPSOLSTAT_NOTSOLVED; 8494 } 8495 8496 /* change bounds in LP */ 8497 if( nbdchg > 0 ) 8498 { 8499 SCIPsetDebugMsg(set, "flushing bound changes: change %d bounds of %d changed columns\n", nbdchg, lp->nchgcols); 8500 SCIP_CALL( SCIPlpiChgBounds(lp->lpi, nbdchg, bdind, lb, ub) ); 8501 8502 /* mark the LP unsolved */ 8503 lp->solved = FALSE; 8504 lp->primalfeasible = FALSE; 8505 lp->primalchecked = FALSE; 8506 lp->lpobjval = SCIP_INVALID; 8507 lp->lpsolstat = SCIP_LPSOLSTAT_NOTSOLVED; 8508 } 8509 8510 lp->nchgcols = 0; 8511 8512 /* free temporary memory */ 8513 SCIPsetFreeBufferArray(set, &ub); 8514 SCIPsetFreeBufferArray(set, &lb); 8515 SCIPsetFreeBufferArray(set, &bdind); 8516 SCIPsetFreeBufferArray(set, &obj); 8517 SCIPsetFreeBufferArray(set, &objind); 8518 8519 return SCIP_OKAY; 8520 } 8521 8522 /** applies all cached row side changes to the LP */ 8523 static 8524 SCIP_RETCODE lpFlushChgRows( 8525 SCIP_LP* lp, /**< current LP data */ 8526 SCIP_SET* set /**< global SCIP settings */ 8527 ) 8528 { 8529 #ifndef NDEBUG 8530 SCIP_Bool lpinone = (strcmp( SCIPlpiGetSolverName(), "NONE") == 0); 8531 #endif 8532 SCIP_ROW* row; 8533 int* ind; 8534 SCIP_Real* lhs; 8535 SCIP_Real* rhs; 8536 SCIP_Real lpiinf; 8537 int i; 8538 int nchg; 8539 8540 assert(lp != NULL); 8541 8542 if( lp->nchgrows == 0 ) 8543 return SCIP_OKAY; 8544 8545 /* get the solver's infinity value */ 8546 lpiinf = SCIPlpiInfinity(lp->lpi); 8547 8548 /* get temporary memory for changes */ 8549 SCIP_CALL( SCIPsetAllocBufferArray(set, &ind, lp->nrows) ); 8550 SCIP_CALL( SCIPsetAllocBufferArray(set, &lhs, lp->nrows) ); 8551 SCIP_CALL( SCIPsetAllocBufferArray(set, &rhs, lp->nrows) ); 8552 8553 /* collect all cached left and right hand side changes */ 8554 nchg = 0; 8555 for( i = 0; i < lp->nchgrows; ++i ) 8556 { 8557 row = lp->chgrows[i]; 8558 assert(row != NULL); 8559 8560 if( row->lpipos >= 0 ) 8561 { 8562 #ifndef NDEBUG 8563 /* do not check consistency of data with LPI in case of LPI=none */ 8564 if( !lpinone ) 8565 { 8566 SCIP_Real lpilhs; 8567 SCIP_Real lpirhs; 8568 8569 SCIP_CALL( SCIPlpiGetSides(lp->lpi, row->lpipos, row->lpipos, &lpilhs, &lpirhs) ); 8570 assert(SCIPsetIsSumEQ(set, lpilhs, row->flushedlhs)); 8571 assert(SCIPsetIsSumEQ(set, lpirhs, row->flushedrhs)); 8572 } 8573 #endif 8574 if( row->lhschanged || row->rhschanged ) 8575 { 8576 SCIP_Real newlhs; 8577 SCIP_Real newrhs; 8578 8579 newlhs = (SCIPsetIsInfinity(set, -row->lhs) ? -lpiinf : row->lhs - row->constant); 8580 newrhs = (SCIPsetIsInfinity(set, row->rhs) ? lpiinf : row->rhs - row->constant); 8581 if( row->flushedlhs != newlhs || row->flushedrhs != newrhs ) /*lint !e777*/ 8582 { 8583 assert(nchg < lp->nrows); 8584 ind[nchg] = row->lpipos; 8585 lhs[nchg] = newlhs; 8586 rhs[nchg] = newrhs; 8587 nchg++; 8588 row->flushedlhs = newlhs; 8589 row->flushedrhs = newrhs; 8590 } 8591 row->lhschanged = FALSE; 8592 row->rhschanged = FALSE; 8593 } 8594 } 8595 } 8596 8597 /* change left and right hand sides in LP */ 8598 if( nchg > 0 ) 8599 { 8600 SCIPsetDebugMsg(set, "flushing side changes: change %d sides of %d rows\n", nchg, lp->nchgrows); 8601 SCIP_CALL( SCIPlpiChgSides(lp->lpi, nchg, ind, lhs, rhs) ); 8602 8603 /* mark the LP unsolved */ 8604 lp->solved = FALSE; 8605 lp->primalfeasible = FALSE; 8606 lp->primalchecked = FALSE; 8607 lp->lpobjval = SCIP_INVALID; 8608 lp->lpsolstat = SCIP_LPSOLSTAT_NOTSOLVED; 8609 } 8610 8611 lp->nchgrows = 0; 8612 8613 /* free temporary memory */ 8614 SCIPsetFreeBufferArray(set, &rhs); 8615 SCIPsetFreeBufferArray(set, &lhs); 8616 SCIPsetFreeBufferArray(set, &ind); 8617 8618 return SCIP_OKAY; 8619 } 8620 8621 /** copy integrality information to the LP */ 8622 static 8623 SCIP_RETCODE lpCopyIntegrality( 8624 SCIP_LP* lp, /**< current LP data */ 8625 SCIP_SET* set /**< global SCIP settings */ 8626 ) 8627 { 8628 int i; 8629 int nintegers; 8630 int* integerInfo; 8631 SCIP_VAR* var; 8632 8633 assert(lp != NULL); 8634 8635 SCIP_CALL( SCIPsetAllocBufferArray(set, &integerInfo, lp->ncols) ); 8636 8637 /* count total number of integralities */ 8638 nintegers = 0; 8639 8640 for( i = 0; i < lp->ncols; ++i ) 8641 { 8642 var = SCIPcolGetVar(lp->cols[i]); 8643 if( SCIPvarIsIntegral(var) || SCIPvarIsBinary(var) ) 8644 { 8645 integerInfo[i] = 1; 8646 ++nintegers; 8647 } 8648 else 8649 integerInfo[i] = 0; 8650 } 8651 8652 /* only pass integrality information if integer variables are present */ 8653 if( nintegers > 0 ) 8654 { 8655 SCIP_CALL( SCIPlpiSetIntegralityInformation(lp->lpi, lp->ncols, integerInfo) ); 8656 } 8657 else 8658 { 8659 SCIP_CALL( SCIPlpiSetIntegralityInformation(lp->lpi, 0, NULL) ); 8660 } 8661 8662 SCIPsetFreeBufferArray(set, &integerInfo); 8663 8664 /* mark integralities to be updated */ 8665 lp->updateintegrality = FALSE; 8666 8667 return SCIP_OKAY; 8668 } 8669 8670 /** applies all cached changes to the LP solver */ 8671 SCIP_RETCODE SCIPlpFlush( 8672 SCIP_LP* lp, /**< current LP data */ 8673 BMS_BLKMEM* blkmem, /**< block memory */ 8674 SCIP_SET* set, /**< global SCIP settings */ 8675 SCIP_PROB* prob, /**< problem data */ 8676 SCIP_EVENTQUEUE* eventqueue /**< event queue */ 8677 ) 8678 { 8679 assert(lp != NULL); 8680 assert(blkmem != NULL); 8681 8682 SCIPsetDebugMsg(set, "flushing LP changes: old (%d cols, %d rows), nchgcols=%d, nchgrows=%d, firstchgcol=%d, firstchgrow=%d, new (%d cols, %d rows), flushed=%u\n", 8683 lp->nlpicols, lp->nlpirows, lp->nchgcols, lp->nchgrows, lp->lpifirstchgcol, lp->lpifirstchgrow, lp->ncols, lp->nrows, lp->flushed); 8684 8685 if( !lp->flushed ) 8686 { 8687 lp->flushdeletedcols = FALSE; 8688 lp->flushaddedcols = FALSE; 8689 lp->flushdeletedrows = FALSE; 8690 lp->flushaddedrows = FALSE; 8691 8692 SCIP_CALL( lpFlushDelCols(lp) ); 8693 SCIP_CALL( lpFlushDelRows(lp, blkmem, set) ); 8694 SCIP_CALL( lpFlushChgCols(lp, set) ); 8695 SCIP_CALL( lpFlushChgRows(lp, set) ); 8696 SCIP_CALL( lpFlushAddCols(lp, blkmem, set, eventqueue) ); 8697 SCIP_CALL( lpFlushAddRows(lp, blkmem, set, eventqueue) ); 8698 8699 lp->flushed = TRUE; 8700 8701 checkLinks(lp); 8702 } 8703 8704 /* if the cutoff bound was changed in between and it is not disabled (e.g. for column generation), 8705 * we want to re-optimize the LP even if nothing else has changed */ 8706 if( lp->cutoffbound != lp->lpiobjlim && lp->ncols > 0 && ! lpCutoffDisabled(set, prob) ) /*lint !e777*/ 8707 { 8708 lp->solved = FALSE; 8709 lp->lpsolstat = SCIP_LPSOLSTAT_NOTSOLVED; 8710 } 8711 8712 assert(lp->nlpicols == lp->ncols); 8713 assert(lp->lpifirstchgcol == lp->nlpicols); 8714 assert(lp->nlpirows == lp->nrows); 8715 assert(lp->lpifirstchgrow == lp->nlpirows); 8716 assert(lp->nchgcols == 0); 8717 assert(lp->nchgrows == 0); 8718 #ifndef NDEBUG 8719 { 8720 int ncols; 8721 int nrows; 8722 8723 SCIP_CALL( SCIPlpiGetNCols(lp->lpi, &ncols) ); 8724 SCIP_CALL( SCIPlpiGetNRows(lp->lpi, &nrows) ); 8725 assert(ncols == lp->ncols); 8726 assert(nrows == lp->nrows); 8727 } 8728 #endif 8729 8730 return SCIP_OKAY; 8731 } 8732 8733 /** marks the LP to be flushed, even if the LP thinks it is not flushed */ 8734 SCIP_RETCODE SCIPlpMarkFlushed( 8735 SCIP_LP* lp, /**< current LP data */ 8736 SCIP_SET* set /**< global SCIP settings */ 8737 ) 8738 { 8739 #ifndef NDEBUG 8740 SCIP_Bool lpinone = (strcmp( SCIPlpiGetSolverName(), "NONE") == 0); 8741 #endif 8742 int i; 8743 8744 assert(lp != NULL); 8745 8746 #ifndef NDEBUG 8747 /* check, if there are really no column or row deletions or coefficient changes left */ 8748 while( lp->lpifirstchgcol < lp->nlpicols 8749 && lp->lpifirstchgcol < lp->ncols 8750 && lp->cols[lp->lpifirstchgcol]->lpipos == lp->lpifirstchgcol 8751 && !lp->cols[lp->lpifirstchgcol]->coefchanged ) 8752 { 8753 assert(lp->cols[lp->lpifirstchgcol] == lp->lpicols[lp->lpifirstchgcol]); 8754 lp->lpifirstchgcol++; 8755 } 8756 assert(lp->nlpicols == lp->lpifirstchgcol); 8757 8758 while( lp->lpifirstchgrow < lp->nlpirows 8759 && lp->lpifirstchgrow < lp->nrows 8760 && lp->rows[lp->lpifirstchgrow]->lpipos == lp->lpifirstchgrow 8761 && !lp->rows[lp->lpifirstchgrow]->coefchanged ) 8762 { 8763 assert(lp->rows[lp->lpifirstchgrow] == lp->lpirows[lp->lpifirstchgrow]); 8764 lp->lpifirstchgrow++; 8765 } 8766 assert(lp->nlpirows == lp->lpifirstchgrow); 8767 #endif 8768 8769 lp->lpifirstchgcol = lp->nlpicols; 8770 lp->lpifirstchgrow = lp->nlpirows; 8771 8772 /* check, if there are really no column or row additions left */ 8773 assert(lp->ncols == lp->nlpicols); 8774 assert(lp->nrows == lp->nlpirows); 8775 8776 /* mark the changed columns to be unchanged, and check, if this is really correct */ 8777 for( i = 0; i < lp->nchgcols; ++i ) 8778 { 8779 SCIP_COL* col; 8780 8781 col = lp->chgcols[i]; 8782 assert(col != NULL); 8783 assert(col->var != NULL); 8784 assert(SCIPvarGetStatus(col->var) == SCIP_VARSTATUS_COLUMN); 8785 assert(SCIPvarGetCol(col->var) == col); 8786 8787 if( col->lpipos >= 0 ) 8788 { 8789 #ifndef NDEBUG 8790 /* do not check consistency of data with LPI in case of LPI=none */ 8791 if( !lpinone ) 8792 { 8793 SCIP_Real lpiobj; 8794 SCIP_Real lpilb; 8795 SCIP_Real lpiub; 8796 8797 SCIP_CALL( SCIPlpiGetObj(lp->lpi, col->lpipos, col->lpipos, &lpiobj) ); 8798 SCIP_CALL( SCIPlpiGetBounds(lp->lpi, col->lpipos, col->lpipos, &lpilb, &lpiub) ); 8799 assert(SCIPsetIsSumEQ(set, lpiobj, col->flushedobj)); 8800 assert(SCIPsetIsSumEQ(set, lpilb, col->flushedlb)); 8801 assert(SCIPsetIsSumEQ(set, lpiub, col->flushedub)); 8802 assert(col->flushedobj == col->obj); /*lint !e777*/ 8803 assert(col->flushedlb == (SCIPsetIsInfinity(set, -col->lb) ? -SCIPlpiInfinity(lp->lpi) : col->lb)); /*lint !e777*/ 8804 assert(col->flushedub == (SCIPsetIsInfinity(set, col->ub) ? SCIPlpiInfinity(lp->lpi) : col->ub)); /*lint !e777*/ 8805 } 8806 #endif 8807 col->objchanged = FALSE; 8808 col->lbchanged = FALSE; 8809 col->ubchanged = FALSE; 8810 } 8811 /* maybe lb/ub/objchanged should be set to false also when lpipos is -1 */ 8812 } 8813 lp->nchgcols = 0; 8814 8815 /* mark the changed rows to be unchanged, and check, if this is really correct */ 8816 for( i = 0; i < lp->nchgrows; ++i ) 8817 { 8818 SCIP_ROW* row; 8819 8820 row = lp->chgrows[i]; 8821 assert(row != NULL); 8822 8823 if( row->lpipos >= 0 ) 8824 { 8825 #ifndef NDEBUG 8826 /* do not check consistency of data with LPI in case of LPI=none */ 8827 if( !lpinone ) 8828 { 8829 SCIP_Real lpilhs; 8830 SCIP_Real lpirhs; 8831 8832 SCIP_CALL( SCIPlpiGetSides(lp->lpi, row->lpipos, row->lpipos, &lpilhs, &lpirhs) ); 8833 assert(SCIPsetIsSumEQ(set, lpilhs, row->flushedlhs)); 8834 assert(SCIPsetIsSumEQ(set, lpirhs, row->flushedrhs)); 8835 assert(row->flushedlhs == (SCIPsetIsInfinity(set, -row->lhs) ? -SCIPlpiInfinity(lp->lpi) : row->lhs - row->constant)); /*lint !e777*/ 8836 assert(row->flushedrhs == (SCIPsetIsInfinity(set, row->rhs) ? SCIPlpiInfinity(lp->lpi) : row->rhs - row->constant)); /*lint !e777*/ 8837 } 8838 #endif 8839 row->lhschanged = FALSE; 8840 row->rhschanged = FALSE; 8841 } 8842 } 8843 lp->nchgrows = 0; 8844 8845 /* mark the LP to be flushed */ 8846 lp->flushed = TRUE; 8847 8848 checkLinks(lp); 8849 8850 return SCIP_OKAY; 8851 } 8852 8853 8854 8855 8856 /* 8857 * LP methods 8858 */ 8859 8860 /** updates link data after addition of column */ 8861 static 8862 void colUpdateAddLP( 8863 SCIP_COL* col, /**< LP column */ 8864 SCIP_SET* set /**< global SCIP settings */ 8865 ) 8866 { 8867 SCIP_ROW* row; 8868 int i; 8869 int pos; 8870 8871 assert(col != NULL); 8872 assert(col->lppos >= 0); 8873 8874 /* update column arrays of all linked rows */ 8875 for( i = 0; i < col->len; ++i ) 8876 { 8877 pos = col->linkpos[i]; 8878 if( pos >= 0 ) 8879 { 8880 row = col->rows[i]; 8881 assert(row != NULL); 8882 assert(row->linkpos[pos] == i); 8883 assert(row->cols[pos] == col); 8884 assert(row->nlpcols <= pos && pos < row->len); 8885 8886 row->nlpcols++; 8887 rowSwapCoefs(row, pos, row->nlpcols-1); 8888 assert(row->cols[row->nlpcols-1] == col); 8889 8890 /* if no swap was necessary, mark lpcols to be unsorted */ 8891 if( pos == row->nlpcols-1 ) 8892 row->lpcolssorted = FALSE; 8893 8894 /* update norms */ 8895 rowAddNorms(row, set, col, row->vals[row->nlpcols-1], FALSE); 8896 } 8897 } 8898 } 8899 8900 /** updates link data after addition of row */ 8901 static 8902 void rowUpdateAddLP( 8903 SCIP_ROW* row /**< LP row */ 8904 ) 8905 { 8906 SCIP_COL* col; 8907 int i; 8908 int pos; 8909 8910 assert(row != NULL); 8911 assert(row->lppos >= 0); 8912 8913 /* update row arrays of all linked columns */ 8914 for( i = 0; i < row->len; ++i ) 8915 { 8916 pos = row->linkpos[i]; 8917 if( pos >= 0 ) 8918 { 8919 col = row->cols[i]; 8920 assert(col != NULL); 8921 assert(col->linkpos[pos] == i); 8922 assert(col->rows[pos] == row); 8923 assert(col->nlprows <= pos && pos < col->len); 8924 8925 col->nlprows++; 8926 colSwapCoefs(col, pos, col->nlprows-1); 8927 8928 /* if no swap was necessary, mark lprows to be unsorted */ 8929 if( pos == col->nlprows-1 ) 8930 col->lprowssorted = FALSE; 8931 } 8932 } 8933 } 8934 8935 /** updates link data after removal of column */ 8936 static 8937 void colUpdateDelLP( 8938 SCIP_COL* col, /**< LP column */ 8939 SCIP_SET* set /**< global SCIP settings */ 8940 ) 8941 { 8942 SCIP_ROW* row; 8943 int i; 8944 int pos; 8945 8946 assert(col != NULL); 8947 assert(col->lppos == -1); 8948 8949 /* update column arrays of all linked rows */ 8950 for( i = 0; i < col->len; ++i ) 8951 { 8952 pos = col->linkpos[i]; 8953 if( pos >= 0 ) 8954 { 8955 row = col->rows[i]; 8956 assert(row != NULL); 8957 assert(row->linkpos[pos] == i); 8958 assert(row->cols[pos] == col); 8959 assert(0 <= pos && pos < row->nlpcols); 8960 8961 /* update norms */ 8962 rowDelNorms(row, set, col, row->vals[pos], TRUE, FALSE, FALSE); 8963 8964 row->nlpcols--; 8965 rowSwapCoefs(row, pos, row->nlpcols); 8966 8967 /* if no swap was necessary, mark nonlpcols to be unsorted */ 8968 if( pos == row->nlpcols ) 8969 row->nonlpcolssorted = FALSE; 8970 } 8971 } 8972 } 8973 8974 /** updates link data after removal of row */ 8975 static 8976 void rowUpdateDelLP( 8977 SCIP_ROW* row /**< LP row */ 8978 ) 8979 { 8980 SCIP_COL* col; 8981 int i; 8982 int pos; 8983 8984 assert(row != NULL); 8985 assert(row->lppos == -1); 8986 8987 /* update row arrays of all linked columns */ 8988 for( i = 0; i < row->len; ++i ) 8989 { 8990 pos = row->linkpos[i]; 8991 if( pos >= 0 ) 8992 { 8993 col = row->cols[i]; 8994 assert(col != NULL); 8995 assert(0 <= pos && pos < col->nlprows); 8996 assert(col->linkpos[pos] == i); 8997 assert(col->rows[pos] == row); 8998 8999 col->nlprows--; 9000 colSwapCoefs(col, pos, col->nlprows); 9001 9002 /* if no swap was necessary, mark lprows to be unsorted */ 9003 if( pos == col->nlprows ) 9004 col->nonlprowssorted = FALSE; 9005 } 9006 } 9007 } 9008 9009 static 9010 SCIP_RETCODE allocDiveChgSideArrays( 9011 SCIP_LP* lp, /**< LP data object */ 9012 int initsize /**< initial size of the arrays */ 9013 ) 9014 { 9015 assert(lp != NULL); 9016 assert(lp->divechgsides == NULL); 9017 assert(lp->divechgsidetypes == NULL); 9018 assert(lp->divechgrows == NULL); 9019 assert(lp->ndivechgsides == 0); 9020 assert(lp->divechgsidessize == 0); 9021 assert(initsize > 0); 9022 9023 lp->divechgsidessize = initsize; 9024 SCIP_ALLOC( BMSallocMemoryArray(&lp->divechgsides, lp->divechgsidessize) ); 9025 SCIP_ALLOC( BMSallocMemoryArray(&lp->divechgsidetypes, lp->divechgsidessize) ); 9026 SCIP_ALLOC( BMSallocMemoryArray(&lp->divechgrows, lp->divechgsidessize) ); 9027 9028 return SCIP_OKAY; 9029 } 9030 9031 static 9032 SCIP_RETCODE reallocDiveChgSideArrays( 9033 SCIP_LP* lp, /**< LP data object */ 9034 int minsize, /**< minimal number of elements */ 9035 SCIP_Real growfact /**< growing factor */ 9036 ) 9037 { 9038 assert(lp != NULL); 9039 assert(lp->divechgsides != NULL); 9040 assert(lp->divechgsidetypes != NULL); 9041 assert(lp->divechgrows != NULL); 9042 assert(lp->ndivechgsides > 0); 9043 assert(lp->divechgsidessize > 0); 9044 assert(minsize > 0); 9045 9046 if( minsize <= lp->divechgsidessize ) 9047 return SCIP_OKAY; 9048 9049 lp->divechgsidessize = MAX(minsize, (int)(lp->divechgsidessize * growfact)); 9050 SCIP_ALLOC( BMSreallocMemoryArray(&lp->divechgsides, lp->divechgsidessize) ); 9051 SCIP_ALLOC( BMSreallocMemoryArray(&lp->divechgsidetypes, lp->divechgsidessize) ); 9052 SCIP_ALLOC( BMSreallocMemoryArray(&lp->divechgrows, lp->divechgsidessize) ); 9053 9054 return SCIP_OKAY; 9055 } 9056 9057 static 9058 void freeDiveChgSideArrays( 9059 SCIP_LP* lp /**< LP data object */ 9060 ) 9061 { 9062 assert(lp != NULL); 9063 assert(lp->divechgsides != NULL); 9064 assert(lp->divechgsidetypes != NULL); 9065 assert(lp->divechgrows != NULL); 9066 assert(lp->ndivechgsides == 0); 9067 assert(lp->divechgsidessize > 0); 9068 9069 BMSfreeMemoryArrayNull(&lp->divechgsides); 9070 BMSfreeMemoryArrayNull(&lp->divechgsidetypes); 9071 BMSfreeMemoryArrayNull(&lp->divechgrows); 9072 lp->divechgsidessize = 0; 9073 } 9074 9075 #define DIVESTACKINITSIZE 100 9076 9077 /** creates empty LP data object */ 9078 SCIP_RETCODE SCIPlpCreate( 9079 SCIP_LP** lp, /**< pointer to LP data object */ 9080 SCIP_SET* set, /**< global SCIP settings */ 9081 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */ 9082 SCIP_STAT* stat, /**< problem statistics */ 9083 const char* name /**< problem name */ 9084 ) 9085 { 9086 SCIP_Bool success; 9087 9088 assert(lp != NULL); 9089 assert(set != NULL); 9090 assert(stat != NULL); 9091 assert(name != NULL); 9092 9093 SCIP_ALLOC( BMSallocMemory(lp) ); 9094 9095 /* open LP Solver interface */ 9096 SCIP_CALL( SCIPlpiCreate(&(*lp)->lpi, messagehdlr, name, SCIP_OBJSEN_MINIMIZE) ); 9097 9098 (*lp)->lpicols = NULL; 9099 (*lp)->lpirows = NULL; 9100 (*lp)->chgcols = NULL; 9101 (*lp)->chgrows = NULL; 9102 (*lp)->cols = NULL; 9103 (*lp)->soldirection = NULL; 9104 (*lp)->lazycols = NULL; 9105 (*lp)->rows = NULL; 9106 (*lp)->lpobjval = 0.0; 9107 (*lp)->glbpseudoobjval = 0.0; 9108 (*lp)->relglbpseudoobjval = 0.0; 9109 (*lp)->glbpseudoobjvalid = TRUE; 9110 (*lp)->glbpseudoobjvalinf = 0; 9111 (*lp)->pseudoobjval = 0.0; 9112 (*lp)->relpseudoobjval = 0.0; 9113 (*lp)->pseudoobjvalid = TRUE; 9114 (*lp)->pseudoobjvalinf = 0; 9115 (*lp)->looseobjval = 0.0; 9116 (*lp)->rellooseobjval = 0.0; 9117 (*lp)->looseobjvalid = TRUE; 9118 (*lp)->looseobjvalinf = 0; 9119 (*lp)->nloosevars = 0; 9120 (*lp)->rootlpobjval = SCIP_INVALID; 9121 (*lp)->rootlooseobjval = SCIP_INVALID; 9122 (*lp)->cutoffbound = SCIPsetInfinity(set); 9123 (*lp)->feastol = SCIP_INVALID; /* to have it initialized */ 9124 SCIPlpResetFeastol(*lp, set); 9125 (*lp)->validdegeneracylp = -1; 9126 (*lp)->objsqrnorm = 0.0; 9127 (*lp)->objsumnorm = 0.0; 9128 (*lp)->lpicolssize = 0; 9129 (*lp)->nlpicols = 0; 9130 (*lp)->lpirowssize = 0; 9131 (*lp)->nlpirows = 0; 9132 (*lp)->lpifirstchgcol = 0; 9133 (*lp)->lpifirstchgrow = 0; 9134 (*lp)->colssize = 0; 9135 (*lp)->soldirectionsize = 0; 9136 (*lp)->ncols = 0; 9137 (*lp)->lazycolssize = 0; 9138 (*lp)->nlazycols = 0; 9139 (*lp)->rowssize = 0; 9140 (*lp)->nrows = 0; 9141 (*lp)->chgcolssize = 0; 9142 (*lp)->nchgcols = 0; 9143 (*lp)->chgrowssize = 0; 9144 (*lp)->nchgrows = 0; 9145 (*lp)->firstnewcol = 0; 9146 (*lp)->firstnewrow = 0; 9147 (*lp)->nremovablecols = 0; 9148 (*lp)->nremovablerows = 0; 9149 (*lp)->validsollp = stat->lpcount; /* the initial (empty) SCIP_LP is solved with primal and dual solution of zero */ 9150 (*lp)->validfarkaslp = -1; 9151 (*lp)->validsoldirlp = -1; 9152 (*lp)->validsoldirsol = NULL; 9153 (*lp)->objsqrnormunreliable = FALSE; 9154 (*lp)->flushdeletedcols = FALSE; 9155 (*lp)->flushaddedcols = FALSE; 9156 (*lp)->flushdeletedrows = FALSE; 9157 (*lp)->flushaddedrows = FALSE; 9158 (*lp)->updateintegrality = TRUE; 9159 (*lp)->flushed = TRUE; 9160 (*lp)->lpsolstat = SCIP_LPSOLSTAT_OPTIMAL; 9161 (*lp)->solved = TRUE; 9162 (*lp)->primalfeasible = TRUE; 9163 (*lp)->primalchecked = TRUE; 9164 (*lp)->dualfeasible = TRUE; 9165 (*lp)->dualchecked = TRUE; 9166 (*lp)->solisbasic = FALSE; 9167 (*lp)->rootlpisrelax = TRUE; 9168 (*lp)->isrelax = TRUE; 9169 (*lp)->installing = FALSE; 9170 (*lp)->strongbranching = FALSE; 9171 (*lp)->strongbranchprobing = FALSE; 9172 (*lp)->probing = FALSE; 9173 (*lp)->diving = FALSE; 9174 (*lp)->divingobjchg = FALSE; 9175 (*lp)->divinglazyapplied = FALSE; 9176 (*lp)->divelpistate = NULL; 9177 (*lp)->divelpwasprimfeas = TRUE; 9178 (*lp)->divelpwasprimchecked = TRUE; 9179 (*lp)->divelpwasdualfeas = TRUE; 9180 (*lp)->divelpwasdualchecked = TRUE; 9181 (*lp)->divechgsides = NULL; 9182 (*lp)->divechgsidetypes = NULL; 9183 (*lp)->divechgrows = NULL; 9184 (*lp)->ndivechgsides = 0; 9185 (*lp)->divechgsidessize = 0; 9186 (*lp)->ndivingrows = 0; 9187 (*lp)->divinglpiitlim = INT_MAX; 9188 (*lp)->resolvelperror = FALSE; 9189 (*lp)->divenolddomchgs = 0; 9190 (*lp)->adjustlpval = FALSE; 9191 (*lp)->lpiobjlim = SCIPlpiInfinity((*lp)->lpi); 9192 (*lp)->lpifeastol = (*lp)->feastol; 9193 (*lp)->lpidualfeastol = SCIPsetDualfeastol(set); 9194 (*lp)->lpibarrierconvtol = SCIPsetBarrierconvtol(set); 9195 (*lp)->lpifromscratch = FALSE; 9196 (*lp)->lpifastmip = set->lp_fastmip; 9197 (*lp)->lpiscaling = set->lp_scaling; 9198 (*lp)->lpipresolving = set->lp_presolving; 9199 (*lp)->lpilpinfo = set->disp_lpinfo; 9200 (*lp)->lpirowrepswitch = set->lp_rowrepswitch; 9201 (*lp)->lpisolutionpolishing = (set->lp_solutionpolishing > 0); 9202 (*lp)->lpirefactorinterval = set->lp_refactorinterval; 9203 (*lp)->lpiconditionlimit = set->lp_conditionlimit; 9204 (*lp)->lpimarkowitz = set->lp_markowitz; 9205 (*lp)->lpiitlim = INT_MAX; 9206 (*lp)->lpipricing = SCIP_PRICING_AUTO; 9207 (*lp)->lastlpalgo = SCIP_LPALGO_DUALSIMPLEX; 9208 (*lp)->lpithreads = set->lp_threads; 9209 (*lp)->lpitiming = (int) set->time_clocktype; 9210 (*lp)->lpirandomseed = set->random_randomseed; 9211 (*lp)->storedsolvals = NULL; 9212 9213 /* allocate arrays for diving */ 9214 SCIP_CALL( allocDiveChgSideArrays(*lp, DIVESTACKINITSIZE) ); 9215 9216 /* set default parameters in LP solver */ 9217 SCIP_CALL( lpSetRealpar(*lp, SCIP_LPPAR_OBJLIM, (*lp)->lpiobjlim, &success) ); 9218 if( !success ) 9219 { 9220 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL, 9221 "LP Solver <%s>: objective limit cannot be set -- can lead to unnecessary simplex iterations\n", 9222 SCIPlpiGetSolverName()); 9223 } 9224 SCIP_CALL( lpSetRealpar(*lp, SCIP_LPPAR_FEASTOL, (*lp)->lpifeastol, &success) ); 9225 (*lp)->lpihasfeastol = success; 9226 if( !success ) 9227 { 9228 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL, 9229 "LP Solver <%s>: primal feasibility tolerance cannot be set -- tolerance of SCIP and LP solver may differ\n", 9230 SCIPlpiGetSolverName()); 9231 } 9232 SCIP_CALL( lpSetRealpar(*lp, SCIP_LPPAR_DUALFEASTOL, (*lp)->lpidualfeastol, &success) ); 9233 (*lp)->lpihasdualfeastol = success; 9234 if( !success ) 9235 { 9236 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL, 9237 "LP Solver <%s>: dual feasibility tolerance cannot be set -- tolerance of SCIP and LP solver may differ\n", 9238 SCIPlpiGetSolverName()); 9239 } 9240 SCIP_CALL( lpSetRealpar(*lp, SCIP_LPPAR_BARRIERCONVTOL, (*lp)->lpibarrierconvtol, &success) ); 9241 (*lp)->lpihasbarrierconvtol = success; 9242 if( !success ) 9243 { 9244 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL, 9245 "LP Solver <%s>: barrier convergence tolerance cannot be set -- tolerance of SCIP and LP solver may differ\n", 9246 SCIPlpiGetSolverName()); 9247 } 9248 SCIP_CALL( lpSetBoolpar(*lp, SCIP_LPPAR_FROMSCRATCH, (*lp)->lpifromscratch, &success) ); 9249 SCIP_CALL( lpSetIntpar(*lp, SCIP_LPPAR_FASTMIP, (*lp)->lpifastmip, &success) ); 9250 (*lp)->lpihasfastmip = success; 9251 if( !success ) 9252 { 9253 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL, 9254 "LP Solver <%s>: fastmip setting not available -- SCIP parameter has no effect\n", 9255 SCIPlpiGetSolverName()); 9256 } 9257 SCIP_CALL( lpSetIntpar(*lp, SCIP_LPPAR_SCALING, (*lp)->lpiscaling, &success) ); 9258 (*lp)->lpihasscaling = success; 9259 if( !success ) 9260 { 9261 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL, 9262 "LP Solver <%s>: scaling not available -- SCIP parameter has no effect\n", 9263 SCIPlpiGetSolverName()); 9264 } 9265 SCIP_CALL( lpSetBoolpar(*lp, SCIP_LPPAR_PRESOLVING, (*lp)->lpipresolving, &success) ); 9266 (*lp)->lpihaspresolving = success; 9267 if( !success ) 9268 { 9269 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL, 9270 "LP Solver <%s>: presolving not available -- SCIP parameter has no effect\n", 9271 SCIPlpiGetSolverName()); 9272 } 9273 SCIP_CALL( lpSetIntpar(*lp, SCIP_LPPAR_TIMING, (*lp)->lpitiming, &success) ); 9274 if( !success ) 9275 { 9276 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL, 9277 "LP Solver <%s>: clock type cannot be set\n", 9278 SCIPlpiGetSolverName()); 9279 } 9280 SCIP_CALL( lpSetIntpar(*lp, SCIP_LPPAR_LPITLIM, (*lp)->lpiitlim, &success) ); 9281 if( !success ) 9282 { 9283 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL, 9284 "LP Solver <%s>: iteration limit cannot be set -- can lead to unnecessary simplex iterations\n", 9285 SCIPlpiGetSolverName()); 9286 } 9287 SCIP_CALL( lpSetIntpar(*lp, SCIP_LPPAR_PRICING, (int)(*lp)->lpipricing, &success) ); 9288 if( !success ) 9289 { 9290 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL, 9291 "LP Solver <%s>: pricing strategy cannot be set -- SCIP parameter has no effect\n", 9292 SCIPlpiGetSolverName()); 9293 } 9294 SCIP_CALL( lpSetBoolpar(*lp, SCIP_LPPAR_LPINFO, (*lp)->lpilpinfo, &success) ); 9295 if( !success ) 9296 { 9297 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL, 9298 "LP Solver <%s>: lpinfo setting not available -- SCIP parameter has no effect\n", 9299 SCIPlpiGetSolverName()); 9300 } 9301 SCIP_CALL( lpSetRealpar(*lp, SCIP_LPPAR_ROWREPSWITCH, (*lp)->lpirowrepswitch, &success) ); 9302 (*lp)->lpihasrowrep = success; 9303 if( !success ) 9304 { 9305 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL, 9306 "LP Solver <%s>: row representation of the basis not available -- SCIP parameter lp/rowrepswitch has no effect\n", 9307 SCIPlpiGetSolverName()); 9308 } 9309 SCIP_CALL( lpSetIntpar(*lp, SCIP_LPPAR_POLISHING, ((*lp)->lpisolutionpolishing ? 1 : 0), &success) ); 9310 (*lp)->lpihaspolishing = success; 9311 if( !success ) 9312 { 9313 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL, 9314 "LP Solver <%s>: solution polishing not available -- SCIP parameter lp/solutionpolishing has no effect\n", 9315 SCIPlpiGetSolverName()); 9316 } 9317 SCIP_CALL( lpSetIntpar(*lp, SCIP_LPPAR_REFACTOR, (*lp)->lpirefactorinterval, &success) ); 9318 (*lp)->lpihasrefactor = success; 9319 if( !success ) 9320 { 9321 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL, 9322 "LP Solver <%s>: refactorization interval not available -- SCIP parameter lp/refactorinterval has no effect\n", 9323 SCIPlpiGetSolverName()); 9324 } 9325 SCIP_CALL( lpSetRealpar(*lp, SCIP_LPPAR_CONDITIONLIMIT, (*lp)->lpiconditionlimit, &success) ); 9326 if( !success ) 9327 { 9328 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL, 9329 "LP Solver <%s>: condition number limit for the basis not available -- SCIP parameter lp/conditionlimit has no effect\n", 9330 SCIPlpiGetSolverName()); 9331 } 9332 SCIP_CALL( lpSetRealpar(*lp, SCIP_LPPAR_MARKOWITZ, (*lp)->lpimarkowitz, &success) ); 9333 if( !success ) 9334 { 9335 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL, 9336 "LP Solver <%s>: markowitz threshhold not available -- SCIP parameter lp/minmarkowitz has no effect\n", 9337 SCIPlpiGetSolverName()); 9338 } 9339 SCIP_CALL( lpSetIntpar(*lp, SCIP_LPPAR_THREADS, (*lp)->lpithreads, &success) ); 9340 if( !success ) 9341 { 9342 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL, 9343 "LP Solver <%s>: number of threads settings not available -- SCIP parameter has no effect\n", 9344 SCIPlpiGetSolverName()); 9345 } 9346 /* keep the default LP random seed if this parameter is set to 0 (current default) */ 9347 if( (*lp)->lpirandomseed != 0 ) 9348 { 9349 SCIP_CALL( lpSetIntpar(*lp, SCIP_LPPAR_RANDOMSEED, (*lp)->lpirandomseed, &success) ); 9350 if( !success ) 9351 { 9352 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL, 9353 "LP Solver <%s>: random seed parameter not available -- SCIP parameter has no effect\n", 9354 SCIPlpiGetSolverName()); 9355 } 9356 } 9357 9358 /* Check that infinity value of LP-solver is at least as large as the one used in SCIP. This is necessary, because we 9359 * transfer SCIP infinity values to the ones by the LPI, but not the converse. */ 9360 if ( set->num_infinity > SCIPlpiInfinity((*lp)->lpi) ) 9361 { 9362 SCIPerrorMessage("The infinity value of the LP solver has to be at least as large as the one of SCIP.\n"); 9363 return SCIP_PARAMETERWRONGVAL; 9364 } 9365 9366 return SCIP_OKAY; 9367 } 9368 9369 /** frees LP data object */ 9370 SCIP_RETCODE SCIPlpFree( 9371 SCIP_LP** lp, /**< pointer to LP data object */ 9372 BMS_BLKMEM* blkmem, /**< block memory */ 9373 SCIP_SET* set, /**< global SCIP settings */ 9374 SCIP_EVENTQUEUE* eventqueue, /**< event queue */ 9375 SCIP_EVENTFILTER* eventfilter /**< global event filter */ 9376 ) 9377 { 9378 int i; 9379 9380 assert(lp != NULL); 9381 assert(*lp != NULL); 9382 9383 SCIP_CALL( SCIPlpClear(*lp, blkmem, set, eventqueue, eventfilter) ); 9384 9385 freeDiveChgSideArrays(*lp); 9386 9387 /* release LPI rows */ 9388 for( i = 0; i < (*lp)->nlpirows; ++i ) 9389 { 9390 SCIP_CALL( SCIProwRelease(&(*lp)->lpirows[i], blkmem, set, *lp) ); 9391 } 9392 9393 if( (*lp)->lpi != NULL ) 9394 { 9395 SCIP_CALL( SCIPlpiFree(&(*lp)->lpi) ); 9396 } 9397 9398 BMSfreeMemoryNull(&(*lp)->storedsolvals); 9399 BMSfreeMemoryArrayNull(&(*lp)->lpicols); 9400 BMSfreeMemoryArrayNull(&(*lp)->lpirows); 9401 BMSfreeMemoryArrayNull(&(*lp)->chgcols); 9402 BMSfreeMemoryArrayNull(&(*lp)->chgrows); 9403 BMSfreeMemoryArrayNull(&(*lp)->lazycols); 9404 BMSfreeMemoryArrayNull(&(*lp)->cols); 9405 BMSfreeMemoryArrayNull(&(*lp)->rows); 9406 BMSfreeMemoryArrayNull(&(*lp)->soldirection); 9407 BMSfreeMemory(lp); 9408 9409 return SCIP_OKAY; 9410 } 9411 9412 /** resets the LP to the empty LP by removing all columns and rows from LP, releasing all rows, and flushing the 9413 * changes to the LP solver 9414 */ 9415 SCIP_RETCODE SCIPlpReset( 9416 SCIP_LP* lp, /**< LP data */ 9417 BMS_BLKMEM* blkmem, /**< block memory */ 9418 SCIP_SET* set, /**< global SCIP settings */ 9419 SCIP_PROB* prob, /**< problem data */ 9420 SCIP_STAT* stat, /**< problem statistics */ 9421 SCIP_EVENTQUEUE* eventqueue, /**< event queue */ 9422 SCIP_EVENTFILTER* eventfilter /**< global event filter */ 9423 ) 9424 { 9425 assert(stat != NULL); 9426 9427 SCIP_CALL( SCIPlpClear(lp, blkmem, set, eventqueue, eventfilter) ); 9428 SCIP_CALL( SCIPlpFlush(lp, blkmem, set, prob, eventqueue) ); 9429 9430 /* mark the empty LP to be solved */ 9431 lp->lpsolstat = SCIP_LPSOLSTAT_OPTIMAL; 9432 lp->lpobjval = 0.0; 9433 lp->validsollp = stat->lpcount; /* the initial (empty) SCIP_LP is solved with primal and dual solution of zero */ 9434 lp->validfarkaslp = -1; 9435 lp->validdegeneracylp = -1; 9436 lp->validsoldirlp = -1; 9437 lp->validsoldirsol = NULL; 9438 lp->solved = TRUE; 9439 lp->primalfeasible = TRUE; 9440 lp->primalchecked = TRUE; 9441 lp->dualfeasible = TRUE; 9442 lp->dualchecked = TRUE; 9443 lp->solisbasic = FALSE; 9444 lp->lastlpalgo = SCIP_LPALGO_DUALSIMPLEX; 9445 9446 return SCIP_OKAY; 9447 } 9448 9449 /** adds a column to the LP */ 9450 SCIP_RETCODE SCIPlpAddCol( 9451 SCIP_LP* lp, /**< LP data */ 9452 SCIP_SET* set, /**< global SCIP settings */ 9453 SCIP_COL* col, /**< LP column */ 9454 int depth /**< depth in the tree where the column addition is performed */ 9455 ) 9456 { 9457 assert(lp != NULL); 9458 assert(!lp->diving); 9459 assert(col != NULL); 9460 assert(col->len == 0 || col->rows != NULL); 9461 assert(col->lppos == -1); 9462 assert(col->var != NULL); 9463 assert(SCIPvarGetStatus(col->var) == SCIP_VARSTATUS_COLUMN); 9464 assert(SCIPvarGetCol(col->var) == col); 9465 assert(SCIPvarIsIntegral(col->var) == col->integral); 9466 9467 SCIPsetDebugMsg(set, "adding column <%s> to LP (%d rows, %d cols)\n", SCIPvarGetName(col->var), lp->nrows, lp->ncols); 9468 #ifdef SCIP_DEBUG 9469 { 9470 int i; 9471 SCIPsetDebugMsgPrint(set, " (obj: %g) [%g,%g]", col->obj, col->lb, col->ub); 9472 for( i = 0; i < col->len; ++i ) 9473 SCIPsetDebugMsgPrint(set, " %+g<%s>", col->vals[i], col->rows[i]->name); 9474 SCIPsetDebugMsgPrint(set, "\n"); 9475 } 9476 #endif 9477 9478 SCIP_CALL( ensureColsSize(lp, set, lp->ncols+1) ); 9479 lp->cols[lp->ncols] = col; 9480 col->lppos = lp->ncols; 9481 col->lpdepth = depth; 9482 col->age = 0; 9483 lp->ncols++; 9484 if( col->removable ) 9485 lp->nremovablecols++; 9486 9487 if( !SCIPsetIsInfinity(set, -col->lazylb) || !SCIPsetIsInfinity(set, col->lazyub) ) 9488 { 9489 SCIP_CALL( ensureLazycolsSize(lp, set, lp->nlazycols+1) ); 9490 lp->lazycols[lp->nlazycols] = col; 9491 lp->nlazycols++; 9492 } 9493 9494 /* mark the current LP unflushed */ 9495 lp->flushed = FALSE; 9496 9497 /* update column arrays of all linked rows */ 9498 colUpdateAddLP(col, set); 9499 9500 /* update the objective function vector norms */ 9501 lpUpdateObjNorms(lp, set, 0.0, col->unchangedobj); 9502 9503 checkLinks(lp); 9504 9505 return SCIP_OKAY; 9506 } 9507 9508 /** adds a row to the LP and captures it */ 9509 SCIP_RETCODE SCIPlpAddRow( 9510 SCIP_LP* lp, /**< LP data */ 9511 BMS_BLKMEM* blkmem, /**< block memory buffers */ 9512 SCIP_SET* set, /**< global SCIP settings */ 9513 SCIP_EVENTQUEUE* eventqueue, /**< event queue */ 9514 SCIP_EVENTFILTER* eventfilter, /**< global event filter */ 9515 SCIP_ROW* row, /**< LP row */ 9516 int depth /**< depth in the tree where the row addition is performed */ 9517 ) 9518 { 9519 assert(lp != NULL); 9520 assert(row != NULL); 9521 assert(row->len == 0 || row->cols != NULL); 9522 assert(row->lppos == -1); 9523 9524 SCIProwCapture(row); 9525 SCIProwLock(row); 9526 9527 SCIPsetDebugMsg(set, "adding row <%s> to LP (%d rows, %d cols)\n", row->name, lp->nrows, lp->ncols); 9528 #ifdef SCIP_DEBUG 9529 { 9530 int i; 9531 SCIPsetDebugMsgPrint(set, " %g <=", row->lhs); 9532 for( i = 0; i < row->len; ++i ) 9533 SCIPsetDebugMsgPrint(set, " %+g<%s>", row->vals[i], SCIPvarGetName(row->cols[i]->var)); 9534 if( !SCIPsetIsZero(set, row->constant) ) 9535 SCIPsetDebugMsgPrint(set, " %+g", row->constant); 9536 SCIPsetDebugMsgPrint(set, " <= %g\n", row->rhs); 9537 } 9538 #endif 9539 9540 SCIP_CALL( ensureRowsSize(lp, set, lp->nrows+1) ); 9541 lp->rows[lp->nrows] = row; 9542 row->lppos = lp->nrows; 9543 row->lpdepth = depth; 9544 row->age = 0; 9545 lp->nrows++; 9546 if( row->removable ) 9547 lp->nremovablerows++; 9548 9549 /* mark the current LP unflushed */ 9550 lp->flushed = FALSE; 9551 9552 /* update row arrays of all linked columns */ 9553 rowUpdateAddLP(row); 9554 9555 checkLinks(lp); 9556 9557 rowCalcNorms(row, set); 9558 9559 /* check, if row addition to LP events are tracked 9560 * if so, issue ROWADDEDLP event 9561 */ 9562 if( (eventfilter->len > 0 && (eventfilter->eventmask & SCIP_EVENTTYPE_ROWADDEDLP) != 0) ) 9563 { 9564 SCIP_EVENT* event; 9565 9566 SCIP_CALL( SCIPeventCreateRowAddedLP(&event, blkmem, row) ); 9567 SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, NULL, NULL, eventfilter, &event) ); 9568 } 9569 9570 return SCIP_OKAY; 9571 } 9572 9573 9574 #ifndef NDEBUG 9575 /** method checks if all columns in the lazycols array have at least one lazy bound and also have a counter part in the 9576 * cols array; furthermore, it is checked if columns in the cols array which have a lazy bound have a counter part in 9577 * the lazycols array 9578 */ 9579 static 9580 void checkLazyColArray( 9581 SCIP_LP* lp, /**< LP data */ 9582 SCIP_SET* set /**< global SCIP settings */ 9583 ) 9584 { 9585 SCIP_Bool contained; 9586 int c; 9587 int i; 9588 9589 assert(lp != NULL); 9590 9591 /* check if each column in the lazy column array has a counter part in the column array */ 9592 for( i = 0; i < lp->nlazycols; ++i ) 9593 { 9594 /* check if each lazy column has at least on lazy bound */ 9595 assert(lp->lazycols[i] != NULL); 9596 assert(!SCIPsetIsInfinity(set, lp->lazycols[i]->lazyub) || !SCIPsetIsInfinity(set, -lp->lazycols[i]->lazylb)); 9597 9598 contained = FALSE; 9599 for( c = 0; c < lp->ncols; ++c ) 9600 { 9601 if( lp->lazycols[i] == lp->cols[c] ) 9602 { 9603 assert(!SCIPsetIsInfinity(set, lp->cols[c]->lazyub) || !SCIPsetIsInfinity(set, -lp->cols[c]->lazylb)); 9604 contained = TRUE; 9605 } 9606 } 9607 assert(contained); 9608 } 9609 9610 /* check if each column in the column array which has at least one lazy bound has a counter part in the lazy column * 9611 * array */ 9612 for( c = 0; c < lp->ncols; ++c ) 9613 { 9614 contained = FALSE; 9615 assert(lp->cols[c] != NULL); 9616 9617 for( i = 0; i < lp->nlazycols; ++i ) 9618 { 9619 if( lp->lazycols[i] == lp->cols[c] ) 9620 { 9621 contained = TRUE; 9622 } 9623 } 9624 9625 assert(contained == (!SCIPsetIsInfinity(set, lp->cols[c]->lazyub) || !SCIPsetIsInfinity(set, -lp->cols[c]->lazylb))); 9626 } 9627 } 9628 #else 9629 #define checkLazyColArray(lp, set) /**/ 9630 #endif 9631 9632 /** removes all columns after the given number of cols from the LP */ 9633 SCIP_RETCODE SCIPlpShrinkCols( 9634 SCIP_LP* lp, /**< LP data */ 9635 SCIP_SET* set, /**< global SCIP settings */ 9636 int newncols /**< new number of columns in the LP */ 9637 ) 9638 { 9639 SCIP_COL* col; 9640 int c; 9641 9642 assert(lp != NULL); 9643 9644 SCIPsetDebugMsg(set, "shrinking LP from %d to %d columns\n", lp->ncols, newncols); 9645 assert(0 <= newncols); 9646 assert(newncols <= lp->ncols); 9647 9648 if( newncols < lp->ncols ) 9649 { 9650 assert(!lp->diving); 9651 9652 for( c = lp->ncols-1; c >= newncols; --c ) 9653 { 9654 col = lp->cols[c]; 9655 assert(col != NULL); 9656 assert(col->len == 0 || col->rows != NULL); 9657 assert(col->var != NULL); 9658 assert(SCIPvarGetStatus(col->var) == SCIP_VARSTATUS_COLUMN); 9659 assert(SCIPvarGetCol(col->var) == lp->cols[c]); 9660 assert(col->lppos == c); 9661 9662 /* mark column to be removed from the LP */ 9663 col->lppos = -1; 9664 col->lpdepth = -1; 9665 lp->ncols--; 9666 9667 /* count removable columns */ 9668 if( col->removable ) 9669 lp->nremovablecols--; 9670 9671 /* update column arrays of all linked rows */ 9672 colUpdateDelLP(col, set); 9673 9674 /* update the objective function vector norms */ 9675 lpUpdateObjNorms(lp, set, col->unchangedobj, 0.0); 9676 } 9677 assert(lp->ncols == newncols); 9678 lp->lpifirstchgcol = MIN(lp->lpifirstchgcol, newncols); 9679 9680 /* remove columns which are deleted from the lazy column array */ 9681 c = 0; 9682 while( c < lp->nlazycols ) 9683 { 9684 if( lp->lazycols[c]->lppos < 0 ) 9685 { 9686 lp->lazycols[c] = lp->lazycols[lp->nlazycols-1]; 9687 lp->nlazycols--; 9688 } 9689 else 9690 c++; 9691 } 9692 9693 /* mark the current LP unflushed */ 9694 lp->flushed = FALSE; 9695 9696 checkLazyColArray(lp, set); 9697 checkLinks(lp); 9698 } 9699 assert(lp->nremovablecols <= lp->ncols); 9700 9701 return SCIP_OKAY; 9702 } 9703 9704 /** removes and releases all rows after the given number of rows from the LP */ 9705 SCIP_RETCODE SCIPlpShrinkRows( 9706 SCIP_LP* lp, /**< LP data */ 9707 BMS_BLKMEM* blkmem, /**< block memory */ 9708 SCIP_SET* set, /**< global SCIP settings */ 9709 SCIP_EVENTQUEUE* eventqueue, /**< event queue */ 9710 SCIP_EVENTFILTER* eventfilter, /**< global event filter */ 9711 int newnrows /**< new number of rows in the LP */ 9712 ) 9713 { 9714 SCIP_ROW* row; 9715 int r; 9716 9717 assert(lp != NULL); 9718 assert(0 <= newnrows && newnrows <= lp->nrows); 9719 9720 SCIPsetDebugMsg(set, "shrinking LP from %d to %d rows\n", lp->nrows, newnrows); 9721 if( newnrows < lp->nrows ) 9722 { 9723 for( r = lp->nrows-1; r >= newnrows; --r ) 9724 { 9725 row = lp->rows[r]; 9726 assert(row != NULL); 9727 assert(row->len == 0 || row->cols != NULL); 9728 assert(row->lppos == r); 9729 9730 /* mark row to be removed from the LP */ 9731 row->lppos = -1; 9732 row->lpdepth = -1; 9733 lp->nrows--; 9734 9735 /* count removable rows */ 9736 if( row->removable ) 9737 lp->nremovablerows--; 9738 9739 /* update row arrays of all linked columns */ 9740 rowUpdateDelLP(row); 9741 9742 SCIProwUnlock(lp->rows[r]); 9743 9744 /* check, if row deletion events are tracked 9745 * if so, issue ROWDELETEDLP event 9746 */ 9747 if( eventfilter->len > 0 && (eventfilter->eventmask & SCIP_EVENTTYPE_ROWDELETEDLP) != 0 ) 9748 { 9749 SCIP_EVENT* event; 9750 9751 SCIP_CALL( SCIPeventCreateRowDeletedLP(&event, blkmem, lp->rows[r]) ); 9752 SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, NULL, NULL, eventfilter, &event) ); 9753 } 9754 9755 SCIP_CALL( SCIProwRelease(&lp->rows[r], blkmem, set, lp) ); 9756 } 9757 assert(lp->nrows == newnrows); 9758 lp->lpifirstchgrow = MIN(lp->lpifirstchgrow, newnrows); 9759 9760 /* mark the current LP unflushed */ 9761 lp->flushed = FALSE; 9762 9763 checkLinks(lp); 9764 } 9765 assert(lp->nremovablerows <= lp->nrows); 9766 9767 return SCIP_OKAY; 9768 } 9769 9770 /** removes all columns and rows from LP, releases all rows */ 9771 SCIP_RETCODE SCIPlpClear( 9772 SCIP_LP* lp, /**< LP data */ 9773 BMS_BLKMEM* blkmem, /**< block memory */ 9774 SCIP_SET* set, /**< global SCIP settings */ 9775 SCIP_EVENTQUEUE* eventqueue, /**< event queue */ 9776 SCIP_EVENTFILTER* eventfilter /**< global event filter */ 9777 ) 9778 { 9779 assert(lp != NULL); 9780 assert(!lp->diving); 9781 9782 SCIPsetDebugMsg(set, "clearing LP\n"); 9783 SCIP_CALL( SCIPlpShrinkCols(lp, set, 0) ); 9784 SCIP_CALL( SCIPlpShrinkRows(lp, blkmem, set, eventqueue, eventfilter, 0) ); 9785 9786 return SCIP_OKAY; 9787 } 9788 9789 /** remembers number of columns and rows to track the newly added ones */ 9790 void SCIPlpMarkSize( 9791 SCIP_LP* lp /**< current LP data */ 9792 ) 9793 { 9794 assert(lp != NULL); 9795 assert(!lp->diving); 9796 9797 lp->firstnewrow = lp->nrows; 9798 lp->firstnewcol = lp->ncols; 9799 } 9800 9801 /** sets the remembered number of columns and rows to the given values */ 9802 void SCIPlpSetSizeMark( 9803 SCIP_LP* lp, /**< current LP data */ 9804 int nrows, /**< number of rows to set the size marker to */ 9805 int ncols /**< number of columns to set the size marker to */ 9806 ) 9807 { 9808 assert(lp != NULL); 9809 assert(!lp->diving); 9810 9811 lp->firstnewrow = nrows; 9812 lp->firstnewcol = ncols; 9813 } 9814 9815 /** gets all indices of basic columns and rows: index i >= 0 corresponds to column i, index i < 0 to row -i-1 */ 9816 SCIP_RETCODE SCIPlpGetBasisInd( 9817 SCIP_LP* lp, /**< LP data */ 9818 int* basisind /**< pointer to store basis indices ready to keep number of rows entries */ 9819 ) 9820 { 9821 assert(lp != NULL); 9822 assert(lp->flushed); 9823 assert(lp->solved); 9824 assert(lp->solisbasic); 9825 assert(basisind != NULL); 9826 9827 SCIP_CALL( SCIPlpiGetBasisInd(lp->lpi, basisind) ); 9828 9829 return SCIP_OKAY; 9830 } 9831 9832 /** gets current basis status for columns and rows; arrays must be large enough to store the basis status */ 9833 SCIP_RETCODE SCIPlpGetBase( 9834 SCIP_LP* lp, /**< LP data */ 9835 int* cstat, /**< array to store column basis status, or NULL */ 9836 int* rstat /**< array to store row basis status, or NULL */ 9837 ) 9838 { 9839 assert(lp != NULL); 9840 assert(lp->flushed); 9841 assert(lp->solved); 9842 assert(lp->solisbasic); 9843 9844 SCIP_CALL( SCIPlpiGetBase(lp->lpi, cstat, rstat) ); 9845 9846 return SCIP_OKAY; 9847 } 9848 9849 /** gets a row from the inverse basis matrix B^-1 */ 9850 SCIP_RETCODE SCIPlpGetBInvRow( 9851 SCIP_LP* lp, /**< LP data */ 9852 int r, /**< row number */ 9853 SCIP_Real* coef, /**< pointer to store the coefficients of the row */ 9854 int* inds, /**< array to store the non-zero indices, or NULL */ 9855 int* ninds /**< pointer to store the number of non-zero indices, or NULL 9856 * (-1: if we do not store sparsity informations) */ 9857 ) 9858 { 9859 assert(lp != NULL); 9860 assert(lp->flushed); 9861 assert(lp->solved); 9862 assert(lp->solisbasic); 9863 assert(0 <= r && r < lp->nrows); /* the basis matrix is nrows x nrows */ 9864 assert(coef != NULL); 9865 9866 SCIP_CALL( SCIPlpiGetBInvRow(lp->lpi, r, coef, inds, ninds) ); 9867 9868 return SCIP_OKAY; 9869 } 9870 9871 /** gets a column from the inverse basis matrix B^-1 */ 9872 SCIP_RETCODE SCIPlpGetBInvCol( 9873 SCIP_LP* lp, /**< LP data */ 9874 int c, /**< column number of B^-1; this is NOT the number of the column in the LP 9875 * returned by SCIPcolGetLPPos(); you have to call SCIPgetBasisInd() 9876 * to get the array which links the B^-1 column numbers to the row and 9877 * column numbers of the LP! c must be between 0 and nrows-1, since the 9878 * basis has the size nrows * nrows */ 9879 SCIP_Real* coef, /**< pointer to store the coefficients of the column */ 9880 int* inds, /**< array to store the non-zero indices, or NULL */ 9881 int* ninds /**< pointer to store the number of non-zero indices, or NULL 9882 * (-1: if we do not store sparsity informations) */ 9883 ) 9884 { 9885 assert(lp != NULL); 9886 assert(lp->flushed); 9887 assert(lp->solved); 9888 assert(lp->solisbasic); 9889 assert(0 <= c && c < lp->nrows); /* the basis matrix is nrows x nrows */ 9890 assert(coef != NULL); 9891 9892 SCIP_CALL( SCIPlpiGetBInvCol(lp->lpi, c, coef, inds, ninds) ); 9893 9894 return SCIP_OKAY; 9895 } 9896 9897 /** gets a row from the product of inverse basis matrix B^-1 and coefficient matrix A (i.e. from B^-1 * A) */ 9898 SCIP_RETCODE SCIPlpGetBInvARow( 9899 SCIP_LP* lp, /**< LP data */ 9900 int r, /**< row number */ 9901 SCIP_Real* binvrow, /**< row in B^-1 from prior call to SCIPlpGetBInvRow(), or NULL */ 9902 SCIP_Real* coef, /**< pointer to store the coefficients of the row */ 9903 int* inds, /**< array to store the non-zero indices, or NULL */ 9904 int* ninds /**< pointer to store the number of non-zero indices, or NULL 9905 * (-1: if we do not store sparsity informations) */ 9906 ) 9907 { 9908 assert(lp != NULL); 9909 assert(lp->flushed); 9910 assert(lp->solved); 9911 assert(lp->solisbasic); 9912 assert(0 <= r && r < lp->nrows); /* the basis matrix is nrows x nrows */ 9913 assert(coef != NULL); 9914 9915 SCIP_CALL( SCIPlpiGetBInvARow(lp->lpi, r, binvrow, coef, inds, ninds) ); 9916 9917 return SCIP_OKAY; 9918 } 9919 9920 /** gets a column from the product of inverse basis matrix B^-1 and coefficient matrix A (i.e. from B^-1 * A), 9921 * i.e., it computes B^-1 * A_c with A_c being the c'th column of A 9922 */ 9923 SCIP_RETCODE SCIPlpGetBInvACol( 9924 SCIP_LP* lp, /**< LP data */ 9925 int c, /**< column number which can be accessed by SCIPcolGetLPPos() */ 9926 SCIP_Real* coef, /**< pointer to store the coefficients of the column */ 9927 int* inds, /**< array to store the non-zero indices, or NULL */ 9928 int* ninds /**< pointer to store the number of non-zero indices, or NULL 9929 * (-1: if we do not store sparsity informations) */ 9930 ) 9931 { 9932 assert(lp != NULL); 9933 assert(lp->flushed); 9934 assert(lp->solved); 9935 assert(lp->solisbasic); 9936 assert(0 <= c && c < lp->ncols); 9937 assert(coef != NULL); 9938 9939 SCIP_CALL( SCIPlpiGetBInvACol(lp->lpi, c, coef, inds, ninds) ); 9940 9941 return SCIP_OKAY; 9942 } 9943 9944 /** calculates a weighted sum of all LP rows; for negative weights, the left and right hand side of the corresponding 9945 * LP row are swapped in the summation 9946 */ 9947 SCIP_RETCODE SCIPlpSumRows( 9948 SCIP_LP* lp, /**< LP data */ 9949 SCIP_SET* set, /**< global SCIP settings */ 9950 SCIP_PROB* prob, /**< problem data */ 9951 SCIP_Real* weights, /**< row weights in row summation */ 9952 SCIP_REALARRAY* sumcoef, /**< array to store sum coefficients indexed by variables' probindex */ 9953 SCIP_Real* sumlhs, /**< pointer to store the left hand side of the row summation */ 9954 SCIP_Real* sumrhs /**< pointer to store the right hand side of the row summation */ 9955 ) 9956 { 9957 SCIP_ROW* row; 9958 int r; 9959 int i; 9960 int idx; 9961 SCIP_Bool lhsinfinite; 9962 SCIP_Bool rhsinfinite; 9963 9964 assert(lp != NULL); 9965 assert(prob != NULL); 9966 assert(weights != NULL); 9967 assert(sumcoef != NULL); 9968 assert(sumlhs != NULL); 9969 assert(sumrhs != NULL); 9970 9971 /**@todo test, if a column based summation is faster */ 9972 9973 SCIP_CALL( SCIPrealarrayClear(sumcoef) ); 9974 SCIP_CALL( SCIPrealarrayExtend(sumcoef, set->mem_arraygrowinit, set->mem_arraygrowfac, 0, prob->nvars-1) ); 9975 *sumlhs = 0.0; 9976 *sumrhs = 0.0; 9977 lhsinfinite = FALSE; 9978 rhsinfinite = FALSE; 9979 for( r = 0; r < lp->nrows; ++r ) 9980 { 9981 if( !SCIPsetIsZero(set, weights[r]) ) 9982 { 9983 row = lp->rows[r]; 9984 assert(row != NULL); 9985 assert(row->len == 0 || row->cols != NULL); 9986 assert(row->len == 0 || row->cols_index != NULL); 9987 assert(row->len == 0 || row->vals != NULL); 9988 9989 /* add the row coefficients to the sum */ 9990 for( i = 0; i < row->len; ++i ) 9991 { 9992 assert(row->cols[i] != NULL); 9993 assert(row->cols[i]->var != NULL); 9994 assert(SCIPvarGetStatus(row->cols[i]->var) == SCIP_VARSTATUS_COLUMN); 9995 assert(SCIPvarGetCol(row->cols[i]->var) == row->cols[i]); 9996 assert(SCIPvarGetProbindex(row->cols[i]->var) == row->cols[i]->var_probindex); 9997 idx = row->cols[i]->var_probindex; 9998 assert(0 <= idx && idx < prob->nvars); 9999 SCIP_CALL( SCIPrealarrayIncVal(sumcoef, set->mem_arraygrowinit, set->mem_arraygrowfac, idx, weights[r] * row->vals[i]) ); 10000 } 10001 10002 /* add the row sides to the sum, depending on the sign of the weight */ 10003 if( weights[r] > 0.0 ) 10004 { 10005 lhsinfinite = lhsinfinite || SCIPsetIsInfinity(set, -row->lhs); 10006 if( !lhsinfinite ) 10007 (*sumlhs) += weights[r] * (row->lhs - row->constant); 10008 rhsinfinite = rhsinfinite || SCIPsetIsInfinity(set, row->rhs); 10009 if( !rhsinfinite ) 10010 (*sumrhs) += weights[r] * (row->rhs - row->constant); 10011 } 10012 else 10013 { 10014 lhsinfinite = lhsinfinite || SCIPsetIsInfinity(set, row->rhs); 10015 if( !lhsinfinite ) 10016 (*sumlhs) += weights[r] * (row->rhs - row->constant); 10017 rhsinfinite = rhsinfinite || SCIPsetIsInfinity(set, -row->lhs); 10018 if( !rhsinfinite ) 10019 (*sumrhs) += weights[r] * (row->lhs - row->constant); 10020 } 10021 } 10022 } 10023 10024 if( lhsinfinite ) 10025 *sumlhs = -SCIPsetInfinity(set); 10026 if( rhsinfinite ) 10027 *sumrhs = SCIPsetInfinity(set); 10028 10029 return SCIP_OKAY; 10030 } 10031 10032 /** stores LP state (like basis information) into LP state object */ 10033 SCIP_RETCODE SCIPlpGetState( 10034 SCIP_LP* lp, /**< LP data */ 10035 BMS_BLKMEM* blkmem, /**< block memory */ 10036 SCIP_LPISTATE** lpistate /**< pointer to LP state information (like basis information) */ 10037 ) 10038 { 10039 assert(lp != NULL); 10040 assert(lp->flushed); 10041 assert(lp->solved); 10042 assert(blkmem != NULL); 10043 assert(lpistate != NULL); 10044 10045 /* check whether there is no lp */ 10046 if( lp->nlpicols == 0 && lp->nlpirows == 0 ) 10047 *lpistate = NULL; 10048 else 10049 { 10050 SCIP_CALL( SCIPlpiGetState(lp->lpi, blkmem, lpistate) ); 10051 } 10052 10053 return SCIP_OKAY; 10054 } 10055 10056 /** loads LP state (like basis information) into solver */ 10057 SCIP_RETCODE SCIPlpSetState( 10058 SCIP_LP* lp, /**< LP data */ 10059 BMS_BLKMEM* blkmem, /**< block memory */ 10060 SCIP_SET* set, /**< global SCIP settings */ 10061 SCIP_PROB* prob, /**< problem data */ 10062 SCIP_EVENTQUEUE* eventqueue, /**< event queue */ 10063 SCIP_LPISTATE* lpistate, /**< LP state information (like basis information) */ 10064 SCIP_Bool wasprimfeas, /**< primal feasibility when LP state information was stored */ 10065 SCIP_Bool wasprimchecked, /**< true if the LP solution has passed the primal feasibility check */ 10066 SCIP_Bool wasdualfeas, /**< dual feasibility when LP state information was stored */ 10067 SCIP_Bool wasdualchecked /**< true if the LP solution has passed the dual feasibility check */ 10068 ) 10069 { 10070 assert(lp != NULL); 10071 assert(blkmem != NULL); 10072 10073 /* flush changes to the LP solver */ 10074 SCIP_CALL( SCIPlpFlush(lp, blkmem, set, prob, eventqueue) ); 10075 assert(lp->flushed); 10076 10077 if( lp->solved && lp->solisbasic ) 10078 return SCIP_OKAY; 10079 10080 /* set LPI state in the LP solver */ 10081 if( lpistate == NULL ) 10082 lp->solisbasic = FALSE; 10083 else 10084 { 10085 SCIP_CALL( SCIPlpiSetState(lp->lpi, blkmem, lpistate) ); 10086 lp->solisbasic = SCIPlpiHasStateBasis(lp->lpi, lpistate); 10087 } 10088 /* @todo: setting feasibility to TRUE might be wrong because in probing mode, the state is even saved when the LP was 10089 * flushed and solved, also, e.g., when we hit the iteration limit 10090 */ 10091 lp->primalfeasible = wasprimfeas; 10092 lp->primalchecked = wasprimchecked; 10093 lp->dualfeasible = wasdualfeas; 10094 lp->dualchecked = wasdualchecked; 10095 10096 return SCIP_OKAY; 10097 } 10098 10099 /** frees LP state information */ 10100 SCIP_RETCODE SCIPlpFreeState( 10101 SCIP_LP* lp, /**< LP data */ 10102 BMS_BLKMEM* blkmem, /**< block memory */ 10103 SCIP_LPISTATE** lpistate /**< pointer to LP state information (like basis information) */ 10104 ) 10105 { 10106 assert(lp != NULL); 10107 10108 if( *lpistate != NULL ) 10109 { 10110 SCIP_CALL( SCIPlpiFreeState(lp->lpi, blkmem, lpistate) ); 10111 } 10112 10113 return SCIP_OKAY; 10114 } 10115 10116 /** interrupts the currently ongoing lp solve, or disables the interrupt */ 10117 SCIP_RETCODE SCIPlpInterrupt( 10118 SCIP_LP* lp, /**< LP data */ 10119 SCIP_Bool interrupt /**< TRUE if interrupt should be set, FALSE if it should be disabled */ 10120 ) 10121 { 10122 assert(lp != NULL); 10123 10124 if( lp->lpi == NULL ) 10125 return SCIP_OKAY; 10126 10127 SCIP_CALL( SCIPlpiInterrupt(lp->lpi, interrupt) ); 10128 10129 return SCIP_OKAY; 10130 } 10131 10132 /** stores pricing norms into LP norms object */ 10133 SCIP_RETCODE SCIPlpGetNorms( 10134 SCIP_LP* lp, /**< LP data */ 10135 BMS_BLKMEM* blkmem, /**< block memory */ 10136 SCIP_LPINORMS** lpinorms /**< pointer to LP pricing norms information */ 10137 ) 10138 { 10139 assert(lp != NULL); 10140 assert(lp->flushed); 10141 assert(lp->solved); 10142 assert(blkmem != NULL); 10143 assert(lpinorms != NULL); 10144 10145 /* check whether there is no lp */ 10146 if( lp->nlpicols == 0 && lp->nlpirows == 0 ) 10147 *lpinorms = NULL; 10148 else 10149 { 10150 SCIP_CALL( SCIPlpiGetNorms(lp->lpi, blkmem, lpinorms) ); 10151 } 10152 10153 return SCIP_OKAY; 10154 } 10155 10156 /** loads pricing norms from LP norms object into solver */ 10157 SCIP_RETCODE SCIPlpSetNorms( 10158 SCIP_LP* lp, /**< LP data */ 10159 BMS_BLKMEM* blkmem, /**< block memory */ 10160 SCIP_LPINORMS* lpinorms /**< LP pricing norms information */ 10161 ) 10162 { 10163 assert(lp != NULL); 10164 assert(blkmem != NULL); 10165 assert(lp->flushed); 10166 10167 /* set LPI norms in the LP solver */ 10168 if( lpinorms != NULL ) 10169 { 10170 SCIP_CALL( SCIPlpiSetNorms(lp->lpi, blkmem, lpinorms) ); 10171 } 10172 10173 return SCIP_OKAY; 10174 } 10175 10176 /** frees pricing norms information */ 10177 SCIP_RETCODE SCIPlpFreeNorms( 10178 SCIP_LP* lp, /**< LP data */ 10179 BMS_BLKMEM* blkmem, /**< block memory */ 10180 SCIP_LPINORMS** lpinorms /**< pointer to LP pricing norms information */ 10181 ) 10182 { 10183 assert(lp != NULL); 10184 10185 SCIP_CALL( SCIPlpiFreeNorms(lp->lpi, blkmem, lpinorms) ); 10186 10187 return SCIP_OKAY; 10188 } 10189 10190 /** return the current cutoff bound of the lp */ 10191 SCIP_Real SCIPlpGetCutoffbound( 10192 SCIP_LP* lp /**< current LP data */ 10193 ) 10194 { 10195 assert(lp != NULL); 10196 10197 return lp->cutoffbound; 10198 } 10199 10200 /** sets the upper objective limit of the LP solver */ 10201 SCIP_RETCODE SCIPlpSetCutoffbound( 10202 SCIP_LP* lp, /**< current LP data */ 10203 SCIP_SET* set, /**< global SCIP settings */ 10204 SCIP_PROB* prob, /**< problem data */ 10205 SCIP_Real cutoffbound /**< new upper objective limit */ 10206 ) 10207 { 10208 assert(lp != NULL); 10209 10210 SCIPsetDebugMsg(set, "setting LP upper objective limit from %g to %g\n", lp->cutoffbound, cutoffbound); 10211 10212 /* if the objective function was changed in diving, the cutoff bound has no meaning (it will be set correctly 10213 * in SCIPendDive()) 10214 */ 10215 if( SCIPlpDivingObjChanged(lp) ) 10216 { 10217 assert(SCIPsetIsInfinity(set, lp->cutoffbound)); 10218 return SCIP_OKAY; 10219 } 10220 10221 /* if the cutoff bound is increased, and the LP was proved to exceed the old cutoff, it is no longer solved */ 10222 if( SCIPlpGetSolstat(lp) == SCIP_LPSOLSTAT_OBJLIMIT && cutoffbound > lp->cutoffbound ) 10223 { 10224 /* mark the current solution invalid */ 10225 lp->solved = FALSE; 10226 lp->lpobjval = SCIP_INVALID; 10227 lp->lpsolstat = SCIP_LPSOLSTAT_NOTSOLVED; 10228 } 10229 /* if the cutoff bound is decreased below the current optimal value, the LP now exceeds the objective limit; 10230 * if the objective limit in the LP solver was disabled, the solution status of the LP is not changed 10231 */ 10232 else if( !lpCutoffDisabled(set, prob) && SCIPlpGetSolstat(lp) == SCIP_LPSOLSTAT_OPTIMAL 10233 && SCIPlpGetObjval(lp, set, prob) >= cutoffbound ) 10234 { 10235 assert(lp->flushed); 10236 assert(lp->solved); 10237 lp->lpsolstat = SCIP_LPSOLSTAT_OBJLIMIT; 10238 } 10239 10240 lp->cutoffbound = cutoffbound; 10241 10242 return SCIP_OKAY; 10243 } 10244 10245 /** gets current primal feasibility tolerance of LP solver */ 10246 SCIP_Real SCIPlpGetFeastol( 10247 SCIP_LP* lp /**< current LP data */ 10248 ) 10249 { 10250 assert(lp != NULL); 10251 10252 return lp->feastol; 10253 } 10254 10255 /** sets primal feasibility tolerance of LP solver */ 10256 void SCIPlpSetFeastol( 10257 SCIP_LP* lp, /**< current LP data */ 10258 SCIP_SET* set, /**< global SCIP settings */ 10259 SCIP_Real newfeastol /**< new primal feasibility tolerance for LP */ 10260 ) 10261 { 10262 assert(lp != NULL); 10263 assert(newfeastol > 0.0); 10264 10265 SCIPsetDebugMsg(set, "setting LP primal feasibility tolerance from %g to %g\n", lp->feastol, newfeastol); 10266 10267 /* mark the LP unsolved, if the primal feasibility tolerance is tightened */ 10268 if( newfeastol < lp->feastol ) 10269 { 10270 lp->solved = FALSE; 10271 lp->lpsolstat = SCIP_LPSOLSTAT_NOTSOLVED; 10272 } 10273 10274 lp->feastol = newfeastol; 10275 } 10276 10277 /** resets primal feasibility tolerance of LP solver 10278 * 10279 * Sets primal feasibility tolerance to min of numerics/lpfeastolfactor * numerics/feastol and relaxfeastol. 10280 */ 10281 void SCIPlpResetFeastol( 10282 SCIP_LP* lp, /**< current LP data */ 10283 SCIP_SET* set /**< global SCIP settings */ 10284 ) 10285 { 10286 assert(lp != NULL); 10287 10288 SCIPsetDebugMsg(set, "reset LP primal feasibility tolerance\n"); 10289 10290 if( SCIPsetRelaxfeastol(set) != SCIP_INVALID ) /*lint !e777*/ 10291 SCIPlpSetFeastol(lp, set, MIN(SCIPsetRelaxfeastol(set), SCIPsetLPFeastolFactor(set) * SCIPsetFeastol(set))); /*lint !e666*/ 10292 else 10293 SCIPlpSetFeastol(lp, set, SCIPsetLPFeastolFactor(set) * SCIPsetFeastol(set)); 10294 } 10295 10296 /** returns the name of the given LP algorithm */ 10297 static 10298 const char* lpalgoName( 10299 SCIP_LPALGO lpalgo /**< LP algorithm */ 10300 ) 10301 { 10302 switch( lpalgo ) 10303 { 10304 case SCIP_LPALGO_PRIMALSIMPLEX: 10305 return "primal simplex"; 10306 case SCIP_LPALGO_DUALSIMPLEX: 10307 return "dual simplex"; 10308 case SCIP_LPALGO_BARRIER: 10309 return "barrier"; 10310 case SCIP_LPALGO_BARRIERCROSSOVER: 10311 return "barrier/crossover"; 10312 default: 10313 SCIPerrorMessage("invalid LP algorithm\n"); 10314 SCIPABORT(); 10315 return "invalid"; /*lint !e527*/ 10316 } 10317 } 10318 10319 /** calls LPI to perform primal simplex, measures time and counts iterations, gets basis feasibility status */ 10320 static 10321 SCIP_RETCODE lpPrimalSimplex( 10322 SCIP_LP* lp, /**< current LP data */ 10323 SCIP_SET* set, /**< global SCIP settings */ 10324 SCIP_STAT* stat, /**< problem statistics */ 10325 SCIP_Bool resolve, /**< is this a resolving call (starting with feasible basis)? */ 10326 SCIP_Bool keepsol, /**< should the old LP solution be kept if no iterations were performed? */ 10327 SCIP_Bool instable, /**< is this a resolving call to avoid instable LPs? */ 10328 SCIP_Bool* lperror /**< pointer to store whether an unresolved LP error occurred */ 10329 ) 10330 { 10331 SCIP_Real timedelta; 10332 SCIP_RETCODE retcode; 10333 int iterations; 10334 10335 assert(lp != NULL); 10336 assert(lp->flushed); 10337 assert(set != NULL); 10338 assert(stat != NULL); 10339 assert(lperror != NULL); 10340 10341 SCIPsetDebugMsg(set, "solving LP %" SCIP_LONGINT_FORMAT " (%d cols, %d rows) with primal simplex (diving=%d, nprimallps=%" SCIP_LONGINT_FORMAT ", ndivinglps=%" SCIP_LONGINT_FORMAT ")\n", 10342 stat->lpcount+1, lp->ncols, lp->nrows, lp->diving || lp->probing, stat->nprimallps, stat->ndivinglps); 10343 10344 *lperror = FALSE; 10345 10346 #ifdef SCIP_MORE_DEBUG /* for debugging: write all root node LP's */ 10347 if( stat->nnodes == 1 && !lp->diving && !lp->probing ) 10348 { 10349 char fname[SCIP_MAXSTRLEN]; 10350 (void) SCIPsnprintf(fname, SCIP_MAXSTRLEN, "lp%" SCIP_LONGINT_FORMAT "_%" SCIP_LONGINT_FORMAT ".lp", stat->nnodes, stat->lpcount); 10351 SCIP_CALL( SCIPlpWrite(lp, fname) ); 10352 SCIPsetDebugMsg(set, "wrote LP to file <%s> (primal simplex, objlim=%.15g, feastol=%.15g/%.15g, fromscratch=%d, fastmip=%d, scaling=%d, presolving=%d)\n", 10353 fname, lp->lpiobjlim, lp->lpifeastol, lp->lpidualfeastol, 10354 lp->lpifromscratch, lp->lpifastmip, lp->lpiscaling, lp->lpipresolving); 10355 } 10356 #endif 10357 10358 /* start timing */ 10359 if( lp->diving || lp->probing ) 10360 { 10361 if( lp->strongbranchprobing ) 10362 SCIPclockStart(stat->strongbranchtime, set); 10363 else 10364 SCIPclockStart(stat->divinglptime, set); 10365 10366 timedelta = 0.0; /* unused for diving or probing */ 10367 } 10368 else 10369 { 10370 SCIPclockStart(stat->primallptime, set); 10371 timedelta = -SCIPclockGetTime(stat->primallptime); 10372 } 10373 10374 /* if this is a call to resolve an instable LP, collect time */ 10375 if( instable ) 10376 { 10377 SCIPclockStart(stat->resolveinstablelptime, set); 10378 } 10379 10380 /* call primal simplex */ 10381 retcode = SCIPlpiSolvePrimal(lp->lpi); 10382 if( retcode == SCIP_LPERROR ) 10383 { 10384 *lperror = TRUE; 10385 SCIPsetDebugMsg(set, "(node %" SCIP_LONGINT_FORMAT ") primal simplex solving error in LP %" SCIP_LONGINT_FORMAT "\n", stat->nnodes, stat->nlps); 10386 } 10387 else 10388 { 10389 SCIP_CALL( retcode ); 10390 } 10391 lp->lastlpalgo = SCIP_LPALGO_PRIMALSIMPLEX; 10392 lp->solisbasic = TRUE; 10393 10394 /* stop timing */ 10395 if( lp->diving || lp->probing ) 10396 { 10397 if( lp->strongbranchprobing ) 10398 SCIPclockStop(stat->strongbranchtime, set); 10399 else 10400 SCIPclockStop(stat->divinglptime, set); 10401 } 10402 else 10403 { 10404 timedelta += SCIPclockGetTime(stat->primallptime); 10405 SCIPclockStop(stat->primallptime, set); 10406 } 10407 10408 if ( instable ) 10409 { 10410 SCIPclockStop(stat->resolveinstablelptime, set); 10411 } 10412 10413 /* count number of iterations */ 10414 SCIPstatIncrement(stat, set, lpcount); 10415 SCIP_CALL( SCIPlpGetIterations(lp, &iterations) ); 10416 if( iterations > 0 ) /* don't count the resolves after removing unused columns/rows */ 10417 { 10418 if( !lp->strongbranchprobing ) 10419 { 10420 SCIPstatIncrement(stat, set, nlps); 10421 SCIPstatAdd( stat, set, nlpiterations, iterations ); 10422 } 10423 if( resolve && !lp->lpifromscratch && stat->nlps > 1 ) 10424 { 10425 SCIPstatIncrement(stat, set, nprimalresolvelps ); 10426 SCIPstatAdd(stat, set, nprimalresolvelpiterations, iterations); 10427 } 10428 if ( instable ) 10429 { 10430 SCIPstatIncrement(stat, set, nresolveinstablelps); 10431 SCIPstatAdd(stat, set, nresolveinstablelpiters, iterations); 10432 } 10433 if( lp->diving || lp->probing ) 10434 { 10435 if( lp->strongbranchprobing ) 10436 { 10437 SCIPstatIncrement(stat, set, nsbdivinglps); 10438 SCIPstatAdd(stat, set, nsbdivinglpiterations, iterations); 10439 } 10440 else 10441 { 10442 SCIPstatUpdate(stat, set, lastdivenode, stat->nnodes); 10443 SCIPstatIncrement(stat, set, ndivinglps); 10444 SCIPstatAdd(stat, set, ndivinglpiterations, iterations); 10445 } 10446 } 10447 else 10448 { 10449 SCIPstatIncrement(stat, set, nprimallps); 10450 SCIPstatAdd(stat, set, nprimallpiterations, iterations); 10451 } 10452 } 10453 else 10454 { 10455 if ( ! lp->diving && ! lp->probing ) 10456 { 10457 SCIPstatIncrement(stat, set, nprimalzeroitlps); 10458 SCIPstatAdd(stat, set, primalzeroittime, timedelta); 10459 } 10460 10461 if ( keepsol && !(*lperror) ) 10462 { 10463 /* the solution didn't change: if the solution was valid before resolve, it is still valid */ 10464 if( lp->validsollp == stat->lpcount-1 ) 10465 lp->validsollp = stat->lpcount; 10466 if( lp->validfarkaslp == stat->lpcount-1 ) 10467 lp->validfarkaslp = stat->lpcount; 10468 } 10469 } 10470 10471 SCIPsetDebugMsg(set, "solved LP %" SCIP_LONGINT_FORMAT " with primal simplex (diving=%d, nprimallps=%" SCIP_LONGINT_FORMAT ", ndivinglps=%" SCIP_LONGINT_FORMAT ")\n", 10472 stat->lpcount, lp->diving || lp->probing, stat->nprimallps, stat->ndivinglps); 10473 10474 return SCIP_OKAY; 10475 } 10476 10477 /** calls LPI to perform dual simplex, measures time and counts iterations */ 10478 static 10479 SCIP_RETCODE lpDualSimplex( 10480 SCIP_LP* lp, /**< current LP data */ 10481 SCIP_SET* set, /**< global SCIP settings */ 10482 SCIP_STAT* stat, /**< problem statistics */ 10483 SCIP_Bool resolve, /**< is this a resolving call (starting with feasible basis)? */ 10484 SCIP_Bool keepsol, /**< should the old LP solution be kept if no iterations were performed? */ 10485 SCIP_Bool instable, /**< is this a resolving call to avoid instable LPs? */ 10486 SCIP_Bool* lperror /**< pointer to store whether an unresolved LP error occurred */ 10487 ) 10488 { 10489 SCIP_Real timedelta; 10490 SCIP_RETCODE retcode; 10491 int iterations; 10492 10493 assert(lp != NULL); 10494 assert(lp->flushed); 10495 assert(set != NULL); 10496 assert(stat != NULL); 10497 assert(lperror != NULL); 10498 10499 SCIPsetDebugMsg(set, "solving LP %" SCIP_LONGINT_FORMAT " (%d cols, %d rows) with dual simplex (diving=%d, nduallps=%" SCIP_LONGINT_FORMAT ", ndivinglps=%" SCIP_LONGINT_FORMAT ")\n", 10500 stat->lpcount+1, lp->ncols, lp->nrows, lp->diving || lp->probing, stat->nduallps, stat->ndivinglps); 10501 10502 *lperror = FALSE; 10503 10504 #ifdef SCIP_MORE_DEBUG /* for debugging: write all root node LP's */ 10505 if( stat->nnodes == 1 && !lp->diving && !lp->probing ) 10506 { 10507 char fname[SCIP_MAXSTRLEN]; 10508 (void) SCIPsnprintf(fname, SCIP_MAXSTRLEN, "lp%" SCIP_LONGINT_FORMAT "_%" SCIP_LONGINT_FORMAT ".lp", stat->nnodes, stat->lpcount); 10509 SCIP_CALL( SCIPlpWrite(lp, fname) ); 10510 SCIPsetDebugMsg(set, "wrote LP to file <%s> (dual simplex, objlim=%.15g, feastol=%.15g/%.15g, fromscratch=%d, fastmip=%d, scaling=%d, presolving=%d)\n", 10511 fname, lp->lpiobjlim, lp->lpifeastol, lp->lpidualfeastol, 10512 lp->lpifromscratch, lp->lpifastmip, lp->lpiscaling, lp->lpipresolving); 10513 } 10514 #endif 10515 10516 /* start timing */ 10517 if( lp->diving || lp->probing ) 10518 { 10519 if( lp->strongbranchprobing ) 10520 SCIPclockStart(stat->strongbranchtime, set); 10521 else 10522 SCIPclockStart(stat->divinglptime, set); 10523 10524 timedelta = 0.0; /* unused for diving or probing */ 10525 } 10526 else 10527 { 10528 SCIPclockStart(stat->duallptime, set); 10529 timedelta = -SCIPclockGetTime(stat->duallptime); 10530 } 10531 10532 /* if this is a call to resolve an instable LP, collect time */ 10533 if ( instable ) 10534 { 10535 SCIPclockStart(stat->resolveinstablelptime, set); 10536 } 10537 10538 /* call dual simplex */ 10539 retcode = SCIPlpiSolveDual(lp->lpi); 10540 if( retcode == SCIP_LPERROR ) 10541 { 10542 *lperror = TRUE; 10543 SCIPsetDebugMsg(set, "(node %" SCIP_LONGINT_FORMAT ") dual simplex solving error in LP %" SCIP_LONGINT_FORMAT "\n", stat->nnodes, stat->nlps); 10544 } 10545 else 10546 { 10547 SCIP_CALL( retcode ); 10548 } 10549 lp->lastlpalgo = SCIP_LPALGO_DUALSIMPLEX; 10550 lp->solisbasic = TRUE; 10551 10552 /* stop timing */ 10553 if( lp->diving || lp->probing ) 10554 { 10555 if( lp->strongbranchprobing ) 10556 SCIPclockStop(stat->strongbranchtime, set); 10557 else 10558 SCIPclockStop(stat->divinglptime, set); 10559 } 10560 else 10561 { 10562 timedelta += SCIPclockGetTime(stat->duallptime); 10563 SCIPclockStop(stat->duallptime, set); 10564 } 10565 10566 if ( instable ) 10567 { 10568 SCIPclockStop(stat->resolveinstablelptime, set); 10569 } 10570 10571 /* count number of iterations */ 10572 SCIPstatIncrement(stat, set, lpcount); 10573 SCIP_CALL( SCIPlpGetIterations(lp, &iterations) ); 10574 if( iterations > 0 ) /* don't count the resolves after removing unused columns/rows */ 10575 { 10576 if( !lp->strongbranchprobing ) 10577 { 10578 SCIPstatIncrement(stat, set, nlps); 10579 SCIPstatAdd(stat, set, nlpiterations, iterations); 10580 } 10581 if( resolve && !lp->lpifromscratch && stat->nlps > 1 ) 10582 { 10583 SCIPstatIncrement(stat, set, ndualresolvelps); 10584 SCIPstatAdd(stat, set, ndualresolvelpiterations, iterations); 10585 } 10586 if ( instable ) 10587 { 10588 SCIPstatIncrement(stat, set, nresolveinstablelps); 10589 SCIPstatAdd(stat, set, nresolveinstablelpiters, iterations); 10590 } 10591 if( lp->diving || lp->probing ) 10592 { 10593 if( lp->strongbranchprobing ) 10594 { 10595 SCIPstatIncrement(stat, set, nsbdivinglps); 10596 SCIPstatAdd(stat, set, nsbdivinglpiterations, iterations); 10597 } 10598 else 10599 { 10600 SCIPstatUpdate(stat, set, lastdivenode, stat->nnodes); 10601 SCIPstatIncrement(stat, set, ndivinglps); 10602 SCIPstatAdd(stat, set, ndivinglpiterations, iterations); 10603 } 10604 } 10605 else 10606 { 10607 SCIPstatIncrement(stat, set, nduallps); 10608 SCIPstatAdd(stat, set, nduallpiterations, iterations); 10609 } 10610 } 10611 else 10612 { 10613 if ( ! lp->diving && ! lp->probing ) 10614 { 10615 SCIPstatIncrement(stat, set, ndualzeroitlps); 10616 SCIPstatAdd(stat, set, dualzeroittime, timedelta); 10617 } 10618 10619 if( keepsol && !(*lperror) ) 10620 { 10621 /* the solution didn't change: if the solution was valid before resolve, it is still valid */ 10622 if( lp->validsollp == stat->lpcount-1 ) 10623 lp->validsollp = stat->lpcount; 10624 if( lp->validfarkaslp == stat->lpcount-1 ) 10625 lp->validfarkaslp = stat->lpcount; 10626 } 10627 } 10628 10629 SCIPsetDebugMsg(set, "solved LP %" SCIP_LONGINT_FORMAT " with dual simplex (diving=%d, nduallps=%" SCIP_LONGINT_FORMAT ", ndivinglps=%" SCIP_LONGINT_FORMAT ")\n", 10630 stat->lpcount, lp->diving || lp->probing, stat->nduallps, stat->ndivinglps); 10631 10632 return SCIP_OKAY; 10633 } 10634 10635 /** calls LPI to perform lexicographic dual simplex to find a lexicographically minimal optimal solution, measures time and counts iterations 10636 * 10637 * We follow the approach of the following paper to find a lexicographically minimal optimal 10638 * solution: 10639 * 10640 * Zanette, Fischetti, Balas@n 10641 * Can pure cutting plane algorithms work?@n 10642 * IPCO 2008, Bertinoro, Italy. 10643 * 10644 * We do, however, not aim for the exact lexicographically minimal optimal solutions, but perform a 10645 * heuristic, i.e., we limit the number of components which are minimized. 10646 * 10647 * More precisely, we first solve the problem with the dual simplex algorithm. Then we fix those 10648 * nonbasic variables to their current value (i.e., one of the bounds except maybe for free 10649 * variables) that have nonzero reduced cost. This fixes the objective function value, because only 10650 * pivots that will not change the objective are allowed afterwards. 10651 * 10652 * Then the not yet fixed variables are considered in turn. If they are at their lower bounds and 10653 * nonbasic, they are fixed to this bound, since their value cannot be decreased further. Once a 10654 * candidate is found, we set the objective to minimize this variable. We run the primal simplex 10655 * algorithm (since the objective is changed the solution is not dual feasible anymore; if 10656 * variables out of the basis have been fixed to their lower bound, the basis is also not primal 10657 * feasible anymore). After the optimization, we again fix nonbasic variables that have nonzero 10658 * reduced cost. We then choose the next variable and iterate. 10659 * 10660 * We stop the process once we do not find candidates or have performed a maximum number of 10661 * iterations. 10662 * 10663 * @todo Does this really produce a lexicographically minimal solution? 10664 * @todo Can we skip the consideration of basic variables that are at their lower bound? How can we 10665 * guarantee that these variables will not be changed in later stages? We can fix these variables 10666 * to their lower bound, but this destroys the basis. 10667 * @todo Should we use lexicographical minimization in diving/probing or not? 10668 */ 10669 static 10670 SCIP_RETCODE lpLexDualSimplex( 10671 SCIP_LP* lp, /**< current LP data */ 10672 SCIP_SET* set, /**< global SCIP settings */ 10673 SCIP_STAT* stat, /**< problem statistics */ 10674 SCIP_Bool resolve, /**< is this a resolving call (starting with feasible basis)? */ 10675 SCIP_Bool keepsol, /**< should the old LP solution be kept if no iterations were performed? */ 10676 SCIP_Bool* lperror /**< pointer to store whether an unresolved LP error occurred */ 10677 ) 10678 { 10679 SCIP_Real timedelta; 10680 SCIP_RETCODE retcode; 10681 int totalIterations; 10682 int lexIterations; 10683 int iterations; 10684 int rounds; 10685 10686 assert(lp != NULL); 10687 assert(lp->flushed); 10688 assert(set != NULL); 10689 assert(stat != NULL); 10690 assert(lperror != NULL); 10691 10692 SCIPsetDebugMsg(set, "solving LP %" SCIP_LONGINT_FORMAT " (%d cols, %d rows) with lex dual simplex (diving=%d, nduallps=%" SCIP_LONGINT_FORMAT ", ndivinglps=%" SCIP_LONGINT_FORMAT ")\n", 10693 stat->lpcount+1, lp->ncols, lp->nrows, lp->diving || lp->probing, stat->nduallps, stat->ndivinglps); 10694 10695 *lperror = FALSE; 10696 10697 /* start timing */ 10698 if( lp->diving || lp->probing ) 10699 { 10700 if( lp->strongbranchprobing ) 10701 SCIPclockStart(stat->strongbranchtime, set); 10702 else 10703 SCIPclockStart(stat->divinglptime, set); 10704 10705 timedelta = 0.0; /* unused for diving or probing */ 10706 } 10707 else 10708 { 10709 SCIPclockStart(stat->duallptime, set); 10710 timedelta = -SCIPclockGetTime(stat->duallptime); 10711 } 10712 10713 /* call dual simplex for first lp */ 10714 retcode = SCIPlpiSolveDual(lp->lpi); 10715 if( retcode == SCIP_LPERROR ) 10716 { 10717 *lperror = TRUE; 10718 SCIPsetDebugMsg(set, "(node %" SCIP_LONGINT_FORMAT ") dual simplex solving error in LP %" SCIP_LONGINT_FORMAT "\n", stat->nnodes, stat->nlps); 10719 } 10720 else 10721 { 10722 SCIP_CALL( retcode ); 10723 } 10724 SCIP_CALL( SCIPlpGetIterations(lp, &iterations) ); 10725 totalIterations = iterations; 10726 10727 /* stop timing */ 10728 if( lp->diving || lp->probing ) 10729 { 10730 if( lp->strongbranchprobing ) 10731 SCIPclockStop(stat->strongbranchtime, set); 10732 else 10733 SCIPclockStop(stat->divinglptime, set); 10734 } 10735 else 10736 { 10737 timedelta += SCIPclockGetTime(stat->duallptime); 10738 SCIPclockStop(stat->duallptime, set); 10739 } 10740 10741 /* count number of iterations */ 10742 SCIPstatIncrement(stat, set, lpcount); 10743 if( iterations > 0 ) /* don't count the resolves after removing unused columns/rows */ 10744 { 10745 if( lp->strongbranchprobing ) 10746 { 10747 SCIPstatAdd(stat, set, nlpiterations, iterations); 10748 } 10749 if( resolve && !lp->lpifromscratch && stat->nlps > 1 ) 10750 { 10751 SCIPstatIncrement(stat, set, ndualresolvelps); 10752 SCIPstatAdd(stat, set, ndualresolvelpiterations, iterations); 10753 } 10754 if( lp->diving || lp->probing ) 10755 { 10756 if( lp->strongbranchprobing ) 10757 { 10758 SCIPstatIncrement(stat, set, nsbdivinglps); 10759 SCIPstatAdd(stat, set, nsbdivinglpiterations, iterations); 10760 } 10761 else 10762 { 10763 SCIPstatUpdate(stat, set, lastdivenode, stat->nnodes); 10764 SCIPstatIncrement(stat, set, ndivinglps); 10765 SCIPstatAdd(stat, set, ndivinglpiterations, iterations); 10766 } 10767 } 10768 else 10769 { 10770 SCIPstatIncrement(stat, set, nduallps); 10771 SCIPstatAdd(stat, set, nduallpiterations, iterations); 10772 } 10773 } 10774 else 10775 { 10776 if ( ! lp->diving && ! lp->probing ) 10777 { 10778 SCIPstatIncrement(stat, set, ndualzeroitlps); 10779 SCIPstatAdd(stat, set, dualzeroittime, timedelta); 10780 } 10781 } 10782 lexIterations = 0; 10783 10784 /* search for lexicographically minimal optimal solution */ 10785 if( !lp->diving && !lp->probing && SCIPlpiIsOptimal(lp->lpi) ) 10786 { 10787 SCIP_Bool chooseBasic; 10788 SCIP_Real* primsol; 10789 SCIP_Real* dualsol; 10790 SCIP_Real* redcost; 10791 int* cstat; 10792 int* rstat; 10793 SCIP_Real* newobj; 10794 SCIP_Real* newlb; 10795 SCIP_Real* newub; 10796 SCIP_Real* newlhs; 10797 SCIP_Real* newrhs; 10798 SCIP_Real* oldlb; 10799 SCIP_Real* oldub; 10800 SCIP_Real* oldlhs; 10801 SCIP_Real* oldrhs; 10802 SCIP_Real* oldobj; 10803 SCIP_Bool* fixedc; 10804 SCIP_Bool* fixedr; 10805 int* indcol; 10806 int* indrow; 10807 int* indallcol; 10808 int* indallrow; 10809 int nDualDeg; 10810 int r, c; 10811 int cntcol; 10812 int cntrow; 10813 int nruns; 10814 int pos; 10815 10816 chooseBasic = set->lp_lexdualbasic; 10817 10818 /* start timing */ 10819 SCIPclockStart(stat->lexduallptime, set); 10820 10821 /* get all solution information */ 10822 SCIP_CALL( SCIPsetAllocBufferArray(set, &dualsol, lp->nlpirows) ); 10823 SCIP_CALL( SCIPsetAllocBufferArray(set, &redcost, lp->nlpicols) ); 10824 if( chooseBasic ) 10825 { 10826 SCIP_CALL( SCIPsetAllocBufferArray(set, &primsol, lp->nlpicols) ); 10827 } 10828 else 10829 primsol = NULL; 10830 10831 /* get basic and nonbasic information */ 10832 SCIP_CALL( SCIPsetAllocBufferArray(set, &cstat, lp->nlpicols) ); 10833 SCIP_CALL( SCIPsetAllocBufferArray(set, &rstat, lp->nlpirows) ); 10834 10835 /* save bounds, lhs/rhs, and objective */ 10836 SCIP_CALL( SCIPsetAllocBufferArray(set, &oldobj, lp->nlpicols) ); 10837 SCIP_CALL( SCIPsetAllocBufferArray(set, &oldlb, lp->nlpicols) ); 10838 SCIP_CALL( SCIPsetAllocBufferArray(set, &oldub, lp->nlpicols) ); 10839 SCIP_CALL( SCIPsetAllocBufferArray(set, &oldlhs, lp->nlpirows) ); 10840 SCIP_CALL( SCIPsetAllocBufferArray(set, &oldrhs, lp->nlpirows) ); 10841 SCIP_CALL( SCIPlpiGetBounds(lp->lpi, 0, lp->nlpicols-1, oldlb, oldub) ); 10842 SCIP_CALL( SCIPlpiGetSides(lp->lpi, 0, lp->nlpirows-1, oldlhs, oldrhs) ); 10843 SCIP_CALL( SCIPlpiGetObj(lp->lpi, 0, lp->nlpicols-1, oldobj) ); 10844 10845 /* get storage for several arrays */ 10846 SCIP_CALL( SCIPsetAllocBufferArray(set, &newlb, lp->nlpicols) ); 10847 SCIP_CALL( SCIPsetAllocBufferArray(set, &newub, lp->nlpicols) ); 10848 SCIP_CALL( SCIPsetAllocBufferArray(set, &indcol, lp->nlpicols) ); 10849 10850 SCIP_CALL( SCIPsetAllocBufferArray(set, &newlhs, lp->nlpirows) ); 10851 SCIP_CALL( SCIPsetAllocBufferArray(set, &newrhs, lp->nlpirows) ); 10852 SCIP_CALL( SCIPsetAllocBufferArray(set, &indrow, lp->nlpirows) ); 10853 10854 SCIP_CALL( SCIPsetAllocBufferArray(set, &indallcol, lp->nlpicols) ); 10855 SCIP_CALL( SCIPsetAllocBufferArray(set, &indallrow, lp->nlpirows) ); 10856 10857 SCIP_CALL( SCIPsetAllocBufferArray(set, &fixedc, lp->nlpicols) ); 10858 SCIP_CALL( SCIPsetAllocBufferArray(set, &fixedr, lp->nlpirows) ); 10859 10860 /* initialize: set objective to 0, get fixed variables */ 10861 SCIP_CALL( SCIPsetAllocBufferArray(set, &newobj, lp->nlpicols) ); 10862 for( c = 0; c < lp->nlpicols; ++c ) 10863 { 10864 newobj[c] = 0.0; 10865 indallcol[c] = c; 10866 if( SCIPsetIsFeasEQ(set, oldlb[c], oldub[c]) ) 10867 fixedc[c] = TRUE; 10868 else 10869 fixedc[c] = FALSE; 10870 } 10871 10872 /* initialize: get fixed slack variables */ 10873 for( r = 0; r < lp->nlpirows; ++r ) 10874 { 10875 indallrow[r] = r; 10876 if( SCIPsetIsFeasEQ(set, oldlhs[r], oldrhs[r]) ) 10877 fixedr[r] = TRUE; 10878 else 10879 fixedr[r] = FALSE; 10880 } 10881 10882 #ifdef DEBUG_LEXDUAL 10883 { 10884 int j; 10885 10886 if( !chooseBasic ) 10887 { 10888 assert(primsol == NULL); 10889 SCIP_CALL( SCIPsetAllocBufferArray(set, &primsol, lp->nlpicols) ); 10890 } 10891 assert(primsol != NULL); 10892 SCIP_CALL( SCIPlpiGetSol(lp->lpi, NULL, primsol, NULL, NULL, NULL) ); 10893 SCIP_CALL( SCIPlpiGetBase(lp->lpi, cstat, rstat) ); 10894 10895 for( j = 0; j < lp->nlpicols; ++j ) 10896 { 10897 if( fixedc[j] ) 10898 { 10899 SCIPsetDebugMsg(set, "%f (%d) [f] ", primsol[j], j); 10900 } 10901 else 10902 { 10903 char type; 10904 switch( (SCIP_BASESTAT) cstat[j] ) 10905 { 10906 case SCIP_BASESTAT_LOWER: 10907 type = 'l'; 10908 break; 10909 case SCIP_BASESTAT_UPPER: 10910 type = 'u'; 10911 break; 10912 case SCIP_BASESTAT_ZERO: 10913 type = 'z'; 10914 break; 10915 case SCIP_BASESTAT_BASIC: 10916 type = 'b'; 10917 break; 10918 default: 10919 type = '?'; 10920 SCIPerrorMessage("unknown base stat %d\n", cstat[j]); 10921 SCIPABORT(); 10922 } 10923 SCIPsetDebugMsg(set, "%f (%d) [%c] ", primsol[j], j, type); 10924 } 10925 } 10926 SCIPsetDebugMsg(set, "\n\n"); 10927 10928 if( !chooseBasic ) 10929 { 10930 SCIPsetFreeBufferArray(set, &primsol); 10931 assert(primsol == NULL); 10932 } 10933 } 10934 #endif 10935 10936 /* perform lexicographic rounds */ 10937 pos = -1; 10938 nruns = 0; 10939 rounds = 0; 10940 /* SCIP_CALL( lpSetLPInfo(lp, TRUE) ); */ 10941 do 10942 { 10943 int oldpos; 10944 10945 /* get current solution */ 10946 if( chooseBasic ) 10947 SCIP_CALL( SCIPlpiGetSol(lp->lpi, NULL, primsol, dualsol, NULL, redcost) ); 10948 else 10949 { 10950 SCIP_CALL( SCIPlpiGetSol(lp->lpi, NULL, NULL, dualsol, NULL, redcost) ); 10951 assert(primsol == NULL); 10952 } 10953 10954 /* get current basis */ 10955 SCIP_CALL( SCIPlpiGetBase(lp->lpi, cstat, rstat) ); 10956 10957 /* check columns: find first candidate (either basic or nonbasic and zero reduced cost) and fix variables */ 10958 nDualDeg = 0; 10959 cntcol = 0; 10960 oldpos = pos; 10961 pos = -1; 10962 for( c = 0; c < lp->nlpicols; ++c ) 10963 { 10964 if( !fixedc[c] ) 10965 { 10966 /* check whether variable is in basis */ 10967 if( (SCIP_BASESTAT) cstat[c] == SCIP_BASESTAT_BASIC ) 10968 { 10969 /* store first candidate */ 10970 if( pos == -1 && c > oldpos ) 10971 { 10972 if( !chooseBasic || !SCIPsetIsIntegral(set, primsol[c]) ) /*lint !e613*/ 10973 pos = c; 10974 } 10975 } 10976 else 10977 { 10978 /* reduced cost == 0 -> possible candidate */ 10979 if( SCIPsetIsDualfeasZero(set, redcost[c]) ) 10980 { 10981 ++nDualDeg; 10982 /* only if we have not yet found a candidate */ 10983 if( pos == -1 && c > oldpos ) 10984 { 10985 /* if the variable is at its lower bound - fix it, because its value cannot be reduced */ 10986 if( (SCIP_BASESTAT) cstat[c] == SCIP_BASESTAT_LOWER ) 10987 { 10988 newlb[cntcol] = oldlb[c]; 10989 newub[cntcol] = oldlb[c]; 10990 indcol[cntcol++] = c; 10991 fixedc[c] = TRUE; 10992 } 10993 else /* found a non-fixed candidate */ 10994 { 10995 if( !chooseBasic ) 10996 pos = c; 10997 } 10998 } 10999 } 11000 else 11001 { 11002 /* nonzero reduced cost -> variable can be fixed */ 11003 if( (SCIP_BASESTAT) cstat[c] == SCIP_BASESTAT_LOWER ) 11004 { 11005 newlb[cntcol] = oldlb[c]; 11006 newub[cntcol] = oldlb[c]; 11007 } 11008 else 11009 { 11010 if( (SCIP_BASESTAT) cstat[c] == SCIP_BASESTAT_UPPER ) 11011 { 11012 newlb[cntcol] = oldub[c]; 11013 newub[cntcol] = oldub[c]; 11014 } 11015 else 11016 { 11017 assert((SCIP_BASESTAT) cstat[c] == SCIP_BASESTAT_ZERO); 11018 newlb[cntcol] = 0.0; 11019 newub[cntcol] = 0.0; 11020 } 11021 } 11022 indcol[cntcol++] = c; 11023 fixedc[c] = TRUE; 11024 } 11025 } 11026 } 11027 } 11028 11029 /* check rows */ 11030 cntrow = 0; 11031 for( r = 0; r < lp->nlpirows; ++r ) 11032 { 11033 if( !fixedr[r] ) 11034 { 11035 /* consider only nonbasic rows */ 11036 if( (SCIP_BASESTAT) rstat[r] != SCIP_BASESTAT_BASIC ) 11037 { 11038 assert((SCIP_BASESTAT) rstat[r] != SCIP_BASESTAT_ZERO); 11039 if( SCIPsetIsFeasZero(set, dualsol[r]) ) 11040 ++nDualDeg; 11041 else 11042 { 11043 if( SCIPsetIsFeasPositive(set, dualsol[r]) ) 11044 { 11045 assert(!SCIPsetIsInfinity(set, -oldlhs[r])); 11046 newlhs[cntrow] = oldlhs[r]; 11047 newrhs[cntrow] = oldlhs[r]; 11048 } 11049 else 11050 { 11051 assert(!SCIPsetIsInfinity(set, oldrhs[r])); 11052 newlhs[cntrow] = oldrhs[r]; 11053 newrhs[cntrow] = oldrhs[r]; 11054 } 11055 indrow[cntrow++] = r; 11056 fixedr[r] = TRUE; 11057 } 11058 } 11059 } 11060 } 11061 11062 if( nDualDeg > 0 && pos >= 0 ) 11063 { 11064 assert(0 <= pos && pos < lp->nlpicols && pos > oldpos); 11065 11066 /* change objective */ 11067 if( nruns == 0 ) 11068 { 11069 /* set objective to appropriate unit vector for first run */ 11070 newobj[pos] = 1.0; 11071 SCIP_CALL( SCIPlpiChgObj(lp->lpi, lp->nlpicols, indallcol, newobj) ); 11072 } 11073 else 11074 { 11075 /* set obj. coef. to 1 for other runs (ones remain in previous positions) */ 11076 SCIP_Real obj = 1.0; 11077 SCIP_CALL( SCIPlpiChgObj(lp->lpi, 1, &pos, &obj) ); 11078 } 11079 11080 /* fix variables */ 11081 SCIP_CALL( SCIPlpiChgBounds(lp->lpi, cntcol, indcol, newlb, newub) ); 11082 SCIP_CALL( SCIPlpiChgSides(lp->lpi, cntrow, indrow, newlhs, newrhs) ); 11083 11084 /* solve with primal simplex, because we are primal feasible, but not necessarily dual feasible */ 11085 retcode = SCIPlpiSolvePrimal(lp->lpi); 11086 if( retcode == SCIP_LPERROR ) 11087 { 11088 *lperror = TRUE; 11089 SCIPsetDebugMsg(set, "(node %" SCIP_LONGINT_FORMAT ") in lex-dual: primal simplex solving error in LP %" SCIP_LONGINT_FORMAT "\n", stat->nnodes, stat->nlps); 11090 } 11091 else 11092 { 11093 SCIP_CALL( retcode ); 11094 } 11095 SCIP_CALL( SCIPlpGetIterations(lp, &iterations) ); 11096 lexIterations += iterations; 11097 11098 #ifdef DEBUG_LEXDUAL 11099 if( iterations > 0 ) 11100 { 11101 int j; 11102 11103 if( !chooseBasic ) 11104 { 11105 assert(primsol == NULL); 11106 SCIP_CALL( SCIPsetAllocBufferArray(set, &primsol, lp->nlpicols) ); 11107 } 11108 assert(primsol != NULL); 11109 SCIP_CALL( SCIPlpiGetSol(lp->lpi, NULL, primsol, NULL, NULL, NULL) ); 11110 11111 for( j = 0; j < lp->nlpicols; ++j ) 11112 { 11113 if( fixedc[j] ) 11114 { 11115 SCIPsetDebugMsg(set, "%f (%d) [f] ", primsol[j], j); 11116 } 11117 else 11118 { 11119 char cstart = '['; 11120 char cend = ']'; 11121 char type; 11122 11123 if(j == pos) 11124 { 11125 cstart = '*'; 11126 cend = '*'; 11127 } 11128 11129 switch( (SCIP_BASESTAT) cstat[j] ) 11130 { 11131 case SCIP_BASESTAT_LOWER: 11132 type = 'l'; 11133 break; 11134 case SCIP_BASESTAT_UPPER: 11135 type = 'u'; 11136 break; 11137 case SCIP_BASESTAT_ZERO: 11138 type = 'z'; 11139 break; 11140 case SCIP_BASESTAT_BASIC: 11141 type = 'b'; 11142 break; 11143 default: 11144 type = '?'; 11145 SCIPerrorMessage("unknown base state %d\n", cstat[j]); 11146 SCIPABORT(); 11147 } 11148 SCIPsetDebugMsg(set, "%f (%d) %c%c%c ", primsol[j], j, cstart, type, cend); 11149 } 11150 } 11151 SCIPsetDebugMsg(set, "\n\n"); 11152 11153 if( !chooseBasic ) 11154 { 11155 SCIPsetFreeBufferArray(set, &primsol); 11156 assert(primsol == NULL); 11157 } 11158 } 11159 #endif 11160 11161 /* count only as round if iterations have been performed */ 11162 if( iterations > 0 ) 11163 ++rounds; 11164 ++nruns; 11165 } 11166 } 11167 while( pos >= 0 && nDualDeg > 0 && (set->lp_lexdualmaxrounds == -1 || rounds < set->lp_lexdualmaxrounds) ); 11168 11169 /* reset bounds, lhs/rhs, and obj */ 11170 SCIP_CALL( SCIPlpiChgBounds(lp->lpi, lp->nlpicols, indallcol, oldlb, oldub) ); 11171 SCIP_CALL( SCIPlpiChgSides(lp->lpi, lp->nlpirows, indallrow, oldlhs, oldrhs) ); 11172 SCIP_CALL( SCIPlpiChgObj(lp->lpi, lp->nlpicols, indallcol, oldobj) ); 11173 11174 /* resolve to update solvers internal data structures - should only produce few pivots - is this needed? */ 11175 retcode = SCIPlpiSolveDual(lp->lpi); 11176 if( retcode == SCIP_LPERROR ) 11177 { 11178 *lperror = TRUE; 11179 SCIPsetDebugMsg(set, "(node %" SCIP_LONGINT_FORMAT ") dual simplex solving error in LP %" SCIP_LONGINT_FORMAT "\n", stat->nnodes, stat->nlps); 11180 } 11181 else 11182 { 11183 SCIP_CALL( retcode ); 11184 } 11185 assert(SCIPlpiIsOptimal(lp->lpi)); 11186 SCIP_CALL( SCIPlpGetIterations(lp, &iterations) ); 11187 lexIterations += iterations; 11188 11189 /* SCIP_CALL( lpSetLPInfo(lp, set->disp_lpinfo) ); */ 11190 11191 /* count number of iterations */ 11192 if( totalIterations == 0 && lexIterations > 0 && !lp->strongbranchprobing ) 11193 SCIPstatIncrement(stat, set, nlps); 11194 11195 if( lexIterations > 0 ) /* don't count the resolves after removing unused columns/rows */ 11196 { 11197 SCIPstatAdd(stat, set, nlpiterations, lexIterations); 11198 if( resolve && !lp->lpifromscratch && stat->nlps > 1 ) 11199 { 11200 SCIPstatIncrement(stat, set, nlexdualresolvelps); 11201 SCIPstatAdd(stat, set, nlexdualresolvelpiterations, lexIterations); 11202 } 11203 SCIPstatIncrement(stat, set, nlexduallps); 11204 SCIPstatAdd(stat, set, nlexduallpiterations, lexIterations); 11205 11206 totalIterations += lexIterations; 11207 } 11208 11209 /* free space */ 11210 SCIPsetFreeBufferArray(set, &newobj); 11211 11212 SCIPsetFreeBufferArray(set, &fixedr); 11213 SCIPsetFreeBufferArray(set, &fixedc); 11214 11215 SCIPsetFreeBufferArray(set, &indallrow); 11216 SCIPsetFreeBufferArray(set, &indallcol); 11217 11218 SCIPsetFreeBufferArray(set, &indrow); 11219 SCIPsetFreeBufferArray(set, &newrhs); 11220 SCIPsetFreeBufferArray(set, &newlhs); 11221 11222 SCIPsetFreeBufferArray(set, &indcol); 11223 SCIPsetFreeBufferArray(set, &newub); 11224 SCIPsetFreeBufferArray(set, &newlb); 11225 11226 SCIPsetFreeBufferArray(set, &oldobj); 11227 SCIPsetFreeBufferArray(set, &oldrhs); 11228 SCIPsetFreeBufferArray(set, &oldlhs); 11229 SCIPsetFreeBufferArray(set, &oldub); 11230 SCIPsetFreeBufferArray(set, &oldlb); 11231 11232 SCIPsetFreeBufferArray(set, &rstat); 11233 SCIPsetFreeBufferArray(set, &cstat); 11234 11235 SCIPsetFreeBufferArray(set, &redcost); 11236 SCIPsetFreeBufferArray(set, &dualsol); 11237 if( chooseBasic ) 11238 SCIPsetFreeBufferArray(set, &primsol); 11239 11240 /* stop timing */ 11241 SCIPclockStop(stat->lexduallptime, set); 11242 11243 SCIPsetDebugMsg(set, "solved LP %" SCIP_LONGINT_FORMAT " with lex dual simplex (diving=%d, nduallps=%" SCIP_LONGINT_FORMAT ", ndivinglps=%" SCIP_LONGINT_FORMAT ")\n", 11244 stat->lpcount, lp->diving || lp->probing, stat->nduallps, stat->ndivinglps); 11245 } 11246 lp->lastlpalgo = SCIP_LPALGO_DUALSIMPLEX; 11247 lp->solisbasic = TRUE; 11248 11249 if( totalIterations > 0 && !lp->strongbranchprobing ) 11250 SCIPstatIncrement(stat, set, nlps); 11251 else 11252 { 11253 if( keepsol && !(*lperror) ) 11254 { 11255 /* the solution didn't change: if the solution was valid before resolve, it is still valid */ 11256 if( lp->validsollp == stat->lpcount-1 ) 11257 lp->validsollp = stat->lpcount; 11258 if( lp->validfarkaslp == stat->lpcount-1 ) 11259 lp->validfarkaslp = stat->lpcount; 11260 } 11261 } 11262 11263 return SCIP_OKAY; 11264 } 11265 11266 /** calls LPI to perform barrier, measures time and counts iterations, gets basis feasibility status */ 11267 static 11268 SCIP_RETCODE lpBarrier( 11269 SCIP_LP* lp, /**< current LP data */ 11270 SCIP_SET* set, /**< global SCIP settings */ 11271 SCIP_STAT* stat, /**< problem statistics */ 11272 SCIP_Bool crossover, /**< should crossover be performed? */ 11273 SCIP_Bool keepsol, /**< should the old LP solution be kept if no iterations were performed? */ 11274 SCIP_Bool* lperror /**< pointer to store whether an unresolved LP error occurred */ 11275 ) 11276 { 11277 SCIP_Real timedelta; 11278 SCIP_RETCODE retcode; 11279 int iterations; 11280 11281 assert(lp != NULL); 11282 assert(lp->flushed); 11283 assert(set != NULL); 11284 assert(stat != NULL); 11285 assert(lperror != NULL); 11286 11287 SCIPsetDebugMsg(set, "solving LP %" SCIP_LONGINT_FORMAT " (%d cols, %d rows) with barrier%s (diving=%d, nbarrierlps=%" SCIP_LONGINT_FORMAT ", ndivinglps=%" SCIP_LONGINT_FORMAT ")\n", 11288 stat->lpcount+1, lp->ncols, lp->nrows, crossover ? "/crossover" : "", lp->diving || lp->probing, 11289 stat->nbarrierlps, stat->ndivinglps); 11290 11291 *lperror = FALSE; 11292 11293 #ifdef SCIP_MORE_DEBUG /* for debugging: write all root node LP's */ 11294 if( stat->nnodes == 1 && !lp->diving && !lp->probing ) 11295 { 11296 char fname[SCIP_MAXSTRLEN]; 11297 (void) SCIPsnprintf(fname, SCIP_MAXSTRLEN, "lp%" SCIP_LONGINT_FORMAT "_%" SCIP_LONGINT_FORMAT ".lp", stat->nnodes, stat->lpcount); 11298 SCIP_CALL( SCIPlpWrite(lp, fname) ); 11299 SCIPsetDebugMsg(set, "wrote LP to file <%s> (barrier, objlim=%.15g, feastol=%.15g/%.15g, convtol=%.15g, fromscratch=%d, fastmip=%d, scaling=%d, presolving=%d)\n", 11300 fname, lp->lpiobjlim, lp->lpifeastol, lp->lpidualfeastol, lp->lpibarrierconvtol, 11301 lp->lpifromscratch, lp->lpifastmip, lp->lpiscaling, lp->lpipresolving); 11302 } 11303 #endif 11304 11305 /* start timing */ 11306 if( lp->diving || lp->probing ) 11307 { 11308 if( lp->strongbranchprobing ) 11309 SCIPclockStart(stat->strongbranchtime, set); 11310 else 11311 SCIPclockStart(stat->divinglptime, set); 11312 11313 timedelta = 0.0; /* unused for diving or probing */ 11314 } 11315 else 11316 { 11317 SCIPclockStart(stat->barrierlptime, set); 11318 timedelta = -SCIPclockGetTime(stat->barrierlptime); 11319 } 11320 11321 /* call barrier algorithm */ 11322 retcode = SCIPlpiSolveBarrier(lp->lpi, crossover); 11323 if( retcode == SCIP_LPERROR ) 11324 { 11325 *lperror = TRUE; 11326 SCIPsetDebugMsg(set, "(node %" SCIP_LONGINT_FORMAT ") barrier solving error in LP %" SCIP_LONGINT_FORMAT "\n", stat->nnodes, stat->nlps); 11327 } 11328 else 11329 { 11330 SCIP_CALL( retcode ); 11331 } 11332 lp->lastlpalgo = (crossover ? SCIP_LPALGO_BARRIERCROSSOVER : SCIP_LPALGO_BARRIER); 11333 lp->solisbasic = crossover; 11334 11335 /* stop timing */ 11336 if( lp->diving || lp->probing ) 11337 { 11338 if( lp->strongbranchprobing ) 11339 SCIPclockStop(stat->strongbranchtime, set); 11340 else 11341 SCIPclockStop(stat->divinglptime, set); 11342 } 11343 else 11344 { 11345 SCIPclockStop(stat->barrierlptime, set); 11346 timedelta += SCIPclockGetTime(stat->barrierlptime); 11347 } 11348 11349 /* count number of iterations */ 11350 SCIPstatIncrement(stat, set, lpcount); 11351 SCIP_CALL( SCIPlpGetIterations(lp, &iterations) ); 11352 if( iterations > 0 ) /* don't count the resolves after removing unused columns/rows */ 11353 { 11354 if( !lp->strongbranchprobing ) 11355 { 11356 SCIPstatIncrement(stat, set, nlps); 11357 SCIPstatAdd(stat, set, nlpiterations, iterations); 11358 } 11359 if( lp->diving || lp->probing ) 11360 { 11361 if( lp->strongbranchprobing ) 11362 { 11363 SCIPstatIncrement(stat, set, nsbdivinglps); 11364 SCIPstatAdd(stat, set, nsbdivinglpiterations, iterations); 11365 } 11366 else 11367 { 11368 SCIPstatUpdate(stat, set, lastdivenode, stat->nnodes); 11369 SCIPstatIncrement(stat, set, ndivinglps); 11370 SCIPstatAdd(stat, set, ndivinglpiterations, iterations); 11371 } 11372 } 11373 else 11374 { 11375 SCIPstatIncrement(stat, set, nbarrierlps); 11376 SCIPstatAdd(stat, set, nbarrierlpiterations, iterations); 11377 } 11378 } 11379 else 11380 { 11381 if ( ! lp->diving && ! lp->probing ) 11382 { 11383 SCIPstatIncrement(stat, set, nbarrierzeroitlps); 11384 SCIPstatAdd(stat, set, barrierzeroittime, timedelta); 11385 } 11386 11387 if( keepsol && !(*lperror) ) 11388 { 11389 /* the solution didn't change: if the solution was valid before resolve, it is still valid */ 11390 if( lp->validsollp == stat->lpcount-1 ) 11391 lp->validsollp = stat->lpcount; 11392 if( lp->validfarkaslp == stat->lpcount-1 ) 11393 lp->validfarkaslp = stat->lpcount; 11394 } 11395 } 11396 11397 SCIPsetDebugMsg(set, "solved LP %" SCIP_LONGINT_FORMAT " with barrier%s (diving=%d, nduallps=%" SCIP_LONGINT_FORMAT ", nbarrierlps=%" SCIP_LONGINT_FORMAT ")\n", 11398 stat->lpcount, crossover ? "/crossover" : "", lp->diving || lp->probing, stat->nbarrierlps, stat->ndivinglps); 11399 11400 return SCIP_OKAY; 11401 } 11402 11403 /** solves the LP with the given algorithm */ 11404 static 11405 SCIP_RETCODE lpAlgorithm( 11406 SCIP_LP* lp, /**< current LP data */ 11407 SCIP_SET* set, /**< global SCIP settings */ 11408 SCIP_STAT* stat, /**< problem statistics */ 11409 SCIP_LPALGO lpalgo, /**< LP algorithm that should be applied */ 11410 SCIP_Bool resolve, /**< is this a resolving call (starting with feasible basis)? */ 11411 SCIP_Bool keepsol, /**< should the old LP solution be kept if no iterations were performed? */ 11412 SCIP_Bool instable, /**< is this a resolving call to avoid instable LPs? */ 11413 SCIP_Bool* timelimit, /**< pointer to store whether the time limit was hit */ 11414 SCIP_Bool* lperror /**< pointer to store whether an unresolved LP error occurred */ 11415 ) 11416 { 11417 SCIP_Real lptimelimit; 11418 SCIP_Bool success; 11419 11420 assert(lp != NULL); 11421 assert(lp->flushed); 11422 assert(lperror != NULL); 11423 11424 /* check if a time limit is set, and set time limit for LP solver accordingly */ 11425 lptimelimit = SCIPlpiInfinity(lp->lpi); 11426 if( set->istimelimitfinite ) 11427 lptimelimit = set->limit_time - SCIPclockGetTime(stat->solvingtime); 11428 11429 success = FALSE; 11430 if( lptimelimit > 0.0 ) 11431 SCIP_CALL( lpSetRealpar(lp, SCIP_LPPAR_LPTILIM, lptimelimit, &success) ); 11432 11433 if( lptimelimit <= 0.0 || !success ) 11434 { 11435 SCIPsetDebugMsg(set, "time limit of %f seconds could not be set\n", lptimelimit); 11436 *lperror = ((lptimelimit > 0.0) ? TRUE : FALSE); 11437 *timelimit = TRUE; 11438 return SCIP_OKAY; 11439 } 11440 SCIPsetDebugMsg(set, "calling LP algorithm <%s> with a time limit of %g seconds\n", lpalgoName(lpalgo), lptimelimit); 11441 11442 /* call appropriate LP algorithm */ 11443 switch( lpalgo ) 11444 { 11445 case SCIP_LPALGO_PRIMALSIMPLEX: 11446 SCIP_CALL( lpPrimalSimplex(lp, set, stat, resolve, keepsol, instable, lperror) ); 11447 break; 11448 11449 case SCIP_LPALGO_DUALSIMPLEX: 11450 /* run dual lexicographic simplex if required */ 11451 if( set->lp_lexdualalgo && (!set->lp_lexdualrootonly || stat->maxdepth == 0) && (!set->lp_lexdualstalling || lp->installing) ) 11452 { 11453 SCIP_CALL( lpLexDualSimplex(lp, set, stat, resolve, keepsol, lperror) ); 11454 } 11455 else 11456 { 11457 SCIP_CALL( lpDualSimplex(lp, set, stat, resolve, keepsol, instable, lperror) ); 11458 } 11459 break; 11460 11461 case SCIP_LPALGO_BARRIER: 11462 SCIP_CALL( lpBarrier(lp, set, stat, FALSE, keepsol, lperror) ); 11463 break; 11464 11465 case SCIP_LPALGO_BARRIERCROSSOVER: 11466 SCIP_CALL( lpBarrier(lp, set, stat, TRUE, keepsol, lperror) ); 11467 break; 11468 11469 default: 11470 SCIPerrorMessage("invalid LP algorithm\n"); 11471 return SCIP_INVALIDDATA; 11472 } 11473 11474 if( !(*lperror) ) 11475 { 11476 /* check for primal and dual feasibility */ 11477 SCIP_CALL( SCIPlpiGetSolFeasibility(lp->lpi, &lp->primalfeasible, &lp->dualfeasible) ); 11478 11479 SCIPsetDebugMsg(set, "LP feasibility: primalfeasible=%u, dualfeasible=%u\n", lp->primalfeasible, lp->dualfeasible); 11480 } 11481 11482 return SCIP_OKAY; 11483 } 11484 11485 /** maximal number of verblevel-high messages about numerical trouble in LP that will be printed 11486 * when this number is reached and display/verblevel is not full, then further messages are suppressed in this run 11487 */ 11488 #define MAXNUMTROUBLELPMSGS 10 11489 11490 /** prints message about numerical trouble 11491 * 11492 * If message has verblevel at most high and display/verblevel is not full, 11493 * then the message is not printed if already MAXNUMTROUBLELPMSGS messages 11494 * were printed before in the current run. 11495 */ 11496 static 11497 void lpNumericalTroubleMessage( 11498 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */ 11499 SCIP_SET* set, /**< global SCIP settings */ 11500 SCIP_STAT* stat, /**< problem statistics */ 11501 SCIP_VERBLEVEL verblevel, /**< verbosity level of message */ 11502 const char* formatstr, /**< message format string */ 11503 ... /**< arguments to format string */ 11504 ) 11505 { 11506 va_list ap; 11507 11508 assert(verblevel > SCIP_VERBLEVEL_NONE); 11509 assert(verblevel <= SCIP_VERBLEVEL_FULL); 11510 assert(set->disp_verblevel <= SCIP_VERBLEVEL_FULL); 11511 11512 if( set->disp_verblevel < SCIP_VERBLEVEL_FULL ) 11513 { 11514 if( verblevel <= SCIP_VERBLEVEL_HIGH ) 11515 { 11516 /* if already max number of messages about numerical trouble in LP on verblevel at most high, then skip message */ 11517 if( stat->nnumtroublelpmsgs > MAXNUMTROUBLELPMSGS ) 11518 return; 11519 11520 /* increase count on messages with verblevel high */ 11521 ++stat->nnumtroublelpmsgs ; 11522 } 11523 11524 /* if messages wouldn't be printed, then return already */ 11525 if( verblevel > set->disp_verblevel ) 11526 return; 11527 } 11528 11529 /* print common begin of message */ 11530 SCIPmessagePrintInfo(messagehdlr, 11531 "(node %" SCIP_LONGINT_FORMAT ") numerical troubles in LP %" SCIP_LONGINT_FORMAT " -- ", 11532 stat->nnodes, stat->nlps); 11533 11534 /* print individual part of message */ 11535 va_start(ap, formatstr); /*lint !e838*/ 11536 SCIPmessageVFPrintInfo(messagehdlr, NULL, formatstr, ap); 11537 va_end(ap); 11538 11539 /* warn that further messages will be suppressed */ 11540 if( set->disp_verblevel < SCIP_VERBLEVEL_FULL && verblevel <= SCIP_VERBLEVEL_HIGH && stat->nnumtroublelpmsgs > MAXNUMTROUBLELPMSGS ) 11541 { 11542 SCIPmessagePrintInfo(messagehdlr, " -- further messages will be suppressed (use display/verblevel=5 to see all)"); 11543 } 11544 11545 /* print closing new-line */ 11546 SCIPmessagePrintInfo(messagehdlr, "\n"); 11547 } 11548 11549 static 11550 SCIP_RETCODE ignoreInstability( 11551 SCIP_LP* lp, /**< current LP data */ 11552 SCIP_SET* set, /**< global SCIP settings */ 11553 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */ 11554 SCIP_STAT* stat, /**< problem statistics */ 11555 SCIP_LPALGO lpalgo, /**< LP algorithm that should be applied */ 11556 SCIP_Bool* success /**< was instability successfully ignored */ 11557 ) 11558 { 11559 assert(lp != NULL); 11560 assert(set != NULL); 11561 11562 SCIP_CALL( SCIPlpiIgnoreInstability(lp->lpi, success) ); 11563 11564 if( *success ) 11565 { 11566 lpNumericalTroubleMessage(messagehdlr, set, stat, SCIP_VERBLEVEL_FULL, "ignoring instability of %s", lpalgoName(lpalgo)); 11567 if( !set->lp_checkdualfeas ) 11568 lp->dualfeasible = TRUE; 11569 if( !set->lp_checkprimfeas ) 11570 lp->primalchecked = TRUE; 11571 } 11572 11573 return SCIP_OKAY; 11574 } 11575 11576 #define FEASTOLTIGHTFAC 0.001 11577 /** solves the LP with the given LP algorithm, and tries to resolve numerical problems */ 11578 static 11579 SCIP_RETCODE lpSolveStable( 11580 SCIP_LP* lp, /**< current LP data */ 11581 SCIP_SET* set, /**< global SCIP settings */ 11582 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */ 11583 SCIP_STAT* stat, /**< problem statistics */ 11584 SCIP_PROB* prob, /**< problem data */ 11585 SCIP_LPALGO lpalgo, /**< LP algorithm that should be applied */ 11586 int itlim, /**< maximal number of LP iterations to perform in first LP calls (before solving from scratch), or -1 for no limit */ 11587 int harditlim, /**< maximal number of LP iterations to perform (hard limit for all LP calls), or -1 for no limit */ 11588 SCIP_Bool resolve, /**< is this a resolving call (starting with feasible basis)? */ 11589 int fastmip, /**< which FASTMIP setting of LP solver should be used? */ 11590 SCIP_Bool tightprimfeastol, /**< should a tighter primal feasibility tolerance be used? */ 11591 SCIP_Bool tightdualfeastol, /**< should a tighter dual feasibility tolerance be used? */ 11592 SCIP_Bool fromscratch, /**< should the LP be solved from scratch without using current basis? */ 11593 int scaling, /**< LP scaling (0: none, 1: normal, 2: aggressive) */ 11594 SCIP_Bool keepsol, /**< should the old LP solution be kept if no iterations were performed? */ 11595 SCIP_Bool* timelimit, /**< pointer to store whether the time limit was hit */ 11596 SCIP_Bool* lperror /**< pointer to store whether an unresolved LP error occurred */ 11597 ) 11598 { 11599 SCIP_Bool success; 11600 SCIP_Bool success2; 11601 SCIP_Bool success3; 11602 SCIP_Bool simplex; 11603 SCIP_Bool itlimishard; 11604 SCIP_Bool usepolishing; 11605 11606 assert(lp != NULL); 11607 assert(lp->flushed); 11608 assert(set != NULL); 11609 assert(stat != NULL); 11610 assert(lperror != NULL); 11611 assert(timelimit != NULL); 11612 11613 *lperror = FALSE; 11614 11615 /**@todo implement solving the LP when loose variables with infinite best bound are present; for this, we need to 11616 * solve with deactivated objective limit in order to determine whether we are (a) infeasible or (b) feasible 11617 * and hence unbounded; to handle case (b) we need to store an array of loose variables with best bound in 11618 * SCIP_LP such that we can return a primal ray 11619 */ 11620 if( lp->looseobjvalinf > 0 ) 11621 { 11622 SCIPerrorMessage("cannot solve LP when loose variable with infinite best bound is present\n"); 11623 return SCIP_ERROR; 11624 } 11625 11626 /* check, whether we solve with a simplex algorithm */ 11627 simplex = (lpalgo == SCIP_LPALGO_PRIMALSIMPLEX || lpalgo == SCIP_LPALGO_DUALSIMPLEX); 11628 11629 /* check whether the iteration limit is a hard one */ 11630 itlimishard = (itlim == harditlim); 11631 11632 /* check whether solution polishing should be used */ 11633 if( lp->lpihaspolishing && (set->lp_solutionpolishing == 2 || (set->lp_solutionpolishing == 1 && stat->nnodes == 1 && !lp->probing) 11634 || (set->lp_solutionpolishing == 3 && ((lp->probing && !lp->strongbranchprobing) || lp->diving))) ) 11635 { 11636 usepolishing = TRUE; 11637 if( lp->updateintegrality ) 11638 { 11639 SCIP_CALL( lpCopyIntegrality(lp, set) ); 11640 } 11641 } 11642 else 11643 usepolishing = FALSE; 11644 11645 /* solve with given settings (usually fast but imprecise) */ 11646 if( SCIPsetIsInfinity(set, lp->cutoffbound) ) 11647 { 11648 SCIP_CALL( lpSetObjlim(lp, set, prob, lp->cutoffbound, &success) ); 11649 } 11650 else 11651 { 11652 SCIP_CALL( lpSetObjlim(lp, set, prob, lp->cutoffbound - getFiniteLooseObjval(lp, set, prob), &success) ); 11653 } 11654 SCIP_CALL( lpSetIterationLimit(lp, itlim) ); 11655 SCIP_CALL( lpSetFeastol(lp, tightprimfeastol ? FEASTOLTIGHTFAC * lp->feastol : lp->feastol, &success) ); 11656 SCIP_CALL( lpSetDualfeastol(lp, tightdualfeastol ? FEASTOLTIGHTFAC * SCIPsetDualfeastol(set) : SCIPsetDualfeastol(set), 11657 &success) ); 11658 SCIP_CALL( lpSetBarrierconvtol(lp, (tightprimfeastol || tightdualfeastol) ? FEASTOLTIGHTFAC * SCIPsetBarrierconvtol(set) 11659 : SCIPsetBarrierconvtol(set), &success) ); 11660 SCIP_CALL( lpSetFromscratch(lp, fromscratch, &success) ); 11661 SCIP_CALL( lpSetFastmip(lp, fastmip, &success) ); 11662 SCIP_CALL( lpSetScaling(lp, scaling, &success) ); 11663 SCIP_CALL( lpSetPresolving(lp, set->lp_presolving, &success) ); 11664 SCIP_CALL( lpSetRowrepswitch(lp, set->lp_rowrepswitch, &success) ); 11665 SCIP_CALL( lpSetPricingChar(lp, set->lp_pricing) ); 11666 SCIP_CALL( lpSetThreads(lp, set->lp_threads, &success) ); 11667 SCIP_CALL( lpSetLPInfo(lp, set->disp_lpinfo) ); 11668 SCIP_CALL( lpSetConditionLimit(lp, set->lp_conditionlimit, &success) ); 11669 SCIP_CALL( lpSetMarkowitz(lp, set->lp_markowitz, &success) ); 11670 SCIP_CALL( lpSetTiming(lp, set->time_clocktype, set->time_enabled, &success) ); 11671 SCIP_CALL( lpSetRandomseed(lp, (int) SCIPsetInitializeRandomSeed(set, (unsigned) set->random_randomseed), &success) ); 11672 SCIP_CALL( lpSetSolutionPolishing(lp, usepolishing, &success) ); 11673 SCIP_CALL( lpSetRefactorInterval(lp, set->lp_refactorinterval, &success) ); 11674 11675 SCIP_CALL( lpAlgorithm(lp, set, stat, lpalgo, resolve, keepsol, FALSE, timelimit, lperror) ); 11676 11677 /* after the first solve, do not use starting basis, since otherwise the solver will probably think the basis is 11678 * optimal without preforming scaling/change tolerances/presolving */ 11679 resolve = FALSE; 11680 11681 /* check for stability; iteration limit exceeded is also treated like instability if the iteration limit is soft */ 11682 if( *timelimit || (!(*lperror) && SCIPlpiIsStable(lp->lpi) && (itlimishard || !SCIPlpiIsIterlimExc(lp->lpi))) ) 11683 return SCIP_OKAY; 11684 11685 if( !set->lp_checkstability ) 11686 { 11687 SCIP_CALL( ignoreInstability(lp, set, messagehdlr, stat, lpalgo, &success) ); 11688 11689 if( success ) 11690 return SCIP_OKAY; 11691 } 11692 11693 /* In the following, whenever the LP iteration limit is exceeded in an LP solving call, we leave out the 11694 * remaining resolving calls with changed settings and go directly to solving the LP from scratch. 11695 */ 11696 11697 /* if FASTMIP is turned on, solve again without FASTMIP (starts from the solution of the last LP solving call); 11698 * do this only if the iteration limit was not exceeded in the last LP solving call 11699 */ 11700 if( fastmip > 0 && simplex && ((*lperror) || !SCIPlpiIsIterlimExc(lp->lpi)) ) 11701 { 11702 SCIP_CALL( lpSetFastmip(lp, 0, &success) ); 11703 if( success ) 11704 { 11705 lpNumericalTroubleMessage(messagehdlr, set, stat, SCIP_VERBLEVEL_FULL, "solve again with %s without FASTMIP", lpalgoName(lpalgo)); 11706 SCIP_CALL( lpAlgorithm(lp, set, stat, lpalgo, resolve, keepsol, TRUE, timelimit, lperror) ); 11707 11708 /* check for stability */ 11709 if( *timelimit || (!(*lperror) && SCIPlpiIsStable(lp->lpi) && (itlimishard || !SCIPlpiIsIterlimExc(lp->lpi))) ) 11710 return SCIP_OKAY; 11711 11712 if( !set->lp_checkstability ) 11713 { 11714 SCIP_CALL( ignoreInstability(lp, set, messagehdlr, stat, lpalgo, &success) ); 11715 11716 if( success ) 11717 return SCIP_OKAY; 11718 } 11719 } 11720 } 11721 11722 /* if the iteration limit was exceeded in the last LP solving call, we leave out the remaining resolving calls with changed settings 11723 * and go directly to solving the LP from scratch 11724 */ 11725 if( (*lperror) || !SCIPlpiIsIterlimExc(lp->lpi) ) 11726 { 11727 /* solve again with opposite scaling setting (starts from the solution of the last LP solving call) */ 11728 SCIP_CALL( lpSetScaling(lp, (scaling > 0) ? 0 : 1, &success) ); 11729 if( success ) 11730 { 11731 lpNumericalTroubleMessage(messagehdlr, set, stat, SCIP_VERBLEVEL_FULL, "solve again with %s %s scaling", 11732 lpalgoName(lpalgo), (scaling == 0) ? "with" : "without"); 11733 SCIP_CALL( lpAlgorithm(lp, set, stat, lpalgo, resolve, keepsol, TRUE, timelimit, lperror) ); 11734 11735 /* check for stability */ 11736 if( *timelimit || (!(*lperror) && SCIPlpiIsStable(lp->lpi) && (itlimishard || !SCIPlpiIsIterlimExc(lp->lpi))) ) 11737 return SCIP_OKAY; 11738 11739 if( !set->lp_checkstability ) 11740 { 11741 SCIP_CALL( ignoreInstability(lp, set, messagehdlr, stat, lpalgo, &success) ); 11742 11743 if( success ) 11744 return SCIP_OKAY; 11745 } 11746 11747 /* reset scaling */ 11748 SCIP_CALL( lpSetScaling(lp, scaling, &success) ); 11749 assert(success); 11750 } 11751 } 11752 11753 /* if the iteration limit was exceeded in the last LP solving call, we leave out the remaining resolving calls with changed settings 11754 * and go directly to solving the LP from scratch */ 11755 if( (*lperror) || !SCIPlpiIsIterlimExc(lp->lpi) ) 11756 { 11757 /* solve again with opposite presolving setting (starts from the solution of the last LP solving call) */ 11758 SCIP_CALL( lpSetPresolving(lp, !set->lp_presolving, &success) ); 11759 if( success ) 11760 { 11761 lpNumericalTroubleMessage(messagehdlr, set, stat, SCIP_VERBLEVEL_FULL, "solve again with %s %s presolving", 11762 lpalgoName(lpalgo), !set->lp_presolving ? "with" : "without"); 11763 SCIP_CALL( lpAlgorithm(lp, set, stat, lpalgo, resolve, keepsol, TRUE, timelimit, lperror) ); 11764 11765 /* check for stability */ 11766 if( *timelimit || (!(*lperror) && SCIPlpiIsStable(lp->lpi) && (itlimishard || !SCIPlpiIsIterlimExc(lp->lpi))) ) 11767 return SCIP_OKAY; 11768 11769 if( !set->lp_checkstability ) 11770 { 11771 SCIP_CALL( ignoreInstability(lp, set, messagehdlr, stat, lpalgo, &success) ); 11772 11773 if( success ) 11774 return SCIP_OKAY; 11775 } 11776 11777 /* reset presolving */ 11778 SCIP_CALL( lpSetPresolving(lp, set->lp_presolving, &success) ); 11779 assert(success); 11780 } 11781 } 11782 11783 /* solve again with a tighter feasibility tolerance (starts from the solution of the last LP solving call); 11784 * do this only if the iteration limit was not exceeded in the last LP solving call 11785 */ 11786 if( ((simplex && (!tightprimfeastol || !tightdualfeastol)) || (!tightprimfeastol && !tightdualfeastol)) && 11787 ((*lperror) || !SCIPlpiIsIterlimExc(lp->lpi)) ) 11788 { 11789 success = FALSE; 11790 if( !tightprimfeastol ) 11791 { 11792 SCIP_CALL( lpSetFeastol(lp, FEASTOLTIGHTFAC * lp->feastol, &success) ); 11793 } 11794 11795 success2 = FALSE; 11796 if( !tightdualfeastol ) 11797 { 11798 SCIP_CALL( lpSetDualfeastol(lp, FEASTOLTIGHTFAC * SCIPsetDualfeastol(set), &success2) ); 11799 } 11800 11801 success3 = FALSE; 11802 if( !simplex && !tightprimfeastol && !tightdualfeastol ) 11803 { 11804 SCIP_CALL( lpSetBarrierconvtol(lp, FEASTOLTIGHTFAC * SCIPsetBarrierconvtol(set), &success3) ); 11805 } 11806 11807 /* only resolve if at least one of the parameters was actually changed in the LP solver */ 11808 if( success || success2 || success3 ) 11809 { 11810 lpNumericalTroubleMessage(messagehdlr, set, stat, SCIP_VERBLEVEL_FULL, "solve again with %s with tighter primal and dual feasibility tolerance", 11811 lpalgoName(lpalgo)); 11812 SCIP_CALL( lpAlgorithm(lp, set, stat, lpalgo, resolve, keepsol, TRUE, timelimit, lperror) ); 11813 11814 /* check for stability */ 11815 if( *timelimit || (!(*lperror) && SCIPlpiIsStable(lp->lpi) && (itlimishard || !SCIPlpiIsIterlimExc(lp->lpi))) ) 11816 return SCIP_OKAY; 11817 11818 if( !set->lp_checkstability ) 11819 { 11820 SCIP_CALL( ignoreInstability(lp, set, messagehdlr, stat, lpalgo, &success) ); 11821 11822 if( success ) 11823 return SCIP_OKAY; 11824 } 11825 11826 /* reset feasibility tolerance */ 11827 if( !tightprimfeastol ) 11828 { 11829 SCIP_CALL( lpSetFeastol(lp, lp->feastol, &success) ); 11830 } 11831 if( !tightdualfeastol ) 11832 { 11833 SCIP_CALL( lpSetDualfeastol(lp, SCIPsetDualfeastol(set), &success) ); 11834 } 11835 if( !simplex && !tightprimfeastol && !tightdualfeastol ) 11836 { 11837 SCIP_CALL( lpSetBarrierconvtol(lp, SCIPsetBarrierconvtol(set), &success) ); 11838 } 11839 } 11840 } 11841 11842 /* all LPs solved after this point are solved from scratch, so set the LP iteration limit to the hard limit; 11843 * the given iteration limit might be a soft one to restrict resolving calls only */ 11844 SCIP_CALL( lpSetIterationLimit(lp, harditlim) ); 11845 11846 /* if not already done, solve again from scratch */ 11847 if( !fromscratch && simplex ) 11848 { 11849 SCIP_CALL( lpSetFromscratch(lp, TRUE, &success) ); 11850 if( success ) 11851 { 11852 lpNumericalTroubleMessage(messagehdlr, set, stat, SCIP_VERBLEVEL_FULL, "solve again from scratch with %s", lpalgoName(lpalgo)); 11853 SCIP_CALL( lpAlgorithm(lp, set, stat, lpalgo, resolve, keepsol, TRUE, timelimit, lperror) ); 11854 11855 /* check for stability */ 11856 if( *timelimit || (!(*lperror) && SCIPlpiIsStable(lp->lpi)) ) 11857 return SCIP_OKAY; 11858 11859 if( !set->lp_checkstability ) 11860 { 11861 SCIP_CALL( ignoreInstability(lp, set, messagehdlr, stat, lpalgo, &success) ); 11862 11863 if( success ) 11864 return SCIP_OKAY; 11865 } 11866 } 11867 } 11868 11869 /* solve again, use other simplex this time */ 11870 if( simplex ) 11871 { 11872 lpalgo = (lpalgo == SCIP_LPALGO_PRIMALSIMPLEX ? SCIP_LPALGO_DUALSIMPLEX : SCIP_LPALGO_PRIMALSIMPLEX); 11873 lpNumericalTroubleMessage(messagehdlr, set, stat, SCIP_VERBLEVEL_FULL, "solve again from scratch with %s", lpalgoName(lpalgo)); 11874 SCIP_CALL( lpAlgorithm(lp, set, stat, lpalgo, resolve, keepsol, TRUE, timelimit, lperror) ); 11875 11876 /* check for stability */ 11877 if( *timelimit || (!(*lperror) && SCIPlpiIsStable(lp->lpi)) ) 11878 return SCIP_OKAY; 11879 11880 if( !set->lp_checkstability ) 11881 { 11882 SCIP_CALL( ignoreInstability(lp, set, messagehdlr, stat, lpalgo, &success) ); 11883 11884 if( success ) 11885 return SCIP_OKAY; 11886 } 11887 11888 /* solve again with opposite scaling and other simplex */ 11889 SCIP_CALL( lpSetScaling(lp, (scaling > 0) ? 0 : 1, &success) ); 11890 if( success ) 11891 { 11892 lpNumericalTroubleMessage(messagehdlr, set, stat, SCIP_VERBLEVEL_FULL, "solve again from scratch with %s %s scaling", 11893 lpalgoName(lpalgo), (scaling == 0) ? "with" : "without"); 11894 SCIP_CALL( lpAlgorithm(lp, set, stat, lpalgo, resolve, keepsol, TRUE, timelimit, lperror) ); 11895 11896 /* check for stability */ 11897 if( *timelimit || (!(*lperror) && SCIPlpiIsStable(lp->lpi)) ) 11898 return SCIP_OKAY; 11899 11900 if( !set->lp_checkstability ) 11901 { 11902 SCIP_CALL( ignoreInstability(lp, set, messagehdlr, stat, lpalgo, &success) ); 11903 11904 if( success ) 11905 return SCIP_OKAY; 11906 } 11907 11908 /* reset scaling */ 11909 SCIP_CALL( lpSetScaling(lp, scaling, &success) ); 11910 assert(success); 11911 } 11912 11913 /* solve again with opposite presolving and other simplex */ 11914 SCIP_CALL( lpSetPresolving(lp, !set->lp_presolving, &success) ); 11915 if( success ) 11916 { 11917 lpNumericalTroubleMessage(messagehdlr, set, stat, SCIP_VERBLEVEL_FULL, "solve again from scratch with %s %s presolving", 11918 lpalgoName(lpalgo), !set->lp_presolving ? "with" : "without"); 11919 SCIP_CALL( lpAlgorithm(lp, set, stat, lpalgo, resolve, keepsol, TRUE, timelimit, lperror) ); 11920 11921 /* check for stability */ 11922 if( *timelimit || (!(*lperror) && SCIPlpiIsStable(lp->lpi)) ) 11923 return SCIP_OKAY; 11924 11925 if( !set->lp_checkstability ) 11926 { 11927 SCIP_CALL( ignoreInstability(lp, set, messagehdlr, stat, lpalgo, &success) ); 11928 11929 if( success ) 11930 return SCIP_OKAY; 11931 } 11932 11933 /* reset presolving */ 11934 SCIP_CALL( lpSetPresolving(lp, set->lp_presolving, &success) ); 11935 assert(success); 11936 } 11937 11938 /* solve again with tighter feasibility tolerance, use other simplex this time */ 11939 if( !tightprimfeastol || !tightdualfeastol ) 11940 { 11941 success = FALSE; 11942 if( !tightprimfeastol ) 11943 { 11944 SCIP_CALL( lpSetFeastol(lp, FEASTOLTIGHTFAC * lp->feastol, &success) ); 11945 } 11946 11947 success2 = FALSE; 11948 if( !tightdualfeastol ) 11949 { 11950 SCIP_CALL( lpSetDualfeastol(lp, FEASTOLTIGHTFAC * SCIPsetDualfeastol(set), &success2) ); 11951 } 11952 11953 /* only resolve if at least one of the parameters was actually changed in the LP solver */ 11954 if( success || success2 ) 11955 { 11956 lpNumericalTroubleMessage(messagehdlr, set, stat, SCIP_VERBLEVEL_FULL, "solve again from scratch with %s with tighter feasibility tolerance", 11957 lpalgoName(lpalgo)); 11958 SCIP_CALL( lpAlgorithm(lp, set, stat, lpalgo, resolve, keepsol, TRUE, timelimit, lperror) ); 11959 11960 /* check for stability */ 11961 if( *timelimit || (!(*lperror) && SCIPlpiIsStable(lp->lpi)) ) 11962 return SCIP_OKAY; 11963 11964 if( !set->lp_checkstability ) 11965 { 11966 SCIP_CALL( ignoreInstability(lp, set, messagehdlr, stat, lpalgo, &success) ); 11967 11968 if( success ) 11969 return SCIP_OKAY; 11970 } 11971 11972 /* reset feasibility tolerance */ 11973 if( !tightprimfeastol ) 11974 { 11975 SCIP_CALL( lpSetFeastol(lp, lp->feastol, &success) ); 11976 } 11977 if( !tightdualfeastol ) 11978 { 11979 SCIP_CALL( lpSetDualfeastol(lp, SCIPsetDualfeastol(set), &success) ); 11980 } 11981 SCIP_UNUSED(success); 11982 } 11983 } 11984 } 11985 11986 /* nothing worked -- exit with an LPERROR */ 11987 lpNumericalTroubleMessage(messagehdlr, set, stat, SCIP_VERBLEVEL_HIGH, "unresolved"); 11988 *lperror = TRUE; 11989 11990 return SCIP_OKAY; 11991 } 11992 11993 /** adjust the LP objective value if it is greater/less than +/- SCIPsetInfinity() */ 11994 static 11995 void adjustLPobjval( 11996 SCIP_LP* lp, /**< current LP data */ 11997 SCIP_SET* set, /**< global SCIP settings */ 11998 SCIP_MESSAGEHDLR* messagehdlr /**< message handler */ 11999 ) 12000 { 12001 assert(lp != NULL); 12002 assert(set != NULL); 12003 12004 if( SCIPsetIsInfinity(set, lp->lpobjval) && lp->lpobjval != SCIPsetInfinity(set) ) /*lint !e777*/ 12005 { 12006 if( !lp->adjustlpval && messagehdlr != NULL ) 12007 { 12008 SCIPmessagePrintWarning(messagehdlr, "LP solution value is above SCIP's infinity value\n"); 12009 lp->adjustlpval = TRUE; 12010 } 12011 lp->lpobjval = SCIPsetInfinity(set); 12012 } 12013 else if( SCIPsetIsInfinity(set, -lp->lpobjval) && lp->lpobjval != -SCIPsetInfinity(set) ) /*lint !e777*/ 12014 { 12015 if( !lp->adjustlpval && messagehdlr != NULL ) 12016 { 12017 SCIPmessagePrintWarning(messagehdlr, "LP solution value is below SCIP's -infinity value\n"); 12018 lp->adjustlpval = TRUE; 12019 } 12020 lp->lpobjval = -SCIPsetInfinity(set); 12021 } 12022 } 12023 12024 /** solves the LP with the given algorithm and evaluates return status */ 12025 static 12026 SCIP_RETCODE lpSolve( 12027 SCIP_LP* lp, /**< current LP data */ 12028 SCIP_SET* set, /**< global SCIP settings */ 12029 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */ 12030 SCIP_STAT* stat, /**< problem statistics */ 12031 SCIP_PROB* prob, /**< problem data */ 12032 SCIP_LPALGO lpalgo, /**< LP algorithm that should be applied */ 12033 int resolveitlim, /**< maximal number of LP iterations to perform in resolving calls, or -1 for no limit */ 12034 int harditlim, /**< maximal number of LP iterations to perform (hard limit for all LP calls), or -1 for no limit */ 12035 SCIP_Bool needprimalray, /**< if the LP is unbounded, do we need a primal ray? */ 12036 SCIP_Bool needdualray, /**< if the LP is infeasible, do we need a dual ray? */ 12037 SCIP_Bool resolve, /**< is this a resolving call (starting with feasible basis)? */ 12038 int fastmip, /**< which FASTMIP setting of LP solver should be used? */ 12039 SCIP_Bool tightprimfeastol, /**< should a tighter primal feasibility tolerance be used? */ 12040 SCIP_Bool tightdualfeastol, /**< should a tighter dual feasibility tolerance be used? */ 12041 SCIP_Bool fromscratch, /**< should the LP be solved from scratch without using current basis? */ 12042 int scaling, /**< LP scaling (0: none, 1: normal, 2: aggressive) */ 12043 SCIP_Bool keepsol, /**< should the old LP solution be kept if no iterations were performed? */ 12044 SCIP_Bool* lperror /**< pointer to store whether an unresolved LP error occurred */ 12045 ) 12046 { 12047 SCIP_Bool solvedprimal; 12048 SCIP_Bool solveddual; 12049 SCIP_Bool timelimit; 12050 int itlim; 12051 12052 assert(lp != NULL); 12053 assert(lp->flushed); 12054 assert(set != NULL); 12055 assert(stat != NULL); 12056 assert(lperror != NULL); 12057 12058 checkLinks(lp); 12059 12060 solvedprimal = FALSE; 12061 solveddual = FALSE; 12062 timelimit = FALSE; 12063 12064 /* select the basic iteration limit depending on whether this is a resolving call or not */ 12065 itlim = ( resolve ? resolveitlim : harditlim ); 12066 12067 SOLVEAGAIN: 12068 /* call simplex */ 12069 SCIP_CALL( lpSolveStable(lp, set, messagehdlr, stat, prob, lpalgo, itlim, harditlim, resolve, fastmip, tightprimfeastol, tightdualfeastol, fromscratch, 12070 scaling, keepsol, &timelimit, lperror) ); 12071 resolve = FALSE; /* only the first solve should be counted as resolving call */ 12072 solvedprimal = solvedprimal || (lp->lastlpalgo == SCIP_LPALGO_PRIMALSIMPLEX); 12073 solveddual = solveddual || (lp->lastlpalgo == SCIP_LPALGO_DUALSIMPLEX); 12074 12075 /* check, if an error occurred */ 12076 if( *lperror ) 12077 { 12078 SCIPsetDebugMsg(set, "unresolved error while solving LP with %s\n", lpalgoName(lp->lastlpalgo)); 12079 lp->solved = FALSE; 12080 lp->lpsolstat = SCIP_LPSOLSTAT_NOTSOLVED; 12081 return SCIP_OKAY; 12082 } 12083 12084 /* check, if a time limit was exceeded */ 12085 if( timelimit ) 12086 { 12087 SCIPsetDebugMsg(set, "time limit exceeded before solving LP\n"); 12088 lp->solved = TRUE; 12089 lp->lpsolstat = SCIP_LPSOLSTAT_TIMELIMIT; 12090 lp->lpobjval = -SCIPsetInfinity(set); 12091 return SCIP_OKAY; 12092 } 12093 12094 /* only one should return true */ 12095 assert(!(SCIPlpiIsOptimal(lp->lpi) && SCIPlpiIsObjlimExc(lp->lpi) && SCIPlpiIsPrimalInfeasible(lp->lpi) && 12096 SCIPlpiExistsPrimalRay(lp->lpi) && SCIPlpiIsIterlimExc(lp->lpi) && SCIPlpiIsTimelimExc(lp->lpi))); 12097 12098 /* evaluate solution status */ 12099 if( SCIPlpiIsOptimal(lp->lpi) ) 12100 { 12101 assert(lp->primalfeasible); 12102 assert(lp->dualfeasible); 12103 lp->lpsolstat = SCIP_LPSOLSTAT_OPTIMAL; 12104 SCIP_CALL( SCIPlpiGetObjval(lp->lpi, &lp->lpobjval) ); 12105 adjustLPobjval(lp, set, messagehdlr); 12106 12107 if( !SCIPsetIsInfinity(set, lp->lpiobjlim) && SCIPsetIsGE(set, lp->lpobjval, lp->lpiobjlim) ) 12108 { 12109 /* the solver may return the optimal value, even if this is greater or equal than the upper bound */ 12110 SCIPsetDebugMsg(set, "optimal solution %.15g exceeds objective limit %.15g\n", lp->lpobjval, lp->lpiobjlim); 12111 lp->lpsolstat = SCIP_LPSOLSTAT_OBJLIMIT; 12112 lp->lpobjval = SCIPsetInfinity(set); 12113 } 12114 /* if we did not disable the cutoff bound in the LP solver, the LP solution status should be objective limit 12115 * reached if the LP objective value is greater than the cutoff bound 12116 */ 12117 assert(lpCutoffDisabled(set, prob) || lp->lpsolstat == SCIP_LPSOLSTAT_OBJLIMIT || SCIPsetIsInfinity(set, lp->cutoffbound) 12118 || SCIPsetIsLE(set, lp->lpobjval + getFiniteLooseObjval(lp, set, prob), lp->cutoffbound)); 12119 } 12120 else if( SCIPlpiIsObjlimExc(lp->lpi) ) 12121 { 12122 assert(!lpCutoffDisabled(set, prob)); 12123 12124 #ifndef NDEBUG 12125 /* the LP solution objective should exceed the limit in this case; if this assert is triggered, it typically means 12126 * that the LP interface method SCIPlpiIsStable() lacks a check for this event and incorrectly returned TRUE */ 12127 SCIP_CALL( SCIPlpiGetObjval(lp->lpi, &lp->lpobjval) ); 12128 assert(!set->lp_checkstability || SCIPsetIsRelGE(set, lp->lpobjval, lp->lpiobjlim)); 12129 #endif 12130 12131 lp->lpsolstat = SCIP_LPSOLSTAT_OBJLIMIT; 12132 lp->lpobjval = SCIPsetInfinity(set); 12133 } 12134 else if( SCIPlpiIsPrimalInfeasible(lp->lpi) ) 12135 { 12136 /* because of numerical instability lpalgo != lp->lastlpalgo might happen - hence, we have to check both */ 12137 if( needdualray && !SCIPlpiHasDualRay(lp->lpi) && !solveddual && lpalgo != SCIP_LPALGO_DUALSIMPLEX ) 12138 { 12139 assert(lp->lastlpalgo != SCIP_LPALGO_DUALSIMPLEX); 12140 lpalgo = SCIP_LPALGO_DUALSIMPLEX; 12141 goto SOLVEAGAIN; 12142 } 12143 lp->lpsolstat = SCIP_LPSOLSTAT_INFEASIBLE; 12144 lp->lpobjval = SCIPsetInfinity(set); 12145 } 12146 else if( SCIPlpiExistsPrimalRay(lp->lpi) ) 12147 { 12148 /* because of numerical instability lpalgo != lp->lastlpalgo might happen - hence, we have to check both */ 12149 if( needprimalray && !SCIPlpiIsPrimalUnbounded(lp->lpi) && !solvedprimal && lpalgo != SCIP_LPALGO_PRIMALSIMPLEX ) 12150 { 12151 /* unboundedness includes that the primal is feasible: ensure a primal solution here */ 12152 assert(lp->lastlpalgo != SCIP_LPALGO_PRIMALSIMPLEX); 12153 lpalgo = SCIP_LPALGO_PRIMALSIMPLEX; 12154 goto SOLVEAGAIN; 12155 } 12156 lp->lpsolstat = SCIP_LPSOLSTAT_UNBOUNDEDRAY; 12157 lp->lpobjval = -SCIPsetInfinity(set); 12158 } 12159 else if( SCIPlpiIsIterlimExc(lp->lpi) ) 12160 { 12161 SCIP_CALL( SCIPlpiGetObjval(lp->lpi, &lp->lpobjval) ); 12162 12163 /* The lpobjval might be infinite, e.g. if the LP solver was not able to produce a valid bound while reaching the 12164 iteration limit. In this case, we avoid the warning in adjustLPobjval() by setting the messagehdlr to NULL. */ 12165 if ( REALABS(lp->lpobjval) == SCIPlpiInfinity(lp->lpi) ) /*lint !e777*/ 12166 adjustLPobjval(lp, set, NULL); 12167 else 12168 adjustLPobjval(lp, set, messagehdlr); 12169 12170 lp->lpsolstat = SCIP_LPSOLSTAT_ITERLIMIT; 12171 } 12172 else if( SCIPlpiIsTimelimExc(lp->lpi) ) 12173 { 12174 lp->lpobjval = -SCIPsetInfinity(set); 12175 lp->lpsolstat = SCIP_LPSOLSTAT_TIMELIMIT; 12176 } 12177 else if( !solveddual && lpalgo != SCIP_LPALGO_DUALSIMPLEX) 12178 { 12179 assert(lp->lastlpalgo != SCIP_LPALGO_DUALSIMPLEX); 12180 lpalgo = SCIP_LPALGO_DUALSIMPLEX; 12181 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL, 12182 "(node %" SCIP_LONGINT_FORMAT ") solution status of LP %" SCIP_LONGINT_FORMAT " could not be proven (internal status:%d) -- solve again with %s\n", 12183 stat->nnodes, stat->nlps, SCIPlpiGetInternalStatus(lp->lpi), lpalgoName(lpalgo)); 12184 goto SOLVEAGAIN; 12185 } 12186 else if( !solvedprimal && lpalgo != SCIP_LPALGO_PRIMALSIMPLEX) 12187 { 12188 assert(lp->lastlpalgo != SCIP_LPALGO_PRIMALSIMPLEX); 12189 lpalgo = SCIP_LPALGO_PRIMALSIMPLEX; 12190 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL, 12191 "(node %" SCIP_LONGINT_FORMAT ") solution status of LP %" SCIP_LONGINT_FORMAT " could not be proven (internal status:%d) -- solve again with %s\n", 12192 stat->nnodes, stat->nlps, SCIPlpiGetInternalStatus(lp->lpi), lpalgoName(lpalgo)); 12193 goto SOLVEAGAIN; 12194 } 12195 else 12196 { 12197 SCIPerrorMessage("(node %" SCIP_LONGINT_FORMAT ") error or unknown return status of %s in LP %" SCIP_LONGINT_FORMAT " (internal status: %d)\n", 12198 stat->nnodes, lpalgoName(lp->lastlpalgo), stat->nlps, SCIPlpiGetInternalStatus(lp->lpi)); 12199 lp->lpsolstat = SCIP_LPSOLSTAT_ERROR; 12200 return SCIP_LPERROR; 12201 } 12202 12203 lp->solved = TRUE; 12204 12205 SCIPsetDebugMsg(set, "solving LP with %s returned solstat=%d (internal status: %d, primalfeasible=%u, dualfeasible=%u)\n", 12206 lpalgoName(lp->lastlpalgo), lp->lpsolstat, SCIPlpiGetInternalStatus(lp->lpi), 12207 SCIPlpiIsPrimalFeasible(lp->lpi), SCIPlpiIsDualFeasible(lp->lpi)); 12208 12209 return SCIP_OKAY; 12210 } 12211 12212 /** flushes the LP and solves it with the primal or dual simplex algorithm, depending on the current basis feasibility */ 12213 static 12214 SCIP_RETCODE lpFlushAndSolve( 12215 SCIP_LP* lp, /**< current LP data */ 12216 BMS_BLKMEM* blkmem, /**< block memory */ 12217 SCIP_SET* set, /**< global SCIP settings */ 12218 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */ 12219 SCIP_STAT* stat, /**< problem statistics */ 12220 SCIP_PROB* prob, /**< problem data */ 12221 SCIP_EVENTQUEUE* eventqueue, /**< event queue */ 12222 int resolveitlim, /**< maximal number of LP iterations to perform in resolving calls, or -1 for no limit */ 12223 int harditlim, /**< maximal number of LP iterations to perform (hard limit for all LP calls), or -1 for no limit */ 12224 SCIP_Bool needprimalray, /**< if the LP is unbounded, do we need a primal ray? */ 12225 SCIP_Bool needdualray, /**< if the LP is infeasible, do we need a dual ray? */ 12226 int fastmip, /**< which FASTMIP setting of LP solver should be used? */ 12227 SCIP_Bool tightprimfeastol, /**< should a tighter primal feasibility tolerance be used? */ 12228 SCIP_Bool tightdualfeastol, /**< should a tighter dual feasibility tolerance be used? */ 12229 SCIP_Bool fromscratch, /**< should the LP be solved from scratch without using current basis? */ 12230 int scaling, /**< LP scaling (0: none, 1: normal, 2: aggressive) */ 12231 SCIP_Bool keepsol, /**< should the old LP solution be kept if no iterations were performed? */ 12232 SCIP_Bool* lperror /**< pointer to store whether an unresolved LP error occurred */ 12233 ) 12234 { 12235 SCIP_Bool resolve; 12236 char algo; 12237 12238 assert(lp != NULL); 12239 assert(set != NULL); 12240 assert(lperror != NULL); 12241 12242 /* flush changes to the LP solver */ 12243 SCIP_CALL( SCIPlpFlush(lp, blkmem, set, prob, eventqueue) ); 12244 fastmip = ((!lp->flushaddedcols && !lp->flushdeletedcols) ? fastmip : 0); /* turn off FASTMIP if columns were changed */ 12245 12246 /* select LP algorithm to apply */ 12247 resolve = lp->solisbasic && (lp->dualfeasible || lp->primalfeasible) && !fromscratch; 12248 algo = resolve ? set->lp_resolvealgorithm : set->lp_initalgorithm; 12249 12250 switch( algo ) 12251 { 12252 case 's': 12253 /* select simplex method */ 12254 if( lp->dualfeasible || !lp->primalfeasible ) 12255 { 12256 SCIPsetDebugMsg(set, "solving dual LP\n"); 12257 SCIP_CALL( lpSolve(lp, set, messagehdlr, stat, prob, SCIP_LPALGO_DUALSIMPLEX, resolveitlim, harditlim, needprimalray, 12258 needdualray, resolve, fastmip, tightprimfeastol, tightdualfeastol, fromscratch, scaling, keepsol, lperror) ); 12259 } 12260 else 12261 { 12262 SCIPsetDebugMsg(set, "solving primal LP\n"); 12263 SCIP_CALL( lpSolve(lp, set, messagehdlr, stat, prob, SCIP_LPALGO_PRIMALSIMPLEX, resolveitlim, harditlim, needprimalray, 12264 needdualray, resolve, fastmip, tightprimfeastol, tightdualfeastol, fromscratch, scaling, keepsol, lperror) ); 12265 } 12266 break; 12267 12268 case 'p': 12269 SCIPsetDebugMsg(set, "solving primal LP\n"); 12270 SCIP_CALL( lpSolve(lp, set, messagehdlr, stat, prob, SCIP_LPALGO_PRIMALSIMPLEX, resolveitlim, harditlim, needprimalray, 12271 needdualray, resolve, fastmip, tightprimfeastol, tightdualfeastol, fromscratch, scaling, keepsol, lperror) ); 12272 break; 12273 12274 case 'd': 12275 SCIPsetDebugMsg(set, "solving dual LP\n"); 12276 SCIP_CALL( lpSolve(lp, set, messagehdlr, stat, prob, SCIP_LPALGO_DUALSIMPLEX, resolveitlim, harditlim, needprimalray, 12277 needdualray, resolve, fastmip, tightprimfeastol, tightdualfeastol, fromscratch, scaling, keepsol, lperror) ); 12278 break; 12279 12280 case 'b': 12281 SCIPsetDebugMsg(set, "solving barrier LP\n"); 12282 SCIP_CALL( lpSolve(lp, set, messagehdlr, stat, prob, SCIP_LPALGO_BARRIER, resolveitlim, harditlim, needprimalray, 12283 needdualray, resolve, fastmip, tightprimfeastol, tightdualfeastol, fromscratch, scaling, keepsol, lperror) ); 12284 break; 12285 12286 case 'c': 12287 SCIPsetDebugMsg(set, "solving barrier LP with crossover\n"); 12288 SCIP_CALL( lpSolve(lp, set, messagehdlr, stat, prob, SCIP_LPALGO_BARRIERCROSSOVER, resolveitlim, harditlim, needprimalray, 12289 needdualray, resolve, fastmip, tightprimfeastol, tightdualfeastol, fromscratch, scaling, keepsol, lperror) ); 12290 break; 12291 12292 default: 12293 SCIPerrorMessage("invalid parameter setting <%c> for LP algorithm\n", algo); 12294 return SCIP_PARAMETERWRONGVAL; 12295 } 12296 assert(!(*lperror) || !lp->solved); 12297 12298 return SCIP_OKAY; 12299 } 12300 12301 #ifndef NDEBUG 12302 /** checks if the lazy bounds are valid */ 12303 static 12304 void checkLazyBounds( 12305 SCIP_LP* lp, /**< LP data */ 12306 SCIP_SET* set /**< global SCIP settings */ 12307 ) 12308 { 12309 SCIP_COL* col; 12310 int c; 12311 12312 assert(lp->flushed); 12313 12314 for( c = 0; c < lp->nlazycols; ++c ) 12315 { 12316 col = lp->lazycols[c]; 12317 12318 /* in case lazy bounds are given, check that the primal solution satisfies them */ 12319 assert(SCIPsetIsInfinity(set, -col->lazylb) || SCIPsetIsFeasGE(set, col->primsol, col->lazylb)); 12320 assert(SCIPsetIsInfinity(set, col->lazyub) || SCIPsetIsFeasLE(set, col->primsol, col->lazyub)); 12321 } 12322 } 12323 #else 12324 #define checkLazyBounds(lp, set) /**/ 12325 #endif 12326 12327 /** marks all lazy columns to be changed; this is needed for reloading/removing bounds of these columns before and after 12328 * diving 12329 */ 12330 static 12331 SCIP_RETCODE updateLazyBounds( 12332 SCIP_LP* lp, /**< LP data */ 12333 SCIP_SET* set /**< global SCIP settings */ 12334 ) 12335 { 12336 SCIP_COL* col; 12337 int c; 12338 12339 assert(lp->nlazycols > 0); 12340 12341 /* return, if we are in diving, and bounds were already applied 12342 * or if we are not in diving and bounds were not applied 12343 */ 12344 if( lp->diving == lp->divinglazyapplied ) 12345 return SCIP_OKAY; 12346 12347 SCIPsetDebugMsg(set, "mark all lazy columns as changed in order to reload bounds (diving=%u, applied=%u)\n", 12348 lp->diving, lp->divinglazyapplied); 12349 12350 for( c = 0; c < lp->nlazycols; ++c ) 12351 { 12352 col = lp->lazycols[c]; 12353 12354 /* if the column has a lazy lower bound, mark its lower bounds as changed */ 12355 if( !SCIPsetIsInfinity(set, -col->lazylb) ) 12356 { 12357 assert((!(lp->divinglazyapplied)) || (col->flushedlb == col->lb) || col->lbchanged); /*lint !e777*/ 12358 assert(lp->divinglazyapplied || SCIPsetIsGT(set, col->lb, col->lazylb) 12359 || (col->flushedlb == -SCIPlpiInfinity(lp->lpi)) || col->lbchanged); /*lint !e777*/ 12360 12361 /* insert column in the chgcols list (if not already there) */ 12362 SCIP_CALL( insertColChgcols(col, set, lp) ); 12363 12364 /* mark bound change in the column */ 12365 col->lbchanged = TRUE; 12366 } 12367 12368 /* if the column has a lazy upper bound, mark its upper bounds as changed */ 12369 if( !SCIPsetIsInfinity(set, col->lazyub) ) 12370 { 12371 assert((!(lp->divinglazyapplied)) || (col->flushedub == col->ub) || col->ubchanged); /*lint !e777*/ 12372 assert(lp->divinglazyapplied || SCIPsetIsLT(set, col->ub, col->lazyub) 12373 || (col->flushedub == SCIPlpiInfinity(lp->lpi)) || col->ubchanged); /*lint !e777*/ 12374 12375 /* insert column in the chgcols list (if not already there) */ 12376 SCIP_CALL( insertColChgcols(col, set, lp) ); 12377 12378 /* mark bound change in the column */ 12379 col->ubchanged = TRUE; 12380 } 12381 } 12382 12383 /* update lp->divinglazyapplied flag: if we are in diving mode, we just applied the lazy bounds, 12384 * if not, we just removed them 12385 */ 12386 lp->divinglazyapplied = lp->diving; 12387 12388 return SCIP_OKAY; 12389 } 12390 12391 /** returns the iteration limit for an LP resolving call */ 12392 static 12393 int lpGetResolveItlim( 12394 SCIP_SET* set, /**< global SCIP settings */ 12395 SCIP_STAT* stat, /**< dynamic problem statistics */ 12396 int itlim /**< hard iteration limit */ 12397 ) 12398 { 12399 /* no limit set or average not yet reliable */ 12400 if( (set->lp_resolveiterfac == -1) || stat->nlps - stat->nrootlps < 5 ) 12401 return itlim; 12402 /* set itlim to INT_MAX if it is -1 to reduce the number of cases to be regarded in the following */ 12403 if( itlim == -1 ) 12404 itlim = INT_MAX; 12405 /* return resolveiterfac * average iteration number per call after root, but at least resolveitermin and at most the hard iteration limit */ 12406 return (int) MIN(itlim, MAX(set->lp_resolveitermin, \ 12407 (set->lp_resolveiterfac * (stat->nlpiterations - stat->nrootlpiterations) / (SCIP_Real)(stat->nlps - stat->nrootlps)))); 12408 } 12409 12410 12411 12412 /** solves the LP with simplex algorithm, and copy the solution into the column's data */ 12413 SCIP_RETCODE SCIPlpSolveAndEval( 12414 SCIP_LP* lp, /**< LP data */ 12415 SCIP_SET* set, /**< global SCIP settings */ 12416 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */ 12417 BMS_BLKMEM* blkmem, /**< block memory buffers */ 12418 SCIP_STAT* stat, /**< problem statistics */ 12419 SCIP_EVENTQUEUE* eventqueue, /**< event queue */ 12420 SCIP_EVENTFILTER* eventfilter, /**< global event filter */ 12421 SCIP_PROB* prob, /**< problem data */ 12422 SCIP_Longint itlim, /**< maximal number of LP iterations to perform, or -1 for no limit */ 12423 SCIP_Bool limitresolveiters, /**< should LP iterations for resolving calls be limited? 12424 * (limit is computed within the method w.r.t. the average LP iterations) */ 12425 SCIP_Bool aging, /**< should aging and removal of obsolete cols/rows be applied? */ 12426 SCIP_Bool keepsol, /**< should the old LP solution be kept if no iterations were performed? */ 12427 SCIP_Bool* lperror /**< pointer to store whether an unresolved LP error occurred */ 12428 ) 12429 { 12430 SCIP_RETCODE retcode; 12431 SCIP_Bool needprimalray; 12432 SCIP_Bool needdualray; 12433 int harditlim; 12434 int resolveitlim; 12435 12436 assert(lp != NULL); 12437 assert(prob != NULL); 12438 assert(prob->nvars >= lp->ncols); 12439 assert(lperror != NULL); 12440 12441 retcode = SCIP_OKAY; 12442 *lperror = FALSE; 12443 12444 if( lp->flushed && lp->solved ) 12445 { 12446 SCIPsetDebugMsg(set, "skipping LP solve: already flushed and solved)\n"); 12447 return SCIP_OKAY; 12448 } 12449 12450 SCIPsetDebugMsg(set, "solving LP: %d rows, %d cols, primalfeasible=%u, dualfeasible=%u, solved=%u, diving=%u, probing=%u, cutoffbnd=%g\n", 12451 lp->nrows, lp->ncols, lp->primalfeasible, lp->dualfeasible, lp->solved, lp->diving, lp->probing, lp->cutoffbound); 12452 12453 /* check whether we need a proof of unboundedness or infeasibility by a primal or dual ray */ 12454 needprimalray = TRUE; 12455 needdualray = (!SCIPprobAllColsInLP(prob, set, lp) || set->misc_exactsolve 12456 || (set->conf_enable && set->conf_useinflp != 'o')); 12457 12458 /* compute the limit for the number of LP resolving iterations, if needed (i.e. if limitresolveiters == TRUE) */ 12459 harditlim = (int) MIN(itlim, INT_MAX); 12460 resolveitlim = ( limitresolveiters ? lpGetResolveItlim(set, stat, harditlim) : harditlim ); 12461 assert(harditlim == -1 || (resolveitlim <= harditlim)); 12462 12463 /* if there are lazy bounds, check whether the bounds should explicitly be put into the LP (diving was started) 12464 * or removed from the LP (diving was ended) 12465 */ 12466 if( lp->nlazycols > 0 ) 12467 { 12468 /* @todo avoid loosing primal feasibility here after changing the objective already did destroy dual feasibility; 12469 * first resolve LP? 12470 */ 12471 SCIP_CALL( updateLazyBounds(lp, set) ); 12472 assert(lp->diving == lp->divinglazyapplied); 12473 } 12474 12475 /* flush changes to the LP solver */ 12476 SCIP_CALL( SCIPlpFlush(lp, blkmem, set, prob, eventqueue) ); 12477 assert(lp->flushed); 12478 12479 /* if the time limit was reached in the last call and the LP did not change, lp->solved is set to TRUE, but we want 12480 * to run again anyway, since there seems to be some time left / the time limit was increased 12481 */ 12482 if( !lp->solved || (lp->lpsolstat == SCIP_LPSOLSTAT_TIMELIMIT && stat->status != SCIP_STATUS_TIMELIMIT) ) 12483 { 12484 SCIP_Bool* primalfeaspointer; 12485 SCIP_Bool* dualfeaspointer; 12486 SCIP_Bool primalfeasible; 12487 SCIP_Bool dualfeasible; 12488 SCIP_Bool farkasvalid; 12489 SCIP_Bool rayfeasible; 12490 SCIP_Bool tightprimfeastol; 12491 SCIP_Bool tightdualfeastol; 12492 SCIP_Bool fromscratch; 12493 SCIP_Bool wasfromscratch; 12494 int scaling; 12495 SCIP_Longint oldnlps; 12496 int fastmip; 12497 12498 /* set initial LP solver settings */ 12499 fastmip = ((lp->lpihasfastmip && !lp->flushaddedcols && !lp->flushdeletedcols && stat->nnodes > 1) ? set->lp_fastmip : 0); 12500 tightprimfeastol = FALSE; 12501 tightdualfeastol = FALSE; 12502 fromscratch = FALSE; 12503 primalfeasible = FALSE; 12504 dualfeasible = FALSE; 12505 wasfromscratch = (stat->nlps == 0); 12506 scaling = set->lp_scaling; 12507 12508 SOLVEAGAIN: 12509 /* solve the LP */ 12510 oldnlps = stat->nlps; 12511 SCIP_CALL( lpFlushAndSolve(lp, blkmem, set, messagehdlr, stat, prob, eventqueue, resolveitlim, harditlim, needprimalray, 12512 needdualray, fastmip, tightprimfeastol, tightdualfeastol, fromscratch, scaling, keepsol, lperror) ); 12513 SCIPsetDebugMsg(set, "lpFlushAndSolve() returned solstat %d (error=%u)\n", SCIPlpGetSolstat(lp), *lperror); 12514 assert(!(*lperror) || !lp->solved); 12515 12516 /* check for error */ 12517 if( *lperror ) 12518 { 12519 retcode = SCIP_OKAY; 12520 goto TERMINATE; 12521 } 12522 12523 /* evaluate solution status */ 12524 switch( SCIPlpGetSolstat(lp) ) 12525 { 12526 case SCIP_LPSOLSTAT_OPTIMAL: 12527 /* get LP solution and possibly check the solution's feasibility again */ 12528 if( set->lp_checkprimfeas ) 12529 { 12530 primalfeaspointer = &primalfeasible; 12531 lp->primalchecked = TRUE; 12532 } 12533 else 12534 { 12535 /* believe in the primal feasibility of the LP solution */ 12536 primalfeasible = TRUE; 12537 primalfeaspointer = NULL; 12538 lp->primalchecked = FALSE; 12539 } 12540 if( set->lp_checkdualfeas ) 12541 { 12542 dualfeaspointer = &dualfeasible; 12543 lp->dualchecked = TRUE; 12544 } 12545 else 12546 { 12547 /* believe in the dual feasibility of the LP solution */ 12548 dualfeasible = TRUE; 12549 dualfeaspointer = NULL; 12550 lp->dualchecked = FALSE; 12551 } 12552 12553 SCIP_CALL( SCIPlpGetSol(lp, set, stat, primalfeaspointer, dualfeaspointer) ); 12554 12555 /* in debug mode, check that lazy bounds (if present) are not violated */ 12556 checkLazyBounds(lp, set); 12557 12558 if( primalfeasible && dualfeasible && aging && !lp->diving && stat->nlps > oldnlps ) 12559 { 12560 /* update ages and remove obsolete columns and rows from LP */ 12561 SCIP_CALL( SCIPlpUpdateAges(lp, stat) ); 12562 if( stat->nlps % ((set->lp_rowagelimit+1)/2 + 1) == 0 ) /*lint !e776*/ 12563 { 12564 SCIP_CALL( SCIPlpRemoveNewObsoletes(lp, blkmem, set, stat, eventqueue, eventfilter) ); 12565 } 12566 12567 if( !lp->solved ) 12568 { 12569 /* resolve LP after removing obsolete columns and rows */ 12570 SCIPsetDebugMsg(set, "removed obsoletes - resolve LP again: %d rows, %d cols\n", lp->nrows, lp->ncols); 12571 aging = FALSE; /* to prevent infinite loops */ 12572 goto SOLVEAGAIN; 12573 } 12574 } 12575 if( !primalfeasible || !dualfeasible ) 12576 { 12577 SCIP_Bool simplex = (lp->lastlpalgo == SCIP_LPALGO_PRIMALSIMPLEX || lp->lastlpalgo == SCIP_LPALGO_DUALSIMPLEX); 12578 12579 if( (fastmip > 0) && simplex ) 12580 { 12581 /* solution is infeasible (this can happen due to numerical problems): solve again without FASTMIP */ 12582 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL, 12583 "(node %" SCIP_LONGINT_FORMAT ") solution of LP %" SCIP_LONGINT_FORMAT " not optimal (pfeas=%u, dfeas=%u) -- solving again without FASTMIP\n", 12584 stat->nnodes, stat->nlps, primalfeasible, dualfeasible); 12585 fastmip = 0; 12586 goto SOLVEAGAIN; 12587 } 12588 else if( (!primalfeasible && !tightprimfeastol) || (!dualfeasible && !tightdualfeastol) ) 12589 { 12590 /* solution is infeasible (this can happen due to numerical problems): solve again with tighter feasibility 12591 * tolerance 12592 */ 12593 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL, 12594 "(node %" SCIP_LONGINT_FORMAT ") solution of LP %" SCIP_LONGINT_FORMAT " not optimal (pfeas=%u, dfeas=%u) -- solving again with tighter feasibility tolerance\n", 12595 stat->nnodes, stat->nlps, primalfeasible, dualfeasible); 12596 tightprimfeastol = tightprimfeastol || !primalfeasible; 12597 tightdualfeastol = tightdualfeastol || !dualfeasible; 12598 goto SOLVEAGAIN; 12599 } 12600 else if( !fromscratch && !wasfromscratch && simplex ) 12601 { 12602 /* solution is infeasible (this can happen due to numerical problems): solve again from scratch */ 12603 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL, 12604 "(node %" SCIP_LONGINT_FORMAT ") solution of LP %" SCIP_LONGINT_FORMAT " not optimal (pfeas=%u, dfeas=%u) -- solving again from scratch\n", 12605 stat->nnodes, stat->nlps, primalfeasible, dualfeasible); 12606 fromscratch = TRUE; 12607 goto SOLVEAGAIN; 12608 } 12609 else 12610 { 12611 lpNumericalTroubleMessage(messagehdlr, set, stat, SCIP_VERBLEVEL_FULL, "unresolved"); 12612 lp->solved = FALSE; 12613 lp->lpsolstat = SCIP_LPSOLSTAT_NOTSOLVED; 12614 *lperror = TRUE; 12615 } 12616 } 12617 SCIPsetDebugMsg(set, " -> LP objective value: %g + %g = %g (solstat=%d, cutoff=%g)\n", 12618 lp->lpobjval, getFiniteLooseObjval(lp, set, prob), lp->lpobjval + getFiniteLooseObjval(lp, set, prob), 12619 lp->lpsolstat, lp->cutoffbound); 12620 break; 12621 12622 case SCIP_LPSOLSTAT_INFEASIBLE: 12623 SCIPsetDebugMsg(set, " -> LP infeasible\n"); 12624 if( !SCIPprobAllColsInLP(prob, set, lp) || set->lp_checkfarkas || set->misc_exactsolve || set->lp_alwaysgetduals ) 12625 { 12626 if( SCIPlpiHasDualRay(lp->lpi) ) 12627 { 12628 SCIP_CALL( SCIPlpGetDualfarkas(lp, set, stat, &farkasvalid) ); 12629 } 12630 /* it might happen that we have no infeasibility proof for the current LP (e.g. if the LP was always solved 12631 * with the primal simplex due to numerical problems) - treat this case like an LP error 12632 */ 12633 else 12634 { 12635 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL, 12636 "(node %" SCIP_LONGINT_FORMAT ") infeasibility of LP %" SCIP_LONGINT_FORMAT " could not be proven by dual ray\n", stat->nnodes, stat->nlps); 12637 lp->solved = FALSE; 12638 lp->lpsolstat = SCIP_LPSOLSTAT_NOTSOLVED; 12639 farkasvalid = FALSE; 12640 *lperror = TRUE; 12641 } 12642 } 12643 else 12644 farkasvalid = TRUE; 12645 12646 /* if the LP solver does not provide a Farkas proof we don't want to resolve the LP */ 12647 if( !farkasvalid && !(*lperror) ) 12648 { 12649 SCIP_Bool simplex = (lp->lastlpalgo == SCIP_LPALGO_PRIMALSIMPLEX || lp->lastlpalgo == SCIP_LPALGO_DUALSIMPLEX); 12650 12651 if( (fastmip > 0) && simplex ) 12652 { 12653 /* the Farkas proof does not prove infeasibility (this can happen due to numerical problems): solve again 12654 * without FASTMIP 12655 */ 12656 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL, 12657 "(node %" SCIP_LONGINT_FORMAT ") proof of infeasible LP %" SCIP_LONGINT_FORMAT " not valid -- solving again without FASTMIP\n", 12658 stat->nnodes, stat->nlps); 12659 fastmip = 0; 12660 goto SOLVEAGAIN; 12661 } 12662 else if( !tightdualfeastol ) 12663 { 12664 /* the Farkas proof does not prove infeasibility (this can happen due to numerical problems): 12665 * solve again with tighter feasibility tolerance 12666 */ 12667 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL, 12668 "(node %" SCIP_LONGINT_FORMAT ") proof of infeasible LP %" SCIP_LONGINT_FORMAT " not valid -- solving again with tighter dual feasibility tolerance\n", 12669 stat->nnodes, stat->nlps); 12670 tightdualfeastol = TRUE; 12671 goto SOLVEAGAIN; 12672 } 12673 else if( !fromscratch && simplex ) 12674 { 12675 /* the Farkas proof does not prove infeasibility (this can happen due to numerical problems): solve again 12676 * from scratch 12677 */ 12678 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL, 12679 "(node %" SCIP_LONGINT_FORMAT ") proof of infeasible LP %" SCIP_LONGINT_FORMAT " not valid -- solving again from scratch\n", 12680 stat->nnodes, stat->nlps); 12681 fromscratch = TRUE; 12682 goto SOLVEAGAIN; 12683 } 12684 else 12685 { 12686 /* the Farkas proof does not prove infeasibility (this can happen due to numerical problems) and nothing 12687 * helped forget about the LP at this node and mark it to be unsolved 12688 */ 12689 lpNumericalTroubleMessage(messagehdlr, set, stat, SCIP_VERBLEVEL_FULL, "unresolved, LP infeasible"); 12690 lp->solved = FALSE; 12691 lp->lpsolstat = SCIP_LPSOLSTAT_NOTSOLVED; 12692 *lperror = TRUE; 12693 } 12694 } 12695 12696 break; 12697 12698 case SCIP_LPSOLSTAT_UNBOUNDEDRAY: 12699 if( set->lp_checkprimfeas ) 12700 { 12701 /* get unbounded LP solution and check the solution's feasibility again */ 12702 SCIP_CALL( SCIPlpGetUnboundedSol(lp, set, stat, &primalfeasible, &rayfeasible) ); 12703 12704 lp->primalchecked = TRUE; 12705 } 12706 else 12707 { 12708 /* get unbounded LP solution believing in the feasibility of the LP solution */ 12709 SCIP_CALL( SCIPlpGetUnboundedSol(lp, set, stat, NULL, NULL) ); 12710 12711 primalfeasible = TRUE; 12712 rayfeasible = TRUE; 12713 lp->primalchecked = FALSE; 12714 } 12715 12716 /* in debug mode, check that lazy bounds (if present) are not violated */ 12717 checkLazyBounds(lp, set); 12718 12719 SCIPsetDebugMsg(set, " -> LP has unbounded primal ray (primalfeas=%u, rayfeas=%u)\n", 12720 primalfeasible, rayfeasible); 12721 12722 if( !primalfeasible || !rayfeasible ) 12723 { 12724 SCIP_Bool simplex = (lp->lastlpalgo == SCIP_LPALGO_PRIMALSIMPLEX || lp->lastlpalgo == SCIP_LPALGO_DUALSIMPLEX); 12725 12726 if( (fastmip > 0) && simplex ) 12727 { 12728 /* unbounded solution is infeasible (this can happen due to numerical problems): solve again without FASTMIP */ 12729 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL, 12730 "(node %" SCIP_LONGINT_FORMAT ") solution of unbounded LP %" SCIP_LONGINT_FORMAT " not optimal (pfeas=%u, rfeas=%u) -- solving again without FASTMIP\n", 12731 stat->nnodes, stat->nlps, primalfeasible, rayfeasible); 12732 fastmip = 0; 12733 goto SOLVEAGAIN; 12734 } 12735 else if( !tightprimfeastol ) 12736 { 12737 /* unbounded solution is infeasible (this can happen due to numerical problems): solve again with tighter feasibility 12738 * tolerance 12739 */ 12740 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL, 12741 "(node %" SCIP_LONGINT_FORMAT ") solution of unbounded LP %" SCIP_LONGINT_FORMAT " not optimal (pfeas=%u, rfeas=%u) -- solving again with tighter primal feasibility tolerance\n", 12742 stat->nnodes, stat->nlps, primalfeasible, rayfeasible); 12743 tightprimfeastol = TRUE; 12744 goto SOLVEAGAIN; 12745 } 12746 else if( !fromscratch && simplex ) 12747 { 12748 /* unbounded solution is infeasible (this can happen due to numerical problems): solve again from scratch */ 12749 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL, 12750 "(node %" SCIP_LONGINT_FORMAT ") solution of unbounded LP %" SCIP_LONGINT_FORMAT " not optimal (pfeas=%u, rfeas=%u) -- solving again from scratch\n", 12751 stat->nnodes, stat->nlps, primalfeasible, rayfeasible); 12752 fromscratch = TRUE; 12753 goto SOLVEAGAIN; 12754 } 12755 else if( scaling > 0 ) 12756 { 12757 /* unbounded solution is infeasible (this can happen due to numerical problems): solve again without scaling */ 12758 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL, 12759 "(node %" SCIP_LONGINT_FORMAT ") solution of unbounded LP %" SCIP_LONGINT_FORMAT " not optimal (pfeas=%u, rfeas=%u) -- solving without scaling\n", 12760 stat->nnodes, stat->nlps, primalfeasible, rayfeasible); 12761 scaling = 0; 12762 goto SOLVEAGAIN; 12763 } 12764 else 12765 { 12766 /* unbounded solution is infeasible (this can happen due to numerical problems) and nothing helped: 12767 * forget about the LP at this node and mark it to be unsolved 12768 */ 12769 lpNumericalTroubleMessage(messagehdlr, set, stat, SCIP_VERBLEVEL_FULL, "unresolved, LP unbounded"); 12770 lp->solved = FALSE; 12771 lp->lpsolstat = SCIP_LPSOLSTAT_NOTSOLVED; 12772 *lperror = TRUE; 12773 } 12774 } 12775 12776 break; 12777 12778 case SCIP_LPSOLSTAT_OBJLIMIT: 12779 assert(!lpCutoffDisabled(set, prob)); 12780 /* Some LP solvers, e.g. CPLEX With FASTMIP setting, do not apply the final pivot to reach the dual solution 12781 * exceeding the objective limit. In some cases like branch-and-price, however, we must make sure that a dual 12782 * feasible solution exists that exceeds the objective limit. Therefore, we have to continue solving it without 12783 * objective limit for at least one iteration. We first try to continue with FASTMIP for one additional simplex 12784 * iteration using the steepest edge pricing rule. If this does not fix the problem, we temporarily disable 12785 * FASTMIP and solve again. */ 12786 if( !SCIPprobAllColsInLP(prob, set, lp) || set->misc_exactsolve ) 12787 { 12788 SCIP_LPI* lpi; 12789 SCIP_Real objval; 12790 12791 lpi = SCIPlpGetLPI(lp); 12792 12793 assert(lpi != NULL); 12794 /* actually, SCIPsetIsGE(set, lp->lpobjval, lp->lpiuobjlim) should hold, but we are a bit less strict in 12795 * the assert by using !SCIPsetIsFeasNegative() 12796 */ 12797 assert(SCIPlpiIsObjlimExc(lpi) || !SCIPsetIsFeasNegative(set, lp->lpobjval - lp->lpiobjlim)); 12798 12799 SCIP_CALL( SCIPlpiGetObjval(lpi, &objval) ); 12800 12801 /* do one additional simplex step if the computed dual solution doesn't exceed the objective limit */ 12802 if( SCIPsetIsLT(set, objval, lp->lpiobjlim) ) 12803 { 12804 SCIP_Real tmpcutoff; 12805 char tmppricingchar; 12806 SCIP_LPSOLSTAT solstat; 12807 12808 SCIPsetDebugMsg(set, "objval = %f < %f = lp->lpiobjlim, but status objlimit\n", objval, lp->lpiobjlim); 12809 12810 /* we want to resolve from the current basis (also if the LP had to be solved from scratch) */ 12811 fromscratch = FALSE; 12812 12813 /* temporarily disable cutoffbound, which also disables the objective limit */ 12814 tmpcutoff = lp->cutoffbound; 12815 lp->cutoffbound = SCIPlpiInfinity(lpi); 12816 12817 /* set lp pricing strategy to steepest edge */ 12818 SCIP_CALL( SCIPsetGetCharParam(set, "lp/pricing", &tmppricingchar) ); 12819 SCIP_CALL( SCIPsetSetCharParam(set, messagehdlr, "lp/pricing", 's') ); 12820 12821 /* resolve LP with an iteration limit of 1 */ 12822 SCIP_CALL( lpSolve(lp, set, messagehdlr, stat, prob, SCIP_LPALGO_DUALSIMPLEX, 1, 1, 12823 FALSE, FALSE, TRUE, fastmip, tightprimfeastol, tightdualfeastol, fromscratch, scaling, keepsol, lperror) ); 12824 12825 /* reinstall old cutoff bound and lp pricing strategy */ 12826 lp->cutoffbound = tmpcutoff; 12827 SCIP_CALL( SCIPsetSetCharParam(set, messagehdlr, "lp/pricing", tmppricingchar) ); 12828 12829 /* get objective value */ 12830 SCIP_CALL( SCIPlpiGetObjval(lpi, &objval) ); 12831 12832 /* get solution status for the lp */ 12833 solstat = SCIPlpGetSolstat(lp); 12834 assert(solstat != SCIP_LPSOLSTAT_OBJLIMIT); 12835 12836 SCIPsetDebugMsg(set, " ---> new objval = %f (solstat: %d, 1 add. step)\n", objval, solstat); 12837 12838 /* the solution is still not exceeding the objective limit and the solving process 12839 * was stopped due to time or iteration limit, solve again with fastmip turned off 12840 */ 12841 if( solstat == SCIP_LPSOLSTAT_ITERLIMIT && 12842 SCIPsetIsLT(set, objval, lp->cutoffbound - getFiniteLooseObjval(lp, set, prob)) ) 12843 { 12844 SCIP_Bool simplex = (lp->lastlpalgo == SCIP_LPALGO_PRIMALSIMPLEX || lp->lastlpalgo == SCIP_LPALGO_DUALSIMPLEX); 12845 if( !(lperror) && (fastmip > 0) && simplex ) 12846 { 12847 fastmip = 0; 12848 SCIP_CALL( lpSolve(lp, set, messagehdlr, stat, prob, SCIP_LPALGO_DUALSIMPLEX, -1, -1, 12849 FALSE, FALSE, TRUE, fastmip, tightprimfeastol, tightdualfeastol, fromscratch, scaling, keepsol, lperror) ); 12850 12851 /* get objective value */ 12852 SCIP_CALL( SCIPlpiGetObjval(lpi, &objval) ); 12853 12854 /* get solution status for the lp */ 12855 solstat = SCIPlpGetSolstat(lp); 12856 12857 SCIPsetDebugMsg(set, " ---> new objval = %f (solstat: %d, without fastmip)\n", objval, solstat); 12858 } 12859 }/*lint !e438*/ 12860 12861 /* check for lp errors */ 12862 if( *lperror || solstat == SCIP_LPSOLSTAT_ERROR || solstat == SCIP_LPSOLSTAT_NOTSOLVED ) 12863 { 12864 SCIPsetDebugMsg(set, "unresolved error while resolving LP in order to exceed the objlimit\n"); 12865 lp->solved = FALSE; 12866 lp->lpsolstat = SCIP_LPSOLSTAT_NOTSOLVED; 12867 12868 retcode = *lperror ? SCIP_OKAY : SCIP_LPERROR; 12869 goto TERMINATE; 12870 } 12871 12872 lp->solved = TRUE; 12873 12874 /* optimal solution / objlimit / itlimit or timelimit, but objlimit exceeded */ 12875 if( solstat == SCIP_LPSOLSTAT_OPTIMAL || solstat == SCIP_LPSOLSTAT_OBJLIMIT 12876 || ( (solstat == SCIP_LPSOLSTAT_ITERLIMIT || solstat == SCIP_LPSOLSTAT_TIMELIMIT) 12877 && SCIPsetIsGE(set, objval, lp->cutoffbound - getFiniteLooseObjval(lp, set, prob)) ) ) 12878 { 12879 /* get LP solution and possibly check the solution's feasibility again */ 12880 if( set->lp_checkprimfeas ) 12881 { 12882 primalfeaspointer = &primalfeasible; 12883 lp->primalchecked = TRUE; 12884 } 12885 else 12886 { 12887 /* believe in the primal feasibility of the LP solution */ 12888 primalfeasible = TRUE; 12889 primalfeaspointer = NULL; 12890 lp->primalchecked = FALSE; 12891 } 12892 if( set->lp_checkdualfeas ) 12893 { 12894 dualfeaspointer = &dualfeasible; 12895 lp->dualchecked = TRUE; 12896 } 12897 else 12898 { 12899 /* believe in the dual feasibility of the LP solution */ 12900 dualfeasible = TRUE; 12901 dualfeaspointer = NULL; 12902 lp->dualchecked = FALSE; 12903 } 12904 12905 SCIP_CALL( SCIPlpGetSol(lp, set, stat, primalfeaspointer, dualfeaspointer) ); 12906 12907 /* in debug mode, check that lazy bounds (if present) are not violated by an optimal LP solution */ 12908 if( solstat == SCIP_LPSOLSTAT_OPTIMAL ) 12909 { 12910 checkLazyBounds(lp, set); 12911 } 12912 12913 /* if objective value is larger than the cutoff bound, set solution status to objective 12914 * limit reached and objective value to infinity, in case solstat = SCIP_LPSOLSTAT_OBJLIMIT, 12915 * this was already done in the lpSolve() method 12916 */ 12917 if( SCIPsetIsGE(set, objval, lp->cutoffbound - getFiniteLooseObjval(lp, set, prob)) ) 12918 { 12919 lp->lpsolstat = SCIP_LPSOLSTAT_OBJLIMIT; 12920 lp->lpobjval = SCIPsetInfinity(set); 12921 } 12922 12923 /* LP solution is not feasible or objective limit was reached without the LP value really exceeding 12924 * the cutoffbound; mark the LP to be unsolved 12925 */ 12926 if( !primalfeasible || !dualfeasible 12927 || (solstat == SCIP_LPSOLSTAT_OBJLIMIT && 12928 !SCIPsetIsGE(set, objval, lp->cutoffbound - getFiniteLooseObjval(lp, set, prob))) ) 12929 { 12930 lpNumericalTroubleMessage(messagehdlr, set, stat, SCIP_VERBLEVEL_HIGH, "unresolved"); 12931 lp->solved = FALSE; 12932 lp->lpsolstat = SCIP_LPSOLSTAT_NOTSOLVED; 12933 *lperror = TRUE; 12934 } 12935 12936 SCIPsetDebugMsg(set, " -> LP objective value: %g + %g = %g (solstat=%d, cutoff=%g)\n", 12937 lp->lpobjval, getFiniteLooseObjval(lp, set, prob), lp->lpobjval + getFiniteLooseObjval(lp, set, prob), 12938 lp->lpsolstat, lp->cutoffbound); 12939 } 12940 /* infeasible solution */ 12941 else if( solstat == SCIP_LPSOLSTAT_INFEASIBLE ) 12942 { 12943 SCIPsetDebugMsg(set, " -> LP infeasible\n"); 12944 12945 if( !SCIPprobAllColsInLP(prob, set, lp) || set->lp_checkfarkas || set->misc_exactsolve ) 12946 { 12947 if( SCIPlpiHasDualRay(lp->lpi) ) 12948 { 12949 SCIP_CALL( SCIPlpGetDualfarkas(lp, set, stat, &farkasvalid) ); 12950 } 12951 /* it might happen that we have no infeasibility proof for the current LP (e.g. if the LP was always solved 12952 * with the primal simplex due to numerical problems) - treat this case like an LP error 12953 */ 12954 else 12955 { 12956 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL, 12957 "(node %" SCIP_LONGINT_FORMAT ") infeasibility of LP %" SCIP_LONGINT_FORMAT " could not be proven by dual ray\n", stat->nnodes, stat->nlps); 12958 lp->solved = FALSE; 12959 lp->lpsolstat = SCIP_LPSOLSTAT_NOTSOLVED; 12960 farkasvalid = FALSE; 12961 *lperror = TRUE; 12962 } 12963 } 12964 else 12965 farkasvalid = TRUE; 12966 12967 if( !farkasvalid ) 12968 { 12969 SCIP_Bool simplex = (lp->lastlpalgo == SCIP_LPALGO_PRIMALSIMPLEX || lp->lastlpalgo == SCIP_LPALGO_DUALSIMPLEX); 12970 12971 if( !tightprimfeastol ) 12972 { 12973 /* the Farkas proof does not prove infeasibility (this can happen due to numerical problems): 12974 * solve again with tighter feasibility tolerance 12975 */ 12976 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL, 12977 "(node %" SCIP_LONGINT_FORMAT ") proof of infeasible LP %" SCIP_LONGINT_FORMAT " not valid -- solving again with tighter primal feasibility tolerance\n", 12978 stat->nnodes, stat->nlps); 12979 tightprimfeastol = TRUE; 12980 goto SOLVEAGAIN; 12981 } 12982 else if( simplex ) 12983 { 12984 /* the Farkas proof does not prove infeasibility (this can happen due to numerical problems): solve again 12985 * from scratch 12986 */ 12987 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL, 12988 "(node %" SCIP_LONGINT_FORMAT ") proof of infeasible LP %" SCIP_LONGINT_FORMAT " not valid -- solving again from scratch\n", 12989 stat->nnodes, stat->nlps); 12990 fromscratch = TRUE; 12991 goto SOLVEAGAIN; 12992 } 12993 else 12994 { 12995 /* the Farkas proof does not prove infeasibility (this can happen due to numerical problems) and nothing 12996 * helped forget about the LP at this node and mark it to be unsolved 12997 */ 12998 lpNumericalTroubleMessage(messagehdlr, set, stat, SCIP_VERBLEVEL_FULL, "unresolved, LP infeasible"); 12999 lp->solved = FALSE; 13000 lp->lpsolstat = SCIP_LPSOLSTAT_NOTSOLVED; 13001 *lperror = TRUE; 13002 } 13003 } 13004 } 13005 /* unbounded solution */ 13006 else if( solstat == SCIP_LPSOLSTAT_UNBOUNDEDRAY ) 13007 { 13008 if( set->lp_checkprimfeas ) 13009 { 13010 /* get unbounded LP solution and check the solution's feasibility again */ 13011 SCIP_CALL( SCIPlpGetUnboundedSol(lp, set, stat, &primalfeasible, &rayfeasible) ); 13012 13013 lp->primalchecked = TRUE; 13014 } 13015 else 13016 { 13017 /* get unbounded LP solution believing in its feasibility */ 13018 SCIP_CALL( SCIPlpGetUnboundedSol(lp, set, stat, NULL, NULL) ); 13019 13020 primalfeasible = TRUE; 13021 rayfeasible = TRUE; 13022 lp->primalchecked = FALSE; 13023 } 13024 13025 SCIPsetDebugMsg(set, " -> LP has unbounded primal ray\n"); 13026 13027 /* in debug mode, check that lazy bounds (if present) are not violated */ 13028 checkLazyBounds(lp, set); 13029 13030 if( !primalfeasible || !rayfeasible ) 13031 { 13032 /* unbounded solution is infeasible (this can happen due to numerical problems): 13033 * forget about the LP at this node and mark it to be unsolved 13034 * 13035 * @todo: like in the default LP solving evaluation, solve without fastmip, 13036 * with tighter feasibility tolerance and from scratch 13037 */ 13038 lpNumericalTroubleMessage(messagehdlr, set, stat, SCIP_VERBLEVEL_FULL, "unresolved, unbounded LP"); 13039 lp->solved = FALSE; 13040 lp->lpsolstat = SCIP_LPSOLSTAT_NOTSOLVED; 13041 *lperror = TRUE; 13042 } 13043 } 13044 13045 assert(lp->lpsolstat != SCIP_LPSOLSTAT_ITERLIMIT); 13046 assert(SCIPsetIsGE(set, objval, lp->cutoffbound - getFiniteLooseObjval(lp, set, prob)) 13047 || lp->lpsolstat != SCIP_LPSOLSTAT_OBJLIMIT); 13048 } 13049 else 13050 { 13051 SCIP_CALL( SCIPlpGetSol(lp, set, stat, NULL, NULL) ); 13052 } 13053 } 13054 SCIPsetDebugMsg(set, " -> LP objective limit reached\n"); 13055 break; 13056 13057 case SCIP_LPSOLSTAT_ITERLIMIT: 13058 SCIPsetDebugMsg(set, " -> LP iteration limit exceeded\n"); 13059 break; 13060 13061 case SCIP_LPSOLSTAT_TIMELIMIT: 13062 SCIPsetDebugMsg(set, " -> LP time limit exceeded\n"); 13063 13064 /* make sure that we evaluate the time limit exactly in order to avoid erroneous warning */ 13065 stat->nclockskipsleft = 0; 13066 if( !stat->userinterrupt && !SCIPsolveIsStopped(set, stat, FALSE) ) 13067 { 13068 SCIPmessagePrintWarning(messagehdlr, "LP solver reached time limit, but SCIP time limit is not exceeded yet; " 13069 "you might consider switching the clock type of SCIP\n"); 13070 stat->status = SCIP_STATUS_TIMELIMIT; 13071 } 13072 break; 13073 13074 case SCIP_LPSOLSTAT_ERROR: 13075 case SCIP_LPSOLSTAT_NOTSOLVED: 13076 SCIPerrorMessage("error in LP solver\n"); 13077 retcode = SCIP_LPERROR; 13078 goto TERMINATE; 13079 13080 default: 13081 SCIPerrorMessage("unknown LP solution status\n"); 13082 retcode = SCIP_ERROR; 13083 goto TERMINATE; 13084 } 13085 } 13086 assert(!(*lperror) || !lp->solved); 13087 13088 TERMINATE: 13089 /* if the LP had to be solved from scratch, we have to reset this flag since it is stored in the LPI; otherwise it 13090 * may happen that we continue to solve from scratch during strong branching */ 13091 if( lp->lpifromscratch ) 13092 { 13093 SCIP_Bool success; 13094 (void) lpSetFromscratch(lp, FALSE, &success); 13095 SCIPsetDebugMsg(set, "resetting parameter SCIP_LPPARAM_FROMSCRATCH to FALSE %s\n", success ? "" : "failed"); 13096 SCIP_UNUSED(success); 13097 } 13098 13099 return retcode; 13100 } 13101 13102 /** gets solution status of current LP */ 13103 SCIP_LPSOLSTAT SCIPlpGetSolstat( 13104 SCIP_LP* lp /**< current LP data */ 13105 ) 13106 { 13107 assert(lp != NULL); 13108 assert(lp->solved || lp->lpsolstat == SCIP_LPSOLSTAT_NOTSOLVED); 13109 13110 return (lp->flushed ? lp->lpsolstat : SCIP_LPSOLSTAT_NOTSOLVED); 13111 } 13112 13113 /** gets objective value of current LP 13114 * 13115 * @note This method returns the objective value of the current LP solution, which might be primal or dual infeasible 13116 * if a limit was hit during solving. It must not be used as a dual bound if the LP solution status is 13117 * SCIP_LPSOLSTAT_ITERLIMIT or SCIP_LPSOLSTAT_TIMELIMIT. 13118 */ 13119 SCIP_Real SCIPlpGetObjval( 13120 SCIP_LP* lp, /**< current LP data */ 13121 SCIP_SET* set, /**< global SCIP settings */ 13122 SCIP_PROB* prob /**< problem data */ 13123 ) 13124 { 13125 assert(lp != NULL); 13126 assert(lp->solved); 13127 assert((lp->nloosevars > 0) || (lp->looseobjvalinf == 0 && lp->looseobjval == 0.0)); 13128 assert(set != NULL); 13129 13130 if( !lp->flushed ) 13131 return SCIP_INVALID; 13132 else if( SCIPsetIsInfinity(set, lp->lpobjval) || SCIPsetIsInfinity(set, -lp->lpobjval)) 13133 return lp->lpobjval; 13134 else if( lp->looseobjvalinf > 0 ) 13135 return -SCIPsetInfinity(set); 13136 else 13137 { 13138 /* recalculate the loose objective value, if needed */ 13139 if( !lp->looseobjvalid ) 13140 recomputeLooseObjectiveValue(lp, set, prob); 13141 13142 return lp->lpobjval + lp->looseobjval; 13143 } 13144 } 13145 13146 /** gets part of objective value of current LP that results from COLUMN variables only */ 13147 SCIP_Real SCIPlpGetColumnObjval( 13148 SCIP_LP* lp /**< current LP data */ 13149 ) 13150 { 13151 assert(lp != NULL); 13152 assert(lp->solved); 13153 13154 return (lp->flushed ? lp->lpobjval : SCIP_INVALID); 13155 } 13156 13157 /** gets part of objective value of current LP that results from LOOSE variables only */ 13158 SCIP_Real SCIPlpGetLooseObjval( 13159 SCIP_LP* lp, /**< current LP data */ 13160 SCIP_SET* set, /**< global SCIP settings */ 13161 SCIP_PROB* prob /**< problem data */ 13162 ) 13163 { 13164 assert(lp != NULL); 13165 assert(lp->solved); 13166 assert((lp->nloosevars > 0) || (lp->looseobjvalinf == 0 && lp->looseobjval == 0.0)); 13167 assert(set != NULL); 13168 13169 if( !lp->flushed ) 13170 return SCIP_INVALID; 13171 else if( lp->looseobjvalinf > 0 ) 13172 return -SCIPsetInfinity(set); 13173 else 13174 return getFiniteLooseObjval(lp, set, prob); 13175 } 13176 13177 /** remembers the current LP objective value as root solution value */ 13178 void SCIPlpStoreRootObjval( 13179 SCIP_LP* lp, /**< current LP data */ 13180 SCIP_SET* set, /**< global SCIP settings */ 13181 SCIP_PROB* prob /**< problem data */ 13182 ) 13183 { 13184 assert(lp != NULL); 13185 13186 lp->rootlpobjval = SCIPlpGetColumnObjval(lp); 13187 lp->rootlooseobjval = SCIPlpGetLooseObjval(lp, set, prob); 13188 } 13189 13190 /** invalidates the root LP solution value */ 13191 void SCIPlpInvalidateRootObjval( 13192 SCIP_LP* lp /**< current LP data */ 13193 ) 13194 { 13195 assert(lp != NULL); 13196 13197 lp->rootlpobjval = SCIP_INVALID; 13198 lp->rootlooseobjval = SCIP_INVALID; 13199 } 13200 13201 /** recomputes local and global pseudo objective values */ 13202 void SCIPlpRecomputeLocalAndGlobalPseudoObjval( 13203 SCIP_LP* lp, /**< current LP data */ 13204 SCIP_SET* set, /**< global SCIP settings */ 13205 SCIP_PROB* prob /**< problem data */ 13206 ) 13207 { 13208 SCIP_VAR** vars; 13209 int nvars; 13210 int v; 13211 13212 assert(lp != NULL); 13213 assert(set != NULL); 13214 assert(prob != NULL); 13215 13216 vars = prob->vars; 13217 nvars = prob->nvars; 13218 13219 lp->glbpseudoobjvalinf = 0; 13220 lp->glbpseudoobjval = 0.0; 13221 13222 lp->pseudoobjvalinf = 0; 13223 lp->pseudoobjval = 0.0; 13224 13225 for( v = 0; v < nvars; ++v ) 13226 { 13227 SCIP_Real obj = SCIPvarGetObj(vars[v]); 13228 13229 if( SCIPsetIsPositive(set, obj) ) 13230 { 13231 /* update the global pseudo objective value */ 13232 if( SCIPsetIsInfinity(set, -SCIPvarGetLbGlobal(vars[v])) ) 13233 ++(lp->glbpseudoobjvalinf); 13234 else 13235 lp->glbpseudoobjval += obj * SCIPvarGetLbGlobal(vars[v]); 13236 13237 /* update the local pseudo objective value */ 13238 if( SCIPsetIsInfinity(set, -SCIPvarGetLbLocal(vars[v])) ) 13239 ++(lp->pseudoobjvalinf); 13240 else 13241 lp->pseudoobjval += obj * SCIPvarGetLbLocal(vars[v]); 13242 } 13243 13244 if( SCIPsetIsNegative(set, obj) ) 13245 { 13246 /* update the global pseudo objective value */ 13247 if( SCIPsetIsInfinity(set, SCIPvarGetUbGlobal(vars[v])) ) 13248 ++(lp->glbpseudoobjvalinf); 13249 else 13250 lp->glbpseudoobjval += obj * SCIPvarGetUbGlobal(vars[v]); 13251 13252 /* update the local pseudo objective value */ 13253 if( SCIPsetIsInfinity(set, SCIPvarGetUbLocal(vars[v])) ) 13254 ++(lp->pseudoobjvalinf); 13255 else 13256 lp->pseudoobjval += obj * SCIPvarGetUbLocal(vars[v]); 13257 } 13258 } 13259 13260 /* the recomputed values are reliable */ 13261 lp->relglbpseudoobjval = lp->glbpseudoobjval; 13262 lp->glbpseudoobjvalid = TRUE; 13263 lp->relpseudoobjval = lp->pseudoobjval; 13264 lp->pseudoobjvalid = TRUE; 13265 } 13266 13267 /** gets the global pseudo objective value; that is all variables set to their best (w.r.t. the objective function) 13268 * global bound 13269 */ 13270 SCIP_Real SCIPlpGetGlobalPseudoObjval( 13271 SCIP_LP* lp, /**< current LP data */ 13272 SCIP_SET* set, /**< global SCIP settings */ 13273 SCIP_PROB* prob /**< problem data */ 13274 ) 13275 { 13276 assert(lp != NULL); 13277 assert(lp->glbpseudoobjvalinf >= 0); 13278 assert(set != NULL); 13279 13280 if( lp->glbpseudoobjvalinf > 0 || set->nactivepricers > 0 ) 13281 return -SCIPsetInfinity(set); 13282 else 13283 { 13284 /* recalculate the global pseudo solution value, if needed */ 13285 if( !lp->glbpseudoobjvalid ) 13286 recomputeGlbPseudoObjectiveValue(lp, set, prob); 13287 13288 /* if the global pseudo objective value is smaller than -infinity, we just return -infinity */ 13289 if( SCIPsetIsInfinity(set, -lp->glbpseudoobjval) ) 13290 return -SCIPsetInfinity(set); 13291 13292 if( SCIPsetIsInfinity(set, lp->glbpseudoobjval) ) 13293 return SCIPsetInfinity(set); 13294 13295 return lp->glbpseudoobjval; 13296 } 13297 } 13298 13299 /** gets the pseudo objective value for the current search node; that is all variables set to their best (w.r.t. the 13300 * objective function) local bound 13301 */ 13302 SCIP_Real SCIPlpGetPseudoObjval( 13303 SCIP_LP* lp, /**< current LP data */ 13304 SCIP_SET* set, /**< global SCIP settings */ 13305 SCIP_PROB* prob /**< problem data */ 13306 ) 13307 { 13308 assert(lp != NULL); 13309 assert(lp->pseudoobjvalinf >= 0); 13310 assert(set != NULL); 13311 13312 if( lp->pseudoobjvalinf > 0 || set->nactivepricers > 0 ) 13313 return -SCIPsetInfinity(set); 13314 else 13315 { 13316 /* recalculate the pseudo solution value, if needed */ 13317 if( !lp->pseudoobjvalid ) 13318 recomputePseudoObjectiveValue(lp, set, prob); 13319 13320 /* if the pseudo objective value is smaller than -infinity, we just return -infinity */ 13321 if( SCIPsetIsInfinity(set, -lp->pseudoobjval) ) 13322 return -SCIPsetInfinity(set); 13323 13324 if( SCIPsetIsInfinity(set, lp->pseudoobjval) ) 13325 return SCIPsetInfinity(set); 13326 13327 return lp->pseudoobjval; 13328 } 13329 } 13330 13331 /** gets pseudo objective value, if a bound of the given variable would be modified in the given way */ 13332 SCIP_Real SCIPlpGetModifiedPseudoObjval( 13333 SCIP_LP* lp, /**< current LP data */ 13334 SCIP_SET* set, /**< global SCIP settings */ 13335 SCIP_PROB* prob, /**< problem data */ 13336 SCIP_VAR* var, /**< problem variable */ 13337 SCIP_Real oldbound, /**< old value for bound */ 13338 SCIP_Real newbound, /**< new value for bound */ 13339 SCIP_BOUNDTYPE boundtype /**< type of bound: lower or upper bound */ 13340 ) 13341 { 13342 SCIP_Real pseudoobjval; 13343 int pseudoobjvalinf; 13344 SCIP_Real obj; 13345 13346 pseudoobjval = getFinitePseudoObjval(lp, set, prob); 13347 pseudoobjvalinf = lp->pseudoobjvalinf; 13348 obj = SCIPvarGetObj(var); 13349 if( !SCIPsetIsZero(set, obj) && boundtype == SCIPvarGetBestBoundType(var) ) 13350 { 13351 if( SCIPsetIsInfinity(set, REALABS(oldbound)) ) 13352 pseudoobjvalinf--; 13353 else 13354 pseudoobjval -= oldbound * obj; 13355 assert(pseudoobjvalinf >= 0); 13356 if( SCIPsetIsInfinity(set, REALABS(newbound)) ) 13357 pseudoobjvalinf++; 13358 else 13359 pseudoobjval += newbound * obj; 13360 } 13361 assert(pseudoobjvalinf >= 0); 13362 13363 if( pseudoobjvalinf > 0 || set->nactivepricers > 0 ) 13364 return -SCIPsetInfinity(set); 13365 else 13366 return pseudoobjval; 13367 } 13368 13369 /** gets pseudo objective value, if a bound of the given variable would be modified in the given way; 13370 * perform calculations with interval arithmetic to get an exact lower bound 13371 */ 13372 SCIP_Real SCIPlpGetModifiedProvedPseudoObjval( 13373 SCIP_LP* lp, /**< current LP data */ 13374 SCIP_SET* set, /**< global SCIP settings */ 13375 SCIP_VAR* var, /**< problem variable */ 13376 SCIP_Real oldbound, /**< old value for bound */ 13377 SCIP_Real newbound, /**< new value for bound */ 13378 SCIP_BOUNDTYPE boundtype /**< type of bound: lower or upper bound */ 13379 ) 13380 { 13381 SCIP_Real pseudoobjval; 13382 int pseudoobjvalinf; 13383 SCIP_Real obj; 13384 13385 assert(lp->pseudoobjvalid); 13386 13387 pseudoobjval = lp->pseudoobjval; 13388 pseudoobjvalinf = lp->pseudoobjvalinf; 13389 obj = SCIPvarGetObj(var); 13390 if( !SCIPsetIsZero(set, obj) && boundtype == SCIPvarGetBestBoundType(var) ) 13391 { 13392 SCIP_INTERVAL objint; 13393 SCIP_INTERVAL bd; 13394 SCIP_INTERVAL prod; 13395 SCIP_INTERVAL psval; 13396 13397 SCIPintervalSet(&psval, pseudoobjval); 13398 SCIPintervalSet(&objint, SCIPvarGetObj(var)); 13399 13400 if( SCIPsetIsInfinity(set, REALABS(oldbound)) ) 13401 pseudoobjvalinf--; 13402 else 13403 { 13404 SCIPintervalSet(&bd, oldbound); 13405 SCIPintervalMul(SCIPsetInfinity(set), &prod, bd, objint); 13406 SCIPintervalSub(SCIPsetInfinity(set), &psval, psval, prod); 13407 } 13408 assert(pseudoobjvalinf >= 0); 13409 if( SCIPsetIsInfinity(set, REALABS(newbound)) ) 13410 pseudoobjvalinf++; 13411 else 13412 { 13413 SCIPintervalSet(&bd, newbound); 13414 SCIPintervalMul(SCIPsetInfinity(set), &prod, bd, objint); 13415 SCIPintervalAdd(SCIPsetInfinity(set), &psval, psval, prod); 13416 } 13417 13418 pseudoobjval = SCIPintervalGetInf(psval); 13419 } 13420 assert(pseudoobjvalinf >= 0); 13421 13422 if( pseudoobjvalinf > 0 || set->nactivepricers > 0 ) 13423 return -SCIPsetInfinity(set); 13424 else 13425 return pseudoobjval; 13426 } 13427 13428 /** compute the objective delta due the new objective coefficient */ 13429 static 13430 void getObjvalDeltaObj( 13431 SCIP_SET* set, /**< global SCIP settings */ 13432 SCIP_Real oldobj, /**< old objective value of variable */ 13433 SCIP_Real newobj, /**< new objective value of variable */ 13434 SCIP_Real lb, /**< lower bound of variable */ 13435 SCIP_Real ub, /**< upper bound of variable */ 13436 SCIP_Real* deltaval, /**< pointer to store the delta value */ 13437 int* deltainf /**< pointer to store the number of variables with infinite best bound */ 13438 ) 13439 { 13440 assert(!SCIPsetIsInfinity(set, REALABS(oldobj))); 13441 assert(!SCIPsetIsInfinity(set, REALABS(newobj))); 13442 assert(!SCIPsetIsInfinity(set, lb)); 13443 assert(!SCIPsetIsInfinity(set, -ub)); 13444 assert(!SCIPsetIsEQ(set, oldobj, newobj)); 13445 13446 (*deltaval) = 0.0; 13447 (*deltainf) = 0; 13448 13449 if( SCIPsetIsPositive(set, oldobj) ) 13450 { 13451 /* sign of objective did not change */ 13452 if( SCIPsetIsPositive(set, newobj) ) 13453 { 13454 /* if the bound is finite, calculate the deltaval */ 13455 if( !SCIPsetIsInfinity(set, -lb) ) 13456 (*deltaval) = lb * (newobj - oldobj); 13457 } 13458 /* sign of objective did change, so the best bound does change */ 13459 else if( SCIPsetIsNegative(set, newobj) ) 13460 { 13461 if( SCIPsetIsInfinity(set, -lb) ) 13462 { 13463 /* old best bound was infinite while new one is not */ 13464 if( !SCIPsetIsInfinity(set, ub) ) 13465 { 13466 (*deltainf) = -1; 13467 (*deltaval) = ub * newobj; 13468 } 13469 } 13470 else 13471 { 13472 /* new best bound is infinite while old one was not */ 13473 if( SCIPsetIsInfinity(set, ub) ) 13474 { 13475 (*deltainf) = 1; 13476 (*deltaval) = -lb * oldobj; 13477 } 13478 /* neither old nor new best bound is infinite, so just calculate the deltaval */ 13479 else 13480 { 13481 (*deltaval) = (ub * newobj) - (lb * oldobj); 13482 } 13483 } 13484 } 13485 /* new objective is 0.0 */ 13486 else 13487 { 13488 if( SCIPsetIsInfinity(set, -lb) ) 13489 (*deltainf) = -1; 13490 else 13491 (*deltaval) = -lb * oldobj; 13492 } 13493 } 13494 else if( SCIPsetIsNegative(set, oldobj) ) 13495 { 13496 /* sign of objective did not change */ 13497 if( SCIPsetIsNegative(set, newobj) ) 13498 { 13499 /* if the bound is finite, calculate the deltaval */ 13500 if( !SCIPsetIsInfinity(set, ub) ) 13501 (*deltaval) = ub * (newobj - oldobj); 13502 } 13503 /* sign of objective did change, so the best bound does change */ 13504 else if( SCIPsetIsPositive(set, newobj) ) 13505 { 13506 if( SCIPsetIsInfinity(set, ub) ) 13507 { 13508 /* old best bound was infinite while new one is not */ 13509 if( !SCIPsetIsInfinity(set, -lb) ) 13510 { 13511 (*deltainf) = -1; 13512 (*deltaval) = lb * newobj; 13513 } 13514 } 13515 else 13516 { 13517 /* new best bound is infinite while old one was not */ 13518 if( SCIPsetIsInfinity(set, -lb) ) 13519 { 13520 (*deltainf) = 1; 13521 (*deltaval) = -ub * oldobj; 13522 } 13523 /* neither old nor new best bound is infinite, so just calculate the deltaval */ 13524 else 13525 { 13526 (*deltaval) = (lb * newobj) - (ub * oldobj); 13527 } 13528 } 13529 } 13530 /* new objective is 0.0 */ 13531 else 13532 { 13533 if( SCIPsetIsInfinity(set, ub) ) 13534 (*deltainf) = -1; 13535 else 13536 (*deltaval) = -ub * oldobj; 13537 } 13538 } 13539 /* old objective was 0.0 */ 13540 else 13541 { 13542 if( SCIPsetIsNegative(set, newobj) ) 13543 { 13544 if( SCIPsetIsInfinity(set, ub) ) 13545 (*deltainf) = 1; 13546 else 13547 (*deltaval) = ub * newobj; 13548 } 13549 else if( SCIPsetIsPositive(set, newobj) ) 13550 { 13551 if( SCIPsetIsInfinity(set, -lb) ) 13552 (*deltainf) = 1; 13553 else 13554 (*deltaval) = lb * newobj; 13555 } 13556 } 13557 } 13558 13559 /** compute the objective delta due the new lower bound */ 13560 static 13561 void getObjvalDeltaLb( 13562 SCIP_SET* set, /**< global SCIP settings */ 13563 SCIP_Real obj, /**< objective value of variable */ 13564 SCIP_Real oldlb, /**< old lower bound of variable */ 13565 SCIP_Real newlb, /**< new lower bound of variable */ 13566 SCIP_Real* deltaval, /**< pointer to store the delta value */ 13567 int* deltainf /**< pointer to store the number of variables with infinite best bound */ 13568 ) 13569 { 13570 assert(!SCIPsetIsInfinity(set, REALABS(obj))); 13571 assert(!SCIPsetIsInfinity(set, oldlb)); 13572 assert(!SCIPsetIsInfinity(set, -oldlb) || !SCIPsetIsInfinity(set, -newlb)); 13573 assert(SCIPsetIsPositive(set, obj)); /* we only need to update if the objective is positive */ 13574 13575 if( SCIPsetIsInfinity(set, -oldlb) ) 13576 { 13577 if( !SCIPsetIsInfinity(set, newlb) ) 13578 { 13579 (*deltainf) = -1; 13580 (*deltaval) = newlb * obj; 13581 } 13582 else 13583 { 13584 (*deltainf) = 0; 13585 (*deltaval) = 0.0; 13586 } 13587 } 13588 else if( SCIPsetIsInfinity(set, REALABS(newlb)) ) 13589 { 13590 (*deltainf) = 1; 13591 (*deltaval) = -oldlb * obj; 13592 } 13593 else 13594 { 13595 (*deltainf) = 0; 13596 (*deltaval) = obj * (newlb - oldlb); 13597 } 13598 } 13599 13600 /** compute the objective delta due the new upper bound */ 13601 static 13602 void getObjvalDeltaUb( 13603 SCIP_SET* set, /**< global SCIP settings */ 13604 SCIP_Real obj, /**< objective value of variable */ 13605 SCIP_Real oldub, /**< old upper bound of variable */ 13606 SCIP_Real newub, /**< new upper bound of variable */ 13607 SCIP_Real* deltaval, /**< pointer to store the delta value */ 13608 int* deltainf /**< pointer to store the number of variables with infinite best bound */ 13609 ) 13610 { 13611 assert(!SCIPsetIsInfinity(set, REALABS(obj))); 13612 assert(!SCIPsetIsInfinity(set, -oldub)); 13613 assert(!SCIPsetIsInfinity(set, oldub) || !SCIPsetIsInfinity(set, newub)); 13614 assert(SCIPsetIsNegative(set, obj)); /* we only need to update if the objective is negative */ 13615 13616 if( SCIPsetIsInfinity(set, oldub) ) 13617 { 13618 if( !SCIPsetIsInfinity(set, -newub) ) 13619 { 13620 (*deltainf) = -1; 13621 (*deltaval) = newub * obj; 13622 } 13623 else 13624 { 13625 (*deltainf) = 0; 13626 (*deltaval) = 0.0; 13627 } 13628 } 13629 else if( SCIPsetIsInfinity(set, REALABS(newub)) ) 13630 { 13631 (*deltainf) = 1; 13632 (*deltaval) = -oldub * obj; 13633 } 13634 else 13635 { 13636 (*deltainf) = 0; 13637 (*deltaval) = obj * (newub - oldub); 13638 } 13639 } 13640 13641 /** updates current pseudo and loose objective values for a change in a variable's objective value or bounds */ 13642 static 13643 void lpUpdateObjval( 13644 SCIP_LP* lp, /**< current LP data */ 13645 SCIP_SET* set, /**< global SCIP settings */ 13646 SCIP_VAR* var, /**< problem variable that changed */ 13647 SCIP_Real deltaval, /**< delta value in the objective function */ 13648 int deltainf, /**< delta value for the number of variables with infinite best bound */ 13649 SCIP_Bool local, /**< should the local pseudo objective value be updated? */ 13650 SCIP_Bool loose, /**< should the loose objective value be updated? */ 13651 SCIP_Bool global /**< should the global pseudo objective value be updated? */ 13652 ) 13653 { 13654 assert(lp != NULL); 13655 assert(lp->looseobjvalinf >= 0); 13656 assert(lp->pseudoobjvalinf >= 0); 13657 assert(lp->glbpseudoobjvalinf >= 0); 13658 13659 /* update the pseudo objective value */ 13660 if( local ) 13661 { 13662 lp->pseudoobjvalinf += deltainf; 13663 if( lp->pseudoobjvalid ) 13664 { 13665 lp->pseudoobjval += deltaval; 13666 13667 /* if the absolute value was increased, this is regarded as reliable, 13668 * otherwise, we check whether we can still trust the updated value 13669 */ 13670 if( REALABS(lp->relpseudoobjval) < REALABS(lp->pseudoobjval) ) 13671 lp->relpseudoobjval = lp->pseudoobjval; 13672 else if( SCIPsetIsUpdateUnreliable(set, lp->pseudoobjval, lp->relpseudoobjval) ) 13673 lp->pseudoobjvalid = FALSE; 13674 } 13675 13676 /* after changing a local bound on a LOOSE variable, we have to update the loose objective value, too */ 13677 if( SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE ) 13678 loose = TRUE; 13679 } 13680 /* update the loose objective value */ 13681 if( loose ) 13682 { 13683 lp->looseobjvalinf += deltainf; 13684 13685 if( deltaval != 0.0 && lp->looseobjvalid ) 13686 { 13687 lp->looseobjval += deltaval; 13688 13689 /* if the absolute value was increased, this is regarded as reliable, 13690 * otherwise, we check whether we can still trust the updated value 13691 */ 13692 if( REALABS(lp->rellooseobjval) < REALABS(lp->looseobjval) ) 13693 lp->rellooseobjval = lp->looseobjval; 13694 else if( SCIPsetIsUpdateUnreliable(set, lp->looseobjval, lp->rellooseobjval) ) 13695 lp->looseobjvalid = FALSE; 13696 } 13697 } 13698 /* update the root pseudo objective values */ 13699 if( global ) 13700 { 13701 lp->glbpseudoobjvalinf += deltainf; 13702 if( lp->glbpseudoobjvalid ) 13703 { 13704 lp->glbpseudoobjval += deltaval; 13705 13706 /* if the absolute value was increased, this is regarded as reliable, 13707 * otherwise, we check whether we can still trust the updated value 13708 */ 13709 if( REALABS(lp->relglbpseudoobjval) < REALABS(lp->glbpseudoobjval) ) 13710 lp->relglbpseudoobjval = lp->glbpseudoobjval; 13711 else if( SCIPsetIsUpdateUnreliable(set, lp->glbpseudoobjval, lp->relglbpseudoobjval) ) 13712 lp->glbpseudoobjvalid = FALSE; 13713 } 13714 } 13715 13716 assert(lp->looseobjvalinf >= 0); 13717 assert(lp->pseudoobjvalinf >= 0); 13718 assert(lp->glbpseudoobjvalinf >= 0); 13719 } 13720 13721 /** updates current pseudo and loose objective values for a change in a variable's objective value or bounds; 13722 * pseudo objective value is calculated with interval arithmetics to get a proved lower bound 13723 */ 13724 static 13725 SCIP_RETCODE lpUpdateVarProved( 13726 SCIP_LP* lp, /**< current LP data */ 13727 SCIP_SET* set, /**< global SCIP settings */ 13728 SCIP_VAR* var, /**< problem variable that changed */ 13729 SCIP_Real oldobj, /**< old objective value of variable */ 13730 SCIP_Real oldlb, /**< old objective value of variable */ 13731 SCIP_Real oldub, /**< old objective value of variable */ 13732 SCIP_Real newobj, /**< new objective value of variable */ 13733 SCIP_Real newlb, /**< new objective value of variable */ 13734 SCIP_Real newub /**< new objective value of variable */ 13735 ) 13736 { 13737 SCIP_INTERVAL deltaval; 13738 SCIP_INTERVAL bd; 13739 SCIP_INTERVAL obj; 13740 SCIP_INTERVAL prod; 13741 SCIP_INTERVAL psval; 13742 int deltainf; 13743 13744 assert(lp != NULL); 13745 assert(lp->pseudoobjvalinf >= 0); 13746 assert(lp->looseobjvalinf >= 0); 13747 assert(!SCIPsetIsInfinity(set, REALABS(oldobj))); 13748 assert(!SCIPsetIsInfinity(set, oldlb)); 13749 assert(!SCIPsetIsInfinity(set, -oldub)); 13750 assert(!SCIPsetIsInfinity(set, REALABS(newobj))); 13751 assert(!SCIPsetIsInfinity(set, newlb)); 13752 assert(!SCIPsetIsInfinity(set, -newub)); 13753 assert(var != NULL); 13754 13755 if( SCIPvarGetStatus(var) != SCIP_VARSTATUS_LOOSE && SCIPvarGetStatus(var) != SCIP_VARSTATUS_COLUMN ) 13756 { 13757 SCIPerrorMessage("LP was informed of an objective change of a non-active variable\n"); 13758 return SCIP_INVALIDDATA; 13759 } 13760 13761 assert(SCIPvarGetProbindex(var) >= 0); 13762 13763 SCIPintervalSet(&deltaval, 0.0); 13764 deltainf = 0; 13765 13766 /* subtract old pseudo objective value */ 13767 if( oldobj > 0.0 ) 13768 { 13769 if( SCIPsetIsInfinity(set, -oldlb) ) 13770 deltainf--; 13771 else 13772 { 13773 SCIPintervalSet(&bd, oldlb); 13774 SCIPintervalSet(&obj, oldobj); 13775 SCIPintervalMul(SCIPsetInfinity(set), &prod, bd, obj); 13776 SCIPintervalSub(SCIPsetInfinity(set), &deltaval, deltaval, prod); /* deltaval -= oldlb * oldobj; */ 13777 } 13778 } 13779 else if( oldobj < 0.0 ) 13780 { 13781 if( SCIPsetIsInfinity(set, oldub) ) 13782 deltainf--; 13783 else 13784 { 13785 SCIPintervalSet(&bd, oldub); 13786 SCIPintervalSet(&obj, oldobj); 13787 SCIPintervalMul(SCIPsetInfinity(set), &prod, bd, obj); 13788 SCIPintervalSub(SCIPsetInfinity(set), &deltaval, deltaval, prod); /* deltaval -= oldub * oldobj; */ 13789 } 13790 } 13791 13792 /* add new pseudo objective value */ 13793 if( newobj > 0.0 ) 13794 { 13795 if( SCIPsetIsInfinity(set, -newlb) ) 13796 deltainf++; 13797 else 13798 { 13799 SCIPintervalSet(&bd, newlb); 13800 SCIPintervalSet(&obj, newobj); 13801 SCIPintervalMul(SCIPsetInfinity(set), &prod, bd, obj); 13802 SCIPintervalAdd(SCIPsetInfinity(set), &deltaval, deltaval, prod); /* deltaval += newlb * newobj; */ 13803 } 13804 } 13805 else if( newobj < 0.0 ) 13806 { 13807 if( SCIPsetIsInfinity(set, newub) ) 13808 deltainf++; 13809 else 13810 { 13811 SCIPintervalSet(&bd, newub); 13812 SCIPintervalSet(&obj, newobj); 13813 SCIPintervalMul(SCIPsetInfinity(set), &prod, bd, obj); 13814 SCIPintervalAdd(SCIPsetInfinity(set), &deltaval, deltaval, prod); /* deltaval += newub * newobj; */ 13815 } 13816 } 13817 13818 /* update the pseudo and loose objective values */ 13819 SCIPintervalSet(&psval, lp->pseudoobjval); 13820 SCIPintervalAdd(SCIPsetInfinity(set), &psval, psval, deltaval); 13821 lp->pseudoobjval = SCIPintervalGetInf(psval); 13822 lp->pseudoobjvalinf += deltainf; 13823 if( SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE ) 13824 { 13825 SCIPintervalSet(&psval, lp->looseobjval); 13826 SCIPintervalAdd(SCIPsetInfinity(set), &psval, psval, deltaval); 13827 lp->looseobjval = SCIPintervalGetInf(psval); 13828 lp->looseobjvalinf += deltainf; 13829 } 13830 13831 assert(lp->pseudoobjvalinf >= 0); 13832 assert(lp->looseobjvalinf >= 0); 13833 13834 return SCIP_OKAY; 13835 } 13836 13837 /** updates current pseudo and loose objective value for a change in a variable's objective coefficient */ 13838 SCIP_RETCODE SCIPlpUpdateVarObj( 13839 SCIP_LP* lp, /**< current LP data */ 13840 SCIP_SET* set, /**< global SCIP settings */ 13841 SCIP_VAR* var, /**< problem variable that changed */ 13842 SCIP_Real oldobj, /**< old objective coefficient of variable */ 13843 SCIP_Real newobj /**< new objective coefficient of variable */ 13844 ) 13845 { 13846 assert(set != NULL); 13847 assert(var != NULL); 13848 13849 if( set->misc_exactsolve ) 13850 { 13851 if( oldobj != newobj ) /*lint !e777*/ 13852 { 13853 SCIP_CALL( lpUpdateVarProved(lp, set, var, oldobj, SCIPvarGetLbLocal(var), SCIPvarGetUbLocal(var), 13854 newobj, SCIPvarGetLbLocal(var), SCIPvarGetUbLocal(var)) ); 13855 } 13856 } 13857 else 13858 { 13859 if( !SCIPsetIsEQ(set, oldobj, newobj) ) 13860 { 13861 SCIP_Real deltaval; 13862 int deltainf; 13863 13864 assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE || SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN); 13865 assert(SCIPvarGetProbindex(var) >= 0); 13866 13867 /* the objective coefficient can only be changed during presolving, that implies that the global and local 13868 * domain of the variable are the same 13869 */ 13870 assert(lp->probing || SCIPsetIsEQ(set, SCIPvarGetLbGlobal(var), SCIPvarGetLbLocal(var))); 13871 assert(lp->probing || SCIPsetIsEQ(set, SCIPvarGetUbGlobal(var), SCIPvarGetUbLocal(var))); 13872 13873 /* compute the pseudo objective delta due the new objective coefficient */ 13874 getObjvalDeltaObj(set, oldobj, newobj, SCIPvarGetLbLocal(var), SCIPvarGetUbLocal(var), &deltaval, &deltainf); 13875 13876 /* update the local pseudo objective value */ 13877 lpUpdateObjval(lp, set, var, deltaval, deltainf, TRUE, FALSE, FALSE); 13878 13879 /* compute the pseudo objective delta due the new objective coefficient */ 13880 getObjvalDeltaObj(set, oldobj, newobj, SCIPvarGetLbGlobal(var), SCIPvarGetUbGlobal(var), &deltaval, &deltainf); 13881 13882 /* update the global pseudo objective value */ 13883 lpUpdateObjval(lp, set, var, deltaval, deltainf, FALSE, FALSE, TRUE); 13884 } 13885 } 13886 13887 return SCIP_OKAY; 13888 } 13889 13890 13891 /** updates current root pseudo objective value for a global change in a variable's lower bound */ 13892 SCIP_RETCODE SCIPlpUpdateVarLbGlobal( 13893 SCIP_LP* lp, /**< current LP data */ 13894 SCIP_SET* set, /**< global SCIP settings */ 13895 SCIP_VAR* var, /**< problem variable that changed */ 13896 SCIP_Real oldlb, /**< old lower bound of variable */ 13897 SCIP_Real newlb /**< new lower bound of variable */ 13898 ) 13899 { 13900 assert(set != NULL); 13901 assert(var != NULL); 13902 13903 if( !SCIPsetIsEQ(set, oldlb, newlb) && SCIPsetIsPositive(set, SCIPvarGetObj(var)) ) 13904 { 13905 SCIP_Real deltaval; 13906 int deltainf; 13907 13908 /* compute the pseudo objective delta due the new lower bound */ 13909 getObjvalDeltaLb(set, SCIPvarGetObj(var), oldlb, newlb, &deltaval, &deltainf); 13910 13911 /* update the root pseudo objective values */ 13912 lpUpdateObjval(lp, set, var, deltaval, deltainf, FALSE, FALSE, TRUE); 13913 } 13914 13915 return SCIP_OKAY; 13916 } 13917 13918 /** updates current pseudo and loose objective value for a change in a variable's lower bound */ 13919 SCIP_RETCODE SCIPlpUpdateVarLb( 13920 SCIP_LP* lp, /**< current LP data */ 13921 SCIP_SET* set, /**< global SCIP settings */ 13922 SCIP_VAR* var, /**< problem variable that changed */ 13923 SCIP_Real oldlb, /**< old lower bound of variable */ 13924 SCIP_Real newlb /**< new lower bound of variable */ 13925 ) 13926 { 13927 assert(set != NULL); 13928 assert(var != NULL); 13929 13930 if( set->misc_exactsolve ) 13931 { 13932 if( oldlb != newlb && SCIPvarGetObj(var) > 0.0 ) /*lint !e777*/ 13933 { 13934 SCIP_CALL( lpUpdateVarProved(lp, set, var, SCIPvarGetObj(var), oldlb, SCIPvarGetUbLocal(var), 13935 SCIPvarGetObj(var), newlb, SCIPvarGetUbLocal(var)) ); 13936 } 13937 } 13938 else 13939 { 13940 if( !SCIPsetIsEQ(set, oldlb, newlb) && SCIPsetIsPositive(set, SCIPvarGetObj(var)) ) 13941 { 13942 SCIP_Real deltaval; 13943 int deltainf; 13944 13945 assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE || SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN); 13946 assert(SCIPvarGetProbindex(var) >= 0); 13947 13948 /* compute the pseudo objective delta due the new lower bound */ 13949 getObjvalDeltaLb(set, SCIPvarGetObj(var), oldlb, newlb, &deltaval, &deltainf); 13950 13951 /* update the pseudo and loose objective values */ 13952 lpUpdateObjval(lp, set, var, deltaval, deltainf, TRUE, FALSE, FALSE); 13953 } 13954 } 13955 13956 return SCIP_OKAY; 13957 } 13958 13959 /** updates current root pseudo objective value for a global change in a variable's upper bound */ 13960 SCIP_RETCODE SCIPlpUpdateVarUbGlobal( 13961 SCIP_LP* lp, /**< current LP data */ 13962 SCIP_SET* set, /**< global SCIP settings */ 13963 SCIP_VAR* var, /**< problem variable that changed */ 13964 SCIP_Real oldub, /**< old upper bound of variable */ 13965 SCIP_Real newub /**< new upper bound of variable */ 13966 ) 13967 { 13968 assert(set != NULL); 13969 assert(var != NULL); 13970 13971 if( !SCIPsetIsEQ(set, oldub, newub) && SCIPsetIsNegative(set, SCIPvarGetObj(var)) ) 13972 { 13973 SCIP_Real deltaval; 13974 int deltainf; 13975 13976 /* compute the pseudo objective delta due the new upper bound */ 13977 getObjvalDeltaUb(set, SCIPvarGetObj(var), oldub, newub, &deltaval, &deltainf); 13978 13979 /* update the root pseudo objective values */ 13980 lpUpdateObjval(lp, set, var, deltaval, deltainf, FALSE, FALSE, TRUE); 13981 } 13982 13983 return SCIP_OKAY; 13984 } 13985 13986 /** updates current pseudo objective value for a change in a variable's upper bound */ 13987 SCIP_RETCODE SCIPlpUpdateVarUb( 13988 SCIP_LP* lp, /**< current LP data */ 13989 SCIP_SET* set, /**< global SCIP settings */ 13990 SCIP_VAR* var, /**< problem variable that changed */ 13991 SCIP_Real oldub, /**< old upper bound of variable */ 13992 SCIP_Real newub /**< new upper bound of variable */ 13993 ) 13994 { 13995 assert(set != NULL); 13996 assert(var != NULL); 13997 13998 if( set->misc_exactsolve ) 13999 { 14000 if( oldub != newub && SCIPvarGetObj(var) < 0.0 ) /*lint !e777*/ 14001 { 14002 SCIP_CALL( lpUpdateVarProved(lp, set, var, SCIPvarGetObj(var), SCIPvarGetLbLocal(var), oldub, 14003 SCIPvarGetObj(var), SCIPvarGetLbLocal(var), newub) ); 14004 } 14005 } 14006 else 14007 { 14008 if( !SCIPsetIsEQ(set, oldub, newub) && SCIPsetIsNegative(set, SCIPvarGetObj(var)) ) 14009 { 14010 SCIP_Real deltaval; 14011 int deltainf; 14012 14013 assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE || SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN); 14014 assert(SCIPvarGetProbindex(var) >= 0); 14015 14016 /* compute the pseudo objective delta due the new upper bound */ 14017 getObjvalDeltaUb(set, SCIPvarGetObj(var), oldub, newub, &deltaval, &deltainf); 14018 14019 /* update the pseudo and loose objective values */ 14020 lpUpdateObjval(lp, set, var, deltaval, deltainf, TRUE, FALSE, FALSE); 14021 } 14022 } 14023 14024 return SCIP_OKAY; 14025 } 14026 14027 /** informs LP, that given variable was added to the problem */ 14028 SCIP_RETCODE SCIPlpUpdateAddVar( 14029 SCIP_LP* lp, /**< current LP data */ 14030 SCIP_SET* set, /**< global SCIP settings */ 14031 SCIP_VAR* var /**< variable that is now a LOOSE problem variable */ 14032 ) 14033 { 14034 assert(lp != NULL); 14035 assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE || SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN); 14036 assert(SCIPvarGetProbindex(var) >= 0); 14037 14038 /* add the variable to the loose objective value sum */ 14039 SCIP_CALL( SCIPlpUpdateVarObj(lp, set, var, 0.0, SCIPvarGetObj(var)) ); 14040 14041 /* update the loose variables counter */ 14042 if( SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE ) 14043 lp->nloosevars++; 14044 14045 return SCIP_OKAY; 14046 } 14047 14048 /** informs LP, that given variable is to be deleted from the problem */ 14049 SCIP_RETCODE SCIPlpUpdateDelVar( 14050 SCIP_LP* lp, /**< current LP data */ 14051 SCIP_SET* set, /**< global SCIP settings */ 14052 SCIP_VAR* var /**< variable that will be deleted from the problem */ 14053 ) 14054 { 14055 assert(lp != NULL); 14056 assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE || SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN); 14057 assert(SCIPvarGetProbindex(var) >= 0); 14058 14059 /* subtract the variable from the loose objective value sum */ 14060 SCIP_CALL( SCIPlpUpdateVarObj(lp, set, var, SCIPvarGetObj(var), 0.0) ); 14061 14062 /* update the loose variables counter */ 14063 if( SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE ) 14064 { 14065 SCIPlpDecNLoosevars(lp); 14066 } 14067 14068 return SCIP_OKAY; 14069 } 14070 14071 /** informs LP, that given formerly loose problem variable is now a column variable */ 14072 static 14073 SCIP_RETCODE lpUpdateVarColumn( 14074 SCIP_LP* lp, /**< current LP data */ 14075 SCIP_SET* set, /**< global SCIP settings */ 14076 SCIP_VAR* var /**< problem variable that changed from LOOSE to COLUMN */ 14077 ) 14078 { 14079 SCIP_Real obj; 14080 SCIP_Real lb; 14081 SCIP_Real ub; 14082 14083 assert(lp != NULL); 14084 assert(lp->nloosevars > 0); 14085 assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN); 14086 assert(SCIPvarGetProbindex(var) >= 0); 14087 assert(lp->looseobjvalinf >= 0); 14088 14089 obj = SCIPvarGetObj(var); 14090 14091 /* update loose objective value */ 14092 if( SCIPsetIsPositive(set, obj) ) 14093 { 14094 lb = SCIPvarGetLbLocal(var); 14095 if( SCIPsetIsInfinity(set, -lb) ) 14096 lp->looseobjvalinf--; 14097 else 14098 lpUpdateObjval(lp, set, var, -lb * obj, 0, FALSE, TRUE, FALSE); 14099 } 14100 else if( SCIPsetIsNegative(set, obj) ) 14101 { 14102 ub = SCIPvarGetUbLocal(var); 14103 if( SCIPsetIsInfinity(set, ub) ) 14104 lp->looseobjvalinf--; 14105 else 14106 lpUpdateObjval(lp, set, var, -ub * obj, 0, FALSE, TRUE, FALSE); 14107 } 14108 14109 SCIPlpDecNLoosevars(lp); 14110 14111 assert(lp->looseobjvalinf >= 0); 14112 14113 return SCIP_OKAY; 14114 } 14115 14116 /** informs LP, that given formerly loose problem variable is now a column variable 14117 * pseudo objective value is calculated with interval arithmetics to get a proved lower bound 14118 */ 14119 static 14120 SCIP_RETCODE lpUpdateVarColumnProved( 14121 SCIP_LP* lp, /**< current LP data */ 14122 SCIP_SET* set, /**< global SCIP settings */ 14123 SCIP_VAR* var /**< problem variable that changed from LOOSE to COLUMN */ 14124 ) 14125 { 14126 SCIP_INTERVAL bd; 14127 SCIP_INTERVAL ob; 14128 SCIP_INTERVAL prod; 14129 SCIP_INTERVAL loose; 14130 SCIP_Real obj; 14131 SCIP_Real lb; 14132 SCIP_Real ub; 14133 14134 assert(lp != NULL); 14135 assert(lp->nloosevars > 0); 14136 assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN); 14137 assert(SCIPvarGetProbindex(var) >= 0); 14138 14139 obj = SCIPvarGetObj(var); 14140 14141 SCIPintervalSet(&loose, lp->looseobjval); 14142 14143 /* update loose objective value corresponding to the deletion of variable */ 14144 if( obj > 0.0 ) 14145 { 14146 lb = SCIPvarGetLbLocal(var); 14147 if( SCIPsetIsInfinity(set, -lb) ) 14148 lp->looseobjvalinf--; 14149 else 14150 { 14151 SCIPintervalSet(&bd, lb); 14152 SCIPintervalSet(&ob, obj); 14153 SCIPintervalMul(SCIPsetInfinity(set), &prod, bd, ob); 14154 SCIPintervalSub(SCIPsetInfinity(set), &loose, loose, prod); /* lp->looseobjval -= lb * obj; */ 14155 } 14156 } 14157 else if( SCIPsetIsNegative(set, obj) ) 14158 { 14159 ub = SCIPvarGetUbLocal(var); 14160 if( SCIPsetIsInfinity(set, ub) ) 14161 lp->looseobjvalinf--; 14162 else 14163 { 14164 SCIPintervalSet(&bd, ub); 14165 SCIPintervalSet(&ob, obj); 14166 SCIPintervalMul(SCIPsetInfinity(set), &prod, bd, ob); 14167 SCIPintervalSub(SCIPsetInfinity(set), &loose, loose, prod); /* lp->looseobjval -= ub * obj; */ 14168 } 14169 } 14170 lp->nloosevars--; 14171 14172 /* get rid of numerical problems: set loose objective value explicitly to zero, if no loose variables remain */ 14173 if( lp->nloosevars == 0 ) 14174 { 14175 assert(lp->looseobjvalinf == 0); 14176 lp->looseobjval = 0.0; 14177 } 14178 else 14179 lp->looseobjval = SCIPintervalGetInf(loose); 14180 14181 return SCIP_OKAY; 14182 } 14183 14184 /** informs LP, that given formerly loose problem variable is now a column variable */ 14185 SCIP_RETCODE SCIPlpUpdateVarColumn( 14186 SCIP_LP* lp, /**< current LP data */ 14187 SCIP_SET* set, /**< global SCIP settings */ 14188 SCIP_VAR* var /**< problem variable that changed from LOOSE to COLUMN */ 14189 ) 14190 { 14191 assert(set != NULL); 14192 14193 if( set->misc_exactsolve ) 14194 { 14195 SCIP_CALL( lpUpdateVarColumnProved(lp, set, var) ); 14196 } 14197 else 14198 { 14199 SCIP_CALL( lpUpdateVarColumn(lp, set, var) ); 14200 } 14201 14202 return SCIP_OKAY; 14203 } 14204 14205 /** informs LP, that given formerly column problem variable is now again a loose variable */ 14206 static 14207 SCIP_RETCODE lpUpdateVarLoose( 14208 SCIP_LP* lp, /**< current LP data */ 14209 SCIP_SET* set, /**< global SCIP settings */ 14210 SCIP_VAR* var /**< problem variable that changed from COLUMN to LOOSE */ 14211 ) 14212 { 14213 SCIP_Real obj; 14214 SCIP_Real lb; 14215 SCIP_Real ub; 14216 14217 assert(lp != NULL); 14218 assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE); 14219 assert(SCIPvarGetProbindex(var) >= 0); 14220 assert(lp->looseobjvalinf >= 0); 14221 14222 obj = SCIPvarGetObj(var); 14223 14224 /* update loose objective value corresponding to the addition of variable */ 14225 if( SCIPsetIsPositive(set, obj) ) 14226 { 14227 lb = SCIPvarGetLbLocal(var); 14228 if( SCIPsetIsInfinity(set, -lb) ) 14229 lp->looseobjvalinf++; 14230 else 14231 lpUpdateObjval(lp, set, var, lb * obj, 0, FALSE, TRUE, FALSE); 14232 } 14233 else if( SCIPsetIsNegative(set, obj) ) 14234 { 14235 ub = SCIPvarGetUbLocal(var); 14236 if( SCIPsetIsInfinity(set, ub) ) 14237 lp->looseobjvalinf++; 14238 else 14239 lpUpdateObjval(lp, set, var, ub * obj, 0, FALSE, TRUE, FALSE); 14240 } 14241 lp->nloosevars++; 14242 14243 assert(lp->looseobjvalinf >= 0); 14244 14245 return SCIP_OKAY; 14246 } 14247 14248 /** informs LP, that given formerly column problem variable is now again a loose variable 14249 * pseudo objective value is calculated with interval arithmetics to get a proved lower bound 14250 */ 14251 static 14252 SCIP_RETCODE lpUpdateVarLooseProved( 14253 SCIP_LP* lp, /**< current LP data */ 14254 SCIP_SET* set, /**< global SCIP settings */ 14255 SCIP_VAR* var /**< problem variable that changed from COLUMN to LOOSE */ 14256 ) 14257 { 14258 SCIP_INTERVAL bd; 14259 SCIP_INTERVAL ob; 14260 SCIP_INTERVAL prod; 14261 SCIP_INTERVAL loose; 14262 SCIP_Real obj; 14263 SCIP_Real lb; 14264 SCIP_Real ub; 14265 14266 assert(lp != NULL); 14267 assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE); 14268 assert(SCIPvarGetProbindex(var) >= 0); 14269 14270 obj = SCIPvarGetObj(var); 14271 14272 SCIPintervalSet(&loose, lp->looseobjval); 14273 14274 /* update loose objective value corresponding to the deletion of variable */ 14275 if( obj > 0.0 ) 14276 { 14277 lb = SCIPvarGetLbLocal(var); 14278 if( SCIPsetIsInfinity(set, -lb) ) 14279 lp->looseobjvalinf++; 14280 else 14281 { 14282 SCIPintervalSet(&bd, lb); 14283 SCIPintervalSet(&ob, obj); 14284 SCIPintervalMul(SCIPsetInfinity(set), &prod, bd, ob); 14285 SCIPintervalAdd(SCIPsetInfinity(set), &loose, loose, prod); /* lp->looseobjval += lb * obj; */ 14286 } 14287 } 14288 else if( SCIPsetIsNegative(set, obj) ) 14289 { 14290 ub = SCIPvarGetUbLocal(var); 14291 if( SCIPsetIsInfinity(set, ub) ) 14292 lp->looseobjvalinf++; 14293 else 14294 { 14295 SCIPintervalSet(&bd, ub); 14296 SCIPintervalSet(&ob, obj); 14297 SCIPintervalMul(SCIPsetInfinity(set), &prod, bd, ob); 14298 SCIPintervalAdd(SCIPsetInfinity(set), &loose, loose, prod); /* lp->looseobjval += ub * obj; */ 14299 } 14300 } 14301 lp->nloosevars++; 14302 14303 lp->looseobjval = SCIPintervalGetInf(loose); 14304 14305 return SCIP_OKAY; 14306 } 14307 14308 /** informs LP, that given formerly column problem variable is now again a loose variable */ 14309 SCIP_RETCODE SCIPlpUpdateVarLoose( 14310 SCIP_LP* lp, /**< current LP data */ 14311 SCIP_SET* set, /**< global SCIP settings */ 14312 SCIP_VAR* var /**< problem variable that changed from COLUMN to LOOSE */ 14313 ) 14314 { 14315 assert(set != NULL); 14316 14317 if( set->misc_exactsolve ) 14318 { 14319 SCIP_CALL( lpUpdateVarLooseProved(lp, set, var) ); 14320 } 14321 else 14322 { 14323 SCIP_CALL( lpUpdateVarLoose(lp, set, var) ); 14324 } 14325 14326 return SCIP_OKAY; 14327 } 14328 14329 /** decrease the number of loose variables by one */ 14330 void SCIPlpDecNLoosevars( 14331 SCIP_LP* lp /**< current LP data */ 14332 ) 14333 { 14334 assert(lp != NULL); 14335 assert(lp->nloosevars > 0); 14336 14337 lp->nloosevars--; 14338 14339 /* get rid of numerical problems: set loose objective value explicitly to zero, if no loose variables remain */ 14340 if( lp->nloosevars == 0 ) 14341 { 14342 assert(lp->looseobjvalinf == 0); 14343 lp->looseobjval = 0.0; 14344 } 14345 } 14346 14347 /** stores the LP solution in the columns and rows */ 14348 SCIP_RETCODE SCIPlpGetSol( 14349 SCIP_LP* lp, /**< current LP data */ 14350 SCIP_SET* set, /**< global SCIP settings */ 14351 SCIP_STAT* stat, /**< problem statistics */ 14352 SCIP_Bool* primalfeasible, /**< pointer to store whether the solution is primal feasible, or NULL */ 14353 SCIP_Bool* dualfeasible /**< pointer to store whether the solution is dual feasible, or NULL */ 14354 ) 14355 { 14356 SCIP_COL** lpicols; 14357 SCIP_ROW** lpirows; 14358 SCIP_Real* primsol; 14359 SCIP_Real* dualsol; 14360 SCIP_Real* activity = NULL; 14361 SCIP_Real* redcost; 14362 SCIP_Real primalbound; 14363 SCIP_Real dualbound; 14364 SCIP_Bool stillprimalfeasible; 14365 SCIP_Bool stilldualfeasible; 14366 int* cstat; 14367 int* rstat; 14368 SCIP_Longint lpcount; 14369 int nlpicols; 14370 int nlpirows; 14371 int c; 14372 int r; 14373 14374 assert(lp != NULL); 14375 assert(lp->flushed); 14376 assert(lp->solved); 14377 assert(set != NULL); 14378 assert(stat != NULL); 14379 assert(lp->validsollp <= stat->lpcount); 14380 14381 assert(lp->lpsolstat == SCIP_LPSOLSTAT_OPTIMAL); 14382 14383 /* initialize return and feasibility flags; if primal oder dual feasibility shall not be checked, we set the 14384 * corresponding flag immediately to FALSE to skip all checks 14385 */ 14386 if( primalfeasible == NULL ) 14387 stillprimalfeasible = FALSE; 14388 else 14389 { 14390 *primalfeasible = TRUE; 14391 stillprimalfeasible = TRUE; 14392 } 14393 if( dualfeasible == NULL ) 14394 stilldualfeasible = FALSE; 14395 else 14396 { 14397 *dualfeasible = TRUE; 14398 stilldualfeasible = TRUE; 14399 } 14400 14401 /* check if the values are already calculated */ 14402 if( lp->validsollp == stat->lpcount ) 14403 return SCIP_OKAY; 14404 lp->validsollp = stat->lpcount; 14405 14406 SCIPsetDebugMsg(set, "getting new LP solution %" SCIP_LONGINT_FORMAT " for solstat %d\n", 14407 stat->lpcount, SCIPlpGetSolstat(lp)); 14408 14409 lpicols = lp->lpicols; 14410 lpirows = lp->lpirows; 14411 nlpicols = lp->nlpicols; 14412 nlpirows = lp->nlpirows; 14413 lpcount = stat->lpcount; 14414 14415 /* get temporary memory */ 14416 SCIP_CALL( SCIPsetAllocBufferArray(set, &primsol, nlpicols) ); 14417 SCIP_CALL( SCIPsetAllocBufferArray(set, &dualsol, nlpirows) ); 14418 #ifdef SCIP_USE_LPSOLVER_ACTIVITY 14419 SCIP_CALL( SCIPsetAllocBufferArray(set, &activity, nlpirows) ); 14420 #endif 14421 SCIP_CALL( SCIPsetAllocBufferArray(set, &redcost, nlpicols) ); 14422 SCIP_CALL( SCIPsetAllocBufferArray(set, &cstat, nlpicols) ); 14423 SCIP_CALL( SCIPsetAllocBufferArray(set, &rstat, nlpirows) ); 14424 14425 SCIP_CALL( SCIPlpiGetSol(lp->lpi, NULL, primsol, dualsol, activity, redcost) ); 14426 if( lp->solisbasic ) 14427 { 14428 SCIP_CALL( SCIPlpiGetBase(lp->lpi, cstat, rstat) ); 14429 } 14430 else 14431 { 14432 BMSclearMemoryArray(cstat, nlpicols); 14433 BMSclearMemoryArray(rstat, nlpirows); 14434 } 14435 14436 primalbound = 0.0; 14437 dualbound = 0.0; 14438 14439 /* copy primal solution and reduced costs into columns */ 14440 for( c = 0; c < nlpicols; ++c ) 14441 { 14442 assert( 0 <= cstat[c] && cstat[c] < 4 ); 14443 lpicols[c]->primsol = primsol[c]; 14444 if( !SCIPisFinite(lpicols[c]->primsol) ) 14445 { 14446 /* calculating with nan or +/-inf can have many unexpected effects 14447 * thus change the solution here to a reasonable value (0.0) and declare it as neither primal nor dual feasible 14448 * this should trigger a resolve of the LP, or a stop with an LP error 14449 */ 14450 stillprimalfeasible = FALSE; 14451 stilldualfeasible = FALSE; 14452 lpicols[c]->primsol = 0.0; 14453 SCIPsetDebugMsg(set, " col <%s>: primsol=%.9f is not finite\n", SCIPvarGetName(lpicols[c]->var), primsol[c]); 14454 } 14455 lpicols[c]->minprimsol = MIN(lpicols[c]->minprimsol, primsol[c]); 14456 lpicols[c]->maxprimsol = MAX(lpicols[c]->maxprimsol, primsol[c]); 14457 lpicols[c]->redcost = redcost[c]; 14458 lpicols[c]->basisstatus = (unsigned int) cstat[c]; 14459 lpicols[c]->validredcostlp = lpcount; 14460 if( stillprimalfeasible ) 14461 { 14462 stillprimalfeasible = 14463 (SCIPsetIsInfinity(set, -lpicols[c]->lb) || SCIPlpIsFeasGE(set, lp, lpicols[c]->primsol, lpicols[c]->lb)) 14464 && (SCIPsetIsInfinity(set, lpicols[c]->ub) || SCIPlpIsFeasLE(set, lp, lpicols[c]->primsol, lpicols[c]->ub)); 14465 primalbound += (lpicols[c]->primsol * lpicols[c]->obj); 14466 } 14467 if( lp->lastlpalgo == SCIP_LPALGO_BARRIER ) 14468 { 14469 double compslack; 14470 14471 /* complementary slackness in barrier solutions is measured as product of primal slack and dual multiplier; 14472 * we use a slack of at most 1, because otherwise we multiply by something like SCIPinfinty() for unbounded 14473 * variables, which would magnify even the tiniest violation in the dual multiplier 14474 */ 14475 if( stilldualfeasible ) 14476 { 14477 compslack = MIN((lpicols[c]->primsol - lpicols[c]->lb), 1.0) * lpicols[c]->redcost; 14478 stilldualfeasible = !SCIPsetIsDualfeasPositive(set, compslack); 14479 } 14480 if( stilldualfeasible ) 14481 { 14482 compslack = MIN((lpicols[c]->ub - lpicols[c]->primsol), 1.0) * lpicols[c]->redcost; 14483 stilldualfeasible = !SCIPsetIsDualfeasNegative(set, compslack); 14484 } 14485 14486 SCIPsetDebugMsg(set, " col <%s> [%.9g,%.9g]: primsol=%.9f, redcost=%.9f, pfeas=%u/%u(%u), dfeas=%d/%d(%u)\n", 14487 SCIPvarGetName(lpicols[c]->var), lpicols[c]->lb, lpicols[c]->ub, lpicols[c]->primsol, lpicols[c]->redcost, 14488 SCIPlpIsFeasGE(set, lp, lpicols[c]->primsol, lpicols[c]->lb), 14489 SCIPlpIsFeasLE(set, lp, lpicols[c]->primsol, lpicols[c]->ub), 14490 primalfeasible != NULL ? stillprimalfeasible : TRUE, 14491 !SCIPsetIsDualfeasPositive(set, MIN((lpicols[c]->primsol - lpicols[c]->lb), 1.0) * lpicols[c]->redcost), 14492 !SCIPsetIsDualfeasNegative(set, MIN((lpicols[c]->ub - lpicols[c]->primsol), 1.0) * lpicols[c]->redcost), 14493 dualfeasible != NULL ? stilldualfeasible : TRUE); 14494 } 14495 else 14496 { 14497 /* if dual feasibility check is disabled, set reduced costs of basic variables to 0 */ 14498 if( dualfeasible == NULL && lpicols[c]->basisstatus == (unsigned int) SCIP_BASESTAT_BASIC ) 14499 { 14500 lpicols[c]->redcost = 0.0; 14501 } 14502 14503 /* complementary slackness means that if a variable is not at its lower or upper bound, its reduced costs 14504 * must be non-positive or non-negative, respectively; in particular, if a variable is strictly within its 14505 * bounds, its reduced cost must be zero 14506 */ 14507 if( stilldualfeasible 14508 && (SCIPsetIsInfinity(set, -lpicols[c]->lb) || SCIPlpIsFeasGT(set, lp, lpicols[c]->primsol, lpicols[c]->lb)) ) 14509 stilldualfeasible = !SCIPsetIsDualfeasPositive(set, lpicols[c]->redcost); 14510 if( stilldualfeasible 14511 && (SCIPsetIsInfinity(set, lpicols[c]->ub) || SCIPlpIsFeasLT(set, lp, lpicols[c]->primsol, lpicols[c]->ub)) ) 14512 stilldualfeasible = !SCIPsetIsDualfeasNegative(set, lpicols[c]->redcost); 14513 14514 SCIPsetDebugMsg(set, " col <%s> [%.9g,%.9g]: primsol=%.9f, redcost=%.9f, pfeas=%u/%u(%u), dfeas=%d/%d(%u)\n", 14515 SCIPvarGetName(lpicols[c]->var), lpicols[c]->lb, lpicols[c]->ub, lpicols[c]->primsol, lpicols[c]->redcost, 14516 SCIPlpIsFeasGE(set, lp, lpicols[c]->primsol, lpicols[c]->lb), 14517 SCIPlpIsFeasLE(set, lp, lpicols[c]->primsol, lpicols[c]->ub), 14518 primalfeasible != NULL ? stillprimalfeasible : TRUE, 14519 !SCIPlpIsFeasGT(set, lp, lpicols[c]->primsol, lpicols[c]->lb) || !SCIPsetIsDualfeasPositive(set, lpicols[c]->redcost), 14520 !SCIPlpIsFeasLT(set, lp, lpicols[c]->primsol, lpicols[c]->ub) || !SCIPsetIsDualfeasNegative(set, lpicols[c]->redcost), 14521 dualfeasible != NULL ? stilldualfeasible : TRUE); 14522 } 14523 14524 /* we intentionally use an exact positive/negative check because ignoring small reduced cost values may lead to a 14525 * wrong bound value; if the corresponding bound is +/-infinity, we use zero reduced cost (if stilldualfeasible is 14526 * TRUE, we are in the case that the reduced cost is tiny with wrong sign) 14527 */ 14528 if( stilldualfeasible ) 14529 { 14530 if( lpicols[c]->redcost > 0.0 && !SCIPsetIsInfinity(set, -lpicols[c]->lb) ) 14531 dualbound += (lpicols[c]->redcost * lpicols[c]->lb); 14532 else if( lpicols[c]->redcost < 0.0 && !SCIPsetIsInfinity(set, lpicols[c]->ub) ) 14533 dualbound += (lpicols[c]->redcost * lpicols[c]->ub); 14534 } 14535 } 14536 14537 /* copy dual solution and activities into rows */ 14538 for( r = 0; r < nlpirows; ++r ) 14539 { 14540 assert( 0 <= rstat[r] && rstat[r] < 4 ); 14541 lpirows[r]->dualsol = dualsol[r]; 14542 #ifdef SCIP_USE_LPSOLVER_ACTIVITY 14543 lpirows[r]->activity = activity[r] + lpirows[r]->constant; 14544 #else 14545 /* calculate row activity if invalid */ 14546 if( lpirows[r]->validactivitylp != stat->lpcount ) 14547 SCIProwRecalcLPActivity(lpirows[r], stat); 14548 #endif 14549 lpirows[r]->basisstatus = (unsigned int) rstat[r]; /*lint !e732*/ 14550 lpirows[r]->validactivitylp = lpcount; 14551 if( stillprimalfeasible ) 14552 { 14553 stillprimalfeasible = 14554 (SCIPsetIsInfinity(set, -lpirows[r]->lhs) || SCIPlpIsFeasGE(set, lp, lpirows[r]->activity, lpirows[r]->lhs)) 14555 && (SCIPsetIsInfinity(set, lpirows[r]->rhs) || SCIPlpIsFeasLE(set, lp, lpirows[r]->activity, lpirows[r]->rhs)); 14556 } 14557 if( lp->lastlpalgo == SCIP_LPALGO_BARRIER ) 14558 { 14559 double compslack; 14560 14561 /* complementary slackness in barrier solutions is measured as product of primal slack and dual multiplier; 14562 * we use a slack of at most 1, because otherwise we multiply by something like SCIPinfinity() for unbounded 14563 * variables, which would magnify even the tiniest violation in the dual multiplier 14564 */ 14565 if( stilldualfeasible ) 14566 { 14567 compslack = MIN((lpirows[r]->activity - lpirows[r]->lhs), 1.0) * lpirows[r]->dualsol; 14568 stilldualfeasible = !SCIPsetIsDualfeasPositive(set, compslack); 14569 } 14570 if( stilldualfeasible ) 14571 { 14572 compslack = MIN((lpirows[r]->rhs - lpirows[r]->activity), 1.0) * lpirows[r]->dualsol; 14573 stilldualfeasible = !SCIPsetIsDualfeasNegative(set, compslack); 14574 } 14575 14576 SCIPsetDebugMsg(set, " row <%s> [%.9g,%.9g]: activity=%.9f, dualsol=%.9f, pfeas=%u/%u(%u), dfeas=%d/%d(%u)\n", 14577 lpirows[r]->name, lpirows[r]->lhs, lpirows[r]->rhs, lpirows[r]->activity, lpirows[r]->dualsol, 14578 SCIPlpIsFeasGE(set, lp, lpirows[r]->activity, lpirows[r]->lhs), 14579 SCIPlpIsFeasLE(set, lp, lpirows[r]->activity, lpirows[r]->rhs), 14580 primalfeasible != NULL ? stillprimalfeasible : TRUE, 14581 !SCIPsetIsDualfeasPositive(set, MIN((lpirows[r]->activity - lpirows[r]->lhs), 1.0) * lpirows[r]->dualsol), 14582 !SCIPsetIsDualfeasNegative(set, MIN((lpirows[r]->rhs - lpirows[r]->activity), 1.0) * lpirows[r]->dualsol), 14583 dualfeasible != NULL ? stilldualfeasible : TRUE); 14584 } 14585 else 14586 { 14587 /* complementary slackness means that if the activity of a row is not at its left-hand or right-hand side, 14588 * its dual multiplier must be non-positive or non-negative, respectively; in particular, if the activity is 14589 * strictly within left-hand and right-hand side, its dual multiplier must be zero 14590 */ 14591 if( stilldualfeasible && 14592 (SCIPsetIsInfinity(set, -lpirows[r]->lhs) || SCIPlpIsFeasGT(set, lp, lpirows[r]->activity, lpirows[r]->lhs)) ) 14593 stilldualfeasible = !SCIPsetIsDualfeasPositive(set, lpirows[r]->dualsol); 14594 if( stilldualfeasible && 14595 (SCIPsetIsInfinity(set,lpirows[r]->rhs) || SCIPlpIsFeasLT(set, lp, lpirows[r]->activity, lpirows[r]->rhs)) ) 14596 stilldualfeasible = !SCIPsetIsDualfeasNegative(set, lpirows[r]->dualsol); 14597 14598 SCIPsetDebugMsg(set, " row <%s> [%.9g,%.9g] + %.9g: activity=%.9f, dualsol=%.9f, pfeas=%u/%u(%u), dfeas=%d/%d(%u)\n", 14599 lpirows[r]->name, lpirows[r]->lhs, lpirows[r]->rhs, lpirows[r]->constant, lpirows[r]->activity, lpirows[r]->dualsol, 14600 SCIPlpIsFeasGE(set, lp, lpirows[r]->activity, lpirows[r]->lhs), 14601 SCIPlpIsFeasLE(set, lp, lpirows[r]->activity, lpirows[r]->rhs), 14602 primalfeasible != NULL ? stillprimalfeasible : TRUE, 14603 !SCIPlpIsFeasGT(set, lp, lpirows[r]->activity, lpirows[r]->lhs) || !SCIPsetIsDualfeasPositive(set, lpirows[r]->dualsol), 14604 !SCIPlpIsFeasLT(set, lp, lpirows[r]->activity, lpirows[r]->rhs) || !SCIPsetIsDualfeasNegative(set, lpirows[r]->dualsol), 14605 dualfeasible != NULL ? stilldualfeasible : TRUE); 14606 } 14607 14608 /* we intentionally use an exact positive/negative check because ignoring small dual multipliers may lead to a 14609 * wrong bound value; if the corresponding side is +/-infinity, we use a zero dual multiplier (if 14610 * stilldualfeasible is TRUE, we are in the case that the dual multiplier is tiny with wrong sign) 14611 */ 14612 if( stilldualfeasible ) 14613 { 14614 if( lpirows[r]->dualsol > 0.0 && !SCIPsetIsInfinity(set, -lpirows[r]->lhs) ) 14615 dualbound += (lpirows[r]->dualsol * (lpirows[r]->lhs - lpirows[r]->constant)); 14616 else if( lpirows[r]->dualsol < 0.0 && !SCIPsetIsInfinity(set, lpirows[r]->rhs) ) 14617 dualbound += (lpirows[r]->dualsol * (lpirows[r]->rhs - lpirows[r]->constant)); 14618 } 14619 } 14620 14621 /* if the objective value returned by the LP solver is smaller than the internally computed primal bound, then we 14622 * declare the solution primal infeasible; we assume primalbound and lp->lpobjval to be equal if they are both +/- 14623 * infinity 14624 */ 14625 /**@todo alternatively, if otherwise the LP solution is feasible, we could simply update the objective value */ 14626 if( stillprimalfeasible && !(SCIPsetIsInfinity(set, primalbound) && SCIPsetIsInfinity(set, lp->lpobjval)) 14627 && !(SCIPsetIsInfinity(set, -primalbound) && SCIPsetIsInfinity(set, -lp->lpobjval)) ) 14628 { 14629 stillprimalfeasible = SCIPsetIsFeasLE(set, primalbound, lp->lpobjval); 14630 SCIPsetDebugMsg(set, " primalbound=%.9f, lpbound=%.9g, pfeas=%u(%u)\n", primalbound, lp->lpobjval, 14631 SCIPsetIsFeasLE(set, primalbound, lp->lpobjval), primalfeasible != NULL ? stillprimalfeasible : TRUE); 14632 } 14633 14634 /* if the objective value returned by the LP solver is smaller than the internally computed dual bound, we declare 14635 * the solution dual infeasible; we assume dualbound and lp->lpobjval to be equal if they are both +/- infinity 14636 */ 14637 /**@todo alternatively, if otherwise the LP solution is feasible, we could simply update the objective value */ 14638 if( stilldualfeasible && !(SCIPsetIsInfinity(set, dualbound) && SCIPsetIsInfinity(set, lp->lpobjval)) 14639 && !(SCIPsetIsInfinity(set, -dualbound) && SCIPsetIsInfinity(set, -lp->lpobjval)) ) 14640 { 14641 stilldualfeasible = SCIPsetIsFeasGE(set, dualbound, lp->lpobjval); 14642 SCIPsetDebugMsg(set, " dualbound=%.9f, lpbound=%.9g, dfeas=%u(%u)\n", dualbound, lp->lpobjval, 14643 SCIPsetIsFeasGE(set, dualbound, lp->lpobjval), dualfeasible != NULL ? stilldualfeasible : TRUE); 14644 } 14645 14646 if( primalfeasible != NULL ) 14647 *primalfeasible = stillprimalfeasible; 14648 if( dualfeasible != NULL ) 14649 *dualfeasible = stilldualfeasible; 14650 14651 /* free temporary memory */ 14652 SCIPsetFreeBufferArray(set, &rstat); 14653 SCIPsetFreeBufferArray(set, &cstat); 14654 SCIPsetFreeBufferArray(set, &redcost); 14655 #ifdef SCIP_USE_LPSOLVER_ACTIVITY 14656 SCIPsetFreeBufferArray(set, &activity); 14657 #endif 14658 SCIPsetFreeBufferArray(set, &dualsol); 14659 SCIPsetFreeBufferArray(set, &primsol); 14660 14661 return SCIP_OKAY; 14662 } 14663 14664 /** stores LP solution with infinite objective value in the columns and rows */ 14665 SCIP_RETCODE SCIPlpGetUnboundedSol( 14666 SCIP_LP* lp, /**< current LP data */ 14667 SCIP_SET* set, /**< global SCIP settings */ 14668 SCIP_STAT* stat, /**< problem statistics */ 14669 SCIP_Bool* primalfeasible, /**< pointer to store whether the solution is primal feasible, or NULL */ 14670 SCIP_Bool* rayfeasible /**< pointer to store whether the primal ray is a feasible unboundedness proof, or NULL */ 14671 ) 14672 { 14673 SCIP_COL** lpicols; 14674 SCIP_ROW** lpirows; 14675 SCIP_Real* primsol; 14676 SCIP_Real* activity; 14677 SCIP_Real* ray; 14678 SCIP_Real rayobjval; 14679 SCIP_Real rayscale; 14680 SCIP_Longint lpcount; 14681 SCIP_COL* col; 14682 int nlpicols; 14683 int nlpirows; 14684 int c; 14685 int r; 14686 14687 assert(lp != NULL); 14688 assert(lp->flushed); 14689 assert(lp->solved); 14690 assert(lp->lpsolstat == SCIP_LPSOLSTAT_UNBOUNDEDRAY); 14691 assert(SCIPsetIsInfinity(set, -lp->lpobjval)); 14692 assert(set != NULL); 14693 assert(stat != NULL); 14694 assert(lp->validsollp <= stat->lpcount); 14695 14696 if( primalfeasible != NULL ) 14697 *primalfeasible = TRUE; 14698 if( rayfeasible != NULL ) 14699 *rayfeasible = TRUE; 14700 14701 /* check if the values are already calculated */ 14702 if( lp->validsollp == stat->lpcount ) 14703 return SCIP_OKAY; 14704 lp->validsollp = stat->lpcount; 14705 14706 /* check if the LP solver is able to provide a primal unbounded ray */ 14707 if( !SCIPlpiHasPrimalRay(lp->lpi) ) 14708 { 14709 SCIPerrorMessage("LP solver has no primal ray to prove unboundedness.\n"); 14710 return SCIP_LPERROR; 14711 } 14712 14713 SCIPsetDebugMsg(set, "getting new unbounded LP solution %" SCIP_LONGINT_FORMAT "\n", stat->lpcount); 14714 14715 /* get temporary memory */ 14716 SCIP_CALL( SCIPsetAllocBufferArray(set, &primsol, lp->nlpicols) ); 14717 SCIP_CALL( SCIPsetAllocBufferArray(set, &activity, lp->nlpirows) ); 14718 SCIP_CALL( SCIPsetAllocBufferArray(set, &ray, lp->nlpicols) ); 14719 14720 /* get primal unbounded ray */ 14721 SCIP_CALL( SCIPlpiGetPrimalRay(lp->lpi, ray) ); 14722 14723 lpicols = lp->lpicols; 14724 lpirows = lp->lpirows; 14725 nlpicols = lp->nlpicols; 14726 nlpirows = lp->nlpirows; 14727 lpcount = stat->lpcount; 14728 14729 /* calculate the objective value decrease of the ray and heuristically try to construct primal solution */ 14730 rayobjval = 0.0; 14731 for( c = 0; c < nlpicols; ++c ) 14732 { 14733 assert(lpicols[c] != NULL); 14734 assert(lpicols[c]->var != NULL); 14735 14736 col = lpicols[c]; 14737 14738 /* there should only be a nonzero value in the ray if there is no finite bound in this direction */ 14739 if( rayfeasible != NULL ) 14740 { 14741 *rayfeasible = *rayfeasible 14742 && (!SCIPsetIsNegative(set, ray[c]) || SCIPsetIsInfinity(set, -col->lb)) 14743 && (!SCIPsetIsPositive(set, ray[c]) || SCIPsetIsInfinity(set, col->ub)); 14744 } 14745 14746 if( ! SCIPsetIsZero(set, ray[c]) ) 14747 rayobjval += ray[c] * col->obj; 14748 14749 /* Many LP solvers cannot directly provide a feasible solution if they detected unboundedness. We therefore first 14750 * heuristically try to construct a primal solution. 14751 */ 14752 primsol[c] = 0.0; 14753 if( SCIPsetIsFeasZero(set, ray[c]) ) 14754 { 14755 /* if the ray component is 0, we try to satisfy as many rows as possible */ 14756 if( SCIPvarGetNLocksDown(col->var) == 0 && ! SCIPsetIsInfinity(set, -col->lb) ) 14757 primsol[c] = col->lb; 14758 else if( SCIPvarGetNLocksUp(col->var) == 0 && ! SCIPsetIsInfinity(set, col->ub) ) 14759 primsol[c] = col->ub; 14760 } 14761 14762 /* make sure we respect the bounds */ 14763 primsol[c] = MAX(primsol[c], col->lb); 14764 primsol[c] = MIN(primsol[c], col->ub); 14765 14766 assert( SCIPlpIsFeasGE(set, lp, primsol[c], col->lb) && SCIPlpIsFeasLE(set, lp, primsol[c], col->ub) ); 14767 } 14768 14769 /* check feasibility of heuristic primal solution */ 14770 for( r = 0; r < nlpirows; ++r ) 14771 { 14772 SCIP_Real act; 14773 SCIP_ROW* row; 14774 14775 row = lpirows[r]; 14776 assert( row != NULL ); 14777 act = row->constant; 14778 14779 for( c = 0; c < row->nlpcols; ++c ) 14780 { 14781 col = row->cols[c]; 14782 14783 assert( col != NULL ); 14784 assert( col->lppos >= 0 ); 14785 assert( row->linkpos[c] >= 0 ); 14786 assert( primsol[col->lppos] != SCIP_INVALID ); /*lint !e777*/ 14787 14788 act += row->vals[c] * primsol[col->lppos]; 14789 } 14790 14791 if( row->nunlinked > 0 ) 14792 { 14793 for( c = row->nlpcols; c < row->len; ++c ) 14794 { 14795 col = row->cols[c]; 14796 assert( col != NULL ); 14797 14798 if( col->lppos >= 0 ) 14799 act += row->vals[c] * primsol[col->lppos]; 14800 } 14801 } 14802 14803 /* check feasibility */ 14804 if( (! SCIPsetIsInfinity(set, -row->lhs) && SCIPlpIsFeasLT(set, lp, act, row->lhs) ) || 14805 (! SCIPsetIsInfinity(set, row->rhs) && SCIPlpIsFeasGT(set, lp, act, row->rhs) ) ) 14806 break; 14807 } 14808 14809 /* if heuristic primal solution is not feasible, try to obtain solution from LPI */ 14810 if( r < nlpirows ) 14811 { 14812 /* get primal feasible point */ 14813 SCIP_CALL( SCIPlpiGetSol(lp->lpi, NULL, primsol, NULL, NULL, NULL) ); 14814 14815 /* check bounds of primal solution */ 14816 if( primalfeasible != NULL ) 14817 { 14818 assert( *primalfeasible ); 14819 for( c = 0; c < nlpicols; ++c ) 14820 { 14821 assert( lpicols[c] != NULL ); 14822 assert( lpicols[c]->var != NULL ); 14823 14824 /* check whether primal solution satisfies the bounds; note that we also ensure that the primal 14825 * solution is within SCIP's infinity bounds; otherwise the rayscale below is not well-defined */ 14826 if( SCIPsetIsInfinity(set, REALABS(primsol[c])) || SCIPlpIsFeasLT(set, lp, primsol[c], lpicols[c]->lb) || 14827 SCIPlpIsFeasGT(set, lp, primsol[c], lpicols[c]->ub) ) 14828 { 14829 *primalfeasible = FALSE; 14830 break; 14831 } 14832 } 14833 } 14834 } 14835 14836 /* compute activity and check feasibility of primal solution and ray */ 14837 for( r = 0; r < nlpirows; ++r ) 14838 { 14839 SCIP_Real primact; 14840 SCIP_Real rayact = 0.0; 14841 SCIP_ROW* row; 14842 14843 row = lpirows[r]; 14844 assert( row != NULL ); 14845 14846 primact = row->constant; 14847 14848 for( c = 0; c < row->nlpcols; ++c ) 14849 { 14850 col = row->cols[c]; 14851 14852 assert( col != NULL ); 14853 assert( col->lppos >= 0 ); 14854 assert( row->linkpos[c] >= 0 ); 14855 assert( primsol[col->lppos] != SCIP_INVALID ); /*lint !e777*/ 14856 14857 primact += row->vals[c] * primsol[col->lppos]; 14858 rayact += row->vals[c] * ray[col->lppos]; 14859 } 14860 14861 if( row->nunlinked > 0 ) 14862 { 14863 for( c = row->nlpcols; c < row->len; ++c ) 14864 { 14865 col = row->cols[c]; 14866 assert( col != NULL ); 14867 14868 if( col->lppos >= 0 ) 14869 { 14870 primact += row->vals[c] * primsol[col->lppos]; 14871 rayact += row->vals[c] * ray[col->lppos]; 14872 } 14873 } 14874 } 14875 14876 /* check feasibility of primal solution */ 14877 if( primalfeasible != NULL && *primalfeasible ) 14878 { 14879 if(( ! SCIPsetIsInfinity(set, -row->lhs) && SCIPlpIsFeasLT(set, lp, primact, row->lhs) ) || 14880 ( ! SCIPsetIsInfinity(set, row->rhs) && SCIPlpIsFeasGT(set, lp, primact, row->rhs) ) ) 14881 *primalfeasible = FALSE; 14882 } 14883 14884 /* check feasibility of ray */ 14885 if( rayfeasible != NULL && *rayfeasible ) 14886 { 14887 if(( ! SCIPsetIsInfinity(set, -row->lhs) && SCIPlpIsFeasLT(set, lp, rayact, 0.0) ) || 14888 ( ! SCIPsetIsInfinity(set, row->rhs) && SCIPlpIsFeasGT(set, lp, rayact, 0.0) ) ) 14889 *rayfeasible = FALSE; 14890 } 14891 14892 /* store activity of primal solution */ 14893 activity[r] = primact; 14894 } 14895 14896 if( primalfeasible != NULL && !(*primalfeasible) ) 14897 { 14898 /* if the finite point is already infeasible, we do not have to add the ray */ 14899 rayscale = 0.0; 14900 } 14901 else if( rayfeasible != NULL && !(*rayfeasible) ) 14902 { 14903 /* if the ray is already infeasible (due to numerics), we do not want to add the ray */ 14904 rayscale = 0.0; 14905 } 14906 else if( !SCIPsetIsNegative(set, rayobjval) ) 14907 { 14908 /* due to numerical problems, the objective of the ray might be nonnegative 14909 * 14910 * @todo How to check for negative objective value here? 14911 */ 14912 if( rayfeasible != NULL ) 14913 *rayfeasible = FALSE; 14914 14915 rayscale = 0.0; 14916 } 14917 else 14918 { 14919 assert(rayobjval != 0.0); 14920 14921 /* scale the ray, such that the resulting point has infinite objective value */ 14922 rayscale = -2.0 * SCIPsetInfinity(set) / rayobjval; 14923 assert(SCIPsetIsFeasPositive(set, rayscale)); 14924 14925 /* ensure that unbounded point does not violate the bounds of the variables */ 14926 for( c = 0; c < nlpicols; ++c ) 14927 { 14928 if( SCIPsetIsPositive(set, ray[c]) ) 14929 { 14930 if( !SCIPsetIsInfinity(set, primsol[c]) ) 14931 rayscale = MIN(rayscale, (lpicols[c]->ub - primsol[c]) / ray[c]); 14932 /* if primsol is infinity, as well as the bound, don't scale the ray to 0 */ 14933 else 14934 { 14935 assert(SCIPsetIsInfinity(set, lpicols[c]->ub)); 14936 rayscale = MIN(rayscale, 1.0 / ray[c]); 14937 } 14938 } 14939 else if( SCIPsetIsNegative(set, ray[c]) ) 14940 { 14941 if( !SCIPsetIsInfinity(set, -primsol[c]) ) 14942 rayscale = MIN(rayscale, (lpicols[c]->lb - primsol[c]) / ray[c]); 14943 /* if primsol is infinity, as well as the bound, don't scale the ray to 0 */ 14944 else 14945 { 14946 assert(SCIPsetIsInfinity(set, -lpicols[c]->lb)); 14947 rayscale = MIN(rayscale, -1.0 / ray[c]); 14948 } 14949 } 14950 14951 assert(SCIPsetIsFeasPositive(set, rayscale)); 14952 } 14953 } 14954 14955 SCIPsetDebugMsg(set, "unbounded LP solution: rayobjval=%f, rayscale=%f\n", rayobjval, rayscale); 14956 14957 /* calculate the unbounded point: x' = x + rayscale * ray */ 14958 /* Note: We do not check the feasibility of the unbounded solution, because it will likely be infeasible due to the 14959 * typically large values in scaling. */ 14960 for( c = 0; c < nlpicols; ++c ) 14961 { 14962 if( SCIPsetIsZero(set, ray[c]) ) 14963 lpicols[c]->primsol = primsol[c]; 14964 else 14965 { 14966 SCIP_Real primsolval; 14967 primsolval = primsol[c] + rayscale * ray[c]; 14968 lpicols[c]->primsol = MAX(-SCIPsetInfinity(set), MIN(SCIPsetInfinity(set), primsolval)); /*lint !e666*/ 14969 } 14970 lpicols[c]->redcost = SCIP_INVALID; 14971 lpicols[c]->validredcostlp = -1; 14972 } 14973 14974 /* transfer solution */ 14975 for( r = 0; r < nlpirows; ++r ) 14976 { 14977 lpirows[r]->dualsol = SCIP_INVALID; 14978 lpirows[r]->activity = activity[r] + lpirows[r]->constant; 14979 lpirows[r]->validactivitylp = lpcount; 14980 } 14981 14982 /* free temporary memory */ 14983 SCIPsetFreeBufferArray(set, &ray); 14984 SCIPsetFreeBufferArray(set, &activity); 14985 SCIPsetFreeBufferArray(set, &primsol); 14986 14987 return SCIP_OKAY; 14988 } 14989 14990 /** returns primal ray proving the unboundedness of the current LP */ 14991 SCIP_RETCODE SCIPlpGetPrimalRay( 14992 SCIP_LP* lp, /**< current LP data */ 14993 SCIP_SET* set, /**< global SCIP settings */ 14994 SCIP_Real* ray /**< array for storing primal ray values, they are stored w.r.t. the problem index of the variables, 14995 * so the size of this array should be at least number of active variables 14996 * (all entries have to be initialized to 0 before) */ 14997 ) 14998 { 14999 SCIP_COL** lpicols; 15000 SCIP_Real* lpiray; 15001 SCIP_VAR* var; 15002 int nlpicols; 15003 int c; 15004 15005 assert(lp != NULL); 15006 assert(set != NULL); 15007 assert(ray != NULL); 15008 assert(lp->flushed); 15009 assert(lp->solved); 15010 assert(lp->lpsolstat == SCIP_LPSOLSTAT_UNBOUNDEDRAY); 15011 assert(SCIPsetIsInfinity(set, -lp->lpobjval)); 15012 15013 /* check if the LP solver is able to provide a primal unbounded ray */ 15014 if( !SCIPlpiHasPrimalRay(lp->lpi) ) 15015 { 15016 SCIPerrorMessage("LP solver has no primal ray for unbounded LP\n"); 15017 return SCIP_LPERROR; 15018 } 15019 15020 /* get temporary memory */ 15021 SCIP_CALL( SCIPsetAllocBufferArray(set, &lpiray, lp->nlpicols) ); 15022 15023 SCIPsetDebugMsg(set, "getting primal ray values\n"); 15024 15025 /* get primal unbounded ray */ 15026 SCIP_CALL( SCIPlpiGetPrimalRay(lp->lpi, lpiray) ); 15027 15028 lpicols = lp->lpicols; 15029 nlpicols = lp->nlpicols; 15030 15031 /* store the ray values of active problem variables */ 15032 for( c = 0; c < nlpicols; c++ ) 15033 { 15034 assert(lpicols[c] != NULL); 15035 15036 var = lpicols[c]->var; 15037 assert(var != NULL); 15038 assert(SCIPvarGetProbindex(var) != -1); 15039 ray[SCIPvarGetProbindex(var)] = lpiray[c]; 15040 } 15041 15042 SCIPsetFreeBufferArray(set, &lpiray); 15043 15044 return SCIP_OKAY; 15045 } 15046 15047 /** stores the dual Farkas multipliers for infeasibility proof in rows. besides, the proof is checked for validity if 15048 * lp/checkfarkas = TRUE. 15049 * 15050 * @note the check will not be performed if @p valid is NULL. 15051 */ 15052 SCIP_RETCODE SCIPlpGetDualfarkas( 15053 SCIP_LP* lp, /**< current LP data */ 15054 SCIP_SET* set, /**< global SCIP settings */ 15055 SCIP_STAT* stat, /**< problem statistics */ 15056 SCIP_Bool* valid /**< pointer to store whether the Farkas proof is valid or NULL */ 15057 ) 15058 { 15059 SCIP_COL** lpicols; 15060 SCIP_ROW** lpirows; 15061 SCIP_Real* dualfarkas; 15062 SCIP_Real* farkascoefs; 15063 SCIP_Real farkaslhs; 15064 SCIP_Real maxactivity; 15065 SCIP_Bool checkfarkas; 15066 int nlpicols; 15067 int nlpirows; 15068 int c; 15069 int r; 15070 15071 assert(lp != NULL); 15072 assert(lp->flushed); 15073 assert(lp->solved); 15074 assert(lp->lpsolstat == SCIP_LPSOLSTAT_INFEASIBLE); 15075 assert(set != NULL); 15076 assert(stat != NULL); 15077 assert(lp->validfarkaslp <= stat->lpcount); 15078 15079 if( valid != NULL ) 15080 *valid = TRUE; 15081 15082 /* check if the values are already calculated */ 15083 if( lp->validfarkaslp == stat->lpcount ) 15084 return SCIP_OKAY; 15085 lp->validfarkaslp = stat->lpcount; 15086 15087 farkascoefs = NULL; 15088 maxactivity = 0.0; 15089 farkaslhs = 0.0; 15090 15091 checkfarkas = (set->lp_checkfarkas && valid != NULL); 15092 15093 /* get temporary memory */ 15094 SCIP_CALL( SCIPsetAllocBufferArray(set, &dualfarkas, lp->nlpirows) ); 15095 15096 if( checkfarkas ) 15097 { 15098 SCIP_CALL( SCIPsetAllocBufferArray(set, &farkascoefs, lp->nlpicols) ); 15099 BMSclearMemoryArray(farkascoefs, lp->nlpicols); 15100 } 15101 15102 /* get dual Farkas infeasibility proof */ 15103 SCIP_CALL( SCIPlpiGetDualfarkas(lp->lpi, dualfarkas) ); 15104 15105 lpicols = lp->lpicols; 15106 lpirows = lp->lpirows; 15107 nlpicols = lp->nlpicols; 15108 nlpirows = lp->nlpirows; 15109 15110 /* store infeasibility proof in rows */ 15111 SCIPsetDebugMsg(set, "LP is infeasible:\n"); 15112 for( r = 0; r < nlpirows; ++r ) 15113 { 15114 SCIPsetDebugMsg(set, " row <%s>: dualfarkas=%f\n", lpirows[r]->name, dualfarkas[r]); 15115 lpirows[r]->dualfarkas = dualfarkas[r]; 15116 lpirows[r]->dualsol = SCIP_INVALID; 15117 lpirows[r]->activity = 0.0; 15118 lpirows[r]->validactivitylp = -1L; 15119 lpirows[r]->basisstatus = (unsigned int) SCIP_BASESTAT_BASIC; 15120 15121 if( checkfarkas ) 15122 { 15123 assert(farkascoefs != NULL); 15124 15125 /* the infeasibility proof would be invalid if 15126 * (i) dualfarkas[r] > 0 and lhs = -inf 15127 * (ii) dualfarkas[r] < 0 and rhs = inf 15128 * however, due to numerics we accept slightly negative / positive values 15129 */ 15130 if( (SCIPsetIsDualfeasGT(set, dualfarkas[r], 0.0) && SCIPsetIsInfinity(set, -lpirows[r]->lhs)) 15131 || (SCIPsetIsDualfeasLT(set, dualfarkas[r], 0.0) && SCIPsetIsInfinity(set, lpirows[r]->rhs)) ) 15132 { 15133 SCIPsetDebugMsg(set, "farkas proof is invalid: row <%s>[lhs=%g,rhs=%g,c=%g] has multiplier %g\n", 15134 SCIProwGetName(lpirows[r]), lpirows[r]->lhs, lpirows[r]->rhs, lpirows[r]->constant, dualfarkas[r]); 15135 15136 if( valid != NULL ) 15137 *valid = FALSE; 15138 15139 goto TERMINATE; 15140 } 15141 15142 /* dual multipliers, for which the corresponding row side in infinite, are treated as zero if they are zero 15143 * within tolerances (see above) but slighty positive / negative 15144 */ 15145 if( (dualfarkas[r] > 0.0 && SCIPsetIsInfinity(set, -lpirows[r]->lhs)) 15146 || (dualfarkas[r] < 0.0 && SCIPsetIsInfinity(set, lpirows[r]->rhs)) ) 15147 continue; 15148 15149 /* iterate over all columns and scale with dual solution */ 15150 for( c = 0; c < lpirows[r]->len; c++ ) 15151 { 15152 int pos = SCIPcolGetLPPos(lpirows[r]->cols[c]); 15153 15154 if( pos == -1 ) 15155 continue; 15156 15157 assert(pos >= 0 && pos < nlpicols); 15158 15159 farkascoefs[pos] += dualfarkas[r] * lpirows[r]->vals[c]; 15160 } 15161 15162 /* the row contributes with its left-hand side to the proof */ 15163 if( dualfarkas[r] > 0.0 ) 15164 { 15165 assert(!SCIPsetIsInfinity(set, -lpirows[r]->lhs)); 15166 15167 farkaslhs += dualfarkas[r] * (lpirows[r]->lhs - lpirows[r]->constant); 15168 } 15169 /* the row contributes with its right-hand side to the proof */ 15170 else if( dualfarkas[r] < 0.0 ) 15171 { 15172 assert(!SCIPsetIsInfinity(set, lpirows[r]->rhs)); 15173 15174 farkaslhs += dualfarkas[r] * (lpirows[r]->rhs - lpirows[r]->constant); 15175 } 15176 } 15177 } 15178 15179 /* set columns as invalid */ 15180 for( c = 0; c < nlpicols; ++c ) 15181 { 15182 lpicols[c]->primsol = SCIP_INVALID; 15183 lpicols[c]->redcost = SCIP_INVALID; 15184 lpicols[c]->validredcostlp = -1L; 15185 lpicols[c]->validfarkaslp = -1L; 15186 15187 if( checkfarkas ) 15188 { 15189 assert(farkascoefs != NULL); 15190 assert(SCIPcolGetLPPos(lpicols[c]) == c); 15191 15192 /* skip coefficients that are too close to zero */ 15193 if( SCIPsetIsFeasZero(set, farkascoefs[c]) ) 15194 continue; 15195 15196 /* calculate the maximal activity */ 15197 if( farkascoefs[c] > 0.0 ) 15198 maxactivity += farkascoefs[c] * SCIPcolGetUb(lpicols[c]); 15199 else 15200 maxactivity += farkascoefs[c] * SCIPcolGetLb(lpicols[c]); 15201 } 15202 } 15203 15204 /* check whether the farkasproof is valid 15205 * due to numerics, it might happen that the left-hand side of the aggregation is larger/smaller or equal than +/- infinity. 15206 * in that case, we declare the Farkas proof to be invalid. 15207 */ 15208 if( checkfarkas && (SCIPsetIsInfinity(set, REALABS(farkaslhs)) || SCIPsetIsGE(set, maxactivity, farkaslhs)) ) 15209 { 15210 SCIPsetDebugMsg(set, "farkas proof is invalid: maxactivity=%.12f, lhs=%.12f\n", maxactivity, farkaslhs); 15211 15212 if( valid != NULL ) 15213 *valid = FALSE; 15214 } 15215 15216 TERMINATE: 15217 /* free temporary memory */ 15218 if( checkfarkas ) 15219 SCIPsetFreeBufferArray(set, &farkascoefs); 15220 15221 SCIPsetFreeBufferArray(set, &dualfarkas); 15222 15223 return SCIP_OKAY; 15224 } 15225 15226 /** get number of iterations used in last LP solve */ 15227 SCIP_RETCODE SCIPlpGetIterations( 15228 SCIP_LP* lp, /**< current LP data */ 15229 int* iterations /**< pointer to store the iteration count */ 15230 ) 15231 { 15232 assert(lp != NULL); 15233 15234 SCIP_CALL( SCIPlpiGetIterations(lp->lpi, iterations) ); 15235 15236 return SCIP_OKAY; 15237 } 15238 15239 /** increases age of columns with solution value 0.0 and basic rows with activity not at its bounds, 15240 * resets age of non-zero columns and sharp rows 15241 */ 15242 SCIP_RETCODE SCIPlpUpdateAges( 15243 SCIP_LP* lp, /**< current LP data */ 15244 SCIP_STAT* stat /**< problem statistics */ 15245 ) 15246 { 15247 SCIP_COL** lpicols; 15248 SCIP_ROW** lpirows; 15249 int nlpicols; 15250 int nlpirows; 15251 int c; 15252 int r; 15253 15254 assert(lp != NULL); 15255 assert(lp->flushed); 15256 assert(lp->solved); 15257 assert(lp->nlpicols == lp->ncols); 15258 assert(lp->nlpirows == lp->nrows); 15259 assert(stat != NULL); 15260 assert(lp->validsollp == stat->lpcount); 15261 15262 SCIPdebugMessage("updating LP ages\n"); 15263 15264 lpicols = lp->lpicols; 15265 lpirows = lp->lpirows; 15266 nlpicols = lp->nlpicols; 15267 nlpirows = lp->nlpirows; 15268 15269 for( c = 0; c < nlpicols; ++c ) 15270 { 15271 assert(lpicols[c] == lp->cols[c]); 15272 if( lpicols[c]->primsol == 0.0 ) /* non-basic columns to remove are exactly at 0.0 */ 15273 lpicols[c]->age++; 15274 else 15275 lpicols[c]->age = 0; 15276 /*SCIPstatDebugMsg(stat, " -> col <%s>: primsol=%f, age=%d\n", 15277 SCIPvarGetName(lpicols[c]->var), lpicols[c]->primsol, lpicols[c]->age);*/ 15278 } 15279 15280 for( r = 0; r < nlpirows; ++r ) 15281 { 15282 lpirows[r]->nlpsaftercreation++; 15283 assert(lpirows[r] == lp->rows[r]); 15284 15285 if( lpirows[r]->dualsol == 0.0 ) /* basic rows to remove are exactly at 0.0 */ 15286 { 15287 lpirows[r]->age++; 15288 } 15289 else 15290 { 15291 lpirows[r]->activeinlpcounter++; 15292 lpirows[r]->age = 0; 15293 } 15294 /*debugMsg(scip, " -> row <%s>: activity=%f, age=%d\n", lpirows[r]->name, lpirows[r]->activity, lpirows[r]->age);*/ 15295 } 15296 15297 return SCIP_OKAY; 15298 } 15299 15300 /* deletes the marked columns from the LP and the LP interface */ 15301 static 15302 SCIP_RETCODE lpDelColset( 15303 SCIP_LP* lp, /**< current LP data */ 15304 SCIP_SET* set, /**< global SCIP settings */ 15305 int* coldstat /**< deletion status of columns: 1 if column should be deleted, 0 if not */ 15306 ) 15307 { 15308 SCIP_COL* col; 15309 int ncols; 15310 int c; 15311 15312 assert(lp != NULL); 15313 assert(lp->flushed); 15314 assert(lp->ncols == lp->nlpicols); 15315 assert(!lp->diving); 15316 assert(coldstat != NULL); 15317 assert(lp->nlazycols <= lp->ncols); 15318 15319 ncols = lp->ncols; 15320 15321 /* delete columns in LP solver */ 15322 SCIP_CALL( SCIPlpiDelColset(lp->lpi, coldstat) ); 15323 15324 /* update LP data respectively */ 15325 for( c = 0; c < ncols; ++c ) 15326 { 15327 col = lp->cols[c]; 15328 assert(col != NULL); 15329 assert(col == lp->lpicols[c]); 15330 assert(coldstat[c] <= c); 15331 col->lppos = coldstat[c]; 15332 if( coldstat[c] == -1 ) 15333 { 15334 assert(col->removable); 15335 15336 /* mark column to be deleted from the LPI, update column arrays of all linked rows, and update the objective 15337 * function vector norms 15338 */ 15339 markColDeleted(col); 15340 colUpdateDelLP(col, set); 15341 lpUpdateObjNorms(lp, set, col->unchangedobj, 0.0); 15342 col->lpdepth = -1; 15343 15344 lp->cols[c] = NULL; 15345 lp->lpicols[c] = NULL; 15346 lp->ncols--; 15347 lp->nremovablecols--; 15348 lp->nlpicols--; 15349 } 15350 else if( coldstat[c] < c ) 15351 { 15352 assert(lp->cols[coldstat[c]] == NULL); 15353 assert(lp->lpicols[coldstat[c]] == NULL); 15354 lp->cols[coldstat[c]] = col; 15355 lp->lpicols[coldstat[c]] = col; 15356 lp->cols[coldstat[c]]->lppos = coldstat[c]; 15357 lp->cols[coldstat[c]]->lpipos = coldstat[c]; 15358 lp->cols[c] = NULL; 15359 lp->lpicols[c] = NULL; 15360 } 15361 } 15362 15363 /* remove columns which are deleted from the lazy column array */ 15364 c = 0; 15365 while( c < lp->nlazycols ) 15366 { 15367 if( lp->lazycols[c]->lpipos < 0 ) 15368 { 15369 lp->lazycols[c] = lp->lazycols[lp->nlazycols-1]; 15370 lp->nlazycols--; 15371 } 15372 else 15373 c++; 15374 } 15375 15376 /* mark LP to be unsolved */ 15377 if( lp->ncols < ncols ) 15378 { 15379 assert(lp->ncols == lp->nlpicols); 15380 assert(lp->nchgcols == 0); 15381 assert(lp->flushed); 15382 15383 lp->lpifirstchgcol = lp->nlpicols; 15384 15385 /* mark the current solution invalid */ 15386 lp->solved = FALSE; 15387 lp->primalfeasible = FALSE; 15388 lp->primalchecked = FALSE; 15389 lp->lpobjval = SCIP_INVALID; 15390 lp->lpsolstat = SCIP_LPSOLSTAT_NOTSOLVED; 15391 } 15392 15393 checkLazyColArray(lp, set); 15394 checkLinks(lp); 15395 15396 return SCIP_OKAY; 15397 } 15398 15399 /* deletes the marked rows from the LP and the LP interface */ 15400 static 15401 SCIP_RETCODE lpDelRowset( 15402 SCIP_LP* lp, /**< current LP data */ 15403 BMS_BLKMEM* blkmem, /**< block memory buffers */ 15404 SCIP_SET* set, /**< global SCIP settings */ 15405 SCIP_EVENTQUEUE* eventqueue, /**< event queue */ 15406 SCIP_EVENTFILTER* eventfilter, /**< global event filter */ 15407 int* rowdstat /**< deletion status of rows: 1 if row should be deleted, 0 if not */ 15408 ) 15409 { 15410 SCIP_ROW* row; 15411 int nrows; 15412 int r; 15413 15414 assert(lp != NULL); 15415 assert(lp->flushed); 15416 assert(lp->nrows == lp->nlpirows); 15417 assert(!lp->diving); 15418 assert(rowdstat != NULL); 15419 15420 nrows = lp->nrows; 15421 15422 /* delete rows in LP solver */ 15423 SCIP_CALL( SCIPlpiDelRowset(lp->lpi, rowdstat) ); 15424 15425 /* update LP data respectively */ 15426 for( r = 0; r < nrows; ++r ) 15427 { 15428 row = lp->rows[r]; 15429 assert(row == lp->lpirows[r]); 15430 assert(rowdstat[r] <= r); 15431 assert(row != NULL); 15432 row->lppos = rowdstat[r]; 15433 if( rowdstat[r] == -1 ) 15434 { 15435 if( row->removable ) 15436 lp->nremovablerows--; 15437 15438 /* mark row to be deleted from the LPI and update row arrays of all linked columns */ 15439 markRowDeleted(row); 15440 rowUpdateDelLP(row); 15441 row->lpdepth = -1; 15442 15443 /* check, if row deletion events are tracked 15444 * if so, issue ROWDELETEDLP event 15445 */ 15446 if( eventfilter->len > 0 && (eventfilter->eventmask & SCIP_EVENTTYPE_ROWDELETEDLP) != 0 ) 15447 { 15448 SCIP_EVENT* event; 15449 15450 SCIP_CALL( SCIPeventCreateRowDeletedLP(&event, blkmem, row) ); 15451 SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, NULL, NULL, eventfilter, &event) ); 15452 } 15453 15454 SCIP_CALL( SCIProwRelease(&lp->lpirows[r], blkmem, set, lp) ); 15455 SCIProwUnlock(lp->rows[r]); 15456 SCIP_CALL( SCIProwRelease(&lp->rows[r], blkmem, set, lp) ); 15457 assert(lp->lpirows[r] == NULL); 15458 assert(lp->rows[r] == NULL); 15459 lp->nrows--; 15460 lp->nlpirows--; 15461 } 15462 else if( rowdstat[r] < r ) 15463 { 15464 assert(lp->rows[rowdstat[r]] == NULL); 15465 assert(lp->lpirows[rowdstat[r]] == NULL); 15466 lp->rows[rowdstat[r]] = row; 15467 lp->lpirows[rowdstat[r]] = row; 15468 lp->rows[rowdstat[r]]->lppos = rowdstat[r]; 15469 lp->rows[rowdstat[r]]->lpipos = rowdstat[r]; 15470 lp->rows[r] = NULL; 15471 lp->lpirows[r] = NULL; 15472 } 15473 } 15474 15475 /* mark LP to be unsolved */ 15476 if( lp->nrows < nrows ) 15477 { 15478 assert(lp->nrows == lp->nlpirows); 15479 assert(lp->nchgrows == 0); 15480 assert(lp->flushed); 15481 15482 lp->lpifirstchgrow = lp->nlpirows; 15483 15484 /* mark the current solution invalid */ 15485 lp->solved = FALSE; 15486 lp->dualfeasible = FALSE; 15487 lp->dualchecked = FALSE; 15488 lp->lpobjval = SCIP_INVALID; 15489 lp->lpsolstat = SCIP_LPSOLSTAT_NOTSOLVED; 15490 } 15491 15492 checkLinks(lp); 15493 15494 return SCIP_OKAY; 15495 } 15496 15497 /** removes all non-basic columns, that are too old, beginning with the given firstcol */ 15498 static 15499 SCIP_RETCODE lpRemoveObsoleteCols( 15500 SCIP_LP* lp, /**< current LP data */ 15501 SCIP_SET* set, /**< global SCIP settings */ 15502 SCIP_STAT* stat, /**< problem statistics */ 15503 int firstcol /**< first column to check for clean up */ 15504 ) 15505 { 15506 SCIP_COL** cols; 15507 #ifndef NDEBUG 15508 SCIP_COL** lpicols; 15509 #endif 15510 int* coldstat; 15511 int ncols; 15512 int ndelcols; 15513 int c; 15514 15515 assert(lp != NULL); 15516 assert(lp->flushed); 15517 assert(lp->ncols == lp->nlpicols); 15518 assert(lp->nremovablecols <= lp->ncols); 15519 assert(!lp->diving); 15520 assert(set != NULL); 15521 assert(stat != NULL); 15522 15523 if( lp->nremovablecols == 0 || set->lp_colagelimit == -1 || !lp->solisbasic ) 15524 return SCIP_OKAY; 15525 15526 ncols = lp->ncols; 15527 cols = lp->cols; 15528 #ifndef NDEBUG 15529 lpicols = lp->lpicols; 15530 #endif 15531 15532 /* get temporary memory */ 15533 SCIP_CALL( SCIPsetAllocBufferArray(set, &coldstat, ncols) ); 15534 15535 /* mark obsolete columns to be deleted */ 15536 ndelcols = 0; 15537 BMSclearMemoryArray(coldstat, ncols); 15538 for( c = firstcol; c < ncols; ++c ) 15539 { 15540 assert(cols[c] == lpicols[c]); 15541 assert(cols[c]->lppos == c); 15542 assert(cols[c]->lpipos == c); 15543 if( cols[c]->removable 15544 && cols[c]->obsoletenode != stat->nnodes /* don't remove column a second time from same node (avoid cycling), or a first time if marked nonremovable locally */ 15545 && cols[c]->age > set->lp_colagelimit 15546 && (SCIP_BASESTAT)cols[c]->basisstatus != SCIP_BASESTAT_BASIC 15547 && SCIPsetIsZero(set, SCIPcolGetBestBound(cols[c])) ) /* bestbd != 0 -> column would be priced in next time */ 15548 { 15549 assert(cols[c]->primsol == 0.0); 15550 coldstat[c] = 1; 15551 ndelcols++; 15552 cols[c]->obsoletenode = stat->nnodes; 15553 SCIPsetDebugMsg(set, "removing obsolete col <%s>: primsol=%f, bounds=[%g,%g]\n", 15554 SCIPvarGetName(cols[c]->var), cols[c]->primsol, cols[c]->lb, cols[c]->ub); 15555 } 15556 } 15557 15558 SCIPsetDebugMsg(set, "removing %d/%d obsolete columns from LP\n", ndelcols, ncols); 15559 15560 /* delete the marked columns in the LP solver interface, update the LP respectively */ 15561 if( ndelcols > 0 ) 15562 { 15563 SCIP_CALL( lpDelColset(lp, set, coldstat) ); 15564 } 15565 assert(lp->ncols == ncols - ndelcols); 15566 15567 /* release temporary memory */ 15568 SCIPsetFreeBufferArray(set, &coldstat); 15569 15570 return SCIP_OKAY; 15571 } 15572 15573 /** removes all basic rows, that are too old, beginning with the given firstrow */ 15574 static 15575 SCIP_RETCODE lpRemoveObsoleteRows( 15576 SCIP_LP* lp, /**< current LP data */ 15577 BMS_BLKMEM* blkmem, /**< block memory buffers */ 15578 SCIP_SET* set, /**< global SCIP settings */ 15579 SCIP_STAT* stat, /**< problem statistics */ 15580 SCIP_EVENTQUEUE* eventqueue, /**< event queue */ 15581 SCIP_EVENTFILTER* eventfilter, /**< global event filter */ 15582 int firstrow /**< first row to check for clean up */ 15583 ) 15584 { 15585 SCIP_ROW** rows; 15586 #ifndef NDEBUG 15587 SCIP_ROW** lpirows; 15588 #endif 15589 int* rowdstat; 15590 int nrows; 15591 int ndelrows; 15592 int r; 15593 15594 assert(lp != NULL); 15595 assert(lp->flushed); 15596 assert(lp->nrows == lp->nlpirows); 15597 assert(lp->nremovablerows <= lp->nrows); 15598 assert(!lp->diving); 15599 assert(set != NULL); 15600 assert(stat != NULL); 15601 15602 if( lp->nremovablerows == 0 || set->lp_rowagelimit == -1 || !lp->solisbasic ) 15603 return SCIP_OKAY; 15604 15605 nrows = lp->nrows; 15606 rows = lp->rows; 15607 #ifndef NDEBUG 15608 lpirows = lp->lpirows; 15609 #endif 15610 15611 /* get temporary memory */ 15612 SCIP_CALL( SCIPsetAllocBufferArray(set, &rowdstat, nrows) ); 15613 15614 /* mark obsolete rows to be deleted */ 15615 ndelrows = 0; 15616 BMSclearMemoryArray(rowdstat, nrows); 15617 for( r = firstrow; r < nrows; ++r ) 15618 { 15619 assert(rows[r] == lpirows[r]); 15620 assert(rows[r]->lppos == r); 15621 assert(rows[r]->lpipos == r); 15622 if( rows[r]->removable 15623 && rows[r]->obsoletenode != stat->nnodes /* don't remove row a second time from same node (avoid cycling), or a first time if marked nonremovable locally */ 15624 && rows[r]->age > set->lp_rowagelimit 15625 && (SCIP_BASESTAT)rows[r]->basisstatus == SCIP_BASESTAT_BASIC ) 15626 { 15627 rowdstat[r] = 1; 15628 ndelrows++; 15629 rows[r]->obsoletenode = stat->nnodes; 15630 SCIPsetDebugMsg(set, "removing obsolete row <%s>: activity=%f, sides=[%g,%g]\n", 15631 rows[r]->name, rows[r]->activity, rows[r]->lhs, rows[r]->rhs); 15632 } 15633 } 15634 15635 SCIPsetDebugMsg(set, "removing %d/%d obsolete rows from LP\n", ndelrows, nrows); 15636 15637 /* delete the marked rows in the LP solver interface, update the LP respectively */ 15638 if( ndelrows > 0 ) 15639 { 15640 SCIP_CALL( lpDelRowset(lp, blkmem, set, eventqueue, eventfilter, rowdstat) ); 15641 } 15642 assert(lp->nrows == nrows - ndelrows); 15643 15644 /* release temporary memory */ 15645 SCIPsetFreeBufferArray(set, &rowdstat); 15646 15647 return SCIP_OKAY; 15648 } 15649 15650 /** removes all non-basic columns and basic rows in the part of the LP created at the current node, that are too old */ 15651 SCIP_RETCODE SCIPlpRemoveNewObsoletes( 15652 SCIP_LP* lp, /**< current LP data */ 15653 BMS_BLKMEM* blkmem, /**< block memory buffers */ 15654 SCIP_SET* set, /**< global SCIP settings */ 15655 SCIP_STAT* stat, /**< problem statistics */ 15656 SCIP_EVENTQUEUE* eventqueue, /**< event queue */ 15657 SCIP_EVENTFILTER* eventfilter /**< global event filter */ 15658 ) 15659 { 15660 assert(lp != NULL); 15661 assert(lp->solved); 15662 assert(!lp->diving); 15663 assert(SCIPlpGetSolstat(lp) == SCIP_LPSOLSTAT_OPTIMAL); 15664 assert(set != NULL); 15665 15666 SCIPsetDebugMsg(set, "removing obsolete columns starting with %d/%d, obsolete rows starting with %d/%d\n", 15667 lp->firstnewcol, lp->ncols, lp->firstnewrow, lp->nrows); 15668 15669 if( lp->firstnewcol < lp->ncols ) 15670 { 15671 SCIP_CALL( lpRemoveObsoleteCols(lp, set, stat, lp->firstnewcol) ); 15672 } 15673 if( lp->firstnewrow < lp->nrows ) 15674 { 15675 SCIP_CALL( lpRemoveObsoleteRows(lp, blkmem, set, stat, eventqueue, eventfilter, lp->firstnewrow) ); 15676 } 15677 15678 return SCIP_OKAY; 15679 } 15680 15681 /** removes all non-basic columns and basic rows in whole LP, that are too old */ 15682 SCIP_RETCODE SCIPlpRemoveAllObsoletes( 15683 SCIP_LP* lp, /**< current LP data */ 15684 BMS_BLKMEM* blkmem, /**< block memory buffers */ 15685 SCIP_SET* set, /**< global SCIP settings */ 15686 SCIP_STAT* stat, /**< problem statistics */ 15687 SCIP_EVENTQUEUE* eventqueue, /**< event queue */ 15688 SCIP_EVENTFILTER* eventfilter /**< global event filter */ 15689 ) 15690 { 15691 assert(lp != NULL); 15692 assert(lp->solved); 15693 assert(!lp->diving); 15694 assert(SCIPlpGetSolstat(lp) == SCIP_LPSOLSTAT_OPTIMAL); 15695 assert(set != NULL); 15696 15697 SCIPsetDebugMsg(set, "removing all obsolete columns and rows\n"); 15698 15699 if( 0 < lp->ncols ) 15700 { 15701 SCIP_CALL( lpRemoveObsoleteCols(lp, set, stat, 0) ); 15702 } 15703 if( 0 < lp->nrows ) 15704 { 15705 SCIP_CALL( lpRemoveObsoleteRows(lp, blkmem, set, stat, eventqueue, eventfilter, 0) ); 15706 } 15707 15708 return SCIP_OKAY; 15709 } 15710 15711 /** removes all non-basic columns at 0.0 beginning with the given firstcol */ 15712 static 15713 SCIP_RETCODE lpCleanupCols( 15714 SCIP_LP* lp, /**< current LP data */ 15715 SCIP_SET* set, /**< global SCIP settings */ 15716 SCIP_STAT* stat, /**< problem statistics */ 15717 int firstcol /**< first column to check for clean up */ 15718 ) 15719 { 15720 SCIP_COL** cols; 15721 SCIP_COL** lpicols; 15722 int* coldstat; 15723 int ncols; 15724 int ndelcols; 15725 int c; 15726 15727 assert(lp != NULL); 15728 assert(lp->flushed); 15729 assert(lp->ncols == lp->nlpicols); 15730 assert(!lp->diving); 15731 assert(stat != NULL); 15732 assert(lp->validsollp == stat->lpcount); 15733 assert(0 <= firstcol && firstcol < lp->ncols); 15734 15735 if( lp->nremovablecols == 0 || !lp->solisbasic ) 15736 return SCIP_OKAY; 15737 15738 ncols = lp->ncols; 15739 cols = lp->cols; 15740 lpicols = lp->lpicols; 15741 15742 /* get temporary memory */ 15743 SCIP_CALL( SCIPsetAllocBufferArray(set, &coldstat, ncols) ); 15744 15745 /* mark unused columns to be deleted */ 15746 ndelcols = 0; 15747 BMSclearMemoryArray(coldstat, ncols); 15748 for( c = firstcol; c < ncols; ++c ) 15749 { 15750 assert(cols[c] == lpicols[c]); 15751 assert(cols[c]->lppos == c); 15752 assert(cols[c]->lpipos == c); 15753 if( lpicols[c]->removable 15754 && (SCIP_BASESTAT)lpicols[c]->basisstatus != SCIP_BASESTAT_BASIC 15755 && lpicols[c]->primsol == 0.0 /* non-basic columns to remove are exactly at 0.0 */ 15756 && SCIPsetIsZero(set, SCIPcolGetBestBound(cols[c])) ) /* bestbd != 0 -> column would be priced in next time */ 15757 { 15758 coldstat[c] = 1; 15759 ndelcols++; 15760 } 15761 } 15762 15763 SCIPsetDebugMsg(set, "removing %d/%d unused columns from LP\n", ndelcols, ncols); 15764 15765 /* delete the marked columns in the LP solver interface, update the LP respectively */ 15766 if( ndelcols > 0 ) 15767 { 15768 SCIP_CALL( lpDelColset(lp, set, coldstat) ); 15769 } 15770 assert(lp->ncols == ncols - ndelcols); 15771 15772 /* release temporary memory */ 15773 SCIPsetFreeBufferArray(set, &coldstat); 15774 15775 return SCIP_OKAY; 15776 } 15777 15778 /** removes all basic rows beginning with the given firstrow */ 15779 static 15780 SCIP_RETCODE lpCleanupRows( 15781 SCIP_LP* lp, /**< current LP data */ 15782 BMS_BLKMEM* blkmem, /**< block memory buffers */ 15783 SCIP_SET* set, /**< global SCIP settings */ 15784 SCIP_STAT* stat, /**< problem statistics */ 15785 SCIP_EVENTQUEUE* eventqueue, /**< event queue */ 15786 SCIP_EVENTFILTER* eventfilter, /**< global event filter */ 15787 int firstrow /**< first row to check for clean up */ 15788 ) 15789 { 15790 #ifndef NDEBUG 15791 SCIP_ROW** rows; 15792 #endif 15793 SCIP_ROW** lpirows; 15794 int* rowdstat; 15795 int nrows; 15796 int ndelrows; 15797 int r; 15798 15799 assert(lp != NULL); 15800 assert(lp->flushed); 15801 assert(lp->ncols == lp->nlpicols); 15802 assert(lp->nrows == lp->nlpirows); 15803 assert(!lp->diving); 15804 assert(stat != NULL); 15805 assert(lp->validsollp == stat->lpcount); 15806 assert(0 <= firstrow && firstrow < lp->nrows); 15807 15808 if( lp->nremovablerows == 0 || !lp->solisbasic ) 15809 return SCIP_OKAY; 15810 15811 #ifndef NDEBUG 15812 rows = lp->rows; 15813 #endif 15814 nrows = lp->nrows; 15815 lpirows = lp->lpirows; 15816 15817 /* get temporary memory */ 15818 SCIP_CALL( SCIPsetAllocBufferArray(set, &rowdstat, nrows) ); 15819 15820 /* mark unused rows to be deleted */ 15821 ndelrows = 0; 15822 BMSclearMemoryArray(rowdstat, nrows); 15823 for( r = firstrow; r < nrows; ++r ) 15824 { 15825 assert(rows[r] == lpirows[r]); 15826 assert(rows[r]->lppos == r); 15827 assert(rows[r]->lpipos == r); 15828 if( lpirows[r]->removable && (SCIP_BASESTAT)lpirows[r]->basisstatus == SCIP_BASESTAT_BASIC ) 15829 { 15830 rowdstat[r] = 1; 15831 ndelrows++; 15832 } 15833 } 15834 15835 SCIPsetDebugMsg(set, "removing %d/%d unused rows from LP\n", ndelrows, nrows); 15836 15837 /* delete the marked rows in the LP solver interface, update the LP respectively */ 15838 if( ndelrows > 0 ) 15839 { 15840 SCIP_CALL( lpDelRowset(lp, blkmem, set, eventqueue, eventfilter, rowdstat) ); 15841 } 15842 assert(lp->nrows == nrows - ndelrows); 15843 15844 /* release temporary memory */ 15845 SCIPsetFreeBufferArray(set, &rowdstat); 15846 15847 return SCIP_OKAY; 15848 } 15849 15850 /** removes all non-basic columns at 0.0 and basic rows in the part of the LP created at the current node */ 15851 SCIP_RETCODE SCIPlpCleanupNew( 15852 SCIP_LP* lp, /**< current LP data */ 15853 BMS_BLKMEM* blkmem, /**< block memory buffers */ 15854 SCIP_SET* set, /**< global SCIP settings */ 15855 SCIP_STAT* stat, /**< problem statistics */ 15856 SCIP_EVENTQUEUE* eventqueue, /**< event queue */ 15857 SCIP_EVENTFILTER* eventfilter, /**< global event filter */ 15858 SCIP_Bool root /**< are we at the root node? */ 15859 ) 15860 { 15861 SCIP_Bool cleanupcols; 15862 SCIP_Bool cleanuprows; 15863 15864 assert(lp != NULL); 15865 assert(lp->solved); 15866 assert(!lp->diving); 15867 assert(SCIPlpGetSolstat(lp) == SCIP_LPSOLSTAT_OPTIMAL); 15868 assert(set != NULL); 15869 15870 /* check, if we want to clean up the columns and rows */ 15871 cleanupcols = (root ? set->lp_cleanupcolsroot : set->lp_cleanupcols); 15872 cleanuprows = (root ? set->lp_cleanuprowsroot : set->lp_cleanuprows); 15873 15874 SCIPsetDebugMsg(set, "removing unused columns starting with %d/%d (%u), unused rows starting with %d/%d (%u), LP algo: %d, basic sol: %u\n", 15875 lp->firstnewcol, lp->ncols, cleanupcols, lp->firstnewrow, lp->nrows, cleanuprows, lp->lastlpalgo, lp->solisbasic); 15876 15877 if( cleanupcols && lp->firstnewcol < lp->ncols ) 15878 { 15879 SCIP_CALL( lpCleanupCols(lp, set, stat, lp->firstnewcol) ); 15880 } 15881 if( cleanuprows && lp->firstnewrow < lp->nrows ) 15882 { 15883 SCIP_CALL( lpCleanupRows(lp, blkmem, set, stat, eventqueue, eventfilter, lp->firstnewrow) ); 15884 } 15885 15886 return SCIP_OKAY; 15887 } 15888 15889 /** removes all non-basic columns at 0.0 and basic rows in the whole LP */ 15890 SCIP_RETCODE SCIPlpCleanupAll( 15891 SCIP_LP* lp, /**< current LP data */ 15892 BMS_BLKMEM* blkmem, /**< block memory buffers */ 15893 SCIP_SET* set, /**< global SCIP settings */ 15894 SCIP_STAT* stat, /**< problem statistics */ 15895 SCIP_EVENTQUEUE* eventqueue, /**< event queue */ 15896 SCIP_EVENTFILTER* eventfilter, /**< global event filter */ 15897 SCIP_Bool root /**< are we at the root node? */ 15898 ) 15899 { 15900 SCIP_Bool cleanupcols; 15901 SCIP_Bool cleanuprows; 15902 15903 assert(lp != NULL); 15904 assert(lp->solved); 15905 assert(!lp->diving); 15906 assert(SCIPlpGetSolstat(lp) == SCIP_LPSOLSTAT_OPTIMAL); 15907 assert(set != NULL); 15908 15909 /* check, if we want to clean up the columns and rows */ 15910 cleanupcols = (root ? set->lp_cleanupcolsroot : set->lp_cleanupcols); 15911 cleanuprows = (root ? set->lp_cleanuprowsroot : set->lp_cleanuprows); 15912 15913 SCIPsetDebugMsg(set, "removing all unused columns (%u) and rows (%u), LP algo: %d, basic sol: %u\n", 15914 cleanupcols, cleanuprows, lp->lastlpalgo, lp->solisbasic); 15915 15916 if( cleanupcols && 0 < lp->ncols ) 15917 { 15918 SCIP_CALL( lpCleanupCols(lp, set, stat, 0) ); 15919 } 15920 if( cleanuprows && 0 < lp->nrows ) 15921 { 15922 SCIP_CALL( lpCleanupRows(lp, blkmem, set, stat, eventqueue, eventfilter, 0) ); 15923 } 15924 15925 return SCIP_OKAY; 15926 } 15927 15928 /** removes all redundant rows that were added at the current node */ 15929 SCIP_RETCODE SCIPlpRemoveRedundantRows( 15930 SCIP_LP* lp, /**< current LP data */ 15931 BMS_BLKMEM* blkmem, /**< block memory buffers */ 15932 SCIP_SET* set, /**< global SCIP settings */ 15933 SCIP_STAT* stat, /**< problem statistics */ 15934 SCIP_EVENTQUEUE* eventqueue, /**< event queue */ 15935 SCIP_EVENTFILTER* eventfilter /**< global event filter */ 15936 ) 15937 { 15938 #ifndef NDEBUG 15939 SCIP_ROW** rows; 15940 #endif 15941 SCIP_ROW** lpirows; 15942 int* rowdstat; 15943 int nrows; 15944 int ndelrows; 15945 int r; 15946 15947 assert(lp != NULL); 15948 assert(lp->flushed); 15949 assert(lp->ncols == lp->nlpicols); 15950 assert(lp->nrows == lp->nlpirows); 15951 assert(!lp->diving); 15952 assert(stat != NULL); 15953 assert(lp->validsollp == stat->lpcount); 15954 assert(lp->firstnewrow <= lp->nrows); 15955 15956 if( lp->firstnewrow == lp->nrows ) 15957 return SCIP_OKAY; 15958 15959 #ifndef NDEBUG 15960 rows = lp->rows; 15961 #endif 15962 nrows = lp->nrows; 15963 lpirows = lp->lpirows; 15964 15965 /* get temporary memory */ 15966 SCIP_CALL( SCIPsetAllocBufferArray(set, &rowdstat, nrows) ); 15967 15968 /* mark redundant rows to be deleted (only delete basic rows!) */ 15969 ndelrows = 0; 15970 BMSclearMemoryArray(rowdstat, nrows); 15971 for( r = lp->firstnewrow; r < nrows; ++r ) 15972 { 15973 assert(rows[r] == lpirows[r]); 15974 assert(rows[r]->lppos == r); 15975 assert(rows[r]->lpipos == r); 15976 if( (!lp->solisbasic || (SCIP_BASESTAT)lpirows[r]->basisstatus == SCIP_BASESTAT_BASIC) 15977 && SCIProwIsRedundant(lpirows[r], set, stat) ) 15978 { 15979 SCIPsetDebugMsg(set, "basic row <%s> is redundant: sides=[%g,%g], act=[%g,%g]\n", 15980 SCIProwGetName(lpirows[r]), SCIProwGetLhs(lpirows[r]), SCIProwGetRhs(lpirows[r]), 15981 SCIProwGetMinActivity(lpirows[r], set, stat), SCIProwGetMaxActivity(lpirows[r], set, stat)); 15982 rowdstat[r] = 1; 15983 ndelrows++; 15984 } 15985 } 15986 15987 SCIPsetDebugMsg(set, "removing %d/%d redundant basic rows from LP\n", ndelrows, nrows); 15988 15989 /* delete the marked rows in the LP solver interface, update the LP respectively */ 15990 if( ndelrows > 0 ) 15991 { 15992 SCIP_CALL( lpDelRowset(lp, blkmem, set, eventqueue, eventfilter, rowdstat) ); 15993 } 15994 assert(lp->nrows == nrows - ndelrows); 15995 15996 /* release temporary memory */ 15997 SCIPsetFreeBufferArray(set, &rowdstat); 15998 15999 return SCIP_OKAY; 16000 } 16001 16002 /** initiates LP diving */ 16003 SCIP_RETCODE SCIPlpStartDive( 16004 SCIP_LP* lp, /**< current LP data */ 16005 BMS_BLKMEM* blkmem, /**< block memory */ 16006 SCIP_SET* set, /**< global SCIP settings */ 16007 SCIP_STAT* stat /**< problem statistics */ 16008 ) 16009 { 16010 int c; 16011 int r; 16012 16013 assert(lp != NULL); 16014 assert(lp->flushed || !lp->solved); 16015 assert(!lp->diving); 16016 assert(!lp->probing); 16017 assert(lp->divelpistate == NULL); 16018 assert(lp->divelpwasprimfeas); 16019 assert(lp->divelpwasdualfeas); 16020 assert(lp->validsollp <= stat->lpcount); 16021 assert(blkmem != NULL); 16022 assert(set != NULL); 16023 assert(lp->ndivechgsides == 0); 16024 16025 SCIPsetDebugMsg(set, "diving started (LP flushed: %u, LP solved: %u, solstat: %d)\n", 16026 lp->flushed, lp->solved, SCIPlpGetSolstat(lp)); 16027 16028 #ifndef NDEBUG 16029 for( c = 0; c < lp->ncols; ++c ) 16030 { 16031 assert(lp->cols[c] != NULL); 16032 assert(lp->cols[c]->var != NULL); 16033 assert(SCIPvarGetStatus(lp->cols[c]->var) == SCIP_VARSTATUS_COLUMN); 16034 assert(SCIPvarGetCol(lp->cols[c]->var) == lp->cols[c]); 16035 assert(SCIPsetIsFeasEQ(set, SCIPvarGetObj(lp->cols[c]->var), lp->cols[c]->obj)); 16036 assert(SCIPsetIsFeasEQ(set, SCIPvarGetLbLocal(lp->cols[c]->var), lp->cols[c]->lb)); 16037 assert(SCIPsetIsFeasEQ(set, SCIPvarGetUbLocal(lp->cols[c]->var), lp->cols[c]->ub)); 16038 } 16039 #endif 16040 16041 /* save current LPI state (basis information) */ 16042 SCIP_CALL( SCIPlpiGetState(lp->lpi, blkmem, &lp->divelpistate) ); 16043 lp->divelpwasprimfeas = lp->primalfeasible; 16044 lp->divelpwasdualfeas = lp->dualfeasible; 16045 lp->divelpwasprimchecked = lp->primalchecked; 16046 lp->divelpwasdualchecked = lp->dualchecked; 16047 16048 /* save current LP values dependent on the solution */ 16049 SCIP_CALL( lpStoreSolVals(lp, stat, blkmem) ); 16050 assert(lp->storedsolvals != NULL); 16051 if( !set->lp_resolverestore && lp->solved ) 16052 { 16053 SCIP_Bool store = TRUE; 16054 16055 switch ( lp->lpsolstat ) 16056 { 16057 case SCIP_LPSOLSTAT_OPTIMAL: 16058 SCIP_CALL( SCIPlpGetSol(lp, set, stat, NULL, NULL) ); 16059 assert(lp->validsollp == stat->lpcount); 16060 break; 16061 case SCIP_LPSOLSTAT_UNBOUNDEDRAY: 16062 SCIP_CALL( SCIPlpGetUnboundedSol(lp, set, stat, NULL, NULL) ); 16063 assert(lp->validsollp == stat->lpcount); 16064 break; 16065 case SCIP_LPSOLSTAT_OBJLIMIT: 16066 case SCIP_LPSOLSTAT_ITERLIMIT: 16067 case SCIP_LPSOLSTAT_TIMELIMIT: 16068 SCIP_CALL( SCIPlpGetSol(lp, set, stat, NULL, NULL) ); 16069 assert(lp->validsollp == stat->lpcount); 16070 break; 16071 case SCIP_LPSOLSTAT_INFEASIBLE: 16072 SCIP_CALL( SCIPlpGetDualfarkas(lp, set, stat, NULL) ); 16073 break; 16074 case SCIP_LPSOLSTAT_NOTSOLVED: 16075 case SCIP_LPSOLSTAT_ERROR: 16076 default: 16077 store = FALSE; 16078 } 16079 16080 if ( store ) 16081 { 16082 for( c = 0; c < lp->ncols; ++c ) 16083 { 16084 SCIP_CALL( colStoreSolVals(lp->cols[c], blkmem) ); 16085 } 16086 for( r = 0; r < lp->nrows; ++r ) 16087 { 16088 SCIP_CALL( rowStoreSolVals(lp->rows[r], blkmem, lp->storedsolvals->lpsolstat == SCIP_LPSOLSTAT_INFEASIBLE) ); 16089 } 16090 } 16091 } 16092 16093 /* store LPI iteration limit */ 16094 SCIP_CALL( SCIPlpiGetIntpar(lp->lpi, SCIP_LPPAR_LPITLIM, &lp->divinglpiitlim) ); 16095 16096 /* remember the number of domain changes */ 16097 lp->divenolddomchgs = stat->domchgcount; 16098 16099 /* store current number of rows */ 16100 lp->ndivingrows = lp->nrows; 16101 16102 /* switch to diving mode */ 16103 lp->diving = TRUE; 16104 16105 return SCIP_OKAY; 16106 } 16107 16108 /** quits LP diving and resets bounds and objective values of columns to the current node's values */ 16109 SCIP_RETCODE SCIPlpEndDive( 16110 SCIP_LP* lp, /**< current LP data */ 16111 BMS_BLKMEM* blkmem, /**< block memory */ 16112 SCIP_SET* set, /**< global SCIP settings */ 16113 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */ 16114 SCIP_STAT* stat, /**< problem statistics */ 16115 SCIP_EVENTQUEUE* eventqueue, /**< event queue */ 16116 SCIP_EVENTFILTER* eventfilter, /**< global event filter */ 16117 SCIP_PROB* prob, /**< problem data */ 16118 SCIP_VAR** vars, /**< array with all active variables */ 16119 int nvars /**< number of active variables */ 16120 ) 16121 { 16122 SCIP_VAR* var; 16123 int v; 16124 16125 assert(lp != NULL); 16126 assert(lp->diving); 16127 assert(blkmem != NULL); 16128 assert(nvars == 0 || vars != NULL); 16129 16130 SCIPsetDebugMsg(set, "diving ended (LP flushed: %u, solstat: %d)\n", lp->flushed, SCIPlpGetSolstat(lp)); 16131 16132 /* reset all columns' objective values and bounds to its original values */ 16133 for( v = 0; v < nvars; ++v ) 16134 { 16135 var = vars[v]; 16136 assert(var != NULL); 16137 if( SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN ) 16138 { 16139 SCIP_CALL( SCIPcolChgObj(SCIPvarGetCol(var), set, lp, SCIPvarGetObj(var)) ); 16140 SCIP_CALL( SCIPcolChgLb(SCIPvarGetCol(var), set, lp, SCIPvarGetLbLocal(var)) ); 16141 SCIP_CALL( SCIPcolChgUb(SCIPvarGetCol(var), set, lp, SCIPvarGetUbLocal(var)) ); 16142 } 16143 } 16144 16145 /* remove rows which were added in diving mode */ 16146 SCIP_CALL( SCIPlpShrinkRows(lp, blkmem, set, eventqueue, eventfilter, lp->ndivingrows) ); 16147 16148 /* undo changes to left hand sides and right hand sides */ 16149 while( lp->ndivechgsides > 0 ) 16150 { 16151 SCIP_Real oldside; 16152 SCIP_SIDETYPE sidetype; 16153 SCIP_ROW* row; 16154 16155 lp->ndivechgsides--; 16156 oldside = lp->divechgsides[lp->ndivechgsides]; 16157 sidetype = lp->divechgsidetypes[lp->ndivechgsides]; 16158 row = lp->divechgrows[lp->ndivechgsides]; 16159 16160 if( sidetype == SCIP_SIDETYPE_LEFT ) 16161 { 16162 SCIP_CALL( SCIProwChgLhs(row, blkmem, set, eventqueue, lp, oldside) ); 16163 } 16164 else 16165 { 16166 SCIP_CALL( SCIProwChgRhs(row, blkmem, set, eventqueue, lp, oldside) ); 16167 } 16168 } 16169 16170 /* restore LPI iteration limit */ 16171 SCIP_CALL( lpSetIterationLimit(lp, lp->divinglpiitlim) ); 16172 16173 /* reload LPI state saved at start of diving and free it afterwards; it may be NULL, in which case simply nothing 16174 * happens 16175 */ 16176 SCIP_CALL( SCIPlpSetState(lp, blkmem, set, prob, eventqueue, lp->divelpistate, 16177 lp->divelpwasprimfeas, lp->divelpwasprimchecked, lp->divelpwasdualfeas, lp->divelpwasdualchecked) ); 16178 SCIP_CALL( SCIPlpFreeState(lp, blkmem, &lp->divelpistate) ); 16179 lp->divelpwasprimfeas = TRUE; 16180 lp->divelpwasdualfeas = TRUE; 16181 lp->divelpwasprimchecked = TRUE; 16182 lp->divelpwasdualchecked = TRUE; 16183 assert(lp->divelpistate == NULL); 16184 16185 /* switch to standard (non-diving) mode */ 16186 lp->diving = FALSE; 16187 lp->divingobjchg = FALSE; 16188 16189 /* if the LP was solved before starting the dive, but not to optimality (or unboundedness), then we need to solve the 16190 * LP again to reset the solution (e.g. we do not save the Farkas proof for infeasible LPs, because we assume that we 16191 * are not called in this case, anyway); restoring by solving the LP again in either case can be forced by setting 16192 * the parameter resolverestore to TRUE 16193 * restoring an unbounded ray after solve does not seem to work currently (bug 631), so we resolve also in this case 16194 */ 16195 assert(lp->storedsolvals != NULL); 16196 if( lp->storedsolvals->lpissolved 16197 && (set->lp_resolverestore || lp->storedsolvals->lpsolstat != SCIP_LPSOLSTAT_OPTIMAL || lp->divenolddomchgs < stat->domchgcount) ) 16198 { 16199 SCIP_Bool lperror; 16200 16201 SCIP_CALL( SCIPlpSolveAndEval(lp, set, messagehdlr, blkmem, stat, eventqueue, eventfilter, prob, -1LL, FALSE, FALSE, FALSE, &lperror) ); 16202 if( lperror ) 16203 { 16204 lpNumericalTroubleMessage(messagehdlr, set, stat, SCIP_VERBLEVEL_FULL, "unresolved when resolving LP after diving"); 16205 lp->resolvelperror = TRUE; 16206 } 16207 else if( SCIPlpGetSolstat(lp) != SCIP_LPSOLSTAT_OPTIMAL 16208 && SCIPlpGetSolstat(lp) != SCIP_LPSOLSTAT_INFEASIBLE 16209 && SCIPlpGetSolstat(lp) != SCIP_LPSOLSTAT_UNBOUNDEDRAY 16210 && SCIPlpGetSolstat(lp) != SCIP_LPSOLSTAT_OBJLIMIT ) 16211 { 16212 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL, 16213 "LP was not resolved to a sufficient status after diving\n"); 16214 lp->resolvelperror = TRUE; 16215 } 16216 } 16217 /* otherwise, we can just reload the buffered LP solution values at start of diving; this has the advantage that we 16218 * are guaranteed to continue with the same LP status as before diving, while in numerically difficult cases, a 16219 * re-solve as above can lead to a different LP status 16220 */ 16221 else 16222 { 16223 int c; 16224 int r; 16225 16226 /* if there are lazy bounds, remove them from the LP */ 16227 if( lp->nlazycols > 0 ) 16228 { 16229 /* @todo avoid loosing primal feasibility here after changing the objective already did destroy dual feasibility; 16230 * first resolve LP? 16231 */ 16232 SCIP_CALL( updateLazyBounds(lp, set) ); 16233 assert(lp->diving == lp->divinglazyapplied); 16234 16235 /* flush changes to the LP solver */ 16236 SCIP_CALL( SCIPlpFlush(lp, blkmem, set, prob, eventqueue) ); 16237 } 16238 16239 /* increment lp counter to ensure that we do not use solution values from the last solved diving lp */ 16240 SCIPstatIncrement(stat, set, lpcount); 16241 16242 /* restore LP solution values in lp data, columns and rows */ 16243 if( lp->storedsolvals->lpissolved && 16244 (lp->storedsolvals->lpsolstat == SCIP_LPSOLSTAT_OPTIMAL || 16245 lp->storedsolvals->lpsolstat == SCIP_LPSOLSTAT_UNBOUNDEDRAY || 16246 lp->storedsolvals->lpsolstat == SCIP_LPSOLSTAT_OBJLIMIT || 16247 lp->storedsolvals->lpsolstat == SCIP_LPSOLSTAT_ITERLIMIT || 16248 lp->storedsolvals->lpsolstat == SCIP_LPSOLSTAT_TIMELIMIT || 16249 lp->storedsolvals->lpsolstat == SCIP_LPSOLSTAT_INFEASIBLE) 16250 ) 16251 { 16252 SCIP_CALL( lpRestoreSolVals(lp, blkmem, stat->lpcount) ); 16253 16254 for( c = 0; c < lp->ncols; ++c ) 16255 { 16256 SCIP_CALL( colRestoreSolVals(lp->cols[c], blkmem, stat->lpcount, set->lp_freesolvalbuffers) ); 16257 } 16258 for( r = 0; r < lp->nrows; ++r ) 16259 { 16260 SCIP_CALL( rowRestoreSolVals(lp->rows[r], blkmem, stat->lpcount, set->lp_freesolvalbuffers, lp->storedsolvals->lpsolstat == SCIP_LPSOLSTAT_INFEASIBLE) ); 16261 } 16262 } 16263 else 16264 { 16265 SCIP_CALL( lpRestoreSolVals(lp, blkmem, -1LL) ); 16266 } 16267 } 16268 16269 #ifndef NDEBUG 16270 { 16271 int c; 16272 for( c = 0; c < lp->ncols; ++c ) 16273 { 16274 assert(lp->cols[c] != NULL); 16275 assert(lp->cols[c]->var != NULL); 16276 assert(SCIPvarGetStatus(lp->cols[c]->var) == SCIP_VARSTATUS_COLUMN); 16277 assert(SCIPvarGetCol(lp->cols[c]->var) == lp->cols[c]); 16278 assert(SCIPsetIsEQ(set, SCIPvarGetObj(lp->cols[c]->var), lp->cols[c]->obj)); 16279 assert(SCIPsetIsEQ(set, SCIPvarGetLbLocal(lp->cols[c]->var), lp->cols[c]->lb)); 16280 assert(SCIPsetIsEQ(set, SCIPvarGetUbLocal(lp->cols[c]->var), lp->cols[c]->ub)); 16281 } 16282 } 16283 #endif 16284 16285 return SCIP_OKAY; 16286 } 16287 16288 #define DIVESTACKGROWFACT 1.5 16289 16290 /** records a current row side such that any change will be undone after diving */ 16291 SCIP_RETCODE SCIPlpRecordOldRowSideDive( 16292 SCIP_LP* lp, /**< LP data object */ 16293 SCIP_ROW* row, /**< row affected by the change */ 16294 SCIP_SIDETYPE sidetype /**< side type */ 16295 ) 16296 { 16297 assert(lp != NULL); 16298 assert(row != NULL); 16299 16300 if( lp->ndivechgsides == lp->divechgsidessize ) 16301 { 16302 SCIP_CALL( reallocDiveChgSideArrays(lp, lp->divechgsidessize + 1, DIVESTACKGROWFACT) ); 16303 } 16304 assert(lp->ndivechgsides < lp->divechgsidessize); 16305 16306 lp->divechgsides[lp->ndivechgsides] = (sidetype == SCIP_SIDETYPE_LEFT) ? row->lhs : row->rhs; 16307 lp->divechgsidetypes[lp->ndivechgsides] = sidetype; 16308 lp->divechgrows[lp->ndivechgsides] = row; 16309 lp->ndivechgsides++; 16310 16311 return SCIP_OKAY; 16312 } 16313 16314 /** informs the LP that probing mode was initiated */ 16315 SCIP_RETCODE SCIPlpStartProbing( 16316 SCIP_LP* lp /**< current LP data */ 16317 ) 16318 { 16319 assert(lp != NULL); 16320 assert(!lp->probing); 16321 assert(!lp->strongbranching); 16322 assert(!lp->strongbranchprobing); 16323 16324 lp->probing = TRUE; 16325 16326 return SCIP_OKAY; 16327 } 16328 16329 /** informs the LP that probing mode was finished */ 16330 SCIP_RETCODE SCIPlpEndProbing( 16331 SCIP_LP* lp /**< current LP data */ 16332 ) 16333 { 16334 assert(lp != NULL); 16335 assert(lp->probing); 16336 assert(!lp->strongbranching); 16337 assert(!lp->strongbranchprobing); 16338 16339 lp->probing = FALSE; 16340 16341 return SCIP_OKAY; 16342 } 16343 16344 /** informs the LP that the probing mode is now used for strongbranching */ 16345 void SCIPlpStartStrongbranchProbing( 16346 SCIP_LP* lp /**< current LP data */ 16347 ) 16348 { 16349 assert(lp != NULL); 16350 assert(lp->probing); 16351 assert(!lp->strongbranching); 16352 assert(!lp->strongbranchprobing); 16353 16354 lp->strongbranchprobing = TRUE; 16355 } 16356 16357 /** informs the LP that the probing mode is not used for strongbranching anymore */ 16358 void SCIPlpEndStrongbranchProbing( 16359 SCIP_LP* lp /**< current LP data */ 16360 ) 16361 { 16362 assert(lp != NULL); 16363 assert(lp->probing); 16364 assert(!lp->strongbranching); 16365 assert(lp->strongbranchprobing); 16366 16367 lp->strongbranchprobing = FALSE; 16368 } 16369 16370 /** calculates y*b + min{(c - y*A)*x | lb <= x <= ub} for given vectors y and c; 16371 * the vector b is defined with b[i] = lhs[i] if y[i] >= 0, b[i] = rhs[i] if y[i] < 0 16372 * Calculating this value in interval arithmetics gives a proved lower LP bound for the following reason (assuming, 16373 * we have only left hand sides): 16374 * min{cx | b <= Ax, lb <= x <= ub} 16375 * >= min{cx | yb <= yAx, lb <= x <= ub} (restriction in minimum is relaxed) 16376 * == yb + min{cx - yb | yb <= yAx, lb <= x <= ub} (added yb - yb == 0) 16377 * >= yb + min{cx - yAx | yb <= yAx, lb <= x <= ub} (because yAx >= yb inside minimum) 16378 * >= yb + min{cx - yAx | lb <= x <= ub} (restriction in minimum is relaxed) 16379 */ 16380 static 16381 SCIP_RETCODE provedBound( 16382 SCIP_LP* lp, /**< current LP data */ 16383 SCIP_SET* set, /**< global SCIP settings */ 16384 SCIP_Bool usefarkas, /**< use y = dual Farkas and c = 0 instead of y = dual solution and c = obj? */ 16385 SCIP_Real* bound /**< result of interval arithmetic minimization */ 16386 ) 16387 { 16388 SCIP_INTERVAL* yinter; 16389 SCIP_INTERVAL b; 16390 SCIP_INTERVAL ytb; 16391 SCIP_INTERVAL prod; 16392 SCIP_INTERVAL diff; 16393 SCIP_INTERVAL x; 16394 SCIP_INTERVAL minprod; 16395 SCIP_INTERVAL a; 16396 SCIP_ROW* row; 16397 SCIP_COL* col; 16398 SCIP_Real y; 16399 SCIP_Real c; 16400 int i; 16401 int j; 16402 16403 assert(lp != NULL); 16404 assert(lp->solved); 16405 assert(set != NULL); 16406 assert(bound != NULL); 16407 16408 /* allocate buffer for storing y in interval arithmetic */ 16409 SCIP_CALL( SCIPsetAllocBufferArray(set, &yinter, lp->nrows) ); 16410 16411 /* create y vector in interval arithmetic, setting near zeros to zero; calculate y^Tb */ 16412 SCIPintervalSet(&ytb, 0.0); 16413 for( j = 0; j < lp->nrows; ++j ) 16414 { 16415 row = lp->rows[j]; 16416 assert(row != NULL); 16417 16418 y = (usefarkas ? row->dualfarkas : row->dualsol); 16419 16420 if( SCIPsetIsFeasPositive(set, y) ) 16421 { 16422 SCIPintervalSet(&yinter[j], y); 16423 SCIPintervalSet(&b, row->lhs - row->constant); 16424 } 16425 else if( SCIPsetIsFeasNegative(set, y) ) 16426 { 16427 SCIPintervalSet(&yinter[j], y); 16428 SCIPintervalSet(&b, row->rhs - row->constant); 16429 } 16430 else 16431 { 16432 SCIPintervalSet(&yinter[j], 0.0); 16433 SCIPintervalSet(&b, 0.0); 16434 } 16435 16436 SCIPintervalMul(SCIPsetInfinity(set), &prod, yinter[j], b); 16437 SCIPintervalAdd(SCIPsetInfinity(set), &ytb, ytb, prod); 16438 } 16439 16440 /* calculate min{(c^T - y^TA)x} */ 16441 SCIPintervalSet(&minprod, 0.0); 16442 for( j = 0; j < lp->ncols; ++j ) 16443 { 16444 col = lp->cols[j]; 16445 assert(col != NULL); 16446 assert(col->nunlinked == 0); 16447 16448 SCIPintervalSetBounds(&x, SCIPcolGetLb(col), SCIPcolGetUb(col)); 16449 16450 c = usefarkas ? 0.0 : col->obj; 16451 SCIPintervalSet(&diff, c); 16452 16453 for( i = 0; i < col->nlprows; ++i ) 16454 { 16455 assert(col->rows[i] != NULL); 16456 assert(col->rows[i]->lppos >= 0); 16457 assert(col->linkpos[i] >= 0); 16458 SCIPintervalSet(&a, col->vals[i]); 16459 SCIPintervalMul(SCIPsetInfinity(set), &prod, yinter[col->rows[i]->lppos], a); 16460 SCIPintervalSub(SCIPsetInfinity(set), &diff, diff, prod); 16461 } 16462 16463 #ifndef NDEBUG 16464 for( i = col->nlprows; i < col->len; ++i ) 16465 { 16466 assert(col->rows[i] != NULL); 16467 assert(col->rows[i]->lppos == -1); 16468 assert(col->rows[i]->dualsol == 0.0); 16469 assert(col->rows[i]->dualfarkas == 0.0); 16470 assert(col->linkpos[i] >= 0); 16471 } 16472 #endif 16473 16474 SCIPintervalSetBounds(&x, col->lb, col->ub); 16475 SCIPintervalMul(SCIPsetInfinity(set), &diff, diff, x); 16476 SCIPintervalAdd(SCIPsetInfinity(set), &minprod, minprod, diff); 16477 } 16478 16479 /* add y^Tb */ 16480 SCIPintervalAdd(SCIPsetInfinity(set), &minprod, minprod, ytb); 16481 16482 /* free buffer for storing y in interval arithmetic */ 16483 SCIPsetFreeBufferArray(set, &yinter); 16484 16485 *bound = SCIPintervalGetInf(minprod); 16486 16487 return SCIP_OKAY; 16488 } 16489 16490 /** gets proven lower (dual) bound of last LP solution */ 16491 SCIP_RETCODE SCIPlpGetProvedLowerbound( 16492 SCIP_LP* lp, /**< current LP data */ 16493 SCIP_SET* set, /**< global SCIP settings */ 16494 SCIP_Real* bound /**< pointer to store proven dual bound */ 16495 ) 16496 { 16497 SCIP_CALL( provedBound(lp, set, FALSE, bound) ); 16498 16499 SCIPsetDebugMsg(set, "proved lower bound of LP: %.15g\n", *bound); 16500 16501 return SCIP_OKAY; 16502 } 16503 16504 /** gets proven dual bound of last LP solution */ 16505 SCIP_RETCODE SCIPlpIsInfeasibilityProved( 16506 SCIP_LP* lp, /**< current LP data */ 16507 SCIP_SET* set, /**< global SCIP settings */ 16508 SCIP_Bool* proved /**< pointer to store whether infeasibility is proven */ 16509 ) 16510 { 16511 SCIP_Real bound; 16512 16513 assert(proved != NULL); 16514 16515 SCIP_CALL( provedBound(lp, set, TRUE, &bound) ); 16516 16517 *proved = (bound > 0.0); 16518 16519 SCIPsetDebugMsg(set, "proved Farkas value of LP: %g -> infeasibility %sproved\n", bound, *proved ? "" : "not "); 16520 16521 return SCIP_OKAY; 16522 } 16523 16524 16525 16526 /** writes LP to a file */ 16527 SCIP_RETCODE SCIPlpWrite( 16528 SCIP_LP* lp, /**< current LP data */ 16529 const char* fname /**< file name */ 16530 ) 16531 { 16532 assert(lp != NULL); 16533 assert(lp->flushed); 16534 assert(fname != NULL); 16535 16536 SCIP_CALL( SCIPlpiWriteLP(lp->lpi, fname) ); 16537 16538 return SCIP_OKAY; 16539 } 16540 16541 /** writes MIP relaxation of the current B&B node to a file */ 16542 SCIP_RETCODE SCIPlpWriteMip( 16543 SCIP_LP* lp, /**< current LP data */ 16544 SCIP_SET* set, /**< global SCIP settings */ 16545 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */ 16546 const char* fname, /**< file name */ 16547 SCIP_Bool genericnames, /**< should generic names like x_i and row_j be used in order to avoid 16548 * troubles with reserved symbols? */ 16549 SCIP_Bool origobj, /**< should the original objective function be used? */ 16550 SCIP_OBJSENSE objsense, /**< objective sense */ 16551 SCIP_Real objscale, /**< objective scaling factor */ 16552 SCIP_Real objoffset, /**< objective offset, e.g., caused by variable fixings in presolving */ 16553 SCIP_Bool lazyconss /**< output removable rows as lazy constraints? */ 16554 ) 16555 { 16556 FILE* file; 16557 int i; 16558 int j; 16559 char rowname[SCIP_MAXSTRLEN]; 16560 SCIP_Real coeff; 16561 16562 assert(lp != NULL); 16563 assert(lp->flushed); 16564 assert(fname != NULL); 16565 16566 SCIPsetDebugMsg(set, "Start to write MIP to file <%s>\n", fname); 16567 file = fopen(fname, "w"); 16568 if( file == NULL ) 16569 { 16570 SCIPerrorMessage("cannot open file <%s> for writing\n", fname); 16571 SCIPprintSysError(fname); 16572 return SCIP_FILECREATEERROR; 16573 } 16574 16575 /* print comments */ 16576 if( genericnames ) 16577 SCIPmessageFPrintInfo(messagehdlr, file, "\\ Original Variable and Constraint Names have been replaced by generic names.\n"); 16578 else 16579 { 16580 SCIPmessageFPrintInfo(messagehdlr, file, "\\ Warning: Variable and Constraint Names should not contain special characters like '+', '=' etc.\n"); 16581 SCIPmessageFPrintInfo(messagehdlr, file, "\\ If this is the case, the model may be corrupted!\n"); 16582 } 16583 16584 if( origobj && objoffset != 0.0 ) 16585 { 16586 SCIPmessageFPrintInfo(messagehdlr, file, "\\ An artificial variable 'objoffset' has been added and fixed to 1.\n"); 16587 SCIPmessageFPrintInfo(messagehdlr, file, "\\ Switching this variable to 0 will disable the offset in the objective.\n\n"); 16588 } 16589 16590 /* print objective function */ 16591 /**@note the transformed problem in SCIP is always a minimization problem */ 16592 if( !origobj || objsense == SCIP_OBJSENSE_MINIMIZE ) 16593 SCIPmessageFPrintInfo(messagehdlr, file, "Minimize"); 16594 else 16595 SCIPmessageFPrintInfo(messagehdlr, file, "Maximize"); 16596 16597 /* print objective */ 16598 SCIPmessageFPrintInfo(messagehdlr, file, "\nObj:"); 16599 j = 0; 16600 for( i = 0; i < lp->ncols; ++i ) 16601 { 16602 if( lp->cols[i]->obj != 0.0 ) 16603 { 16604 coeff = lp->cols[i]->obj; 16605 if( origobj ) 16606 { 16607 coeff *= (SCIP_Real) objsense; 16608 coeff *= objscale; 16609 } 16610 16611 if( genericnames ) 16612 SCIPmessageFPrintInfo(messagehdlr, file, " %+.15g x_%d", coeff, lp->cols[i]->lppos); 16613 else 16614 SCIPmessageFPrintInfo(messagehdlr, file, " %+.15g %s", coeff, lp->cols[i]->var->name); 16615 16616 ++j; 16617 if( j % 10 == 0 ) 16618 SCIPmessageFPrintInfo(messagehdlr, file, "\n "); 16619 } 16620 } 16621 /* add artificial variable 'objoffset' to transfer objective offset */ 16622 if( origobj && objoffset != 0.0 ) 16623 SCIPmessageFPrintInfo(messagehdlr, file, " %+.15g objoffset", objoffset * (SCIP_Real) objsense * objscale); 16624 16625 /* print constraint section */ 16626 SCIPmessageFPrintInfo(messagehdlr, file, "\nSubject to\n"); 16627 for( i = 0; i < lp->nrows; i++ ) 16628 { 16629 char type = 'i'; 16630 16631 /* skip removable rows if we want to write them as lazy constraints */ 16632 if ( lazyconss && SCIProwIsRemovable(lp->rows[i]) ) 16633 continue; 16634 16635 /* constraint types: 'l' means: only lhs exists, 'r' means: only rhs exists, 'e' means: both sides exist and are 16636 * equal, 'b' and 'B' mean: both sides exist, if the type is 'b', the lhs will be written, if the type is 'B', 16637 * the rhs will be written. Ergo: set type to b first, change it to 'B' afterwards and go back to WRITEROW. 16638 * type 'i' means: lhs and rhs are both infinite */ 16639 if( SCIPsetIsInfinity(set, REALABS(lp->rows[i]->lhs)) && !SCIPsetIsInfinity(set, REALABS(lp->rows[i]->rhs)) ) 16640 type = 'r'; 16641 else if( !SCIPsetIsInfinity(set, REALABS(lp->rows[i]->lhs)) && SCIPsetIsInfinity(set, REALABS(lp->rows[i]->rhs)) ) 16642 type = 'l'; 16643 else if( !SCIPsetIsInfinity(set, REALABS(lp->rows[i]->lhs)) && SCIPsetIsEQ(set, lp->rows[i]->lhs, lp->rows[i]->rhs) ) 16644 type = 'e'; 16645 else if( !SCIPsetIsInfinity(set, REALABS(lp->rows[i]->lhs)) && !SCIPsetIsInfinity(set, REALABS(lp->rows[i]->rhs)) ) 16646 type = 'b'; 16647 16648 /* print name of row */ 16649 if( genericnames ) 16650 (void) SCIPsnprintf(rowname, SCIP_MAXSTRLEN, "row_%d", lp->rows[i]->lppos); 16651 else 16652 (void) SCIPsnprintf(rowname, SCIP_MAXSTRLEN, "%s", lp->rows[i]->name); 16653 16654 WRITEROW: 16655 switch( type ) 16656 { 16657 case 'r': 16658 case 'l': 16659 case 'e': 16660 if( strlen(rowname) > 0 ) 16661 SCIPmessageFPrintInfo(messagehdlr, file, "%s: ", rowname); 16662 break; 16663 case 'i': 16664 SCIPmessageFPrintInfo(messagehdlr, file, "\\\\ WARNING: The lhs and the rhs of the row with original name <%s>", lp->rows[i]->name); 16665 SCIPmessageFPrintInfo(messagehdlr, file, "are not in a valid range. The following two constraints may be corrupted!\n"); 16666 SCIPmessagePrintWarning(messagehdlr, "The lhs and rhs of row <%s> are not in a valid range.\n", lp->rows[i]->name); 16667 type = 'b'; 16668 /*lint -fallthrough*/ 16669 case 'b': 16670 SCIPmessageFPrintInfo(messagehdlr, file, "%s_lhs: ", rowname); 16671 break; 16672 default: 16673 assert(type == 'B'); 16674 SCIPmessageFPrintInfo(messagehdlr, file, "%s_rhs: ", rowname); 16675 break; 16676 } 16677 16678 /* print coefficients and variables */ 16679 for( j = 0; j < lp->rows[i]->nlpcols; ++j ) 16680 { 16681 if( genericnames ) 16682 SCIPmessageFPrintInfo(messagehdlr, file, " %+.15g x_%d", lp->rows[i]->vals[j], lp->rows[i]->cols[j]->lppos); 16683 else 16684 SCIPmessageFPrintInfo(messagehdlr, file, " %+.15g %s", lp->rows[i]->vals[j], lp->rows[i]->cols[j]->var->name); 16685 16686 if( (j+1) % 10 == 0 ) 16687 SCIPmessageFPrintInfo(messagehdlr, file, "\n "); 16688 } 16689 16690 /* print right hand side */ 16691 switch( type ) 16692 { 16693 case 'b': 16694 SCIPmessageFPrintInfo(messagehdlr, file, " >= %.15g\n", lp->rows[i]->lhs - lp->rows[i]->constant); 16695 type = 'B'; 16696 goto WRITEROW; 16697 case 'l': 16698 SCIPmessageFPrintInfo(messagehdlr, file, " >= %.15g\n", lp->rows[i]->lhs - lp->rows[i]->constant); 16699 break; 16700 case 'B': 16701 case 'r': 16702 SCIPmessageFPrintInfo(messagehdlr, file, " <= %.15g\n", lp->rows[i]->rhs - lp->rows[i]->constant); 16703 break; 16704 case 'e': 16705 SCIPmessageFPrintInfo(messagehdlr, file, " = %.15g\n", lp->rows[i]->lhs - lp->rows[i]->constant); 16706 break; 16707 default: 16708 SCIPerrorMessage("Undefined row type!\n"); 16709 fclose(file); 16710 return SCIP_ERROR; 16711 } 16712 } 16713 16714 if ( lazyconss ) 16715 { 16716 /* print lazy constraint section */ 16717 SCIPmessageFPrintInfo(messagehdlr, file, "lazy constraints\n"); 16718 for( i = 0; i < lp->nrows; i++ ) 16719 { 16720 char type = 'i'; 16721 16722 /* skip non-removable rows if we want to write lazy constraints */ 16723 if ( ! SCIProwIsRemovable(lp->rows[i]) ) 16724 continue; 16725 16726 /* constraint types: 'l' means: only lhs exists, 'r' means: only rhs exists, 'e' means: both sides exist and are 16727 * equal, 'b' and 'B' mean: both sides exist, if the type is 'b', the lhs will be written, if the type is 'B', 16728 * the rhs will be written. Ergo: set type to b first, change it to 'B' afterwards and go back to WRITEROW. 16729 * type 'i' means: lhs and rhs are both infinite */ 16730 if( SCIPsetIsInfinity(set, REALABS(lp->rows[i]->lhs)) && !SCIPsetIsInfinity(set, REALABS(lp->rows[i]->rhs)) ) 16731 type = 'r'; 16732 else if( !SCIPsetIsInfinity(set, REALABS(lp->rows[i]->lhs)) && SCIPsetIsInfinity(set, REALABS(lp->rows[i]->rhs)) ) 16733 type = 'l'; 16734 else if( !SCIPsetIsInfinity(set, REALABS(lp->rows[i]->lhs)) && SCIPsetIsEQ(set, lp->rows[i]->lhs, lp->rows[i]->rhs) ) 16735 type = 'e'; 16736 else if( !SCIPsetIsInfinity(set, REALABS(lp->rows[i]->lhs)) && !SCIPsetIsInfinity(set, REALABS(lp->rows[i]->rhs)) ) 16737 type = 'b'; 16738 16739 /* print name of row */ 16740 if( genericnames ) 16741 (void) SCIPsnprintf(rowname, SCIP_MAXSTRLEN, "row_%d", lp->rows[i]->lppos); 16742 else 16743 (void) SCIPsnprintf(rowname, SCIP_MAXSTRLEN, "%s", lp->rows[i]->name); 16744 16745 WRITELAZYROW: 16746 switch( type ) 16747 { 16748 case 'r': 16749 case 'l': 16750 case 'e': 16751 if( strlen(rowname) > 0 ) 16752 SCIPmessageFPrintInfo(messagehdlr, file, "%s: ", rowname); 16753 break; 16754 case 'i': 16755 SCIPmessageFPrintInfo(messagehdlr, file, "\\\\ WARNING: The lhs and the rhs of the row with original name <%s>", lp->rows[i]->name); 16756 SCIPmessageFPrintInfo(messagehdlr, file, "are not in a valid range. The following two constraints may be corrupted!\n"); 16757 SCIPmessagePrintWarning(messagehdlr, "The lhs and rhs of row <%s> are not in a valid range.\n",lp->rows[i]->name); 16758 type = 'b'; 16759 /*lint -fallthrough*/ 16760 case 'b': 16761 SCIPmessageFPrintInfo(messagehdlr, file, "%s_lhs: ", rowname); 16762 break; 16763 default: 16764 assert(type == 'B'); 16765 SCIPmessageFPrintInfo(messagehdlr, file, "%s_rhs: ", rowname); 16766 break; 16767 } 16768 16769 /* print coefficients and variables */ 16770 for( j = 0; j < lp->rows[i]->nlpcols; ++j ) 16771 { 16772 if( genericnames ) 16773 SCIPmessageFPrintInfo(messagehdlr, file, " %+.15g x_%d", lp->rows[i]->vals[j], lp->rows[i]->cols[j]->lppos); 16774 else 16775 SCIPmessageFPrintInfo(messagehdlr, file, " %+.15g %s", lp->rows[i]->vals[j], lp->rows[i]->cols[j]->var->name); 16776 16777 if( (j+1) % 10 == 0 ) 16778 SCIPmessageFPrintInfo(messagehdlr, file, "\n "); 16779 } 16780 16781 /* print right hand side */ 16782 switch( type ) 16783 { 16784 case 'b': 16785 SCIPmessageFPrintInfo(messagehdlr, file, " >= %.15g\n", lp->rows[i]->lhs - lp->rows[i]->constant); 16786 type = 'B'; 16787 goto WRITELAZYROW; 16788 case 'l': 16789 SCIPmessageFPrintInfo(messagehdlr, file, " >= %.15g\n", lp->rows[i]->lhs - lp->rows[i]->constant); 16790 break; 16791 case 'B': 16792 case 'r': 16793 SCIPmessageFPrintInfo(messagehdlr, file, " <= %.15g\n", lp->rows[i]->rhs - lp->rows[i]->constant); 16794 break; 16795 case 'e': 16796 SCIPmessageFPrintInfo(messagehdlr, file, " = %.15g\n", lp->rows[i]->lhs - lp->rows[i]->constant); 16797 break; 16798 default: 16799 SCIPerrorMessage("Undefined row type!\n"); 16800 fclose(file); 16801 return SCIP_ERROR; 16802 } 16803 } 16804 } 16805 16806 /* print variable bounds */ 16807 SCIPmessageFPrintInfo(messagehdlr, file, "Bounds\n"); 16808 for( i = 0; i < lp->ncols; ++i ) 16809 { 16810 if( !SCIPsetIsInfinity(set,-lp->cols[i]->lb) || !SCIPsetIsInfinity(set,lp->cols[i]->ub) ) 16811 { 16812 /* print lower bound as far this one is not infinity */ 16813 if( !SCIPsetIsInfinity(set,-lp->cols[i]->lb) ) 16814 SCIPmessageFPrintInfo(messagehdlr, file, " %.15g <=", lp->cols[i]->lb); 16815 16816 /* print variable name */ 16817 if( genericnames ) 16818 SCIPmessageFPrintInfo(messagehdlr, file, " x_%d ", lp->cols[i]->lppos); 16819 else 16820 SCIPmessageFPrintInfo(messagehdlr, file, " %s ", lp->cols[i]->var->name); 16821 16822 /* print upper bound as far this one is not infinity */ 16823 if( !SCIPsetIsInfinity(set,lp->cols[i]->ub) ) 16824 SCIPmessageFPrintInfo(messagehdlr, file, "<= %.15g", lp->cols[i]->ub); 16825 SCIPmessageFPrintInfo(messagehdlr, file, "\n"); 16826 } 16827 } 16828 if( origobj && objoffset != 0.0 ) 16829 SCIPmessageFPrintInfo(messagehdlr, file, " objoffset = 1\n"); 16830 16831 /* print integer variables */ 16832 SCIPmessageFPrintInfo(messagehdlr, file, "Generals\n"); 16833 j = 0; 16834 for( i = 0; i < lp->ncols; ++i ) 16835 { 16836 if( SCIPvarIsIntegral(lp->cols[i]->var) ) 16837 { 16838 /* print variable name */ 16839 if( genericnames ) 16840 SCIPmessageFPrintInfo(messagehdlr, file, " x_%d ", lp->cols[i]->lppos); 16841 else 16842 SCIPmessageFPrintInfo(messagehdlr, file, " %s ", lp->cols[i]->var->name); 16843 16844 j++; 16845 if( j % 10 == 0 ) 16846 SCIPmessageFPrintInfo(messagehdlr, file, "\n"); 16847 } 16848 } 16849 16850 SCIPmessageFPrintInfo(messagehdlr, file, "\nEnd"); 16851 fclose(file); 16852 16853 return SCIP_OKAY; 16854 } 16855 16856 /* 16857 * simple functions implemented as defines 16858 */ 16859 16860 /* In debug mode, the following methods are implemented as function calls to ensure 16861 * type validity. 16862 * In optimized mode, the methods are implemented as defines to improve performance. 16863 * However, we want to have them in the library anyways, so we have to undef the defines. 16864 */ 16865 16866 #undef SCIPcolGetObj 16867 #undef SCIPcolGetLb 16868 #undef SCIPcolGetUb 16869 #undef SCIPcolGetBestBound 16870 #undef SCIPcolGetPrimsol 16871 #undef SCIPcolGetMinPrimsol 16872 #undef SCIPcolGetMaxPrimsol 16873 #undef SCIPcolGetBasisStatus 16874 #undef SCIPcolGetVar 16875 #undef SCIPcolGetIndex 16876 #undef SCIPcolGetVarProbindex 16877 #undef SCIPcolIsIntegral 16878 #undef SCIPcolIsRemovable 16879 #undef SCIPcolGetLPPos 16880 #undef SCIPcolGetLPDepth 16881 #undef SCIPcolIsInLP 16882 #undef SCIPcolGetNNonz 16883 #undef SCIPcolGetNLPNonz 16884 #undef SCIPcolGetRows 16885 #undef SCIPcolGetVals 16886 #undef SCIPcolGetStrongbranchNode 16887 #undef SCIPcolGetNStrongbranchs 16888 #undef SCIPcolGetAge 16889 #undef SCIPboundtypeOpposite 16890 #undef SCIProwGetNNonz 16891 #undef SCIProwGetNLPNonz 16892 #undef SCIProwGetCols 16893 #undef SCIProwGetVals 16894 #undef SCIProwGetConstant 16895 #undef SCIProwGetNorm 16896 #undef SCIProwGetSumNorm 16897 #undef SCIProwGetLhs 16898 #undef SCIProwGetRhs 16899 #undef SCIProwGetDualsol 16900 #undef SCIProwGetDualfarkas 16901 #undef SCIProwGetBasisStatus 16902 #undef SCIProwGetName 16903 #undef SCIProwGetIndex 16904 #undef SCIProwGetAge 16905 #undef SCIProwGetRank 16906 #undef SCIProwIsIntegral 16907 #undef SCIProwIsLocal 16908 #undef SCIProwIsModifiable 16909 #undef SCIProwIsRemovable 16910 #undef SCIProwGetOrigintype 16911 #undef SCIProwGetOriginCons 16912 #undef SCIProwGetOriginConshdlr 16913 #undef SCIProwGetOriginSepa 16914 #undef SCIProwIsInGlobalCutpool 16915 #undef SCIProwGetLPPos 16916 #undef SCIProwGetLPDepth 16917 #undef SCIProwIsInLP 16918 #undef SCIProwGetActiveLPCount 16919 #undef SCIProwGetNLPsAfterCreation 16920 #undef SCIProwChgRank 16921 #undef SCIPlpGetCols 16922 #undef SCIPlpGetNCols 16923 #undef SCIPlpGetRows 16924 #undef SCIPlpGetNRows 16925 #undef SCIPlpGetNewcols 16926 #undef SCIPlpGetNNewcols 16927 #undef SCIPlpGetNewrows 16928 #undef SCIPlpGetNNewrows 16929 #undef SCIPlpGetObjNorm 16930 #undef SCIPlpGetRootObjval 16931 #undef SCIPlpGetRootColumnObjval 16932 #undef SCIPlpGetRootLooseObjval 16933 #undef SCIPlpGetLPI 16934 #undef SCIPlpSetIsRelax 16935 #undef SCIPlpIsRelax 16936 #undef SCIPlpIsSolved 16937 #undef SCIPlpIsSolBasic 16938 #undef SCIPlpDiving 16939 #undef SCIPlpDivingObjChanged 16940 #undef SCIPlpMarkDivingObjChanged 16941 #undef SCIPlpUnmarkDivingObjChanged 16942 #undef SCIPlpDivingRowsChanged 16943 #undef SCIPlpIsFeasEQ 16944 #undef SCIPlpIsFeasLT 16945 #undef SCIPlpIsFeasLE 16946 #undef SCIPlpIsFeasGT 16947 #undef SCIPlpIsFeasGE 16948 #undef SCIPlpIsFeasZero 16949 #undef SCIPlpIsFeasPositive 16950 #undef SCIPlpIsFeasNegative 16951 16952 /** gets objective value of column */ 16953 SCIP_Real SCIPcolGetObj( 16954 SCIP_COL* col /**< LP column */ 16955 ) 16956 { 16957 assert(col != NULL); 16958 16959 return col->obj; 16960 } 16961 16962 /** gets lower bound of column */ 16963 SCIP_Real SCIPcolGetLb( 16964 SCIP_COL* col /**< LP column */ 16965 ) 16966 { 16967 assert(col != NULL); 16968 16969 return col->lb; 16970 } 16971 16972 /** gets upper bound of column */ 16973 SCIP_Real SCIPcolGetUb( 16974 SCIP_COL* col /**< LP column */ 16975 ) 16976 { 16977 assert(col != NULL); 16978 16979 return col->ub; 16980 } 16981 16982 /** gets best bound of column with respect to the objective function */ 16983 SCIP_Real SCIPcolGetBestBound( 16984 SCIP_COL* col /**< LP column */ 16985 ) 16986 { 16987 assert(col != NULL); 16988 16989 if( col->obj >= 0.0 ) 16990 return col->lb; 16991 else 16992 return col->ub; 16993 } 16994 16995 /** gets the primal LP solution of a column */ 16996 SCIP_Real SCIPcolGetPrimsol( 16997 SCIP_COL* col /**< LP column */ 16998 ) 16999 { 17000 assert(col != NULL); 17001 17002 if( col->lppos >= 0 ) 17003 return col->primsol; 17004 else 17005 return 0.0; 17006 } 17007 17008 /** gets the minimal LP solution value, this column ever assumed */ 17009 SCIP_Real SCIPcolGetMinPrimsol( 17010 SCIP_COL* col /**< LP column */ 17011 ) 17012 { 17013 assert(col != NULL); 17014 17015 return col->minprimsol; 17016 } 17017 17018 /** gets the maximal LP solution value, this column ever assumed */ 17019 SCIP_Real SCIPcolGetMaxPrimsol( 17020 SCIP_COL* col /**< LP column */ 17021 ) 17022 { 17023 assert(col != NULL); 17024 17025 return col->maxprimsol; 17026 } 17027 17028 /** gets the basis status of a column in the LP solution; only valid for LPs with status SCIP_LPSOLSTAT_OPTIMAL 17029 * and with SCIPisLPSolBasic(scip) == TRUE; returns SCIP_BASESTAT_ZERO for columns not in the current SCIP_LP 17030 */ 17031 SCIP_BASESTAT SCIPcolGetBasisStatus( 17032 SCIP_COL* col /**< LP column */ 17033 ) 17034 { 17035 assert(col != NULL); 17036 assert(col->lppos >= 0 || (SCIP_BASESTAT)col->basisstatus == SCIP_BASESTAT_ZERO); 17037 17038 return (SCIP_BASESTAT)col->basisstatus; 17039 } 17040 17041 /** gets variable this column represents */ 17042 SCIP_VAR* SCIPcolGetVar( 17043 SCIP_COL* col /**< LP column */ 17044 ) 17045 { 17046 assert(col != NULL); 17047 17048 return col->var; 17049 } 17050 17051 /** gets unique index of col */ 17052 int SCIPcolGetIndex( 17053 SCIP_COL* col /**< LP col */ 17054 ) 17055 { 17056 assert(col != NULL); 17057 17058 return col->index; 17059 } 17060 17061 /** gets probindex of corresponding variable */ 17062 int SCIPcolGetVarProbindex( 17063 SCIP_COL* col /**< LP col */ 17064 ) 17065 { 17066 assert(col != NULL); 17067 17068 return col->var_probindex; 17069 } 17070 17071 /** returns whether the associated variable is of integral type (binary, integer, implicit integer) */ 17072 SCIP_Bool SCIPcolIsIntegral( 17073 SCIP_COL* col /**< LP column */ 17074 ) 17075 { 17076 assert(col != NULL); 17077 assert(SCIPvarIsIntegral(col->var) == col->integral); 17078 17079 return col->integral; 17080 } 17081 17082 /** returns TRUE iff column is removable from the LP (due to aging or cleanup) */ 17083 SCIP_Bool SCIPcolIsRemovable( 17084 SCIP_COL* col /**< LP column */ 17085 ) 17086 { 17087 assert(col != NULL); 17088 17089 return col->removable; 17090 } 17091 17092 /** gets position of column in current LP, or -1 if it is not in LP */ 17093 int SCIPcolGetLPPos( 17094 SCIP_COL* col /**< LP column */ 17095 ) 17096 { 17097 assert(col != NULL); 17098 assert((col->lppos == -1) == (col->lpdepth == -1)); 17099 17100 return col->lppos; 17101 } 17102 17103 /** gets depth in the tree where the column entered the LP, or -1 if it is not in LP */ 17104 int SCIPcolGetLPDepth( 17105 SCIP_COL* col /**< LP column */ 17106 ) 17107 { 17108 assert(col != NULL); 17109 assert((col->lppos == -1) == (col->lpdepth == -1)); 17110 17111 return col->lpdepth; 17112 } 17113 17114 /** returns TRUE iff column is member of current LP */ 17115 SCIP_Bool SCIPcolIsInLP( 17116 SCIP_COL* col /**< LP column */ 17117 ) 17118 { 17119 assert(col != NULL); 17120 assert((col->lppos == -1) == (col->lpdepth == -1)); 17121 17122 return (col->lppos >= 0); 17123 } 17124 17125 /** get number of nonzero entries in column vector */ 17126 int SCIPcolGetNNonz( 17127 SCIP_COL* col /**< LP column */ 17128 ) 17129 { 17130 assert(col != NULL); 17131 17132 return col->len; 17133 } 17134 17135 /** get number of nonzero entries in column vector, that correspond to rows currently in the SCIP_LP; 17136 * 17137 * @warning This method is only applicable on columns, that are completely linked to their rows (e.g. a column 17138 * that is in the current LP and the LP was solved, or a column that was in a solved LP and didn't change afterwards 17139 */ 17140 int SCIPcolGetNLPNonz( 17141 SCIP_COL* col /**< LP column */ 17142 ) 17143 { 17144 assert(col != NULL); 17145 assert(col->nunlinked == 0); 17146 17147 return col->nlprows; 17148 } 17149 17150 /** gets array with rows of nonzero entries */ 17151 SCIP_ROW** SCIPcolGetRows( 17152 SCIP_COL* col /**< LP column */ 17153 ) 17154 { 17155 assert(col != NULL); 17156 17157 return col->rows; 17158 } 17159 17160 /** gets array with coefficients of nonzero entries */ 17161 SCIP_Real* SCIPcolGetVals( 17162 SCIP_COL* col /**< LP column */ 17163 ) 17164 { 17165 assert(col != NULL); 17166 17167 return col->vals; 17168 } 17169 17170 /** gets node number of the last node in current branch and bound run, where strong branching was used on the 17171 * given column, or -1 if strong branching was never applied to the column in current run 17172 */ 17173 SCIP_Longint SCIPcolGetStrongbranchNode( 17174 SCIP_COL* col /**< LP column */ 17175 ) 17176 { 17177 assert(col != NULL); 17178 17179 return col->sbnode; 17180 } 17181 17182 /** gets number of times, strong branching was applied in current run on the given column */ 17183 int SCIPcolGetNStrongbranchs( 17184 SCIP_COL* col /**< LP column */ 17185 ) 17186 { 17187 assert(col != NULL); 17188 17189 return col->nsbcalls; 17190 } 17191 17192 /** gets the age of a column, i.e., the total number of successive times a column was in the LP and was 0.0 in the solution */ 17193 int SCIPcolGetAge( 17194 SCIP_COL* col /**< LP column */ 17195 ) 17196 { 17197 assert(col != NULL); 17198 17199 return col->age; 17200 } 17201 17202 /** gets opposite bound type of given bound type */ 17203 SCIP_BOUNDTYPE SCIPboundtypeOpposite( 17204 SCIP_BOUNDTYPE boundtype /**< type of bound (lower or upper) */ 17205 ) 17206 { 17207 assert(boundtype == SCIP_BOUNDTYPE_LOWER || boundtype == SCIP_BOUNDTYPE_UPPER); 17208 17209 return (boundtype == SCIP_BOUNDTYPE_LOWER ? SCIP_BOUNDTYPE_UPPER : SCIP_BOUNDTYPE_LOWER); 17210 } 17211 17212 /** get number of nonzero entries in row vector */ 17213 int SCIProwGetNNonz( 17214 SCIP_ROW* row /**< LP row */ 17215 ) 17216 { 17217 assert(row != NULL); 17218 17219 return row->len; 17220 } 17221 17222 /** get number of nonzero entries in row vector, that correspond to columns currently in the SCIP_LP; 17223 * 17224 * @warning This method is only applicable on rows, that are completely linked to their columns (e.g. a row 17225 * that is in the current LP and the LP was solved, or a row that was in a solved LP and didn't change afterwards 17226 */ 17227 int SCIProwGetNLPNonz( 17228 SCIP_ROW* row /**< LP row */ 17229 ) 17230 { 17231 assert(row != NULL); 17232 assert(row->nunlinked == 0); 17233 17234 return row->nlpcols; 17235 } 17236 17237 /** gets array with columns of nonzero entries */ 17238 SCIP_COL** SCIProwGetCols( 17239 SCIP_ROW* row /**< LP row */ 17240 ) 17241 { 17242 assert(row != NULL); 17243 17244 return row->cols; 17245 } 17246 17247 /** gets array with coefficients of nonzero entries */ 17248 SCIP_Real* SCIProwGetVals( 17249 SCIP_ROW* row /**< LP row */ 17250 ) 17251 { 17252 assert(row != NULL); 17253 17254 return row->vals; 17255 } 17256 17257 /** gets constant shift of row */ 17258 SCIP_Real SCIProwGetConstant( 17259 SCIP_ROW* row /**< LP row */ 17260 ) 17261 { 17262 assert(row != NULL); 17263 17264 return row->constant; 17265 } 17266 17267 /** gets Euclidean norm of row vector */ 17268 SCIP_Real SCIProwGetNorm( 17269 SCIP_ROW* row /**< LP row */ 17270 ) 17271 { 17272 assert(row != NULL); 17273 17274 checkRowSqrnorm(row); 17275 17276 return sqrt(row->sqrnorm); 17277 } 17278 17279 /** gets sum norm of row vector (sum of absolute values of coefficients) */ 17280 SCIP_Real SCIProwGetSumNorm( 17281 SCIP_ROW* row /**< LP row */ 17282 ) 17283 { 17284 assert(row != NULL); 17285 17286 checkRowSumnorm(row); 17287 17288 return row->sumnorm; 17289 } 17290 17291 /** returns the left hand side of the row */ 17292 SCIP_Real SCIProwGetLhs( 17293 SCIP_ROW* row /**< LP row */ 17294 ) 17295 { 17296 assert(row != NULL); 17297 17298 return row->lhs; 17299 } 17300 17301 /** returns the right hand side of the row */ 17302 SCIP_Real SCIProwGetRhs( 17303 SCIP_ROW* row /**< LP row */ 17304 ) 17305 { 17306 assert(row != NULL); 17307 17308 return row->rhs; 17309 } 17310 17311 /** gets the dual LP solution of a row */ 17312 SCIP_Real SCIProwGetDualsol( 17313 SCIP_ROW* row /**< LP row */ 17314 ) 17315 { 17316 assert(row != NULL); 17317 17318 if( row->lppos >= 0 ) 17319 return row->dualsol; 17320 else 17321 return 0.0; 17322 } 17323 17324 /** gets the dual Farkas coefficient of a row in an infeasible LP */ 17325 SCIP_Real SCIProwGetDualfarkas( 17326 SCIP_ROW* row /**< LP row */ 17327 ) 17328 { 17329 assert(row != NULL); 17330 17331 if( row->lppos >= 0 ) 17332 return row->dualfarkas; 17333 else 17334 return 0.0; 17335 } 17336 17337 /** gets the basis status of a row in the LP solution; only valid for LPs with status SCIP_LPSOLSTAT_OPTIMAL 17338 * and with SCIPisLPSolBasic(scip) == TRUE; returns SCIP_BASESTAT_BASIC for rows not in the current SCIP_LP 17339 */ 17340 SCIP_BASESTAT SCIProwGetBasisStatus( 17341 SCIP_ROW* row /**< LP row */ 17342 ) 17343 { 17344 assert(row != NULL); 17345 assert(row->lppos >= 0 || (SCIP_BASESTAT)row->basisstatus == SCIP_BASESTAT_BASIC); 17346 17347 return (SCIP_BASESTAT)row->basisstatus; 17348 } 17349 17350 /** returns the name of the row */ 17351 const char* SCIProwGetName( 17352 SCIP_ROW* row /**< LP row */ 17353 ) 17354 { 17355 assert(row != NULL); 17356 17357 return row->name; 17358 } 17359 17360 /** gets unique index of row */ 17361 int SCIProwGetIndex( 17362 SCIP_ROW* row /**< LP row */ 17363 ) 17364 { 17365 assert(row != NULL); 17366 17367 return row->index; 17368 } 17369 17370 /** gets age of row */ 17371 int SCIProwGetAge( 17372 SCIP_ROW* row /**< LP row */ 17373 ) 17374 { 17375 assert(row != NULL); 17376 17377 return row->age; 17378 } 17379 17380 /** gets rank of row */ 17381 int SCIProwGetRank( 17382 SCIP_ROW* row /**< LP row */ 17383 ) 17384 { 17385 assert(row != NULL); 17386 17387 return row->rank; 17388 } 17389 17390 /** returns TRUE iff the activity of the row (without the row's constant) is always integral in a feasible solution */ 17391 SCIP_Bool SCIProwIsIntegral( 17392 SCIP_ROW* row /**< LP row */ 17393 ) 17394 { 17395 assert(row != NULL); 17396 17397 return row->integral; 17398 } 17399 17400 /** returns TRUE iff row is only valid locally */ 17401 SCIP_Bool SCIProwIsLocal( 17402 SCIP_ROW* row /**< LP row */ 17403 ) 17404 { 17405 assert(row != NULL); 17406 17407 return row->local; 17408 } 17409 17410 /** returns TRUE iff row is modifiable during node processing (subject to column generation) */ 17411 SCIP_Bool SCIProwIsModifiable( 17412 SCIP_ROW* row /**< LP row */ 17413 ) 17414 { 17415 assert(row != NULL); 17416 17417 return row->modifiable; 17418 } 17419 17420 /** returns TRUE iff row is removable from the LP (due to aging or cleanup) */ 17421 SCIP_Bool SCIProwIsRemovable( 17422 SCIP_ROW* row /**< LP row */ 17423 ) 17424 { 17425 assert(row != NULL); 17426 17427 return row->removable; 17428 } 17429 17430 /** returns type of origin that created the row */ 17431 SCIP_ROWORIGINTYPE SCIProwGetOrigintype( 17432 SCIP_ROW* row /**< LP row */ 17433 ) 17434 { 17435 assert( row != NULL ); 17436 17437 return (SCIP_ROWORIGINTYPE) row->origintype; 17438 } 17439 17440 /** returns origin constraint that created the row (NULL if not available) */ 17441 SCIP_CONS* SCIProwGetOriginCons( 17442 SCIP_ROW* row /**< LP row */ 17443 ) 17444 { 17445 assert( row != NULL ); 17446 17447 if ( (SCIP_ROWORIGINTYPE) row->origintype == SCIP_ROWORIGINTYPE_CONS ) 17448 { 17449 assert( row->origin != NULL ); 17450 return (SCIP_CONS*) row->origin; 17451 } 17452 return NULL; 17453 } 17454 17455 /** returns origin constraint handler that created the row (NULL if not available) */ 17456 SCIP_CONSHDLR* SCIProwGetOriginConshdlr( 17457 SCIP_ROW* row /**< LP row */ 17458 ) 17459 { 17460 assert( row != NULL ); 17461 17462 if ( (SCIP_ROWORIGINTYPE) row->origintype == SCIP_ROWORIGINTYPE_CONSHDLR ) 17463 { 17464 assert( row->origin != NULL ); 17465 return (SCIP_CONSHDLR*) row->origin; 17466 } 17467 else if( (SCIP_ROWORIGINTYPE) row->origintype == SCIP_ROWORIGINTYPE_CONS ) 17468 { 17469 assert(row->origin != NULL); 17470 return SCIPconsGetHdlr((SCIP_CONS*)row->origin); 17471 } 17472 return NULL; 17473 } 17474 17475 /** returns origin separator that created the row (NULL if not available) */ 17476 SCIP_SEPA* SCIProwGetOriginSepa( 17477 SCIP_ROW* row /**< LP row */ 17478 ) 17479 { 17480 assert( row != NULL ); 17481 17482 if ( (SCIP_ROWORIGINTYPE) row->origintype == SCIP_ROWORIGINTYPE_SEPA ) 17483 { 17484 assert( row->origin != NULL ); 17485 return (SCIP_SEPA*) row->origin; 17486 } 17487 return NULL; 17488 } 17489 17490 /** returns TRUE iff row is member of the global cut pool */ 17491 SCIP_Bool SCIProwIsInGlobalCutpool( 17492 SCIP_ROW* row /**< LP row */ 17493 ) 17494 { 17495 assert(row != NULL); 17496 17497 return row->inglobalcutpool; 17498 } 17499 17500 /** gets position of row in current LP, or -1 if it is not in LP */ 17501 int SCIProwGetLPPos( 17502 SCIP_ROW* row /**< LP row */ 17503 ) 17504 { 17505 assert(row != NULL); 17506 assert((row->lppos == -1) == (row->lpdepth == -1)); 17507 17508 return row->lppos; 17509 } 17510 17511 /** gets depth in the tree where the row entered the LP, or -1 if it is not in LP */ 17512 int SCIProwGetLPDepth( 17513 SCIP_ROW* row /**< LP row */ 17514 ) 17515 { 17516 assert(row != NULL); 17517 assert((row->lppos == -1) == (row->lpdepth == -1)); 17518 17519 return row->lpdepth; 17520 } 17521 17522 /** returns TRUE iff row is member of current LP */ 17523 SCIP_Bool SCIProwIsInLP( 17524 SCIP_ROW* row /**< LP row */ 17525 ) 17526 { 17527 assert(row != NULL); 17528 assert((row->lppos == -1) == (row->lpdepth == -1)); 17529 17530 return (row->lppos >= 0); 17531 } 17532 17533 /** changes the rank of LP row */ 17534 void SCIProwChgRank( 17535 SCIP_ROW* row, /**< LP row */ 17536 int rank /**< new value for rank */ 17537 ) 17538 { 17539 assert(row != NULL); 17540 17541 row->rank = rank; 17542 } 17543 17544 /** returns the number of times that this row has been sharp in an optimal LP solution */ 17545 SCIP_Longint SCIProwGetActiveLPCount( 17546 SCIP_ROW* row /**< row */ 17547 ) 17548 { 17549 assert(row != NULL); 17550 17551 return row->activeinlpcounter; 17552 } 17553 17554 /** returns the number of LPs since this row has been created */ 17555 SCIP_Longint SCIProwGetNLPsAfterCreation( 17556 SCIP_ROW* row /**< row */ 17557 ) 17558 { 17559 assert(row != NULL); 17560 17561 return row->nlpsaftercreation; 17562 } 17563 17564 /** gets array with columns of the LP */ 17565 SCIP_COL** SCIPlpGetCols( 17566 SCIP_LP* lp /**< current LP data */ 17567 ) 17568 { 17569 assert(lp != NULL); 17570 17571 return lp->cols; 17572 } 17573 17574 /** gets current number of columns in LP */ 17575 int SCIPlpGetNCols( 17576 SCIP_LP* lp /**< current LP data */ 17577 ) 17578 { 17579 assert(lp != NULL); 17580 17581 return lp->ncols; 17582 } 17583 17584 /** gets current number of unfixed columns in LP */ 17585 int SCIPlpGetNUnfixedCols( 17586 SCIP_LP* lp, /**< current LP data */ 17587 SCIP_Real eps /**< numerical tolerance */ 17588 ) 17589 { 17590 SCIP_COL** lpcols; 17591 int nlpcols; 17592 int nunfixedcols; 17593 int c; 17594 17595 assert(lp != NULL); 17596 assert(eps > 0.0); 17597 17598 lpcols = lp->cols; 17599 nlpcols = lp->ncols; 17600 17601 nunfixedcols = 0; 17602 for( c = 0; c < nlpcols; ++c ) 17603 { 17604 if( lpcols[c]->ub - lpcols[c]->lb > eps ) 17605 ++nunfixedcols; 17606 } 17607 17608 return nunfixedcols; 17609 } 17610 17611 /** gets array with rows of the LP */ 17612 SCIP_ROW** SCIPlpGetRows( 17613 SCIP_LP* lp /**< current LP data */ 17614 ) 17615 { 17616 assert(lp != NULL); 17617 17618 return lp->rows; 17619 } 17620 17621 /** gets current number of rows in LP */ 17622 int SCIPlpGetNRows( 17623 SCIP_LP* lp /**< current LP data */ 17624 ) 17625 { 17626 assert(lp != NULL); 17627 17628 return lp->nrows; 17629 } 17630 17631 /** gets array with newly added columns after the last mark */ 17632 SCIP_COL** SCIPlpGetNewcols( 17633 SCIP_LP* lp /**< current LP data */ 17634 ) 17635 { 17636 assert(lp != NULL); 17637 assert(0 <= lp->firstnewcol && lp->firstnewcol <= lp->ncols); 17638 17639 return &(lp->cols[lp->firstnewcol]); 17640 } 17641 17642 /** gets number of newly added columns after the last mark */ 17643 int SCIPlpGetNNewcols( 17644 SCIP_LP* lp /**< current LP data */ 17645 ) 17646 { 17647 assert(lp != NULL); 17648 assert(0 <= lp->firstnewcol && lp->firstnewcol <= lp->ncols); 17649 17650 return lp->ncols - lp->firstnewcol; 17651 } 17652 17653 /** gets array with newly added rows after the last mark */ 17654 SCIP_ROW** SCIPlpGetNewrows( 17655 SCIP_LP* lp /**< current LP data */ 17656 ) 17657 { 17658 assert(lp != NULL); 17659 assert(0 <= lp->firstnewrow && lp->firstnewrow <= lp->nrows); 17660 17661 return &(lp->rows[lp->firstnewrow]); 17662 } 17663 17664 /** gets number of newly added rows after the last mark */ 17665 int SCIPlpGetNNewrows( 17666 SCIP_LP* lp /**< current LP data */ 17667 ) 17668 { 17669 assert(lp != NULL); 17670 assert(0 <= lp->firstnewrow && lp->firstnewrow <= lp->nrows); 17671 17672 return lp->nrows - lp->firstnewrow; 17673 } 17674 17675 /** recalculates Euclidean norm of objective function vector of column variables if it have gotten unreliable during calculation */ 17676 void SCIPlpRecalculateObjSqrNorm( 17677 SCIP_SET* set, /**< global SCIP settings */ 17678 SCIP_LP* lp /**< LP data */ 17679 ) 17680 { 17681 if( lp->objsqrnormunreliable ) 17682 { 17683 SCIP_COL** cols; 17684 int c; 17685 17686 cols = lp->cols; 17687 assert(cols != NULL || lp->ncols == 0); 17688 17689 lp->objsqrnorm = 0.0; 17690 17691 for( c = lp->ncols - 1; c >= 0; --c ) 17692 { 17693 lp->objsqrnorm += SQR(cols[c]->unchangedobj); /*lint !e613*/ 17694 } 17695 assert(SCIPsetIsGE(set, lp->objsqrnorm, 0.0)); 17696 17697 /* due to numerical troubles it still can appear that lp->objsqrnorm is a little bit smaller than 0 */ 17698 lp->objsqrnorm = MAX(lp->objsqrnorm, 0.0); 17699 17700 lp->objsqrnormunreliable = FALSE; 17701 } 17702 return; 17703 } 17704 17705 /** gets Euclidean norm of objective function vector of column variables, only use this method if 17706 * lp->objsqrnormunreliable == FALSE, so probably you have to call SCIPlpRecalculateObjSqrNorm before */ 17707 SCIP_Real SCIPlpGetObjNorm( 17708 SCIP_LP* lp /**< LP data */ 17709 ) 17710 { 17711 assert(lp != NULL); 17712 assert(!lp->objsqrnormunreliable); 17713 assert(lp->objsqrnorm >= 0.0); 17714 17715 return SQRT(lp->objsqrnorm); 17716 } 17717 17718 /** sets whether the root lp is a relaxation of the problem and its optimal objective value is a global lower bound */ 17719 void SCIPlpSetRootLPIsRelax( 17720 SCIP_LP* lp, /**< LP data */ 17721 SCIP_Bool isrelax /**< is the root lp a relaxation of the problem? */ 17722 ) 17723 { 17724 assert(lp != NULL); 17725 17726 lp->rootlpisrelax = isrelax; 17727 } 17728 17729 /** returns whether the root lp is a relaxation of the problem and its optimal objective value is a global lower bound */ 17730 SCIP_Bool SCIPlpIsRootLPRelax( 17731 SCIP_LP* lp /**< LP data */ 17732 ) 17733 { 17734 assert(lp != NULL); 17735 17736 return lp->rootlpisrelax; 17737 } 17738 17739 /** gets the objective value of the root node LP; returns SCIP_INVALID if the root node LP was not (yet) solved */ 17740 SCIP_Real SCIPlpGetRootObjval( 17741 SCIP_LP* lp /**< LP data */ 17742 ) 17743 { 17744 assert(lp != NULL); 17745 17746 return MIN(lp->rootlpobjval + lp->rootlooseobjval, SCIP_INVALID); 17747 } 17748 17749 /** gets part of the objective value of the root node LP that results from COLUMN variables only; 17750 * returns SCIP_INVALID if the root node LP was not (yet) solved 17751 */ 17752 SCIP_Real SCIPlpGetRootColumnObjval( 17753 SCIP_LP* lp /**< LP data */ 17754 ) 17755 { 17756 assert(lp != NULL); 17757 17758 return lp->rootlpobjval; 17759 } 17760 17761 /** gets part of the objective value of the root node LP that results from LOOSE variables only; 17762 * returns SCIP_INVALID if the root node LP was not (yet) solved 17763 */ 17764 SCIP_Real SCIPlpGetRootLooseObjval( 17765 SCIP_LP* lp /**< LP data */ 17766 ) 17767 { 17768 assert(lp != NULL); 17769 17770 return lp->rootlooseobjval; 17771 } 17772 17773 /** gets the LP solver interface */ 17774 SCIP_LPI* SCIPlpGetLPI( 17775 SCIP_LP* lp /**< current LP data */ 17776 ) 17777 { 17778 assert(lp != NULL); 17779 17780 return lp->lpi; 17781 } 17782 17783 /** sets whether the current LP is a relaxation of the current problem and its optimal objective value is a local lower bound */ 17784 void SCIPlpSetIsRelax( 17785 SCIP_LP* lp, /**< LP data */ 17786 SCIP_Bool relax /**< is the current lp a relaxation? */ 17787 ) 17788 { 17789 assert(lp != NULL); 17790 17791 lp->isrelax = relax; 17792 } 17793 17794 /** returns whether the current LP is a relaxation of the problem for which it has been solved and its 17795 * solution value a valid local lower bound? 17796 */ 17797 SCIP_Bool SCIPlpIsRelax( 17798 SCIP_LP* lp /**< LP data */ 17799 ) 17800 { 17801 assert(lp != NULL); 17802 17803 return lp->isrelax; 17804 } 17805 17806 /** returns whether the current LP is flushed and solved */ 17807 SCIP_Bool SCIPlpIsSolved( 17808 SCIP_LP* lp /**< current LP data */ 17809 ) 17810 { 17811 assert(lp != NULL); 17812 17813 return lp->flushed && lp->solved; 17814 } 17815 17816 /** return whether the current LP solution passed the primal feasibility check */ 17817 SCIP_Bool SCIPlpIsPrimalReliable( 17818 SCIP_LP* lp /**< current LP data */ 17819 ) 17820 { 17821 assert(lp != NULL); 17822 17823 return (lp->primalchecked && lp->primalfeasible); 17824 } 17825 17826 /** return whether the current LP solution passed the dual feasibility check */ 17827 SCIP_Bool SCIPlpIsDualReliable( 17828 SCIP_LP* lp /**< current LP data */ 17829 ) 17830 { 17831 assert(lp != NULL); 17832 17833 return (lp->dualchecked && lp->dualfeasible); 17834 } 17835 17836 /** returns whether the current LP solution is a basic solution */ 17837 SCIP_Bool SCIPlpIsSolBasic( 17838 SCIP_LP* lp /**< current LP data */ 17839 ) 17840 { 17841 assert(lp != NULL); 17842 17843 return lp->solisbasic; 17844 } 17845 17846 /** returns whether the LP is in diving mode */ 17847 SCIP_Bool SCIPlpDiving( 17848 SCIP_LP* lp /**< current LP data */ 17849 ) 17850 { 17851 assert(lp != NULL); 17852 17853 return lp->diving; 17854 } 17855 17856 /** returns whether the LP is in diving mode and the objective value of at least one column was changed */ 17857 SCIP_Bool SCIPlpDivingObjChanged( 17858 SCIP_LP* lp /**< current LP data */ 17859 ) 17860 { 17861 assert(lp != NULL); 17862 17863 return lp->divingobjchg; 17864 } 17865 17866 /** marks the diving LP to have a changed objective function */ 17867 void SCIPlpMarkDivingObjChanged( 17868 SCIP_LP* lp /**< current LP data */ 17869 ) 17870 { 17871 assert(lp != NULL); 17872 assert(lp->diving || lp->probing); 17873 17874 lp->divingobjchg = TRUE; 17875 } 17876 17877 /** marks the diving LP to not have a changed objective function anymore */ 17878 void SCIPlpUnmarkDivingObjChanged( 17879 SCIP_LP* lp /**< current LP data */ 17880 ) 17881 { 17882 assert(lp != NULL); 17883 assert(lp->diving || lp->probing); 17884 17885 lp->divingobjchg = FALSE; 17886 } 17887 17888 /* returns TRUE if at least one left/right hand side of an LP row was changed during diving mode */ 17889 SCIP_Bool SCIPlpDivingRowsChanged( 17890 SCIP_LP* lp /**< current LP data */ 17891 ) 17892 { 17893 assert(lp != NULL); 17894 assert(lp->diving || lp->ndivechgsides == 0); 17895 17896 return (lp->ndivechgsides > 0); 17897 } 17898 17899 /** compute relative interior point with auxiliary lpi, see SCIPlpComputeRelIntPoint() */ 17900 static 17901 SCIP_RETCODE computeRelIntPoint( 17902 SCIP_LPI* lpi, /**< auxiliary LP interface */ 17903 SCIP_SET* set, /**< global SCIP settings */ 17904 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */ 17905 SCIP_LP* lp, /**< LP data */ 17906 SCIP_PROB* prob, /**< problem data */ 17907 SCIP_Bool relaxrows, /**< should the rows be relaxed */ 17908 SCIP_Bool inclobjcutoff, /**< should a row for the objective cutoff be included */ 17909 SCIP_Real timelimit, /**< time limit for LP solver */ 17910 int iterlimit, /**< iteration limit for LP solver */ 17911 SCIP_Real* point, /**< array to store relative interior point on exit */ 17912 SCIP_Bool* success /**< buffer to indicate whether interior point was successfully computed */ 17913 ) 17914 { 17915 SCIP_RETCODE retcode; 17916 SCIP_Real* primal; 17917 SCIP_Real* obj; 17918 SCIP_Real* lb; 17919 SCIP_Real* ub; 17920 SCIP_Real* matvals; 17921 SCIP_Real* matlhs; 17922 SCIP_Real* matrhs; 17923 SCIP_Real objval; 17924 SCIP_Real alpha; 17925 int* matinds; 17926 int* matbeg; 17927 #ifndef NDEBUG 17928 int nslacks; 17929 #endif 17930 int nnewcols; 17931 int ntotnonz = 0; 17932 int ntotrows = 0; 17933 int matrowidx; 17934 int matidx; 17935 int cnt; 17936 int j; 17937 int i; 17938 17939 assert(lpi != NULL); 17940 17941 retcode = SCIPlpiSetRealpar(lpi, SCIP_LPPAR_FEASTOL, lp->feastol); 17942 if( retcode != SCIP_OKAY ) 17943 { 17944 /* stop execution on error, since result is likely to be unsuable */ 17945 SCIPmessagePrintWarning(messagehdlr, "Could not set feasibility tolerance of LP solver for relative interior point computation.\n"); 17946 return SCIP_LPERROR; 17947 } 17948 17949 retcode = SCIPlpiSetRealpar(lpi, SCIP_LPPAR_DUALFEASTOL, SCIPsetDualfeastol(set)); 17950 if( retcode != SCIP_OKAY ) 17951 { 17952 /* stop execution on error, since result is likely to be unsuable */ 17953 SCIPmessagePrintWarning(messagehdlr, "Could not set dual feasibility tolerance of LP solver for relative interior point computation.\n"); 17954 return SCIP_LPERROR; 17955 } 17956 17957 /* get storage */ 17958 nnewcols = 3*lp->ncols + 2*lp->nrows + (inclobjcutoff ? 1 : 0) + 1; 17959 SCIP_CALL( SCIPsetAllocBufferArray(set, &lb, nnewcols) ); 17960 SCIP_CALL( SCIPsetAllocBufferArray(set, &ub, nnewcols) ); 17961 SCIP_CALL( SCIPsetAllocBufferArray(set, &obj, nnewcols) ); 17962 17963 /* create original columns (bounds are relaxed below, unless the variable is fixed) */ 17964 for( j = 0; j < lp->ncols; ++j ) 17965 { 17966 /* note: if the variable is fixed we cannot simply fix the variables (because alpha scales the problem) */ 17967 obj[j] = 0.0; 17968 lb[j] = -SCIPlpiInfinity(lpi); 17969 ub[j] = SCIPlpiInfinity(lpi); 17970 /* note: we could also use the original bounds - free variables seem to be faster. */ 17971 } 17972 17973 /* add artificial alpha variable */ 17974 nnewcols = lp->ncols; 17975 obj[nnewcols] = 0.0; 17976 lb[nnewcols] = 1.0; 17977 ub[nnewcols] = SCIPlpiInfinity(lpi); 17978 ++nnewcols; 17979 17980 /* create slacks for rows */ 17981 for( i = 0; i < lp->nrows; ++i ) 17982 { 17983 SCIP_ROW* row; 17984 17985 row = lp->rows[i]; 17986 assert( row != NULL ); 17987 17988 if( SCIProwIsModifiable(row) ) 17989 continue; 17990 17991 /* make sure row is sorted */ 17992 rowSortLP(row); 17993 assert( row->lpcolssorted ); 17994 17995 /* check whether we have an equation */ 17996 if( SCIPsetIsEQ(set, row->lhs, row->rhs) ) 17997 { 17998 assert( !SCIPsetIsInfinity(set, REALABS(row->lhs)) ); 17999 assert( !SCIPsetIsInfinity(set, REALABS(row->rhs)) ); 18000 ntotnonz += row->nlpcols + 1; 18001 ++ntotrows; 18002 } 18003 else 18004 { 18005 /* otherwise add slacks for each side if necessary */ 18006 if ( ! SCIPsetIsInfinity(set, REALABS(row->lhs)) ) 18007 { 18008 if ( relaxrows ) 18009 { 18010 lb[nnewcols] = 0.0; 18011 ub[nnewcols] = 1.0; 18012 obj[nnewcols++] = 1.0; 18013 ntotnonz += row->nlpcols + 2; 18014 } 18015 else 18016 ntotnonz += row->nlpcols + 1; 18017 ++ntotrows; 18018 } 18019 if ( ! SCIPsetIsInfinity(set, REALABS(row->rhs)) ) 18020 { 18021 if ( relaxrows ) 18022 { 18023 lb[nnewcols] = 0.0; 18024 ub[nnewcols] = 1.0; 18025 obj[nnewcols++] = 1.0; 18026 ntotnonz += row->nlpcols + 2; 18027 } 18028 else 18029 ntotnonz += row->nlpcols + 1; 18030 ++ntotrows; 18031 } 18032 } 18033 } 18034 18035 /* create slacks for objective cutoff row */ 18036 if( inclobjcutoff && relaxrows ) 18037 { 18038 /* add slacks for right hand side */ 18039 lb[nnewcols] = 0.0; 18040 ub[nnewcols] = 1.0; 18041 obj[nnewcols++] = 1.0; 18042 ntotnonz += lp->ncols + 2; 18043 ++ntotrows; 18044 } 18045 18046 /* create slacks for bounds */ 18047 for( j = 0; j < lp->ncols; ++j ) 18048 { 18049 SCIP_COL* col; 18050 18051 col = lp->cols[j]; 18052 assert( col != NULL ); 18053 18054 /* no slacks for fixed variables */ 18055 if( SCIPsetIsEQ(set, col->lb, col->ub) ) 18056 { 18057 ++ntotrows; 18058 ntotnonz += 2; 18059 } 18060 else 18061 { 18062 /* add slacks for each bound if necessary */ 18063 if ( ! SCIPsetIsInfinity(set, REALABS(col->lb)) ) 18064 { 18065 lb[nnewcols] = 0.0; 18066 ub[nnewcols] = 1.0; 18067 obj[nnewcols++] = 1.0; 18068 ntotnonz += 3; 18069 ++ntotrows; 18070 } 18071 if( ! SCIPsetIsInfinity(set, REALABS(col->ub)) ) 18072 { 18073 lb[nnewcols] = 0.0; 18074 ub[nnewcols] = 1.0; 18075 obj[nnewcols++] = 1.0; 18076 ntotnonz += 3; 18077 ++ntotrows; 18078 } 18079 } 18080 } 18081 #ifndef NDEBUG 18082 nslacks = nnewcols - lp->ncols - 1; 18083 assert( nslacks >= 0 ); 18084 assert( nnewcols <= 3*lp->ncols + 2*lp->nrows + (inclobjcutoff ? 1 : 0) + 1 ); 18085 #endif 18086 18087 /* add columns */ 18088 SCIP_CALL( SCIPlpiAddCols(lpi, nnewcols, obj, lb, ub, NULL, 0, NULL, NULL, NULL) ); 18089 18090 /* free storage */ 18091 SCIPsetFreeBufferArray(set, &obj); 18092 SCIPsetFreeBufferArray(set, &ub); 18093 SCIPsetFreeBufferArray(set, &lb); 18094 18095 /* prepare storage for rows */ 18096 SCIP_CALL( SCIPsetAllocBufferArray(set, &matinds, ntotnonz) ); 18097 SCIP_CALL( SCIPsetAllocBufferArray(set, &matvals, ntotnonz) ); 18098 SCIP_CALL( SCIPsetAllocBufferArray(set, &matbeg, ntotrows) ); 18099 SCIP_CALL( SCIPsetAllocBufferArray(set, &matlhs, ntotrows) ); 18100 SCIP_CALL( SCIPsetAllocBufferArray(set, &matrhs, ntotrows) ); 18101 18102 /* create rows arising from original rows */ 18103 cnt = 0; 18104 matrowidx = 0; 18105 matidx = 0; 18106 for( i = 0; i < lp->nrows; ++i ) 18107 { 18108 SCIP_ROW* row; 18109 SCIP_COL** rowcols; 18110 SCIP_Real* rowvals; 18111 SCIP_Real lhs; 18112 SCIP_Real rhs; 18113 int nnonz; 18114 18115 row = lp->rows[i]; 18116 assert( row != NULL ); 18117 18118 if( SCIProwIsModifiable(row) ) 18119 continue; 18120 assert( row->lpcolssorted ); 18121 18122 /* get row data */ 18123 lhs = row->lhs - (SCIPsetIsInfinity(set, -row->lhs) ? 0.0 : row->constant); 18124 rhs = row->rhs - (SCIPsetIsInfinity(set, row->rhs) ? 0.0 : row->constant); 18125 nnonz = row->nlpcols; 18126 assert( nnonz <= lp->ncols ); 18127 rowcols = row->cols; 18128 rowvals = row->vals; 18129 18130 /* if we have an equation */ 18131 if( SCIPsetIsEQ(set, lhs, rhs) ) 18132 { 18133 /* set up indices */ 18134 matbeg[matrowidx] = matidx; 18135 for( j = 0; j < nnonz; ++j ) 18136 { 18137 assert( rowcols[j] != NULL ); 18138 assert( 0 <= rowcols[j]->lppos && rowcols[j]->lppos < lp->ncols ); 18139 assert( lp->cols[rowcols[j]->lppos] == rowcols[j] ); 18140 assert( ! SCIPsetIsZero(set, rowvals[j]) ); 18141 matinds[matidx] = rowcols[j]->lppos; 18142 matvals[matidx++] = rowvals[j]; 18143 assert( matidx <= ntotnonz ); 18144 } 18145 18146 /* add artificial variable */ 18147 if ( ! SCIPsetIsZero(set, rhs) ) 18148 { 18149 matinds[matidx] = lp->ncols; 18150 matvals[matidx++] = -rhs; 18151 assert( matidx <= ntotnonz ); 18152 } 18153 18154 matlhs[matrowidx] = 0.0; 18155 matrhs[matrowidx++] = 0.0; 18156 assert( matrowidx <= ntotrows ); 18157 } 18158 else 18159 { 18160 SCIP_Real abslhs = REALABS(lhs); 18161 SCIP_Real absrhs = REALABS(rhs); 18162 18163 assert(!SCIPsetIsEQ(set, lhs, rhs)); 18164 18165 /* treat lhs */ 18166 if( !SCIPsetIsInfinity(set, abslhs) ) 18167 { 18168 /* set up indices */ 18169 matbeg[matrowidx] = matidx; 18170 for( j = 0; j < nnonz; ++j ) 18171 { 18172 assert( rowcols[j] != NULL ); 18173 assert( 0 <= rowcols[j]->lppos && rowcols[j]->lppos < lp->ncols ); 18174 assert( lp->cols[rowcols[j]->lppos] == rowcols[j] ); 18175 assert( ! SCIPsetIsZero(set, rowvals[j]) ); 18176 matinds[matidx] = rowcols[j]->lppos; 18177 matvals[matidx++] = rowvals[j]; 18178 assert( matidx <= ntotnonz ); 18179 } 18180 18181 /* add artificial variable */ 18182 if ( ! SCIPsetIsZero(set, lhs) ) 18183 { 18184 matinds[matidx] = lp->ncols; 18185 matvals[matidx++] = -lhs; 18186 assert( matidx <= ntotnonz ); 18187 } 18188 18189 if( relaxrows ) 18190 { 18191 /* add slack variable */ 18192 matvals[matidx] = -MAX(1.0, lhs); /*lint !e679*/ 18193 matinds[matidx++] = lp->ncols + 1 + cnt; /*lint !e679*/ 18194 assert( matidx <= ntotnonz ); 18195 ++cnt; 18196 } 18197 18198 matlhs[matrowidx] = 0.0; 18199 matrhs[matrowidx++] = SCIPlpiInfinity(lpi); 18200 assert( matrowidx <= ntotrows ); 18201 } 18202 18203 /* treat rhs */ 18204 if( !SCIPsetIsInfinity(set, absrhs) ) 18205 { 18206 /* set up indices */ 18207 matbeg[matrowidx] = matidx; 18208 for( j = 0; j < nnonz; ++j ) 18209 { 18210 assert( rowcols[j] != NULL ); 18211 assert( 0 <= rowcols[j]->lppos && rowcols[j]->lppos < lp->ncols ); 18212 assert( lp->cols[rowcols[j]->lppos] == rowcols[j] ); 18213 assert( ! SCIPsetIsZero(set, rowvals[j]) ); 18214 matinds[matidx] = rowcols[j]->lppos; 18215 matvals[matidx++] = rowvals[j]; 18216 assert( matidx <= ntotnonz ); 18217 } 18218 18219 /* add artificial variable */ 18220 if ( ! SCIPsetIsZero(set, rhs) ) 18221 { 18222 matinds[matidx] = lp->ncols; 18223 matvals[matidx++] = -rhs; 18224 assert( matidx <= ntotnonz ); 18225 } 18226 18227 if( relaxrows ) 18228 { 18229 /* add slack variable */ 18230 matvals[matidx] = MAX(1.0, absrhs); /*lint !e679*/ 18231 matinds[matidx++] = lp->ncols + 1 + cnt; /*lint !e679*/ 18232 ++cnt; 18233 } 18234 18235 matlhs[matrowidx] = -SCIPlpiInfinity(lpi); 18236 matrhs[matrowidx++] = 0.0; 18237 assert( matrowidx <= ntotrows ); 18238 } 18239 } 18240 } 18241 18242 /* create row arising from objective cutoff */ 18243 if( inclobjcutoff ) 18244 { 18245 SCIP_Real rhs; 18246 18247 /* get row data */ 18248 assert(lp->looseobjvalinf == 0); 18249 rhs = lp->cutoffbound - getFiniteLooseObjval(lp, set, prob); 18250 18251 /* set up indices and coefficients */ 18252 matbeg[matrowidx] = matidx; 18253 for( j = 0; j < lp->ncols; ++j ) 18254 { 18255 assert( lp->cols[j] != NULL ); 18256 assert( 0 <= lp->cols[j]->lppos && lp->cols[j]->lppos < lp->ncols ); 18257 assert( lp->cols[lp->cols[j]->lppos] == lp->cols[j] ); 18258 18259 if( ! SCIPsetIsZero(set, lp->cols[j]->obj) ) 18260 { 18261 matinds[matidx] = lp->cols[j]->lppos; 18262 matvals[matidx++] = lp->cols[j]->obj; 18263 assert( matidx <= ntotnonz ); 18264 } 18265 } 18266 18267 /* treat rhs */ 18268 18269 /* add artificial variable */ 18270 if ( ! SCIPsetIsZero(set, rhs) ) 18271 { 18272 matinds[matidx] = lp->ncols; 18273 matvals[matidx++] = -rhs; 18274 assert( matidx <= ntotnonz ); 18275 } 18276 18277 if( relaxrows ) 18278 { 18279 SCIP_Real absrhs = REALABS(rhs); 18280 18281 /* add slack variable */ 18282 matvals[matidx] = MAX(1.0, absrhs); 18283 matinds[matidx++] = lp->ncols + 1 + cnt; 18284 assert( matidx <= ntotnonz ); 18285 ++cnt; 18286 } 18287 matlhs[matrowidx] = -SCIPsetInfinity(set); 18288 matrhs[matrowidx++] = 0.0; 18289 assert( matrowidx <= ntotrows ); 18290 } 18291 18292 /* create rows arising from bounds */ 18293 for( j = 0; j < lp->ncols; ++j ) 18294 { 18295 SCIP_COL* col; 18296 SCIP_Real abscollb; 18297 SCIP_Real abscolub; 18298 18299 col = lp->cols[j]; 18300 assert( col != NULL ); 18301 assert( col->lppos == j ); 18302 18303 /* fixed variable */ 18304 if( SCIPsetIsEQ(set, col->lb, col->ub) ) 18305 { 18306 /* set up index of column */ 18307 matbeg[matrowidx] = matidx; 18308 18309 matinds[matidx] = j; 18310 matvals[matidx++] = 1.0; 18311 assert( matidx <= ntotnonz ); 18312 18313 /* add artificial variable */ 18314 if ( ! SCIPsetIsZero(set, col->ub) ) 18315 { 18316 matinds[matidx] = lp->ncols; 18317 matvals[matidx++] = -col->ub; 18318 assert( matidx <= ntotnonz ); 18319 } 18320 18321 matlhs[matrowidx] = 0.0; 18322 matrhs[matrowidx++] = 0.0; 18323 assert( matrowidx <= ntotrows ); 18324 18325 continue; 18326 } 18327 18328 abscollb = REALABS(col->lb); 18329 abscolub = REALABS(col->ub); 18330 18331 /* lower bound */ 18332 if ( ! SCIPsetIsInfinity(set, abscollb) ) 18333 { 18334 /* set up index of column */ 18335 matbeg[matrowidx] = matidx; 18336 18337 matinds[matidx] = j; 18338 matvals[matidx++] = 1.0; 18339 assert( matidx <= ntotnonz ); 18340 18341 /* add artificial variable */ 18342 if ( ! SCIPsetIsZero(set, col->lb) ) 18343 { 18344 matinds[matidx] = lp->ncols; 18345 matvals[matidx++] = -col->lb; 18346 assert( matidx <= ntotnonz ); 18347 } 18348 18349 /* add slack variable */ 18350 matvals[matidx] = -MAX(1.0, abscollb); 18351 matinds[matidx++] = lp->ncols + 1 + cnt; 18352 assert( matidx <= ntotnonz ); 18353 ++cnt; 18354 18355 matlhs[matrowidx] = 0.0; 18356 matrhs[matrowidx++] = SCIPsetInfinity(set); 18357 assert( matrowidx <= ntotrows ); 18358 } 18359 18360 /* upper bound */ 18361 if ( ! SCIPsetIsInfinity(set, abscolub) ) 18362 { 18363 /* set up index of column */ 18364 matbeg[matrowidx] = matidx; 18365 18366 matinds[matidx] = j; 18367 matvals[matidx++] = 1.0; 18368 assert( matidx <= ntotnonz ); 18369 18370 /* add artificial variable */ 18371 if ( ! SCIPsetIsZero(set, col->ub) ) 18372 { 18373 matinds[matidx] = lp->ncols; 18374 matvals[matidx++] = -col->ub; 18375 assert( matidx <= ntotnonz ); 18376 } 18377 18378 /* add slack variable */ 18379 matvals[matidx] = MAX(1.0, abscolub); 18380 matinds[matidx++] = lp->ncols + 1 + cnt; 18381 assert( matidx <= ntotnonz ); 18382 ++cnt; 18383 18384 matlhs[matrowidx] = -SCIPsetInfinity(set); 18385 matrhs[matrowidx++] = 0.0; 18386 assert( matrowidx <= ntotrows ); 18387 } 18388 } 18389 assert( cnt == nslacks ); 18390 assert( matrowidx == ntotrows ); 18391 18392 /* add rows */ 18393 SCIP_CALL( SCIPlpiAddRows(lpi, ntotrows, matlhs, matrhs, NULL, matidx, matbeg, matinds, matvals) ); 18394 18395 SCIPsetFreeBufferArray(set, &matrhs); 18396 SCIPsetFreeBufferArray(set, &matlhs); 18397 SCIPsetFreeBufferArray(set, &matbeg); 18398 SCIPsetFreeBufferArray(set, &matvals); 18399 SCIPsetFreeBufferArray(set, &matinds); 18400 18401 #ifdef SCIP_OUTPUT 18402 SCIP_CALL( SCIPlpiWriteLP(lpi, "relativeInterior.lp") ); 18403 #endif 18404 18405 #ifndef NDEBUG 18406 { 18407 int ncols; 18408 SCIP_CALL( SCIPlpiGetNCols(lpi, &ncols) ); 18409 assert( ncols == nnewcols ); 18410 } 18411 #endif 18412 18413 /* set time limit */ 18414 if( SCIPsetIsInfinity(set, timelimit) ) 18415 timelimit = SCIPlpiInfinity(lpi); 18416 retcode = SCIPlpiSetRealpar(lpi, SCIP_LPPAR_LPTILIM, timelimit); 18417 18418 /* check, if parameter is unknown */ 18419 if( retcode == SCIP_PARAMETERUNKNOWN ) 18420 SCIPmessagePrintWarning(messagehdlr, "Could not set time limit of LP solver for relative interior point computation.\n"); 18421 else if ( retcode != SCIP_OKAY ) 18422 return retcode; 18423 18424 /* set iteration limit */ 18425 retcode = SCIPlpiSetIntpar(lpi, SCIP_LPPAR_LPITLIM, iterlimit); 18426 18427 /* check, if parameter is unknown */ 18428 if( retcode == SCIP_PARAMETERUNKNOWN ) 18429 SCIPmessagePrintWarning(messagehdlr, "Could not set iteration limit of LP solver for relative interior point computation.\n"); 18430 else if ( retcode != SCIP_OKAY ) 18431 return retcode; 18432 18433 /* solve and store point */ 18434 /* SCIP_CALL( SCIPlpiSolvePrimal(lpi) ); */ 18435 SCIP_CALL( SCIPlpiSolveDual(lpi) ); /* dual is usually faster */ 18436 18437 #ifndef NDEBUG 18438 if ( SCIPlpiIsIterlimExc(lpi) ) 18439 SCIPmessagePrintWarning(messagehdlr, "Iteration limit exceeded in relative interior point computation.\n"); 18440 if ( SCIPlpiIsTimelimExc(lpi) ) 18441 SCIPmessagePrintWarning(messagehdlr, "Time limit exceeded in relative interior point computation.\n"); 18442 #endif 18443 18444 if( SCIPlpiIsOptimal(lpi) ) 18445 { 18446 /* get primal solution */ 18447 SCIP_CALL( SCIPsetAllocBufferArray(set, &primal, nnewcols) ); 18448 SCIP_CALL( SCIPlpiGetSol(lpi, &objval, primal, NULL, NULL, NULL) ); 18449 alpha = primal[lp->ncols]; 18450 assert( SCIPsetIsFeasGE(set, alpha, 1.0) ); 18451 18452 SCIPsetDebugMsg(set, "Solved relative interior lp with objective %g.\n", objval); 18453 18454 /* construct relative interior point */ 18455 for( j = 0; j < lp->ncols; ++j ) 18456 point[j] = primal[j]/alpha; 18457 18458 #ifdef SCIP_DEBUG 18459 /* check whether the point is a relative interior point */ 18460 cnt = 0; 18461 if( relaxrows ) 18462 { 18463 for( i = 0; i < lp->nrows; ++i ) 18464 { 18465 SCIP_ROW* row; 18466 SCIP_COL** rowcols; 18467 SCIP_Real* rowvals; 18468 SCIP_Real lhs; 18469 SCIP_Real rhs; 18470 SCIP_Real sum; 18471 int nnonz; 18472 18473 row = lp->rows[i]; 18474 assert( row != NULL ); 18475 18476 /* get row data */ 18477 lhs = row->lhs - (SCIPsetIsInfinity(set, -row->lhs) ? 0.0 : row->constant); 18478 rhs = row->rhs - (SCIPsetIsInfinity(set, row->rhs) ? 0.0 : row->constant); 18479 nnonz = row->nlpcols; 18480 assert( nnonz <= lp->ncols ); 18481 rowcols = row->cols; 18482 rowvals = row->vals; 18483 18484 sum = 0.0; 18485 for( j = 0; j < nnonz; ++j ) 18486 sum += rowvals[j] * primal[rowcols[j]->lppos]; 18487 sum /= alpha; 18488 18489 /* if we have an equation */ 18490 if( SCIPsetIsEQ(set, lhs, rhs) ) 18491 { 18492 assert( SCIPsetIsFeasEQ(set, sum, lhs) ); 18493 } 18494 else 18495 { 18496 /* treat lhs */ 18497 if( !SCIPsetIsInfinity(set, REALABS(lhs)) ) 18498 { 18499 assert( SCIPsetIsFeasZero(set, primal[lp->ncols+1+cnt]) || SCIPsetIsFeasGT(set, sum, lhs) ); 18500 ++cnt; 18501 } 18502 /* treat rhs */ 18503 if( !SCIPsetIsInfinity(set, REALABS(rhs)) ) 18504 { 18505 assert( SCIPsetIsFeasZero(set, primal[lp->ncols+1+cnt]) || SCIPsetIsFeasLT(set, sum, rhs) ); 18506 ++cnt; 18507 } 18508 } 18509 } 18510 if( inclobjcutoff ) 18511 { 18512 SCIP_Real sum; 18513 #ifndef NDEBUG 18514 SCIP_Real rhs; 18515 18516 rhs = lp->cutoffbound - getFiniteLooseObjval(lp, set, prob); 18517 #endif 18518 sum = 0.0; 18519 for( j = 0; j < lp->ncols; ++j ) 18520 sum += lp->cols[j]->obj * primal[lp->cols[j]->lppos]; 18521 sum /= alpha; 18522 18523 assert( SCIPsetIsFeasZero(set, primal[lp->ncols+1+cnt]) || SCIPsetIsFeasLT(set, sum, rhs) ); 18524 ++cnt; 18525 } 18526 } 18527 /* check bounds */ 18528 for( j = 0; j < lp->ncols; ++j ) 18529 { 18530 SCIP_COL* col; 18531 #ifndef NDEBUG 18532 SCIP_Real val; 18533 #endif 18534 18535 col = lp->cols[j]; 18536 assert( col != NULL ); 18537 #ifndef NDEBUG 18538 val = primal[col->lppos] / alpha; 18539 #endif 18540 /* if the variable is not fixed */ 18541 if( !SCIPsetIsEQ(set, col->lb, col->ub) ) 18542 { 18543 /* treat lb */ 18544 if( !SCIPsetIsInfinity(set, REALABS(col->lb)) ) 18545 { 18546 assert( SCIPsetIsFeasZero(set, primal[lp->ncols+1+cnt]) || SCIPsetIsFeasGT(set, val, col->lb) ); 18547 ++cnt; 18548 } 18549 /* treat rhs */ 18550 if( !SCIPsetIsInfinity(set, REALABS(col->ub)) ) 18551 { 18552 assert( SCIPsetIsFeasZero(set, primal[lp->ncols+1+cnt]) || SCIPsetIsFeasLT(set, val, col->ub) ); 18553 ++cnt; 18554 } 18555 } 18556 } 18557 #endif 18558 18559 /* free */ 18560 SCIPsetFreeBufferArray(set, &primal); 18561 18562 *success = TRUE; 18563 } 18564 18565 return SCIP_OKAY; 18566 } 18567 18568 /** compute relative interior point 18569 * 18570 * We use the approach of@par 18571 * R. Freund, R. Roundy, M. J. Todd@par 18572 * "Identifying the Set of Always-Active Constraints in a System of Linear Inequalities by a Single Linear Program"@par 18573 * Tech. Rep, No. 1674-85, Sloan School, M.I.T., 1985 18574 * 18575 * to compute a relative interior point for the current LP. 18576 * 18577 * Assume the original LP looks as follows: 18578 * \f[ 18579 * \begin{array}{rrl} 18580 * \min & c^T x &\\ 18581 * & A x & \geq a\\ 18582 * & B x & \leq b\\ 18583 * & D x & = d. 18584 * \end{array} 18585 * \f] 18586 * Note that bounds should be included in the system. 18587 * 18588 * To find an interior point the following LP does the job: 18589 * \f[ 18590 * \begin{array}{rrl} 18591 * \max & 1^T y &\\ 18592 * & A x - y - \alpha a & \geq 0\\ 18593 * & B x + y - \alpha b & \leq 0\\ 18594 * & D x - \alpha d & = 0\\ 18595 * & 0 \leq y & \leq 1\\ 18596 * & \alpha & \geq 1. 18597 * \end{array} 18598 * \f] 18599 * If the original LP is feasible, this LP is feasible as well. Any optimal solution yields the relative interior point 18600 * \f$x^*_j/\alpha^*\f$. Note that this will just produce some relative interior point. It does not produce a 18601 * particular relative interior point, e.g., one that maximizes the distance to the boundary in some norm. 18602 */ 18603 SCIP_RETCODE SCIPlpComputeRelIntPoint( 18604 SCIP_SET* set, /**< global SCIP settings */ 18605 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */ 18606 SCIP_LP* lp, /**< LP data */ 18607 SCIP_PROB* prob, /**< problem data */ 18608 SCIP_Bool relaxrows, /**< should the rows be relaxed */ 18609 SCIP_Bool inclobjcutoff, /**< should a row for the objective cutoff be included */ 18610 SCIP_Real timelimit, /**< time limit for LP solver */ 18611 int iterlimit, /**< iteration limit for LP solver */ 18612 SCIP_Real* point, /**< array to store relative interior point on exit */ 18613 SCIP_Bool* success /**< buffer to indicate whether interior point was successfully computed */ 18614 ) 18615 { 18616 SCIP_LPI* lpi; 18617 SCIP_RETCODE retcode; 18618 18619 assert(set != NULL); 18620 assert(lp != NULL); 18621 assert(point != NULL); 18622 assert(success != NULL); 18623 18624 *success = FALSE; 18625 18626 /* check time and iteration limits */ 18627 if ( timelimit <= 0.0 || iterlimit <= 0 ) 18628 return SCIP_OKAY; 18629 18630 /* exit if there are no columns */ 18631 assert(lp->nrows >= 0); 18632 assert(lp->ncols >= 0); 18633 if( lp->ncols == 0 ) 18634 return SCIP_OKAY; 18635 18636 /* disable objective cutoff if we have none */ 18637 if( inclobjcutoff && (SCIPsetIsInfinity(set, lp->cutoffbound) || lp->looseobjvalinf > 0 || lp->looseobjval == SCIP_INVALID) ) /*lint !e777 */ 18638 inclobjcutoff = FALSE; 18639 18640 SCIPsetDebugMsg(set, "Computing relative interior point to current LP.\n"); 18641 18642 /* if there are no rows, we return the zero point */ 18643 if( lp->nrows == 0 && !inclobjcutoff ) 18644 { 18645 /* create zero point */ 18646 BMSclearMemoryArray(point, lp->ncols); 18647 *success = TRUE; 18648 18649 return SCIP_OKAY; 18650 } 18651 18652 /* create auxiliary LP */ 18653 SCIP_CALL( SCIPlpiCreate(&lpi, messagehdlr, "relativeInterior", SCIP_OBJSEN_MAXIMIZE) ); 18654 18655 /* catch return code and ensure that lpi is freed, anyway */ 18656 retcode = computeRelIntPoint(lpi, set, messagehdlr, lp, prob, relaxrows, inclobjcutoff, timelimit, iterlimit, point, success); 18657 18658 SCIP_CALL( SCIPlpiFree(&lpi) ); 18659 18660 /* return error, unless we obtained an LP error */ 18661 if ( retcode != SCIP_OKAY && retcode != SCIP_LPERROR ) 18662 { 18663 SCIP_CALL( retcode ); 18664 } 18665 18666 return SCIP_OKAY; 18667 } 18668 18669 /** computes two measures for dual degeneracy (dual degeneracy rate and variable-constraint ratio) 18670 * based on the changes applied when reducing the problem to the optimal face 18671 * 18672 * returns the dual degeneracy rate, i.e., the share of nonbasic variables with reduced cost 0 18673 * and the variable-constraint ratio, i.e., the number of unfixed variables in relation to the basis size 18674 */ 18675 SCIP_RETCODE SCIPlpGetDualDegeneracy( 18676 SCIP_LP* lp, /**< LP data */ 18677 SCIP_SET* set, /**< global SCIP settings */ 18678 SCIP_STAT* stat, /**< problem statistics */ 18679 SCIP_Real* degeneracy, /**< pointer to store the dual degeneracy rate */ 18680 SCIP_Real* varconsratio /**< pointer to store the variable-constraint ratio */ 18681 ) 18682 { 18683 assert(lp != NULL); 18684 assert(lp->solved); 18685 assert(lp->flushed); 18686 18687 if( lp->validdegeneracylp != stat->nlps ) 18688 { 18689 lp->validdegeneracylp = stat->nlps; 18690 18691 /* if the LP was solved to optimality, we determine the dual degeneracy */ 18692 if( SCIPlpGetSolstat(lp) == SCIP_LPSOLSTAT_OPTIMAL ) 18693 { 18694 SCIP_COL** cols; 18695 SCIP_ROW** rows; 18696 SCIP_COL* col; 18697 int ncols; 18698 int nrows; 18699 int nfixedcols = 0; 18700 int nalreadyfixedcols = 0; 18701 int nfixedrows = 0; 18702 #ifndef NDEBUG 18703 int nimplicitfixedrows = 0; 18704 #endif 18705 int nineq = 0; 18706 int c; 18707 int r; 18708 int nbasicequalities = 0; 18709 18710 cols = lp->cols; 18711 rows = lp->rows; 18712 ncols = lp->ncols; 18713 nrows = lp->nrows; 18714 18715 /* count number of columns that will be fixed when reducing the LP to the optimal face */ 18716 for( c = ncols - 1 ; c >= 0; --c ) 18717 { 18718 col = cols[c]; 18719 assert(SCIPcolIsInLP(col)); 18720 18721 /* column is not basic and not fixed already */ 18722 if( (SCIPcolGetBasisStatus(col) != SCIP_BASESTAT_BASIC) ) 18723 { 18724 /* variable with nonzero reduced costs are fixed */ 18725 /* @todo which tolerance should be used here? epsilon or dualfeastol? */ 18726 if( !SCIPsetIsZero(set, SCIPcolGetRedcost(col, stat, lp)) ) 18727 ++nfixedcols; 18728 else if( SCIPsetIsEQ(set, SCIPcolGetLb(col), SCIPcolGetUb(col)) ) 18729 ++nalreadyfixedcols; 18730 } 18731 } 18732 18733 /* count number of rows that will be turned into equations when reducing the LP to the optimal face */ 18734 for( r = nrows - 1; r >= 0; --r ) 18735 { 18736 SCIP_ROW* row = rows[r]; 18737 18738 assert(SCIProwIsInLP(row)); 18739 18740 if( !SCIPsetIsEQ(set, SCIProwGetLhs(row), SCIProwGetRhs(row)) ) 18741 { 18742 SCIP_Real dualsol = SCIProwGetDualsol(row); 18743 18744 ++nineq; 18745 18746 if( (SCIProwGetBasisStatus(row) != SCIP_BASESTAT_BASIC) ) 18747 { 18748 /* rows with nonzero dual solution are turned into equations */ 18749 /* @todo which tolerance should be used here? epsilon or dualfeastol? */ 18750 if( !SCIPsetIsZero(set, dualsol) ) 18751 { 18752 if( SCIPsetIsEQ(set, SCIProwGetLhs(row), SCIProwGetLPActivity(row, set, stat, lp)) ) 18753 { 18754 assert(!SCIPlpIsDualReliable(lp) || !SCIPsetIsDualfeasNegative(set, dualsol)); 18755 ++nfixedrows; 18756 } 18757 else if( SCIPsetIsEQ(set, SCIProwGetRhs(row), SCIProwGetLPActivity(row, set, stat, lp)) ) 18758 { 18759 assert(!SCIPlpIsDualReliable(lp) || !SCIPsetIsDualfeasPositive(set, dualsol)); 18760 ++nfixedrows; 18761 } 18762 } 18763 #ifndef NDEBUG 18764 else if( SCIPsetIsEQ(set, SCIProwGetLhs(row), SCIProwGetMaxActivity(row, set, stat)) 18765 || SCIPsetIsEQ(set, SCIProwGetRhs(row), SCIProwGetMinActivity(row, set, stat)) ) 18766 { 18767 ++nimplicitfixedrows; 18768 } 18769 #endif 18770 } 18771 } 18772 else if( SCIProwGetBasisStatus(row) == SCIP_BASESTAT_BASIC ) 18773 ++nbasicequalities; 18774 } 18775 assert(nfixedcols + nfixedrows <= ncols + nineq + nbasicequalities - nrows - nalreadyfixedcols - nimplicitfixedrows); 18776 18777 if( ncols + nineq - nrows + nbasicequalities - nalreadyfixedcols > 0 ) 18778 lp->degeneracy = 1.0 - 1.0 * (nfixedcols + nfixedrows) / (ncols + nineq - nrows + nbasicequalities - nalreadyfixedcols); 18779 else 18780 lp->degeneracy = 0.0; 18781 18782 if( nrows > 0 ) 18783 lp->varconsratio = 1.0 * (ncols + nineq + nbasicequalities - nfixedcols - nfixedrows - nalreadyfixedcols) / nrows; 18784 else 18785 lp->varconsratio = 1.0; /* @todo should this rather be set to a large value? */ 18786 assert(lp->degeneracy >= 0); 18787 assert(SCIPsetIsLE(set, lp->degeneracy, 1.0)); 18788 assert(SCIPsetIsGE(set, lp->varconsratio, 1.0)); 18789 } 18790 else 18791 { 18792 lp->degeneracy = 0.0; 18793 lp->varconsratio = 0.0; 18794 } 18795 } 18796 18797 *degeneracy = lp->degeneracy; 18798 *varconsratio = lp->varconsratio; 18799 18800 return SCIP_OKAY; 18801 } 18802 18803 /** checks, if absolute difference of values is in range of LP primal feastol */ 18804 SCIP_Bool SCIPlpIsFeasEQ( 18805 SCIP_SET* set, /**< global SCIP settings */ 18806 SCIP_LP* lp, /**< current LP data */ 18807 SCIP_Real val1, /**< first value to be compared */ 18808 SCIP_Real val2 /**< second value to be compared */ 18809 ) 18810 { 18811 assert(set != NULL); 18812 assert(lp != NULL); 18813 18814 /* avoid to compare two different infinities; the reason for that is 18815 * that such a comparison can lead to unexpected results */ 18816 assert( ((!SCIPsetIsInfinity(set, val1) || !SCIPsetIsInfinity(set, val2)) 18817 && (!SCIPsetIsInfinity(set, -val1) || !SCIPsetIsInfinity(set, -val2))) 18818 || val1 == val2 ); /*lint !e777*/ 18819 18820 return EPSEQ(val1, val2, lp->feastol); 18821 } 18822 18823 /** checks, if absolute difference of val1 and val2 is lower than LP primal feastol */ 18824 SCIP_Bool SCIPlpIsFeasLT( 18825 SCIP_SET* set, /**< global SCIP settings */ 18826 SCIP_LP* lp, /**< current LP data */ 18827 SCIP_Real val1, /**< first value to be compared */ 18828 SCIP_Real val2 /**< second value to be compared */ 18829 ) 18830 { 18831 assert(set != NULL); 18832 assert(lp != NULL); 18833 18834 /* avoid to compare two different infinities; the reason for that is 18835 * that such a comparison can lead to unexpected results */ 18836 assert( ((!SCIPsetIsInfinity(set, val1) || !SCIPsetIsInfinity(set, val2)) 18837 && (!SCIPsetIsInfinity(set, -val1) || !SCIPsetIsInfinity(set, -val2))) 18838 || val1 == val2 ); /*lint !e777*/ 18839 18840 return EPSLT(val1, val2, lp->feastol); 18841 } 18842 18843 /** checks, if absolute difference of val1 and val2 is not greater than LP primal feastol */ 18844 SCIP_Bool SCIPlpIsFeasLE( 18845 SCIP_SET* set, /**< global SCIP settings */ 18846 SCIP_LP* lp, /**< current LP data */ 18847 SCIP_Real val1, /**< first value to be compared */ 18848 SCIP_Real val2 /**< second value to be compared */ 18849 ) 18850 { 18851 assert(set != NULL); 18852 assert(lp != NULL); 18853 18854 /* avoid to compare two different infinities; the reason for that is 18855 * that such a comparison can lead to unexpected results */ 18856 assert( ((!SCIPsetIsInfinity(set, val1) || !SCIPsetIsInfinity(set, val2)) 18857 && (!SCIPsetIsInfinity(set, -val1) || !SCIPsetIsInfinity(set, -val2))) 18858 || val1 == val2 ); /*lint !e777*/ 18859 18860 return EPSLE(val1, val2, lp->feastol); 18861 } 18862 18863 /** checks, if absolute difference of val1 and val2 is greater than LP primal feastol */ 18864 SCIP_Bool SCIPlpIsFeasGT( 18865 SCIP_SET* set, /**< global SCIP settings */ 18866 SCIP_LP* lp, /**< current LP data */ 18867 SCIP_Real val1, /**< first value to be compared */ 18868 SCIP_Real val2 /**< second value to be compared */ 18869 ) 18870 { 18871 assert(set != NULL); 18872 assert(lp != NULL); 18873 18874 /* avoid to compare two different infinities; the reason for that is 18875 * that such a comparison can lead to unexpected results */ 18876 assert( ((!SCIPsetIsInfinity(set, val1) || !SCIPsetIsInfinity(set, val2)) 18877 && (!SCIPsetIsInfinity(set, -val1) || !SCIPsetIsInfinity(set, -val2))) 18878 || val1 == val2 ); /*lint !e777*/ 18879 18880 return EPSGT(val1, val2, lp->feastol); 18881 } 18882 18883 /** checks, if absolute difference of val1 and val2 is not lower than -LP primal feastol */ 18884 SCIP_Bool SCIPlpIsFeasGE( 18885 SCIP_SET* set, /**< global SCIP settings */ 18886 SCIP_LP* lp, /**< current LP data */ 18887 SCIP_Real val1, /**< first value to be compared */ 18888 SCIP_Real val2 /**< second value to be compared */ 18889 ) 18890 { 18891 assert(set != NULL); 18892 assert(lp != NULL); 18893 18894 /* avoid to compare two different infinities; the reason for that is 18895 * that such a comparison can lead to unexpected results */ 18896 assert( ((!SCIPsetIsInfinity(set, val1) || !SCIPsetIsInfinity(set, val2)) 18897 && (!SCIPsetIsInfinity(set, -val1) || !SCIPsetIsInfinity(set, -val2))) 18898 || val1 == val2 ); /*lint !e777*/ 18899 18900 return EPSGE(val1, val2, lp->feastol); 18901 } 18902 18903 /** checks, if value is in range LP primal feasibility tolerance of 0.0 */ 18904 SCIP_Bool SCIPlpIsFeasZero( 18905 SCIP_LP* lp, /**< current LP data */ 18906 SCIP_Real val /**< value to process */ 18907 ) 18908 { 18909 assert(lp != NULL); 18910 18911 return EPSZ(val, lp->feastol); 18912 } 18913 18914 /** checks, if value is greater than LP primal feasibility tolerance */ 18915 SCIP_Bool SCIPlpIsFeasPositive( 18916 SCIP_LP* lp, /**< current LP data */ 18917 SCIP_Real val /**< value to process */ 18918 ) 18919 { 18920 assert(lp != NULL); 18921 18922 return EPSP(val, lp->feastol); 18923 } 18924 18925 /** checks, if value is lower than -LP primal feasibility tolerance */ 18926 SCIP_Bool SCIPlpIsFeasNegative( 18927 SCIP_LP* lp, /**< current LP data */ 18928 SCIP_Real val /**< value to process */ 18929 ) 18930 { 18931 assert(lp != NULL); 18932 18933 return EPSN(val, lp->feastol); 18934 } 18935