1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 2 /* */ 3 /* This file is part of the class library */ 4 /* SoPlex --- the Sequential object-oriented simPlex. */ 5 /* */ 6 /* Copyright (c) 1996-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 SoPlex; see the file LICENSE. If not email to soplex@zib.de. */ 22 /* */ 23 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 24 25 #include <assert.h> 26 #include <iostream> 27 28 #include "soplex/spxdefines.h" 29 #include "soplex/spxsolver.h" 30 #include "soplex/spxpricer.h" 31 #include "soplex/spxratiotester.h" 32 #include "soplex/exceptions.h" 33 34 namespace soplex 35 { 36 37 template <class R> 38 void SPxSolverBase<R>::addedRows(int n) 39 { 40 41 if(n > 0) 42 { 43 SPxLPBase<R>::addedRows(n); 44 45 unInit(); 46 reDim(); 47 48 if(SPxBasisBase<R>::status() > SPxBasisBase<R>::NO_PROBLEM) 49 SPxBasisBase<R>::addedRows(n); 50 } 51 52 /* we must not assert consistency here, since addedCols() might be still necessary to obtain a consistent basis */ 53 } 54 55 template <class R> 56 void SPxSolverBase<R>::addedCols(int n) 57 { 58 59 if(n > 0) 60 { 61 SPxLPBase<R>::addedCols(n); 62 63 unInit(); 64 reDim(); 65 66 if(SPxBasisBase<R>::status() > SPxBasisBase<R>::NO_PROBLEM) 67 SPxBasisBase<R>::addedCols(n); 68 } 69 70 /* we must not assert consistency here, since addedRows() might be still necessary to obtain a consistent basis */ 71 } 72 73 template <class R> 74 void SPxSolverBase<R>::doRemoveRow(int i) 75 { 76 77 SPxLPBase<R>::doRemoveRow(i); 78 79 unInit(); 80 81 if(SPxBasisBase<R>::status() > SPxBasisBase<R>::NO_PROBLEM) 82 { 83 this->removedRow(i); 84 85 switch(SPxBasisBase<R>::status()) 86 { 87 case SPxBasisBase<R>::DUAL: 88 case SPxBasisBase<R>::INFEASIBLE: 89 setBasisStatus(SPxBasisBase<R>::REGULAR); 90 break; 91 92 case SPxBasisBase<R>::OPTIMAL: 93 setBasisStatus(SPxBasisBase<R>::PRIMAL); 94 break; 95 96 default: 97 break; 98 } 99 } 100 } 101 102 template <class R> 103 void SPxSolverBase<R>::doRemoveRows(int perm[]) 104 { 105 106 SPxLPBase<R>::doRemoveRows(perm); 107 108 unInit(); 109 110 if(SPxBasisBase<R>::status() > SPxBasisBase<R>::NO_PROBLEM) 111 { 112 this->removedRows(perm); 113 114 switch(SPxBasisBase<R>::status()) 115 { 116 case SPxBasisBase<R>::DUAL: 117 case SPxBasisBase<R>::INFEASIBLE: 118 setBasisStatus(SPxBasisBase<R>::REGULAR); 119 break; 120 121 case SPxBasisBase<R>::OPTIMAL: 122 setBasisStatus(SPxBasisBase<R>::PRIMAL); 123 break; 124 125 default: 126 break; 127 } 128 } 129 } 130 131 template <class R> 132 void SPxSolverBase<R>::doRemoveCol(int i) 133 { 134 forceRecompNonbasicValue(); 135 136 SPxLPBase<R>::doRemoveCol(i); 137 138 unInit(); 139 140 if(SPxBasisBase<R>::status() > SPxBasisBase<R>::NO_PROBLEM) 141 { 142 this->removedCol(i); 143 144 switch(SPxBasisBase<R>::status()) 145 { 146 case SPxBasisBase<R>::PRIMAL: 147 case SPxBasisBase<R>::UNBOUNDED: 148 setBasisStatus(SPxBasisBase<R>::REGULAR); 149 break; 150 151 case SPxBasisBase<R>::OPTIMAL: 152 setBasisStatus(SPxBasisBase<R>::DUAL); 153 break; 154 155 default: 156 break; 157 } 158 } 159 } 160 161 template <class R> 162 void SPxSolverBase<R>::doRemoveCols(int perm[]) 163 { 164 forceRecompNonbasicValue(); 165 166 SPxLPBase<R>::doRemoveCols(perm); 167 168 unInit(); 169 170 if(SPxBasisBase<R>::status() > SPxBasisBase<R>::NO_PROBLEM) 171 { 172 this->removedCols(perm); 173 174 switch(SPxBasisBase<R>::status()) 175 { 176 case SPxBasisBase<R>::PRIMAL: 177 case SPxBasisBase<R>::UNBOUNDED: 178 setBasisStatus(SPxBasisBase<R>::REGULAR); 179 break; 180 181 case SPxBasisBase<R>::OPTIMAL: 182 setBasisStatus(SPxBasisBase<R>::DUAL); 183 break; 184 185 default: 186 break; 187 } 188 } 189 } 190 191 template <class R> 192 void SPxSolverBase<R>::changeObj(const VectorBase<R>& newObj, bool scale) 193 { 194 forceRecompNonbasicValue(); 195 196 SPxLPBase<R>::changeObj(newObj, scale); 197 198 /**@todo Factorization remains valid, we do not need a reDim() 199 * pricing vectors should be recomputed. 200 */ 201 unInit(); 202 } 203 204 template <class R> 205 void SPxSolverBase<R>::changeObj(int i, const R& newVal, bool scale) 206 { 207 forceRecompNonbasicValue(); 208 209 SPxLPBase<R>::changeObj(i, newVal, scale); 210 211 212 /**@todo Factorization remains valid, we do not need a reDim() 213 * pricing vectors should be recomputed. 214 */ 215 unInit(); 216 } 217 218 template <class R> 219 void SPxSolverBase<R>::changeMaxObj(const VectorBase<R>& newObj, bool scale) 220 { 221 forceRecompNonbasicValue(); 222 223 SPxLPBase<R>::changeMaxObj(newObj, scale); 224 225 /**@todo Factorization remains valid, we do not need a reDim() 226 * pricing vectors should be recomputed. 227 */ 228 unInit(); 229 } 230 231 template <class R> 232 void SPxSolverBase<R>::changeMaxObj(int i, const R& newVal, bool scale) 233 { 234 forceRecompNonbasicValue(); 235 236 SPxLPBase<R>::changeMaxObj(i, newVal, scale); 237 238 /**@todo Factorization remains valid, we do not need a reDim() 239 * pricing vectors should be recomputed. 240 */ 241 unInit(); 242 } 243 244 template <class R> 245 void SPxSolverBase<R>::changeRowObj(const VectorBase<R>& newObj, bool scale) 246 { 247 forceRecompNonbasicValue(); 248 249 SPxLPBase<R>::changeRowObj(newObj, scale); 250 251 /**@todo Factorization remains valid, we do not need a reDim() 252 * pricing vectors should be recomputed. 253 */ 254 unInit(); 255 } 256 257 template <class R> 258 void SPxSolverBase<R>::changeRowObj(int i, const R& newVal, bool scale) 259 { 260 forceRecompNonbasicValue(); 261 262 SPxLPBase<R>::changeRowObj(i, newVal, scale); 263 264 /**@todo Factorization remains valid, we do not need a reDim() 265 * pricing vectors should be recomputed. 266 */ 267 unInit(); 268 } 269 270 template <class R> 271 void SPxSolverBase<R>::changeLowerStatus(int i, R newLower, R oldLower) 272 { 273 typename SPxBasisBase<R>::Desc::Status& stat = this->desc().colStatus(i); 274 R currUpper = this->upper(i); 275 R objChange = 0.0; 276 277 SPxOut::debug(this, "DCHANG01 changeLowerStatus(): col {} [{}:{}] {}", i, newLower, currUpper, 278 stat); 279 280 switch(stat) 281 { 282 case SPxBasisBase<R>::Desc::P_ON_LOWER: 283 if(newLower <= R(-infinity)) 284 { 285 if(currUpper >= R(infinity)) 286 { 287 stat = SPxBasisBase<R>::Desc::P_FREE; 288 289 if(m_nonbasicValueUpToDate && rep() == COLUMN) 290 objChange = -theLCbound[i] * oldLower; 291 } 292 else 293 { 294 stat = SPxBasisBase<R>::Desc::P_ON_UPPER; 295 296 if(m_nonbasicValueUpToDate && rep() == COLUMN) 297 objChange = (theUCbound[i] * currUpper) - (theLCbound[i] * oldLower); 298 } 299 } 300 else if(EQ(newLower, currUpper, R(this->tolerances()->epsilon()))) 301 { 302 stat = SPxBasisBase<R>::Desc::P_FIXED; 303 304 if(m_nonbasicValueUpToDate && rep() == COLUMN) 305 objChange = this->maxObj(i) * (newLower - oldLower); 306 } 307 else if(m_nonbasicValueUpToDate && rep() == COLUMN) 308 objChange = theLCbound[i] * (newLower - oldLower); 309 310 break; 311 312 case SPxBasisBase<R>::Desc::P_ON_UPPER: 313 if(EQ(newLower, currUpper, this->tolerances()->epsilon())) 314 stat = SPxBasisBase<R>::Desc::P_FIXED; 315 316 break; 317 318 case SPxBasisBase<R>::Desc::P_FREE: 319 if(newLower > R(-infinity)) 320 { 321 stat = SPxBasisBase<R>::Desc::P_ON_LOWER; 322 323 if(m_nonbasicValueUpToDate && rep() == COLUMN) 324 objChange = theLCbound[i] * newLower; 325 } 326 327 break; 328 329 case SPxBasisBase<R>::Desc::P_FIXED: 330 if(NE(newLower, currUpper, this->tolerances()->epsilon())) 331 { 332 stat = SPxBasisBase<R>::Desc::P_ON_UPPER; 333 334 if(isInitialized()) 335 theUCbound[i] = this->maxObj(i); 336 } 337 338 break; 339 340 case SPxBasisBase<R>::Desc::D_FREE: 341 case SPxBasisBase<R>::Desc::D_ON_UPPER: 342 case SPxBasisBase<R>::Desc::D_ON_LOWER: 343 case SPxBasisBase<R>::Desc::D_ON_BOTH: 344 case SPxBasisBase<R>::Desc::D_UNDEFINED: 345 if(rep() == ROW && theShift > 0.0) 346 forceRecompNonbasicValue(); 347 348 stat = this->dualColStatus(i); 349 break; 350 351 default: 352 throw SPxInternalCodeException("XCHANG01 This should never happen."); 353 } 354 355 SPxOut::debug(this, " -> {}\n", stat); 356 357 // we only need to update the nonbasic value in column representation (see nonbasicValue() for comparison/explanation) 358 if(rep() == COLUMN) 359 updateNonbasicValue(objChange); 360 } 361 362 template <class R> 363 void SPxSolverBase<R>::changeLower(const VectorBase<R>& newLower, bool scale) 364 { 365 // we better recompute the nonbasic value when changing all lower bounds 366 forceRecompNonbasicValue(); 367 368 SPxLPBase<R>::changeLower(newLower, scale); 369 370 if(SPxBasisBase<R>::status() > SPxBasisBase<R>::NO_PROBLEM) 371 { 372 for(int i = 0; i < newLower.dim(); ++i) 373 changeLowerStatus(i, this->lower(i)); 374 375 unInit(); 376 } 377 } 378 379 template <class R> 380 void SPxSolverBase<R>::changeLower(int i, const R& newLower, bool scale) 381 { 382 if(newLower != (scale ? this->lowerUnscaled(i) : this->lower(i))) 383 { 384 forceRecompNonbasicValue(); 385 386 R oldLower = this->lower(i); 387 // This has to be done before calling changeLowerStatus() because that is calling 388 // basis.dualColStatus() which calls lower() and needs the changed value. 389 SPxLPBase<R>::changeLower(i, newLower, scale); 390 391 if(SPxBasisBase<R>::status() > SPxBasisBase<R>::NO_PROBLEM) 392 { 393 changeLowerStatus(i, this->lower(i), oldLower); 394 unInit(); 395 } 396 } 397 } 398 399 template <class R> 400 void SPxSolverBase<R>::changeUpperStatus(int i, R newUpper, R oldUpper) 401 { 402 typename SPxBasisBase<R>::Desc::Status& stat = this->desc().colStatus(i); 403 R currLower = this->lower(i); 404 R objChange = 0.0; 405 406 SPxOut::debug(this, "DCHANG02 changeUpperStatus(): col {} [{}:{}] {}", i, currLower, newUpper, 407 stat); 408 409 switch(stat) 410 { 411 case SPxBasisBase<R>::Desc::P_ON_LOWER: 412 if(newUpper == currLower) 413 stat = SPxBasisBase<R>::Desc::P_FIXED; 414 415 break; 416 417 case SPxBasisBase<R>::Desc::P_ON_UPPER: 418 if(newUpper >= R(infinity)) 419 { 420 if(currLower <= R(-infinity)) 421 { 422 stat = SPxBasisBase<R>::Desc::P_FREE; 423 424 if(m_nonbasicValueUpToDate && rep() == COLUMN) 425 objChange = -theUCbound[i] * oldUpper; 426 } 427 else 428 { 429 stat = SPxBasisBase<R>::Desc::P_ON_LOWER; 430 431 if(m_nonbasicValueUpToDate && rep() == COLUMN) 432 objChange = (theLCbound[i] * currLower) - (theUCbound[i] * oldUpper); 433 } 434 } 435 else if(EQ(newUpper, currLower, this->tolerances()->epsilon())) 436 { 437 stat = SPxBasisBase<R>::Desc::P_FIXED; 438 439 if(m_nonbasicValueUpToDate && rep() == COLUMN) 440 objChange = this->maxObj(i) * (newUpper - oldUpper); 441 } 442 else if(m_nonbasicValueUpToDate && rep() == COLUMN) 443 objChange = theUCbound[i] * (newUpper - oldUpper); 444 445 break; 446 447 case SPxBasisBase<R>::Desc::P_FREE: 448 if(newUpper < R(infinity)) 449 { 450 stat = SPxBasisBase<R>::Desc::P_ON_UPPER; 451 452 if(m_nonbasicValueUpToDate && rep() == COLUMN) 453 objChange = theUCbound[i] * newUpper; 454 } 455 456 break; 457 458 case SPxBasisBase<R>::Desc::P_FIXED: 459 if(NE(newUpper, currLower, this->tolerances()->epsilon())) 460 { 461 stat = SPxBasisBase<R>::Desc::P_ON_LOWER; 462 463 if(isInitialized()) 464 theLCbound[i] = this->maxObj(i); 465 } 466 467 break; 468 469 case SPxBasisBase<R>::Desc::D_FREE: 470 case SPxBasisBase<R>::Desc::D_ON_UPPER: 471 case SPxBasisBase<R>::Desc::D_ON_LOWER: 472 case SPxBasisBase<R>::Desc::D_ON_BOTH: 473 case SPxBasisBase<R>::Desc::D_UNDEFINED: 474 if(rep() == ROW && theShift > 0.0) 475 forceRecompNonbasicValue(); 476 477 stat = this->dualColStatus(i); 478 break; 479 480 default: 481 throw SPxInternalCodeException("XCHANG02 This should never happen."); 482 } 483 484 SPxOut::debug(this, " -> {}\n", stat); 485 486 // we only need to update the nonbasic value in column representation (see nonbasicValue() for comparison/explanation) 487 if(rep() == COLUMN) 488 updateNonbasicValue(objChange); 489 } 490 491 template <class R> 492 void SPxSolverBase<R>::changeUpper(const VectorBase<R>& newUpper, bool scale) 493 { 494 // we better recompute the nonbasic value when changing all upper bounds 495 forceRecompNonbasicValue(); 496 497 SPxLPBase<R>::changeUpper(newUpper, scale); 498 499 if(SPxBasisBase<R>::status() > SPxBasisBase<R>::NO_PROBLEM) 500 { 501 for(int i = 0; i < newUpper.dim(); ++i) 502 changeUpperStatus(i, this->upper(i)); 503 504 unInit(); 505 } 506 } 507 508 template <class R> 509 void SPxSolverBase<R>::changeUpper(int i, const R& newUpper, bool scale) 510 { 511 if(newUpper != (scale ? this->upperUnscaled(i) : this->upper(i))) 512 { 513 forceRecompNonbasicValue(); 514 515 R oldUpper = this->upper(i); 516 SPxLPBase<R>::changeUpper(i, newUpper, scale); 517 518 if(SPxBasisBase<R>::status() > SPxBasisBase<R>::NO_PROBLEM) 519 { 520 changeUpperStatus(i, this->upper(i), oldUpper); 521 unInit(); 522 } 523 } 524 } 525 526 template <class R> 527 void SPxSolverBase<R>::changeBounds(const VectorBase<R>& newLower, const VectorBase<R>& newUpper, 528 bool scale) 529 { 530 changeLower(newLower, scale); 531 changeUpper(newUpper, scale); 532 } 533 534 template <class R> 535 void SPxSolverBase<R>::changeBounds(int i, const R& newLower, const R& newUpper, bool scale) 536 { 537 changeLower(i, newLower, scale); 538 changeUpper(i, newUpper, scale); 539 } 540 541 template <class R> 542 void SPxSolverBase<R>::changeLhsStatus(int i, R newLhs, R oldLhs) 543 { 544 typename SPxBasisBase<R>::Desc::Status& stat = this->desc().rowStatus(i); 545 R currRhs = this->rhs(i); 546 R objChange = 0.0; 547 548 SPxOut::debug(this, "DCHANG03 changeLhsStatus() : row {}: {}", i, stat); 549 550 switch(stat) 551 { 552 case SPxBasisBase<R>::Desc::P_ON_LOWER: 553 if(newLhs <= R(-infinity)) 554 { 555 if(currRhs >= R(infinity)) 556 { 557 stat = SPxBasisBase<R>::Desc::P_FREE; 558 559 if(m_nonbasicValueUpToDate && rep() == COLUMN) 560 objChange = -theURbound[i] * oldLhs; 561 } 562 else 563 { 564 stat = SPxBasisBase<R>::Desc::P_ON_UPPER; 565 566 if(m_nonbasicValueUpToDate && rep() == COLUMN) 567 objChange = (theLRbound[i] * currRhs) - (theURbound[i] * oldLhs); 568 } 569 } 570 else if(EQ(newLhs, currRhs, this->tolerances()->epsilon())) 571 { 572 stat = SPxBasisBase<R>::Desc::P_FIXED; 573 574 if(m_nonbasicValueUpToDate && rep() == COLUMN) 575 objChange = this->maxRowObj(i) * (newLhs - oldLhs); 576 } 577 else if(m_nonbasicValueUpToDate && rep() == COLUMN) 578 objChange = theURbound[i] * (newLhs - oldLhs); 579 580 break; 581 582 case SPxBasisBase<R>::Desc::P_ON_UPPER: 583 if(EQ(newLhs, currRhs, this->tolerances()->epsilon())) 584 stat = SPxBasisBase<R>::Desc::P_FIXED; 585 586 break; 587 588 case SPxBasisBase<R>::Desc::P_FREE: 589 if(newLhs > R(-infinity)) 590 { 591 stat = SPxBasisBase<R>::Desc::P_ON_LOWER; 592 593 if(m_nonbasicValueUpToDate && rep() == COLUMN) 594 objChange = theURbound[i] * newLhs; 595 } 596 597 break; 598 599 case SPxBasisBase<R>::Desc::P_FIXED: 600 if(NE(newLhs, currRhs, this->tolerances()->epsilon())) 601 { 602 stat = SPxBasisBase<R>::Desc::P_ON_UPPER; 603 604 if(isInitialized()) 605 theLRbound[i] = this->maxRowObj(i); 606 } 607 608 break; 609 610 case SPxBasisBase<R>::Desc::D_FREE: 611 case SPxBasisBase<R>::Desc::D_ON_UPPER: 612 case SPxBasisBase<R>::Desc::D_ON_LOWER: 613 case SPxBasisBase<R>::Desc::D_ON_BOTH: 614 case SPxBasisBase<R>::Desc::D_UNDEFINED: 615 if(rep() == ROW && theShift > 0.0) 616 forceRecompNonbasicValue(); 617 618 stat = this->dualRowStatus(i); 619 break; 620 621 default: 622 throw SPxInternalCodeException("XCHANG03 This should never happen."); 623 } 624 625 SPxOut::debug(this, " -> {}\n", stat); 626 627 // we only need to update the nonbasic value in column representation (see nonbasicValue() for comparison/explanation) 628 if(rep() == COLUMN) 629 updateNonbasicValue(objChange); 630 } 631 632 template <class R> 633 void SPxSolverBase<R>::changeLhs(const VectorBase<R>& newLhs, bool scale) 634 { 635 // we better recompute the nonbasic value when changing all lhs 636 forceRecompNonbasicValue(); 637 638 SPxLPBase<R>::changeLhs(newLhs, scale); 639 640 if(SPxBasisBase<R>::status() > SPxBasisBase<R>::NO_PROBLEM) 641 { 642 for(int i = 0; i < this->nRows(); ++i) 643 changeLhsStatus(i, this->lhs(i)); 644 645 unInit(); 646 } 647 } 648 649 template <class R> 650 void SPxSolverBase<R>::changeLhs(int i, const R& newLhs, bool scale) 651 { 652 if(newLhs != (scale ? this->lhsUnscaled(i) : this->lhs(i))) 653 { 654 forceRecompNonbasicValue(); 655 656 R oldLhs = this->lhs(i); 657 SPxLPBase<R>::changeLhs(i, newLhs, scale); 658 659 if(SPxBasisBase<R>::status() > SPxBasisBase<R>::NO_PROBLEM) 660 { 661 changeLhsStatus(i, this->lhs(i), oldLhs); 662 unInit(); 663 } 664 } 665 } 666 667 template <class R> 668 void SPxSolverBase<R>::changeRhsStatus(int i, R newRhs, R oldRhs) 669 { 670 typename SPxBasisBase<R>::Desc::Status& stat = this->desc().rowStatus(i); 671 R currLhs = this->lhs(i); 672 R objChange = 0.0; 673 674 SPxOut::debug(this, "DCHANG04 changeRhsStatus() : row {}: {}", i, stat); 675 676 switch(stat) 677 { 678 case SPxBasisBase<R>::Desc::P_ON_UPPER: 679 if(newRhs >= R(infinity)) 680 { 681 if(currLhs <= R(-infinity)) 682 { 683 stat = SPxBasisBase<R>::Desc::P_FREE; 684 685 if(m_nonbasicValueUpToDate && rep() == COLUMN) 686 objChange = -theLRbound[i] * oldRhs; 687 } 688 else 689 { 690 stat = SPxBasisBase<R>::Desc::P_ON_LOWER; 691 692 if(m_nonbasicValueUpToDate && rep() == COLUMN) 693 objChange = (theURbound[i] * currLhs) - (theLRbound[i] * oldRhs); 694 } 695 } 696 else if(EQ(newRhs, currLhs, this->tolerances()->epsilon())) 697 { 698 stat = SPxBasisBase<R>::Desc::P_FIXED; 699 700 if(m_nonbasicValueUpToDate && rep() == COLUMN) 701 objChange = this->maxRowObj(i) * (newRhs - oldRhs); 702 } 703 else if(m_nonbasicValueUpToDate && rep() == COLUMN) 704 objChange = theLRbound[i] * (newRhs - oldRhs); 705 706 break; 707 708 case SPxBasisBase<R>::Desc::P_ON_LOWER: 709 if(EQ(newRhs, currLhs, this->tolerances()->epsilon())) 710 stat = SPxBasisBase<R>::Desc::P_FIXED; 711 712 break; 713 714 case SPxBasisBase<R>::Desc::P_FREE: 715 if(newRhs < R(infinity)) 716 { 717 stat = SPxBasisBase<R>::Desc::P_ON_UPPER; 718 719 if(m_nonbasicValueUpToDate && rep() == COLUMN) 720 objChange = theLRbound[i] * newRhs; 721 } 722 723 break; 724 725 case SPxBasisBase<R>::Desc::P_FIXED: 726 if(NE(newRhs, currLhs, this->tolerances()->epsilon())) 727 { 728 stat = SPxBasisBase<R>::Desc::P_ON_LOWER; 729 730 if(isInitialized()) 731 theURbound[i] = this->maxRowObj(i); 732 } 733 734 break; 735 736 case SPxBasisBase<R>::Desc::D_FREE: 737 case SPxBasisBase<R>::Desc::D_ON_UPPER: 738 case SPxBasisBase<R>::Desc::D_ON_LOWER: 739 case SPxBasisBase<R>::Desc::D_ON_BOTH: 740 case SPxBasisBase<R>::Desc::D_UNDEFINED: 741 if(rep() == ROW && theShift > 0.0) 742 forceRecompNonbasicValue(); 743 744 stat = this->dualRowStatus(i); 745 break; 746 747 default: 748 throw SPxInternalCodeException("XCHANG04 This should never happen."); 749 } 750 751 SPxOut::debug(this, " -> {}\n", stat); 752 753 // we only need to update the nonbasic value in column representation (see nonbasicValue() for comparison/explanation) 754 if(rep() == COLUMN) 755 updateNonbasicValue(objChange); 756 } 757 758 759 template <class R> 760 void SPxSolverBase<R>::changeRhs(const VectorBase<R>& newRhs, bool scale) 761 { 762 // we better recompute the nonbasic value when changing all rhs 763 forceRecompNonbasicValue(); 764 765 SPxLPBase<R>::changeRhs(newRhs, scale); 766 767 if(SPxBasisBase<R>::status() > SPxBasisBase<R>::NO_PROBLEM) 768 { 769 for(int i = 0; i < this->nRows(); ++i) 770 changeRhsStatus(i, this->rhs(i)); 771 772 unInit(); 773 } 774 } 775 776 template <class R> 777 void SPxSolverBase<R>::changeRhs(int i, const R& newRhs, bool scale) 778 { 779 if(newRhs != (scale ? this->rhsUnscaled(i) : this->rhs(i))) 780 { 781 forceRecompNonbasicValue(); 782 783 R oldRhs = this->rhs(i); 784 SPxLPBase<R>::changeRhs(i, newRhs, scale); 785 786 if(SPxBasisBase<R>::status() > SPxBasisBase<R>::NO_PROBLEM) 787 { 788 changeRhsStatus(i, this->rhs(i), oldRhs); 789 unInit(); 790 } 791 } 792 } 793 794 template <class R> 795 void SPxSolverBase<R>::changeRange(const VectorBase<R>& newLhs, const VectorBase<R>& newRhs, 796 bool scale) 797 { 798 // we better recompute the nonbasic value when changing all ranges 799 forceRecompNonbasicValue(); 800 801 SPxLPBase<R>::changeLhs(newLhs, scale); 802 SPxLPBase<R>::changeRhs(newRhs, scale); 803 804 if(SPxBasisBase<R>::status() > SPxBasisBase<R>::NO_PROBLEM) 805 { 806 for(int i = this->nRows() - 1; i >= 0; --i) 807 { 808 changeLhsStatus(i, this->lhs(i)); 809 changeRhsStatus(i, this->rhs(i)); 810 } 811 812 unInit(); 813 } 814 } 815 816 template <class R> 817 void SPxSolverBase<R>::changeRange(int i, const R& newLhs, const R& newRhs, bool scale) 818 { 819 R oldLhs = this->lhs(i); 820 R oldRhs = this->rhs(i); 821 822 SPxLPBase<R>::changeLhs(i, newLhs, scale); 823 824 if(EQ(newLhs, newRhs, this->tolerances()->epsilon())) 825 SPxLPBase<R>::changeRhs(i, newLhs, scale); 826 else 827 SPxLPBase<R>::changeRhs(i, newRhs, scale); 828 829 if(SPxBasisBase<R>::status() > SPxBasisBase<R>::NO_PROBLEM) 830 { 831 changeLhsStatus(i, this->lhs(i), oldLhs); 832 changeRhsStatus(i, this->rhs(i), oldRhs); 833 unInit(); 834 } 835 } 836 837 template <class R> 838 void SPxSolverBase<R>::changeRow(int i, const LPRowBase<R>& newRow, bool scale) 839 { 840 forceRecompNonbasicValue(); 841 842 SPxLPBase<R>::changeRow(i, newRow, scale); 843 844 if(SPxBasisBase<R>::status() > SPxBasisBase<R>::NO_PROBLEM) 845 SPxBasisBase<R>::changedRow(i); 846 847 unInit(); 848 } 849 850 template <class R> 851 void SPxSolverBase<R>::changeCol(int i, const LPColBase<R>& newCol, bool scale) 852 { 853 if(i < 0) 854 return; 855 856 forceRecompNonbasicValue(); 857 858 SPxLPBase<R>::changeCol(i, newCol, scale); 859 860 if(SPxBasisBase<R>::status() > SPxBasisBase<R>::NO_PROBLEM) 861 SPxBasisBase<R>::changedCol(i); 862 863 unInit(); 864 } 865 866 template <class R> 867 void SPxSolverBase<R>::changeElement(int i, int j, const R& val, bool scale) 868 { 869 if(i < 0 || j < 0) 870 return; 871 872 forceRecompNonbasicValue(); 873 874 SPxLPBase<R>::changeElement(i, j, val, scale); 875 876 if(SPxBasisBase<R>::status() > SPxBasisBase<R>::NO_PROBLEM) 877 SPxBasisBase<R>::changedElement(i, j); 878 879 unInit(); 880 } 881 882 template <class R> 883 void SPxSolverBase<R>::changeSense(typename SPxLPBase<R>::SPxSense sns) 884 { 885 886 SPxLPBase<R>::changeSense(sns); 887 unInit(); 888 } 889 } // namespace soplex 890