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 #include <sstream> 28 29 #include "soplex/spxdefines.h" 30 // #include "soplex.h" 31 #include "soplex/spxpricer.h" 32 #include "soplex/spxratiotester.h" 33 #include "soplex/spxstarter.h" 34 #include "soplex/spxout.h" 35 #include "soplex/timerfactory.h" 36 37 namespace soplex 38 { 39 template <class R> 40 bool SPxSolverBase<R>::read(std::istream& in, NameSet* rowNames, 41 NameSet* colNames, DIdxSet* intVars) 42 { 43 if(initialized) 44 { 45 clear(); 46 unInit(); 47 48 if(thepricer) 49 thepricer->clear(); 50 51 if(theratiotester) 52 theratiotester->clear(); 53 } 54 55 this->unLoad(); 56 57 if(!SPxLPBase<R>::read(in, rowNames, colNames, intVars)) 58 return false; 59 60 this->theLP = this; 61 62 return true; 63 } 64 65 template <class R> 66 void SPxSolverBase<R>::reLoad() 67 { 68 forceRecompNonbasicValue(); 69 unInit(); 70 this->unLoad(); 71 this->theLP = this; 72 m_status = SPxSolverBase<R>::UNKNOWN; 73 74 if(thepricer) 75 thepricer->clear(); 76 77 if(theratiotester) 78 theratiotester->clear(); 79 } 80 81 template <class R> 82 void SPxSolverBase<R>::loadLP(const SPxLPBase<R>& lp, bool initSlackBasis) 83 { 84 clear(); 85 unInit(); 86 this->unLoad(); 87 resetClockStats(); 88 89 if(thepricer) 90 thepricer->clear(); 91 92 if(theratiotester) 93 theratiotester->clear(); 94 95 SPxLPBase<R>::operator=(lp); 96 reDim(); 97 SPxBasisBase<R>::load(this, initSlackBasis); 98 } 99 100 template <class R> 101 void SPxSolverBase<R>::setBasisSolver(SLinSolver<R>* slu, const bool destroy) 102 { 103 // we need to set the outstream before we load the solver to ensure that the basis 104 // can be initialized with this pointer in loadSolver() 105 assert(spxout != 0); 106 slu->spxout = spxout; 107 SPxBasisBase<R>::loadBasisSolver(slu, destroy); 108 } 109 110 template <class R> 111 void SPxSolverBase<R>::loadBasis(const typename SPxBasisBase<R>::Desc& p_desc) 112 { 113 unInit(); 114 115 if(SPxBasisBase<R>::status() == SPxBasisBase<R>::NO_PROBLEM) 116 { 117 SPxBasisBase<R>::load(this, false); 118 } 119 120 setBasisStatus(SPxBasisBase<R>::REGULAR); 121 SPxBasisBase<R>::loadDesc(p_desc); 122 } 123 124 template <class R> 125 void SPxSolverBase<R>::setPricer(SPxPricer<R>* x, const bool destroy) 126 { 127 128 assert(!freePricer || thepricer != 0); 129 130 if(freePricer) 131 { 132 delete thepricer; 133 thepricer = 0; 134 } 135 136 if(x != 0 && x != thepricer) 137 { 138 setPricing(FULL); 139 140 if(isInitialized()) 141 x->load(this); 142 else 143 x->clear(); 144 } 145 146 if(thepricer && thepricer != x) 147 thepricer->clear(); 148 149 thepricer = x; 150 thepricer->setTolerances(this->tolerances()); 151 152 freePricer = destroy; 153 } 154 155 template <class R> 156 void SPxSolverBase<R>::setTester(SPxRatioTester<R>* x, const bool destroy) 157 { 158 assert(!freeRatioTester || theratiotester != 0); 159 160 if(freeRatioTester) 161 { 162 delete theratiotester; 163 theratiotester = 0; 164 } 165 166 theratiotester = x; 167 168 // set the solver pointer inside the ratiotester 169 if(theratiotester != 0) 170 { 171 if(isInitialized()) 172 theratiotester->load(this); 173 else 174 theratiotester->clear(); 175 } 176 177 theratiotester->setTolerances(this->tolerances()); 178 179 freeRatioTester = destroy; 180 } 181 182 template <class R> 183 void SPxSolverBase<R>::setStarter(SPxStarter<R>* x, const bool destroy) 184 { 185 186 assert(!freeStarter || thestarter != 0); 187 188 if(freeStarter) 189 { 190 delete thestarter; 191 thestarter = nullptr; 192 } 193 194 thestarter = x; 195 196 if(thestarter != nullptr) 197 thestarter->setTolerances(this->tolerances()); 198 199 freeStarter = destroy; 200 } 201 202 template <class R> 203 void SPxSolverBase<R>::setType(Type tp) 204 { 205 206 if(theType != tp) 207 { 208 theType = tp; 209 210 forceRecompNonbasicValue(); 211 212 unInit(); 213 #if 0 214 else 215 { 216 if(!matrixIsSetup) 217 { 218 SPxBasisBase<R>::load(this); 219 // SPxBasisBase<R>::load(desc()); 220 // not needed, because load(this) allready loads descriptor 221 } 222 223 factorized = false; 224 m_numCycle = 0; 225 #endif 226 SPX_MSG_INFO3((*spxout), (*spxout) << "Switching to " 227 << static_cast<const char*>((tp == LEAVE) 228 ? "leaving" : "entering") 229 << " algorithm" << std::endl;) 230 } 231 } 232 233 template <class R> 234 void SPxSolverBase<R>::initRep(Representation p_rep) 235 { 236 theRep = p_rep; 237 238 if(theRep == COLUMN) 239 { 240 thevectors = this->colSet(); 241 thecovectors = this->rowSet(); 242 theFrhs = &primRhs; 243 theFvec = &primVec; 244 theCoPrhs = &dualRhs; 245 theCoPvec = &dualVec; 246 thePvec = &addVec; 247 theRPvec = theCoPvec; 248 theCPvec = thePvec; 249 theUbound = &theUCbound; 250 theLbound = &theLCbound; 251 theCoUbound = &theURbound; 252 theCoLbound = &theLRbound; 253 } 254 else 255 { 256 assert(theRep == ROW); 257 258 thevectors = this->rowSet(); 259 thecovectors = this->colSet(); 260 theFrhs = &dualRhs; 261 theFvec = &dualVec; 262 theCoPrhs = &primRhs; 263 theCoPvec = &primVec; 264 thePvec = &addVec; 265 theRPvec = thePvec; 266 theCPvec = theCoPvec; 267 theUbound = &theURbound; 268 theLbound = &theLRbound; 269 theCoUbound = &theUCbound; 270 theCoLbound = &theLCbound; 271 } 272 273 unInit(); 274 reDim(); 275 276 forceRecompNonbasicValue(); 277 278 SPxBasisBase<R>::setRep(); 279 280 if(SPxBasisBase<R>::status() > SPxBasisBase<R>::NO_PROBLEM) 281 SPxBasisBase<R>::loadDesc(this->desc()); 282 283 if(thepricer && thepricer->solver() == this) 284 thepricer->setRep(p_rep); 285 } 286 287 template <class R> 288 void SPxSolverBase<R>::setRep(Representation p_rep) 289 { 290 291 if(p_rep != theRep) 292 initRep(p_rep); 293 } 294 295 // needed for strongbranching. use carefully 296 template <class R> 297 void SPxSolverBase<R>::reinitializeVecs() 298 { 299 300 initialized = true; 301 302 if(type() == ENTER) 303 { 304 if(rep() == COLUMN) 305 setPrimalBounds(); 306 else 307 setDualRowBounds(); 308 309 setEnterBounds(); 310 computeEnterCoPrhs(); 311 } 312 else 313 { 314 if(rep() == ROW) 315 setPrimalBounds(); 316 else 317 setDualColBounds(); 318 319 setLeaveBounds(); 320 computeLeaveCoPrhs(); 321 } 322 323 SPxBasisBase<R>::coSolve(*theCoPvec, *theCoPrhs); 324 computePvec(); 325 computeFrhs(); 326 SPxBasisBase<R>::solve(*theFvec, *theFrhs); 327 328 theShift = 0.0; 329 lastShift = 0.0; 330 331 if(type() == ENTER) 332 { 333 computeCoTest(); 334 computeTest(); 335 } 336 else 337 { 338 computeFtest(); 339 } 340 341 assert((testBounds(), 1)); 342 } 343 344 template <class R> 345 void SPxSolverBase<R>::resetClockStats() 346 { 347 nClckSkipsLeft = 0; 348 nCallsToTimelim = 0; 349 theCumulativeTime = 0.0; 350 } 351 352 template <class R> 353 void SPxSolverBase<R>::init() 354 { 355 356 assert(thepricer != 0); 357 assert(theratiotester != 0); 358 359 if(!initialized) 360 { 361 initialized = true; 362 clearUpdateVecs(); 363 reDim(); 364 365 if(SPxBasisBase<R>::status() <= SPxBasisBase<R>::NO_PROBLEM || this->solver() != this) 366 SPxBasisBase<R>::load(this); 367 368 initialized = false; 369 } 370 371 if(!this->matrixIsSetup) 372 SPxBasisBase<R>::loadDesc(this->desc()); 373 374 // Inna/Tobi: don't "upgrade" a singular basis to a regular one 375 if(SPxBasisBase<R>::status() == SPxBasisBase<R>::SINGULAR) 376 return; 377 378 // catch pathological case for LPs with zero constraints 379 if(dim() == 0) 380 { 381 this->factorized = true; 382 } 383 384 // we better factorize explicitly before solving 385 if(!this->factorized) 386 { 387 try 388 { 389 SPxBasisBase<R>::factorize(); 390 } 391 catch(const SPxException&) 392 { 393 // reload inital slack basis in case the factorization failed 394 assert(SPxBasisBase<R>::status() <= SPxBasisBase<R>::SINGULAR); 395 SPxBasisBase<R>::restoreInitialBasis(); 396 SPxBasisBase<R>::factorize(); 397 assert(this->factorized); 398 } 399 } 400 401 m_numCycle = 0; 402 403 if(type() == ENTER) 404 { 405 if(rep() == COLUMN) 406 { 407 setPrimalBounds(); 408 setBasisStatus(SPxBasisBase<R>::PRIMAL); 409 } 410 else 411 { 412 setDualRowBounds(); 413 setBasisStatus(SPxBasisBase<R>::DUAL); 414 } 415 416 setEnterBounds(); 417 computeEnterCoPrhs(); 418 // prepare support vectors for sparse pricing 419 infeasibilities.setMax(dim()); 420 infeasibilitiesCo.setMax(coDim()); 421 isInfeasible.reSize(dim()); 422 isInfeasibleCo.reSize(coDim()); 423 theratiotester->setDelta(entertol()); 424 } 425 else 426 { 427 if(rep() == ROW) 428 { 429 setPrimalBounds(); 430 setBasisStatus(SPxBasisBase<R>::PRIMAL); 431 } 432 else 433 { 434 setDualColBounds(); 435 setBasisStatus(SPxBasisBase<R>::DUAL); 436 } 437 438 setLeaveBounds(); 439 computeLeaveCoPrhs(); 440 // prepare support vectors for sparse pricing 441 infeasibilities.setMax(dim()); 442 isInfeasible.reSize(dim()); 443 theratiotester->setDelta(leavetol()); 444 } 445 446 SPxBasisBase<R>::coSolve(*theCoPvec, *theCoPrhs); 447 computePvec(); 448 computeFrhs(); 449 SPxBasisBase<R>::solve(*theFvec, *theFrhs); 450 451 theShift = 0.0; 452 453 if(type() == ENTER) 454 { 455 shiftFvec(); 456 lastShift = theShift + entertol(); 457 458 computeCoTest(); 459 computeTest(); 460 } 461 else 462 { 463 shiftPvec(); 464 lastShift = theShift + leavetol(); 465 466 computeFtest(); 467 } 468 469 if(!initialized) 470 { 471 // if(thepricer->solver() != this) 472 thepricer->load(this); 473 // if(theratiotester->solver() != this) 474 theratiotester->load(this); 475 initialized = true; 476 } 477 } 478 479 template <class R> 480 void SPxSolverBase<R>::setPricing(Pricing pr) 481 { 482 thePricing = pr; 483 484 if(initialized && type() == ENTER) 485 { 486 computePvec(); 487 computeCoTest(); 488 computeTest(); 489 } 490 } 491 492 template <class R> 493 void SPxSolverBase<R>::setDecompStatus(DecompStatus decomp_stat) 494 { 495 if(decomp_stat == FINDSTARTBASIS) 496 getStartingDecompBasis = true; 497 else 498 getStartingDecompBasis = false; 499 } 500 501 /* 502 The following method resizes all vectors and arrays of |SoPlex| 503 (excluding inherited vectors). 504 */ 505 template <class R> 506 void SPxSolverBase<R>::reDim() 507 { 508 509 int newsize = SPxLPBase<R>::nCols() > SPxLPBase<R>::nRows() ? SPxLPBase<R>::nCols() : 510 SPxLPBase<R>::nRows(); 511 512 if(newsize > unitVecs.size()) 513 { 514 unitVecs.reSize(newsize); 515 516 while(newsize-- > 0) 517 unitVecs[newsize] = UnitVectorBase<R>(newsize); 518 } 519 520 if(isInitialized()) 521 { 522 theFrhs->reDim(dim()); 523 theFvec->reDim(dim()); 524 thePvec->reDim(coDim()); 525 526 theCoPrhs->reDim(dim()); 527 theCoPvec->reDim(dim()); 528 529 theTest.reDim(coDim()); 530 theCoTest.reDim(dim()); 531 532 theURbound.reDim(SPxLPBase<R>::nRows()); 533 theLRbound.reDim(SPxLPBase<R>::nRows()); 534 theUCbound.reDim(SPxLPBase<R>::nCols()); 535 theLCbound.reDim(SPxLPBase<R>::nCols()); 536 theUBbound.reDim(dim()); 537 theLBbound.reDim(dim()); 538 } 539 } 540 541 template <class R> 542 void SPxSolverBase<R>::clear() 543 { 544 unitVecs.reSize(0); 545 546 dualRhs.clear(); 547 dualVec.clear(); 548 primRhs.clear(); 549 primVec.clear(); 550 addVec.clear(); 551 theURbound.clear(); 552 theLRbound.clear(); 553 theUCbound.clear(); 554 theLCbound.clear(); 555 theTest.clear(); 556 theCoTest.clear(); 557 558 forceRecompNonbasicValue(); 559 unInit(); 560 SPxLPBase<R>::clear(); 561 setBasisStatus(SPxBasisBase<R>::NO_PROBLEM); 562 563 // clear the basis only when theLP is present, because LP data (nrows, ncols) is used in reDim() 564 if(this->theLP != 0) 565 SPxBasisBase<R>::reDim(); 566 567 infeasibilities.clear(); 568 infeasibilitiesCo.clear(); 569 isInfeasible.clear(); 570 isInfeasibleCo.clear(); 571 } 572 573 template <class R> 574 void SPxSolverBase<R>::unscaleLPandReloadBasis() 575 { 576 SPxLPBase<R>::unscaleLP(); 577 SPxBasisBase<R>::invalidate(); 578 unInit(); 579 init(); 580 } 581 582 template <class R> 583 void SPxSolverBase<R>::invalidateBasis() 584 { 585 SPxBasisBase<R>::invalidate(); 586 unInit(); 587 init(); 588 } 589 590 template <class R> 591 void SPxSolverBase<R>::clearUpdateVecs(void) 592 { 593 theFvec->clearUpdate(); 594 thePvec->clearUpdate(); 595 theCoPvec->clearUpdate(); 596 solveVector2 = 0; 597 solveVector3 = 0; 598 coSolveVector2 = 0; 599 coSolveVector3 = 0; 600 } 601 602 /* 603 When the basis matrix factorization is recomputed from scratch, 604 we also recompute the vectors. 605 */ 606 template <class R> 607 void SPxSolverBase<R>::factorize() 608 { 609 610 SPX_MSG_INFO3((*spxout), (*spxout) << " --- refactorizing basis matrix" << std::endl;) 611 612 try 613 { 614 SPxBasisBase<R>::factorize(); 615 } 616 catch(const SPxStatusException&) 617 { 618 assert(SPxBasisBase<R>::status() == SPxBasisBase<R>::SINGULAR); 619 m_status = SINGULAR; 620 std::stringstream s; 621 s << "Basis is singular (numerical troubles, feastol = " 622 << tolerances()->floatingPointFeastol() 623 << ", opttol = " << tolerances()->floatingPointOpttol() << ")"; 624 throw SPxStatusException(s.str()); 625 } 626 627 if(!initialized) 628 { 629 init(); // not sure if init() is neccessary here 630 // we must not go on here because not all vectors (e.g. fVec) may be set up correctly 631 return; 632 } 633 634 if(SPxBasisBase<R>::status() >= SPxBasisBase<R>::REGULAR) 635 { 636 #ifndef NDEBUG 637 VectorBase<R> ftmp(fVec()); 638 VectorBase<R> ptmp(pVec()); 639 VectorBase<R> ctmp(coPvec()); 640 #endif // NDEBUG 641 642 if(type() == LEAVE) 643 { 644 /* we have to recompute theFrhs, because roundoff errors can occur during updating, especially when 645 * columns/rows with large bounds are present 646 */ 647 computeFrhs(); 648 SPxBasisBase<R>::solve(*theFvec, *theFrhs); 649 SPxBasisBase<R>::coSolve(*theCoPvec, *theCoPrhs); 650 651 #ifndef NDEBUG 652 ftmp -= fVec(); 653 ptmp -= pVec(); 654 ctmp -= coPvec(); 655 656 if(ftmp.length() > SOPLEX_DEFAULT_BND_VIOL) 657 { 658 SPxOut::debug(this, "DSOLVE21 fVec: {}\n", ftmp.length()); 659 ftmp = fVec(); 660 this->multBaseWith(ftmp); 661 ftmp -= fRhs(); 662 663 if(ftmp.length() > SOPLEX_DEFAULT_BND_VIOL) 664 SPX_MSG_INFO1((*spxout), (*spxout) << "ESOLVE29 " << this->iteration() << ": fVec error = " 665 << ftmp.length() << " exceeding SOPLEX_DEFAULT_BND_VIOL = " << SOPLEX_DEFAULT_BND_VIOL << std::endl; 666 ) 667 } 668 669 if(ctmp.length() > SOPLEX_DEFAULT_BND_VIOL) 670 { 671 SPxOut::debug(this, "DSOLVE23 coPvec: {}\n", ctmp.length()); 672 ctmp = coPvec(); 673 this->multWithBase(ctmp); 674 ctmp -= coPrhs(); 675 676 if(ctmp.length() > SOPLEX_DEFAULT_BND_VIOL) 677 SPX_MSG_INFO1((*spxout), (*spxout) << "ESOLVE30 " << this->iteration() << ": coPvec error = " 678 << ctmp.length() << " exceeding SOPLEX_DEFAULT_BND_VIOL = " << SOPLEX_DEFAULT_BND_VIOL << std::endl; 679 ) 680 } 681 682 if(ptmp.length() > SOPLEX_DEFAULT_BND_VIOL) 683 { 684 SPxOut::debug(this, "DSOLVE24 pVec: {}\n", ptmp.length()); 685 } 686 687 #endif // NDEBUG 688 689 computeFtest(); 690 } 691 else 692 { 693 assert(type() == ENTER); 694 695 SPxBasisBase<R>::coSolve(*theCoPvec, *theCoPrhs); 696 computeCoTest(); 697 698 if(pricing() == FULL) 699 { 700 /* to save time only recompute the row activities (in row rep) when we are already nearly optimal to 701 * avoid missing any violations from previous updates */ 702 if(rep() == ROW && m_pricingViolCo < entertol() && m_pricingViol < entertol()) 703 computePvec(); 704 705 /* was deactivated, but this leads to warnings in testVecs() */ 706 computeTest(); 707 } 708 } 709 } 710 711 #ifdef ENABLE_ADDITIONAL_CHECKS 712 713 /* moved this test after the computation of fTest and coTest below, since these vectors might not be set up at top, e.g. for an initial basis */ 714 if(SPxBasisBase<R>::status() > SPxBasisBase<R>::SINGULAR) 715 testVecs(); 716 717 #endif 718 } 719 720 /* We compute how much the current solution violates (primal or dual) feasibility. In the 721 row/enter or column/leave algorithm the maximum violation of dual feasibility is 722 computed. In the row/leave or column/enter algorithm the primal feasibility is checked. 723 Additionally, the violation from pricing is taken into account. */ 724 template <class R> 725 R SPxSolverBase<R>::maxInfeas() const 726 { 727 R inf = 0.0; 728 729 if(type() == ENTER) 730 { 731 if(m_pricingViolUpToDate && m_pricingViolCoUpToDate) 732 inf = m_pricingViol + m_pricingViolCo; 733 734 for(int i = 0; i < dim(); i++) 735 { 736 if((*theFvec)[i] > theUBbound[i]) 737 inf = SOPLEX_MAX(inf, (*theFvec)[i] - theUBbound[i]); 738 else if((*theFvec)[i] < theLBbound[i]) 739 inf = SOPLEX_MAX(inf, theLBbound[i] - (*theFvec)[i]); 740 } 741 } 742 else 743 { 744 assert(type() == LEAVE); 745 746 if(m_pricingViolUpToDate) 747 inf = m_pricingViol; 748 749 for(int i = 0; i < dim(); i++) 750 { 751 if((*theCoPvec)[i] > (*theCoUbound)[i]) 752 inf = SOPLEX_MAX(inf, (*theCoPvec)[i] - (*theCoUbound)[i]); 753 else if((*theCoPvec)[i] < (*theCoLbound)[i]) 754 inf = SOPLEX_MAX(inf, (*theCoLbound)[i] - (*theCoPvec)[i]); 755 } 756 757 for(int i = 0; i < coDim(); i++) 758 { 759 if((*thePvec)[i] > (*theUbound)[i]) 760 inf = SOPLEX_MAX(inf, (*thePvec)[i] - (*theUbound)[i]); 761 else if((*thePvec)[i] < (*theLbound)[i]) 762 inf = SOPLEX_MAX(inf, (*theLbound)[i] - (*thePvec)[i]); 763 } 764 } 765 766 return inf; 767 } 768 769 /* check for (dual) violations above tol and immediately return false w/o checking the remaining values 770 This method is useful for verifying whether an objective limit can be used as termination criterion */ 771 template <class R> 772 bool SPxSolverBase<R>::noViols(R tol) const 773 { 774 assert(tol >= R(0.0)); 775 776 if(type() == ENTER) 777 { 778 for(int i = 0; i < dim(); i++) 779 { 780 if((*theFvec)[i] - theUBbound[i] > tol) 781 return false; 782 783 if(theLBbound[i] - (*theFvec)[i] > tol) 784 return false; 785 } 786 } 787 else 788 { 789 assert(type() == LEAVE); 790 791 for(int i = 0; i < dim(); i++) 792 { 793 if((*theCoPvec)[i] - (*theCoUbound)[i] > tol) 794 return false; 795 796 if((*theCoLbound)[i] - (*theCoPvec)[i] > tol) 797 return false; 798 } 799 800 for(int i = 0; i < coDim(); i++) 801 { 802 if((*thePvec)[i] - (*theUbound)[i] > tol) 803 return false; 804 805 if((*theLbound)[i] - (*thePvec)[i] > tol) 806 return false; 807 } 808 } 809 810 return true; 811 } 812 813 template <class R> 814 R SPxSolverBase<R>::nonbasicValue() 815 { 816 int i; 817 StableSum<R> val; 818 const typename SPxBasisBase<R>::Desc& ds = this->desc(); 819 820 #ifndef ENABLE_ADDITIONAL_CHECKS 821 822 // if the value is available we don't need to recompute it 823 if(m_nonbasicValueUpToDate) 824 return m_nonbasicValue; 825 826 #endif 827 828 if(rep() == COLUMN) 829 { 830 if(type() == LEAVE) 831 { 832 for(i = this->nCols() - 1; i >= 0; --i) 833 { 834 switch(ds.colStatus(i)) 835 { 836 case SPxBasisBase<R>::Desc::P_ON_UPPER : 837 val += theUCbound[i] * SPxLPBase<R>::upper(i); 838 //@ val += maxObj(i) * SPxLPBase<R>::upper(i); 839 break; 840 841 case SPxBasisBase<R>::Desc::P_ON_LOWER : 842 val += theLCbound[i] * SPxLPBase<R>::lower(i); 843 //@ val += maxObj(i) * SPxLPBase<R>::lower(i); 844 break; 845 846 case SPxBasisBase<R>::Desc::P_FIXED : 847 assert(EQ(SPxLPBase<R>::lower(i), SPxLPBase<R>::upper(i), this->epsilon())); 848 val += this->maxObj(i) * SPxLPBase<R>::lower(i); 849 break; 850 851 default: 852 break; 853 } 854 } 855 856 for(i = this->nRows() - 1; i >= 0; --i) 857 { 858 switch(ds.rowStatus(i)) 859 { 860 case SPxBasisBase<R>::Desc::P_ON_UPPER : 861 val += theLRbound[i] * SPxLPBase<R>::rhs(i); 862 break; 863 864 case SPxBasisBase<R>::Desc::P_ON_LOWER : 865 val += theURbound[i] * SPxLPBase<R>::lhs(i); 866 break; 867 868 case SPxBasisBase<R>::Desc::P_FIXED : 869 assert(EQ(SPxLPBase<R>::lhs(i), SPxLPBase<R>::rhs(i), this->epsilon())); 870 val += this->maxRowObj(i) * SPxLPBase<R>::lhs(i); 871 break; 872 873 default: 874 break; 875 } 876 } 877 } 878 else 879 { 880 assert(type() == ENTER); 881 882 for(i = this->nCols() - 1; i >= 0; --i) 883 { 884 switch(ds.colStatus(i)) 885 { 886 case SPxBasisBase<R>::Desc::P_ON_UPPER : 887 val += this->maxObj(i) * theUCbound[i]; 888 break; 889 890 case SPxBasisBase<R>::Desc::P_ON_LOWER : 891 val += this->maxObj(i) * theLCbound[i]; 892 break; 893 894 case SPxBasisBase<R>::Desc::P_FIXED : 895 assert(EQ(theLCbound[i], theUCbound[i], this->epsilon())); 896 val += this->maxObj(i) * theLCbound[i]; 897 break; 898 899 default: 900 break; 901 } 902 } 903 904 for(i = this->nRows() - 1; i >= 0; --i) 905 { 906 switch(ds.rowStatus(i)) 907 { 908 case SPxBasisBase<R>::Desc::P_ON_UPPER : 909 val += this->maxRowObj(i) * theLRbound[i]; 910 break; 911 912 case SPxBasisBase<R>::Desc::P_ON_LOWER : 913 val += this->maxRowObj(i) * theURbound[i]; 914 break; 915 916 case SPxBasisBase<R>::Desc::P_FIXED : 917 assert(EQ(theLRbound[i], theURbound[i], this->epsilon())); 918 val += this->maxRowObj(i) * theURbound[i]; 919 break; 920 921 default: 922 break; 923 } 924 } 925 } 926 } 927 else 928 { 929 assert(rep() == ROW); 930 assert(type() == ENTER); 931 932 for(i = this->nCols() - 1; i >= 0; --i) 933 { 934 switch(ds.colStatus(i)) 935 { 936 case SPxBasisBase<R>::Desc::D_ON_UPPER : 937 val += theUCbound[i] * this->lower(i); 938 break; 939 940 case SPxBasisBase<R>::Desc::D_ON_LOWER : 941 val += theLCbound[i] * this->upper(i); 942 break; 943 944 case SPxBasisBase<R>::Desc::D_ON_BOTH : 945 val += theLCbound[i] * this->upper(i); 946 val += theUCbound[i] * this->lower(i); 947 break; 948 949 default: 950 break; 951 } 952 } 953 954 for(i = this->nRows() - 1; i >= 0; --i) 955 { 956 switch(ds.rowStatus(i)) 957 { 958 case SPxBasisBase<R>::Desc::D_ON_UPPER : 959 val += theURbound[i] * this->lhs(i); 960 break; 961 962 case SPxBasisBase<R>::Desc::D_ON_LOWER : 963 val += theLRbound[i] * this->rhs(i); 964 break; 965 966 case SPxBasisBase<R>::Desc::D_ON_BOTH : 967 val += theLRbound[i] * this->rhs(i); 968 val += theURbound[i] * this->lhs(i); 969 break; 970 971 default: 972 break; 973 } 974 } 975 } 976 977 #ifdef ENABLE_ADDITIONAL_CHECKS 978 979 if(m_nonbasicValueUpToDate && NE(m_nonbasicValue, val)) 980 { 981 SPX_MSG_ERROR(std::cerr << "stored nonbasic value: " << m_nonbasicValue 982 << ", correct nonbasic value: " << val 983 << ", violation: " << val - m_nonbasicValue << std::endl;) 984 assert(EQrel(m_nonbasicValue, val, 1e-12)); 985 } 986 987 #endif 988 989 if(!m_nonbasicValueUpToDate) 990 { 991 m_nonbasicValue = R(val); 992 m_nonbasicValueUpToDate = true; 993 } 994 995 return val; 996 } 997 998 template <class R> 999 R SPxSolverBase<R>::value() 1000 { 1001 assert(isInitialized()); 1002 1003 R x; 1004 1005 // calling value() without having a suitable status is an error. 1006 if(!isInitialized()) 1007 return R(infinity); 1008 1009 if(rep() == ROW) 1010 { 1011 if(type() == LEAVE) 1012 x = int(SPxLPBase<R>::spxSense()) * (coPvec() * 1013 fRhs()); // the contribution of maxRowObj() is missing 1014 else 1015 x = int(SPxLPBase<R>::spxSense()) * (nonbasicValue() + (coPvec() * fRhs())); 1016 } 1017 else 1018 x = int(SPxLPBase<R>::spxSense()) * (nonbasicValue() + fVec() * coPrhs()); 1019 1020 return x + this->objOffset(); 1021 } 1022 1023 template <class R> 1024 bool SPxSolverBase<R>::updateNonbasicValue(R objChange) 1025 { 1026 if(m_nonbasicValueUpToDate) 1027 m_nonbasicValue += objChange; 1028 1029 SPxOut::debug(this, "Iteration: {} updated objValue: {} new value: {} correct value: {}\n", 1030 this->iteration(), objChange, m_nonbasicValue, m_nonbasicValueUpToDate ? nonbasicValue() : -1e100); 1031 1032 return m_nonbasicValueUpToDate; 1033 } 1034 1035 template <class R> 1036 void SPxSolverBase<R>::hyperPricing(bool h) 1037 { 1038 hyperPricingEnter = h; 1039 hyperPricingLeave = h; 1040 1041 if(h) 1042 { 1043 updateViols.setMax(dim()); 1044 updateViolsCo.setMax(coDim()); 1045 } 1046 } 1047 1048 template <class R> 1049 SPxSolverBase<R>::SPxSolverBase( 1050 Type p_type, 1051 Representation p_rep, 1052 Timer::TYPE ttype) 1053 : theType(p_type) 1054 , thePricing(FULL) 1055 , theRep(p_rep) 1056 , polishObj(POLISH_OFF) 1057 , theTime(nullptr) 1058 , timerType(ttype) 1059 , theCumulativeTime(0.0) 1060 , maxIters(-1) 1061 , maxTime(R(infinity)) 1062 , nClckSkipsLeft(0) 1063 , nCallsToTimelim(0) 1064 , objLimit(R(infinity)) 1065 , m_status(UNKNOWN) 1066 , m_nonbasicValue(0.0) 1067 , m_nonbasicValueUpToDate(false) 1068 , m_pricingViol(0.0) 1069 , m_pricingViolUpToDate(false) 1070 , m_pricingViolCo(0.0) 1071 , m_pricingViolCoUpToDate(false) 1072 , m_numViol(0) 1073 , entertolscale(1.0) 1074 , leavetolscale(1.0) 1075 , theShift(0) 1076 , m_maxCycle(100) 1077 , m_numCycle(0) 1078 , initialized(false) 1079 , solveVector2(0) 1080 , solveVector3(0) 1081 , coSolveVector2(0) 1082 , coSolveVector3(0) 1083 , freePricer(false) 1084 , freeRatioTester(false) 1085 , freeStarter(false) 1086 , displayLine(0) 1087 , displayFreq(200) 1088 , sparsePricingFactor(SOPLEX_SPARSITYFACTOR) 1089 , getStartingDecompBasis(false) 1090 , computeDegeneracy(false) 1091 , degenCompIterOffset(0) 1092 , fullPerturbation(false) 1093 , printBasisMetric(0) 1094 , unitVecs(0) 1095 , primVec(0) 1096 , dualVec(0) 1097 , addVec(0) 1098 , thepricer(0) 1099 , theratiotester(0) 1100 , thestarter(0) 1101 , boundrange(0.0) 1102 , siderange(0.0) 1103 , objrange(0.0) 1104 , infeasibilities(0) 1105 , infeasibilitiesCo(0) 1106 , isInfeasible(0) 1107 , isInfeasibleCo(0) 1108 , sparsePricingLeave(false) 1109 , sparsePricingEnter(false) 1110 , sparsePricingEnterCo(false) 1111 , hyperPricingLeave(true) 1112 , hyperPricingEnter(true) 1113 , remainingRoundsLeave(0) 1114 , remainingRoundsEnter(0) 1115 , remainingRoundsEnterCo(0) 1116 , weights(0) 1117 , coWeights(0) 1118 , weightsAreSetup(false) 1119 , multSparseCalls(0) 1120 , multFullCalls(0) 1121 , multColwiseCalls(0) 1122 , multUnsetupCalls(0) 1123 , integerVariables(0) 1124 { 1125 theTime = TimerFactory::createTimer(timerType); 1126 1127 multTimeSparse = TimerFactory::createTimer(timerType); 1128 multTimeFull = TimerFactory::createTimer(timerType); 1129 multTimeColwise = TimerFactory::createTimer(timerType); 1130 multTimeUnsetup = TimerFactory::createTimer(timerType); 1131 1132 this->theLP = this; 1133 initRep(p_rep); 1134 1135 // info: SPxBasisBase is not consistent in this moment. 1136 //assert(SPxSolverBase<R>::isConsistent()); 1137 } 1138 1139 template <class R> 1140 SPxSolverBase<R>::~SPxSolverBase() 1141 { 1142 assert(!freePricer || thepricer != 0); 1143 assert(!freeRatioTester || theratiotester != 0); 1144 assert(!freeStarter || thestarter != 0); 1145 1146 if(freePricer) 1147 { 1148 delete thepricer; 1149 thepricer = 0; 1150 } 1151 1152 if(freeRatioTester) 1153 { 1154 delete theratiotester; 1155 theratiotester = 0; 1156 } 1157 1158 if(freeStarter) 1159 { 1160 delete thestarter; 1161 thestarter = 0; 1162 } 1163 1164 // free the timers 1165 assert(theTime); 1166 assert(multTimeSparse); 1167 assert(multTimeFull); 1168 assert(multTimeColwise); 1169 assert(multTimeUnsetup); 1170 theTime->~Timer(); 1171 multTimeSparse->~Timer(); 1172 multTimeFull->~Timer(); 1173 multTimeColwise->~Timer(); 1174 multTimeUnsetup->~Timer(); 1175 spx_free(theTime); 1176 spx_free(multTimeSparse); 1177 spx_free(multTimeFull); 1178 spx_free(multTimeColwise); 1179 spx_free(multTimeUnsetup); 1180 } 1181 1182 1183 template <class R> 1184 SPxSolverBase<R>& SPxSolverBase<R>::operator=(const SPxSolverBase<R>& base) 1185 { 1186 if(this != &base) 1187 { 1188 SPxLPBase<R>::operator=(base); 1189 SPxBasisBase<R>::operator=(base); 1190 theType = base.theType; 1191 thePricing = base.thePricing; 1192 theRep = base.theRep; 1193 polishObj = base.polishObj; 1194 timerType = base.timerType; 1195 maxIters = base.maxIters; 1196 maxTime = base.maxTime; 1197 objLimit = base.objLimit; 1198 m_status = base.m_status; 1199 m_nonbasicValue = base.m_nonbasicValue; 1200 m_nonbasicValueUpToDate = base.m_nonbasicValueUpToDate; 1201 m_pricingViol = base.m_pricingViol; 1202 m_pricingViolUpToDate = base.m_pricingViolUpToDate; 1203 m_pricingViolCo = base.m_pricingViolCo; 1204 m_pricingViolCoUpToDate = base.m_pricingViolCoUpToDate; 1205 m_numViol = base.m_numViol; 1206 entertolscale = base.entertolscale; 1207 leavetolscale = base.leavetolscale; 1208 theShift = base.theShift; 1209 lastShift = base.lastShift; 1210 m_maxCycle = base.m_maxCycle; 1211 m_numCycle = base.m_numCycle; 1212 initialized = base.initialized; 1213 instableLeaveNum = base.instableLeaveNum; 1214 instableLeave = base.instableLeave; 1215 instableLeaveVal = base.instableLeaveVal; 1216 instableEnterId = base.instableEnterId; 1217 instableEnter = base.instableEnter; 1218 instableEnterVal = base.instableEnterVal; 1219 displayLine = base.displayLine; 1220 displayFreq = base.displayFreq; 1221 sparsePricingFactor = base.sparsePricingFactor; 1222 getStartingDecompBasis = base.getStartingDecompBasis; 1223 computeDegeneracy = base.computeDegeneracy; 1224 degenCompIterOffset = base.degenCompIterOffset; 1225 decompIterationLimit = base.decompIterationLimit; 1226 fullPerturbation = base.fullPerturbation; 1227 printBasisMetric = base.printBasisMetric; 1228 unitVecs = base.unitVecs; 1229 primRhs = base.primRhs; 1230 primVec = base.primVec; 1231 dualRhs = base.dualRhs; 1232 dualVec = base.dualVec; 1233 addVec = base.addVec; 1234 theURbound = base.theURbound; 1235 theLRbound = base.theLRbound; 1236 theUCbound = base.theUCbound; 1237 theLCbound = base.theLCbound; 1238 theUBbound = base.theUBbound; 1239 theLBbound = base.theLBbound; 1240 theCoTest = base.theCoTest; 1241 theTest = base.theTest; 1242 primalRay = base.primalRay; 1243 dualFarkas = base.dualFarkas; 1244 leaveCount = base.leaveCount; 1245 enterCount = base.enterCount; 1246 theCumulativeTime = base.theCumulativeTime; 1247 primalCount = base.primalCount; 1248 polishCount = base.polishCount; 1249 boundflips = base.boundflips; 1250 totalboundflips = base.totalboundflips; 1251 enterCycles = base.enterCycles; 1252 leaveCycles = base.leaveCycles; 1253 enterDegenCand = base.enterDegenCand; 1254 leaveDegenCand = base.leaveDegenCand; 1255 primalDegenSum = base.primalDegenSum; 1256 boundrange = base.boundrange; 1257 siderange = base.siderange; 1258 objrange = base.objrange; 1259 infeasibilities = base.infeasibilities; 1260 infeasibilitiesCo = base.infeasibilitiesCo; 1261 isInfeasible = base.isInfeasible; 1262 isInfeasibleCo = base.isInfeasibleCo; 1263 sparsePricingLeave = base.sparsePricingLeave; 1264 sparsePricingEnter = base.sparsePricingEnter; 1265 sparsePricingEnterCo = base.sparsePricingEnterCo; 1266 sparsePricingFactor = base.sparsePricingFactor; 1267 hyperPricingLeave = base.hyperPricingLeave; 1268 hyperPricingEnter = base.hyperPricingEnter; 1269 remainingRoundsLeave = base.remainingRoundsLeave; 1270 remainingRoundsEnter = base.remainingRoundsEnter; 1271 remainingRoundsEnterCo = base.remainingRoundsEnterCo; 1272 weights = base.weights; 1273 coWeights = base.coWeights; 1274 weightsAreSetup = base.weightsAreSetup; 1275 multSparseCalls = base.multSparseCalls; 1276 multFullCalls = base.multFullCalls; 1277 multColwiseCalls = base.multColwiseCalls; 1278 multUnsetupCalls = base.multUnsetupCalls; 1279 spxout = base.spxout; 1280 integerVariables = base.integerVariables; 1281 1282 if(base.theRep == COLUMN) 1283 { 1284 thevectors = this->colSet(); 1285 thecovectors = this->rowSet(); 1286 theFrhs = &primRhs; 1287 theFvec = &primVec; 1288 theCoPrhs = &dualRhs; 1289 theCoPvec = &dualVec; 1290 thePvec = &addVec; 1291 theRPvec = theCoPvec; 1292 theCPvec = thePvec; 1293 theUbound = &theUCbound; 1294 theLbound = &theLCbound; 1295 theCoUbound = &theURbound; 1296 theCoLbound = &theLRbound; 1297 } 1298 else 1299 { 1300 assert(base.theRep == ROW); 1301 1302 thevectors = this->rowSet(); 1303 thecovectors = this->colSet(); 1304 theFrhs = &dualRhs; 1305 theFvec = &dualVec; 1306 theCoPrhs = &primRhs; 1307 theCoPvec = &primVec; 1308 thePvec = &addVec; 1309 theRPvec = thePvec; 1310 theCPvec = theCoPvec; 1311 theUbound = &theURbound; 1312 theLbound = &theLRbound; 1313 theCoUbound = &theUCbound; 1314 theCoLbound = &theLCbound; 1315 } 1316 1317 SPxBasisBase<R>::theLP = this; 1318 1319 assert(!freePricer || thepricer != 0); 1320 assert(!freeRatioTester || theratiotester != 0); 1321 assert(!freeStarter || thestarter != 0); 1322 1323 // thepricer 1324 if(freePricer) 1325 { 1326 delete thepricer; 1327 thepricer = 0; 1328 } 1329 1330 if(base.thepricer == 0) 1331 { 1332 thepricer = 0; 1333 freePricer = false; 1334 } 1335 else 1336 { 1337 thepricer = base.thepricer->clone(); 1338 freePricer = true; 1339 thepricer->load(this); 1340 } 1341 1342 // theratiotester 1343 if(freeRatioTester) 1344 { 1345 delete theratiotester; 1346 theratiotester = 0; 1347 } 1348 1349 if(base.theratiotester == 0) 1350 { 1351 theratiotester = 0; 1352 freeRatioTester = false; 1353 } 1354 else 1355 { 1356 theratiotester = base.theratiotester->clone(); 1357 freeRatioTester = true; 1358 theratiotester->setTolerances(this->tolerances()); 1359 theratiotester->load(this); 1360 } 1361 1362 // thestarter 1363 if(freeStarter) 1364 { 1365 delete thestarter; 1366 thestarter = 0; 1367 } 1368 1369 if(base.thestarter == 0) 1370 { 1371 thestarter = 0; 1372 freeStarter = false; 1373 } 1374 else 1375 { 1376 thestarter = base.thestarter->clone(); 1377 freeStarter = true; 1378 } 1379 1380 assert(SPxSolverBase<R>::isConsistent()); 1381 } 1382 1383 return *this; 1384 } 1385 1386 1387 template <class R> 1388 SPxSolverBase<R>::SPxSolverBase(const SPxSolverBase<R>& base) 1389 : SPxLPBase<R> (base) 1390 , SPxBasisBase<R>(this->basSe) 1391 , theType(base.theType) 1392 , thePricing(base.thePricing) 1393 , theRep(base.theRep) 1394 , polishObj(base.polishObj) 1395 , timerType(base.timerType) 1396 , theCumulativeTime(base.theCumulativeTime) 1397 , maxIters(base.maxIters) 1398 , maxTime(base.maxTime) 1399 , nClckSkipsLeft(base.nClckSkipsLeft) 1400 , nCallsToTimelim(base.nCallsToTimelim) 1401 , objLimit(base.objLimit) 1402 , m_status(base.m_status) 1403 , m_nonbasicValue(base.m_nonbasicValue) 1404 , m_nonbasicValueUpToDate(base.m_nonbasicValueUpToDate) 1405 , m_pricingViol(base.m_pricingViol) 1406 , m_pricingViolUpToDate(base.m_pricingViolUpToDate) 1407 , m_pricingViolCo(base.m_pricingViolCo) 1408 , m_pricingViolCoUpToDate(base.m_pricingViolCoUpToDate) 1409 , m_numViol(base.m_numViol) 1410 , entertolscale(base.entertolscale) 1411 , leavetolscale(base.leavetolscale) 1412 , theShift(base.theShift) 1413 , lastShift(base.lastShift) 1414 , m_maxCycle(base.m_maxCycle) 1415 , m_numCycle(base.m_numCycle) 1416 , initialized(base.initialized) 1417 , solveVector2(0) 1418 , solveVector2rhs(base.solveVector2rhs) 1419 , solveVector3(0) 1420 , solveVector3rhs(base.solveVector3rhs) 1421 , coSolveVector2(0) 1422 , coSolveVector2rhs(base.coSolveVector2rhs) 1423 , coSolveVector3(0) 1424 , coSolveVector3rhs(base.coSolveVector3rhs) 1425 , instableLeaveNum(base.instableLeaveNum) 1426 , instableLeave(base.instableLeave) 1427 , instableLeaveVal(base.instableLeaveVal) 1428 , instableEnterId(base.instableEnterId) 1429 , instableEnter(base.instableEnter) 1430 , instableEnterVal(base.instableEnterVal) 1431 , displayLine(base.displayLine) 1432 , displayFreq(base.displayFreq) 1433 , sparsePricingFactor(base.sparsePricingFactor) 1434 , getStartingDecompBasis(base.getStartingDecompBasis) 1435 , computeDegeneracy(base.computeDegeneracy) 1436 , degenCompIterOffset(base.degenCompIterOffset) 1437 , decompIterationLimit(base.decompIterationLimit) 1438 , fullPerturbation(base.fullPerturbation) 1439 , printBasisMetric(base.printBasisMetric) 1440 , unitVecs(base.unitVecs) 1441 , primRhs(base.primRhs) 1442 , primVec(base.primVec) 1443 , dualRhs(base.dualRhs) 1444 , dualVec(base.dualVec) 1445 , addVec(base.addVec) 1446 , theURbound(base.theURbound) 1447 , theLRbound(base.theLRbound) 1448 , theUCbound(base.theUCbound) 1449 , theLCbound(base.theLCbound) 1450 , theUBbound(base.theUBbound) 1451 , theLBbound(base.theLBbound) 1452 , theCoTest(base.theCoTest) 1453 , theTest(base.theTest) 1454 , primalRay(base.primalRay) 1455 , dualFarkas(base.dualFarkas) 1456 , leaveCount(base.leaveCount) 1457 , enterCount(base.enterCount) 1458 , primalCount(base.primalCount) 1459 , polishCount(base.polishCount) 1460 , boundflips(base.boundflips) 1461 , totalboundflips(base.totalboundflips) 1462 , enterCycles(base.enterCycles) 1463 , leaveCycles(base.leaveCycles) 1464 , enterDegenCand(base.enterDegenCand) 1465 , leaveDegenCand(base.leaveDegenCand) 1466 , primalDegenSum(base.primalDegenSum) 1467 , dualDegenSum(base.dualDegenSum) 1468 , boundrange(base.boundrange) 1469 , siderange(base.siderange) 1470 , objrange(base.objrange) 1471 , infeasibilities(base.infeasibilities) 1472 , infeasibilitiesCo(base.infeasibilitiesCo) 1473 , isInfeasible(base.isInfeasible) 1474 , isInfeasibleCo(base.isInfeasibleCo) 1475 , sparsePricingLeave(base.sparsePricingLeave) 1476 , sparsePricingEnter(base.sparsePricingEnter) 1477 , sparsePricingEnterCo(base.sparsePricingEnterCo) 1478 , hyperPricingLeave(base.hyperPricingLeave) 1479 , hyperPricingEnter(base.hyperPricingEnter) 1480 , remainingRoundsLeave(base.remainingRoundsLeave) 1481 , remainingRoundsEnter(base.remainingRoundsEnter) 1482 , remainingRoundsEnterCo(base.remainingRoundsEnterCo) 1483 , weights(base.weights) 1484 , coWeights(base.coWeights) 1485 , weightsAreSetup(base.weightsAreSetup) 1486 , multSparseCalls(base.multSparseCalls) 1487 , multFullCalls(base.multFullCalls) 1488 , multColwiseCalls(base.multColwiseCalls) 1489 , multUnsetupCalls(base.multUnsetupCalls) 1490 , spxout(base.spxout) 1491 , integerVariables(base.integerVariables) 1492 { 1493 theTime = TimerFactory::createTimer(timerType); 1494 multTimeSparse = TimerFactory::createTimer(timerType); 1495 multTimeFull = TimerFactory::createTimer(timerType); 1496 multTimeColwise = TimerFactory::createTimer(timerType); 1497 multTimeUnsetup = TimerFactory::createTimer(timerType); 1498 1499 if(base.theRep == COLUMN) 1500 { 1501 thevectors = this->colSet(); 1502 thecovectors = this->rowSet(); 1503 theFrhs = &primRhs; 1504 theFvec = &primVec; 1505 theCoPrhs = &dualRhs; 1506 theCoPvec = &dualVec; 1507 thePvec = &addVec; 1508 theRPvec = theCoPvec; 1509 theCPvec = thePvec; 1510 theUbound = &theUCbound; 1511 theLbound = &theLCbound; 1512 theCoUbound = &theURbound; 1513 theCoLbound = &theLRbound; 1514 } 1515 else 1516 { 1517 assert(base.theRep == ROW); 1518 1519 thevectors = this->rowSet(); 1520 thecovectors = this->colSet(); 1521 theFrhs = &dualRhs; 1522 theFvec = &dualVec; 1523 theCoPrhs = &primRhs; 1524 theCoPvec = &primVec; 1525 thePvec = &addVec; 1526 theRPvec = thePvec; 1527 theCPvec = theCoPvec; 1528 theUbound = &theURbound; 1529 theLbound = &theLRbound; 1530 theCoUbound = &theUCbound; 1531 theCoLbound = &theLCbound; 1532 } 1533 1534 SPxBasisBase<R>::theLP = this; 1535 1536 if(base.thepricer == 0) 1537 { 1538 thepricer = 0; 1539 freePricer = false; 1540 } 1541 else 1542 { 1543 thepricer = base.thepricer->clone(); 1544 freePricer = true; 1545 thepricer->clear(); 1546 thepricer->load(this); 1547 } 1548 1549 if(base.theratiotester == 0) 1550 { 1551 theratiotester = 0; 1552 freeRatioTester = false; 1553 } 1554 else 1555 { 1556 theratiotester = base.theratiotester->clone(); 1557 freeRatioTester = true; 1558 theratiotester->clear(); 1559 theratiotester->load(this); 1560 } 1561 1562 if(base.thestarter == 0) 1563 { 1564 thestarter = 0; 1565 freeStarter = false; 1566 } 1567 else 1568 { 1569 thestarter = base.thestarter->clone(); 1570 freeStarter = true; 1571 } 1572 1573 assert(SPxSolverBase<R>::isConsistent()); 1574 } 1575 1576 template <class R> 1577 bool SPxSolverBase<R>::isConsistent() const 1578 { 1579 #ifdef ENABLE_CONSISTENCY_CHECKS 1580 1581 if(epsilon() < 0 || tolerances() == nullptr) 1582 return SPX_MSG_INCONSISTENT("SPxSolverBase"); 1583 1584 if(primVec.delta().tolerances() != dualVec.delta().tolerances()) 1585 return SPX_MSG_INCONSISTENT("SPxSolverBase"); 1586 1587 if(dualVec.delta().tolerances() != addVec.delta().tolerances()) 1588 return SPX_MSG_INCONSISTENT("SPxSolverBase"); 1589 1590 if(unitVecs.size() < SPxLPBase<R>::nCols() || unitVecs.size() < SPxLPBase<R>::nRows()) 1591 return SPX_MSG_INCONSISTENT("SPxSolverBase"); 1592 1593 if(initialized) 1594 { 1595 if(theFrhs->dim() != dim()) 1596 return SPX_MSG_INCONSISTENT("SPxSolverBase"); 1597 1598 if(theFvec->dim() != dim()) 1599 return SPX_MSG_INCONSISTENT("SPxSolverBase"); 1600 1601 if(theCoPrhs->dim() != dim()) 1602 return SPX_MSG_INCONSISTENT("SPxSolverBase"); 1603 1604 if(thePvec->dim() != coDim()) 1605 return SPX_MSG_INCONSISTENT("SPxSolverBase"); 1606 1607 if(theCoPvec->dim() != dim()) 1608 return SPX_MSG_INCONSISTENT("SPxSolverBase"); 1609 1610 if(theTest.dim() != coDim()) 1611 return SPX_MSG_INCONSISTENT("SPxSolverBase"); 1612 1613 if(theCoTest.dim() != dim()) 1614 return SPX_MSG_INCONSISTENT("SPxSolverBase"); 1615 1616 if(theURbound.dim() != SPxLPBase<R>::nRows()) 1617 return SPX_MSG_INCONSISTENT("SPxSolverBase"); 1618 1619 if(theLRbound.dim() != SPxLPBase<R>::nRows()) 1620 return SPX_MSG_INCONSISTENT("SPxSolverBase"); 1621 1622 if(theUCbound.dim() != SPxLPBase<R>::nCols()) 1623 return SPX_MSG_INCONSISTENT("SPxSolverBase"); 1624 1625 if(theLCbound.dim() != SPxLPBase<R>::nCols()) 1626 return SPX_MSG_INCONSISTENT("SPxSolverBase"); 1627 1628 if(theUBbound.dim() != dim()) 1629 return SPX_MSG_INCONSISTENT("SPxSolverBase"); 1630 1631 if(theLBbound.dim() != dim()) 1632 return SPX_MSG_INCONSISTENT("SPxSolverBase"); 1633 } 1634 1635 if(rep() == COLUMN) 1636 { 1637 if(thecovectors != 1638 reinterpret_cast<const SVSetBase<R> *>(static_cast<const LPRowSetBase<R>*>(this)) 1639 || thevectors != 1640 reinterpret_cast<const SVSetBase<R> *>(static_cast<const LPColSetBase<R>*>(this)) 1641 || theFrhs != &primRhs || 1642 theFvec != &primVec || 1643 theCoPrhs != &dualRhs || 1644 theCoPvec != &dualVec || 1645 thePvec != &addVec || 1646 theRPvec != theCoPvec || 1647 theCPvec != thePvec || 1648 theUbound != &theUCbound || 1649 theLbound != &theLCbound || 1650 theCoUbound != &theURbound || 1651 theCoLbound != &theLRbound) 1652 return SPX_MSG_INCONSISTENT("SPxSolverBase"); 1653 } 1654 else 1655 { 1656 if(thecovectors 1657 != reinterpret_cast<const SVSetBase<R> *>(static_cast<const LPColSetBase<R>*>(this)) 1658 || thevectors 1659 != reinterpret_cast<const SVSetBase<R> *>(static_cast<const LPRowSetBase<R>*>(this)) 1660 || theFrhs != &dualRhs || 1661 theFvec != &dualVec || 1662 theCoPrhs != &primRhs || 1663 theCoPvec != &primVec || 1664 thePvec != &addVec || 1665 theRPvec != thePvec || 1666 theCPvec != theCoPvec || 1667 theUbound != &theURbound || 1668 theLbound != &theLRbound || 1669 theCoUbound != &theUCbound || 1670 theCoLbound != &theLCbound) 1671 return SPX_MSG_INCONSISTENT("SPxSolverBase"); 1672 } 1673 1674 return SPxLPBase<R>::isConsistent() 1675 && primRhs.isConsistent() 1676 && primVec.isConsistent() 1677 && dualRhs.isConsistent() 1678 && dualVec.isConsistent() 1679 && addVec.isConsistent() 1680 && theTest.isConsistent() 1681 && theCoTest.isConsistent() 1682 && theURbound.isConsistent() 1683 && theLRbound.isConsistent() 1684 && theUCbound.isConsistent() 1685 && theLCbound.isConsistent() 1686 && SPxBasisBase<R>::isConsistent() 1687 ; 1688 #else 1689 return true; 1690 #endif 1691 } 1692 1693 1694 template <class R> 1695 void SPxSolverBase<R>::setTerminationTime(Real p_time) 1696 { 1697 if(p_time < 0.0) 1698 p_time = 0.0; 1699 1700 maxTime = p_time; 1701 } 1702 1703 template <class R> 1704 Real SPxSolverBase<R>::terminationTime() const 1705 { 1706 return maxTime; 1707 } 1708 1709 template <class R> 1710 void SPxSolverBase<R>::setTerminationIter(int p_iteration) 1711 { 1712 if(p_iteration < 0) 1713 p_iteration = -1; 1714 1715 maxIters = p_iteration; 1716 } 1717 1718 template <class R> 1719 int SPxSolverBase<R>::terminationIter() const 1720 { 1721 return maxIters; 1722 } 1723 1724 // returns whether current time limit is reached; call to time() may be skipped unless \p forceCheck is true 1725 template <class R> 1726 bool SPxSolverBase<R>::isTimeLimitReached(const bool forceCheck) 1727 { 1728 // always update the number of calls, since the user might set a time limit later in the solving process 1729 ++nCallsToTimelim; 1730 1731 // check if a time limit is actually set 1732 if(maxTime >= R(infinity)) 1733 return false; 1734 1735 // check if the expensive system call to update the time should be skipped again 1736 if(forceCheck || nCallsToTimelim < SOPLEX_NINITCALLS || nClckSkipsLeft <= 0) 1737 { 1738 Real currtime = time(); 1739 1740 if(currtime >= maxTime) 1741 return true; 1742 1743 // determine the number of times the clock can be skipped again. 1744 int nClckSkips = SOPLEX_MAXNCLCKSKIPS; 1745 Real avgtimeinterval = (currtime + cumulativeTime()) / (Real)(nCallsToTimelim); 1746 1747 // it would not be safe to skip the clock so many times since we are approaching the time limit 1748 if(SOPLEX_SAFETYFACTOR * (maxTime - currtime) / (avgtimeinterval + 1e-6) < nClckSkips) 1749 nClckSkips = 0; 1750 1751 nClckSkipsLeft = nClckSkips; 1752 } 1753 else 1754 --nClckSkipsLeft; 1755 1756 return false; 1757 } 1758 1759 1760 /**@todo A first version for the termination value is 1761 * implemented. Currently we check if no bound violations (shifting) 1762 * is present. It might be even possible to use this termination 1763 * value in case of bound violations (shifting) but in this case it 1764 * is quite difficult to determine if we already reached the limit. 1765 */ 1766 template <class R> 1767 void SPxSolverBase<R>::setTerminationValue(R p_value) 1768 { 1769 objLimit = p_value; 1770 } 1771 1772 template <class R> 1773 R SPxSolverBase<R>::terminationValue() const 1774 { 1775 return objLimit; 1776 } 1777 1778 template <class R> 1779 typename SPxSolverBase<R>::VarStatus 1780 SPxSolverBase<R>::basisStatusToVarStatus(typename SPxBasisBase<R>::Desc::Status stat) const 1781 { 1782 VarStatus vstat; 1783 1784 switch(stat) 1785 { 1786 case SPxBasisBase<R>::Desc::P_ON_LOWER: 1787 vstat = ON_LOWER; 1788 break; 1789 1790 case SPxBasisBase<R>::Desc::P_ON_UPPER: 1791 vstat = ON_UPPER; 1792 break; 1793 1794 case SPxBasisBase<R>::Desc::P_FIXED: 1795 vstat = FIXED; 1796 break; 1797 1798 case SPxBasisBase<R>::Desc::P_FREE: 1799 vstat = ZERO; 1800 break; 1801 1802 case SPxBasisBase<R>::Desc::D_ON_UPPER: 1803 case SPxBasisBase<R>::Desc::D_ON_LOWER: 1804 case SPxBasisBase<R>::Desc::D_ON_BOTH: 1805 case SPxBasisBase<R>::Desc::D_UNDEFINED: 1806 case SPxBasisBase<R>::Desc::D_FREE: 1807 vstat = BASIC; 1808 break; 1809 1810 default: 1811 SPX_MSG_ERROR(std::cerr << "ESOLVE26 ERROR: unknown basis status (" << static_cast<int>(stat) << ")" 1812 << std::endl;) 1813 throw SPxInternalCodeException("XSOLVE22 This should never happen."); 1814 } 1815 1816 return vstat; 1817 } 1818 1819 template <class R> 1820 typename SPxBasisBase<R>::Desc::Status 1821 SPxSolverBase<R>::varStatusToBasisStatusRow(int row, 1822 typename SPxSolverBase<R>::VarStatus stat) const 1823 { 1824 typename SPxBasisBase<R>::Desc::Status rstat; 1825 1826 switch(stat) 1827 { 1828 case FIXED : 1829 assert(EQ(this->rhs(row), this->lhs(row), tolerances()->floatingPointFeastol())); 1830 rstat = SPxBasisBase<R>::Desc::P_FIXED; 1831 break; 1832 1833 case ON_UPPER : 1834 assert(this->rhs(row) < R(infinity)); 1835 rstat = this->lhs(row) < this->rhs(row) 1836 ? SPxBasisBase<R>::Desc::P_ON_UPPER 1837 : SPxBasisBase<R>::Desc::P_FIXED; 1838 break; 1839 1840 case ON_LOWER : 1841 assert(this->lhs(row) > R(-infinity)); 1842 rstat = this->lhs(row) < this->rhs(row) 1843 ? SPxBasisBase<R>::Desc::P_ON_LOWER 1844 : SPxBasisBase<R>::Desc::P_FIXED; 1845 break; 1846 1847 case ZERO : 1848 /* A 'free' row (i.e., infinite lower & upper bounds) does not really make sense. The user 1849 * might (think to) know better, e.g., when temporarily turning off a row. We therefore apply 1850 * the same adjustment as in the column case in varStatusToBasisStatusCol(). */ 1851 rstat = SPxBasisBase<R>::Desc::P_FREE; 1852 break; 1853 1854 case BASIC : 1855 rstat = this->dualRowStatus(row); 1856 break; 1857 1858 default: 1859 SPX_MSG_ERROR(std::cerr << "ESOLVE27 ERROR: unknown VarStatus (" << int(stat) << ")" 1860 << std::endl;) 1861 throw SPxInternalCodeException("XSOLVE23 This should never happen."); 1862 } 1863 1864 return rstat; 1865 } 1866 1867 template <class R> 1868 typename SPxBasisBase<R>::Desc::Status 1869 SPxSolverBase<R>::varStatusToBasisStatusCol(int col, 1870 typename SPxSolverBase<R>::VarStatus stat) const 1871 { 1872 typename SPxBasisBase<R>::Desc::Status cstat; 1873 1874 switch(stat) 1875 { 1876 case FIXED : 1877 if(this->upper(col) == this->lower(col)) 1878 cstat = SPxBasisBase<R>::Desc::P_FIXED; 1879 else if(this->maxObj(col) > 0.0) 1880 cstat = SPxBasisBase<R>::Desc::P_ON_UPPER; 1881 else 1882 cstat = SPxBasisBase<R>::Desc::P_ON_LOWER; 1883 1884 break; 1885 1886 case ON_UPPER : 1887 assert(this->upper(col) < R(infinity)); 1888 cstat = this->lower(col) < this->upper(col) 1889 ? SPxBasisBase<R>::Desc::P_ON_UPPER 1890 : SPxBasisBase<R>::Desc::P_FIXED; 1891 break; 1892 1893 case ON_LOWER : 1894 assert(this->lower(col) > R(-infinity)); 1895 cstat = this->lower(col) < this->upper(col) 1896 ? SPxBasisBase<R>::Desc::P_ON_LOWER 1897 : SPxBasisBase<R>::Desc::P_FIXED; 1898 break; 1899 1900 case ZERO : 1901 1902 /* In this case the upper and lower bounds on the variable should be infinite. The bounds 1903 * might, however, have changed and we try to recover from this by changing the status to 1904 * 'resonable' settings. Since the status should be implicit free we still always set it 1905 * to P_FREE to be consistent */ 1906 cstat = SPxBasisBase<R>::Desc::P_FREE; 1907 break; 1908 1909 case BASIC : 1910 cstat = this->dualColStatus(col); 1911 break; 1912 1913 default: 1914 SPX_MSG_ERROR(std::cerr << "ESOLVE28 ERROR: unknown VarStatus (" << int(stat) << ")" 1915 << std::endl;) 1916 throw SPxInternalCodeException("XSOLVE24 This should never happen."); 1917 } 1918 1919 return cstat; 1920 } 1921 1922 template <class R> 1923 typename SPxSolverBase<R>::VarStatus SPxSolverBase<R>::getBasisRowStatus(int row) const 1924 { 1925 assert(0 <= row && row < this->nRows()); 1926 return basisStatusToVarStatus(this->desc().rowStatus(row)); 1927 } 1928 1929 template <class R> 1930 typename SPxSolverBase<R>::VarStatus SPxSolverBase<R>::getBasisColStatus(int col) const 1931 { 1932 assert(0 <= col && col < this->nCols()); 1933 return basisStatusToVarStatus(this->desc().colStatus(col)); 1934 } 1935 1936 template <class R> 1937 typename SPxSolverBase<R>::Status SPxSolverBase<R>::getBasis(VarStatus row[], VarStatus col[], 1938 const int rowsSize, const int colsSize) const 1939 { 1940 const typename SPxBasisBase<R>::Desc& d = this->desc(); 1941 int i; 1942 1943 assert(rowsSize < 0 || rowsSize >= this->nRows()); 1944 assert(colsSize < 0 || colsSize >= this->nCols()); 1945 1946 if(col) 1947 for(i = this->nCols() - 1; i >= 0; --i) 1948 col[i] = basisStatusToVarStatus(d.colStatus(i)); 1949 1950 if(row) 1951 for(i = this->nRows() - 1; i >= 0; --i) 1952 row[i] = basisStatusToVarStatus(d.rowStatus(i)); 1953 1954 return status(); 1955 } 1956 1957 template <class R> 1958 bool SPxSolverBase<R>::isBasisValid(DataArray<VarStatus> p_rows, DataArray<VarStatus> p_cols) 1959 { 1960 1961 int basisdim; 1962 1963 if(p_rows.size() != this->nRows() || p_cols.size() != this->nCols()) 1964 return false; 1965 1966 basisdim = 0; 1967 1968 for(int row = this->nRows() - 1; row >= 0; --row) 1969 { 1970 if(p_rows[row] == UNDEFINED) 1971 return false; 1972 // row is basic 1973 else if(p_rows[row] == BASIC) 1974 { 1975 basisdim++; 1976 } 1977 // row is nonbasic 1978 else 1979 { 1980 if((p_rows[row] == FIXED && this->lhs(row) != this->rhs(row)) 1981 || (p_rows[row] == ON_UPPER && this->rhs(row) >= R(infinity)) 1982 || (p_rows[row] == ON_LOWER && this->lhs(row) <= R(-infinity))) 1983 return false; 1984 } 1985 } 1986 1987 for(int col = this->nCols() - 1; col >= 0; --col) 1988 { 1989 if(p_cols[col] == UNDEFINED) 1990 return false; 1991 // col is basic 1992 else if(p_cols[col] == BASIC) 1993 { 1994 basisdim++; 1995 } 1996 // col is nonbasic 1997 else 1998 { 1999 if((p_cols[col] == FIXED && this->lower(col) != this->upper(col)) 2000 || (p_cols[col] == ON_UPPER && this->upper(col) >= R(infinity)) 2001 || (p_cols[col] == ON_LOWER && this->lower(col) <= R(-infinity))) 2002 return false; 2003 } 2004 } 2005 2006 if(basisdim != dim()) 2007 return false; 2008 2009 // basis valid 2010 return true; 2011 } 2012 2013 template <class R> 2014 void SPxSolverBase<R>::setBasis(const VarStatus p_rows[], const VarStatus p_cols[]) 2015 { 2016 if(SPxBasisBase<R>::status() == SPxBasisBase<R>::NO_PROBLEM) 2017 SPxBasisBase<R>::load(this, false); 2018 2019 typename SPxBasisBase<R>::Desc ds = this->desc(); 2020 int i; 2021 2022 for(i = 0; i < this->nRows(); i++) 2023 ds.rowStatus(i) = varStatusToBasisStatusRow(i, p_rows[i]); 2024 2025 for(i = 0; i < this->nCols(); i++) 2026 ds.colStatus(i) = varStatusToBasisStatusCol(i, p_cols[i]); 2027 2028 loadBasis(ds); 2029 forceRecompNonbasicValue(); 2030 } 2031 2032 // NOTE: This only works for the row representation. Need to update to account for column representation. 2033 // The degenvec differs relative to the algorithm being used. 2034 // For the primal simplex, degenvec is the primal solution values. 2035 // For the dual simplex, the degenvec is the feasvec (ROW) and pVec (COLUMN). 2036 template <class R> 2037 R SPxSolverBase<R>::getDegeneracyLevel(VectorBase<R> degenvec) 2038 { 2039 int numDegenerate = 0; 2040 R degeneracyLevel = 0; 2041 2042 // iterating over all columns in the basis matrix 2043 // this identifies the basis indices and those that have a zero dual multiplier (rows) or zero reduced cost (cols). 2044 if(rep() == ROW) 2045 { 2046 for(int i = 0; i < this->nCols(); 2047 ++i) // @todo Check the use of numColsReal for the reduced problem. 2048 { 2049 // degeneracy in the dual simplex exists if there are rows with a zero dual multiplier or columns with a zero 2050 // reduced costs. This requirement is regardless of the objective sense. 2051 if(isZero(degenvec[i], tolerances()->floatingPointFeastol())) 2052 numDegenerate++; 2053 } 2054 2055 if(type() == ENTER) // dual simplex 2056 degeneracyLevel = R(numDegenerate) / this->nCols(); 2057 else // primal simplex 2058 { 2059 assert(type() == LEAVE); 2060 R degenVars = (numDegenerate > (this->nCols() - this->nRows())) ? R(numDegenerate - 2061 (this->nCols() - this->nRows())) : 0.0; 2062 degeneracyLevel = degenVars / this->nRows(); 2063 } 2064 } 2065 else 2066 { 2067 assert(rep() == COLUMN); 2068 2069 for(int i = 0; i < this->nCols(); i++) 2070 { 2071 if(type() == LEAVE) // dual simplex 2072 { 2073 if(isZero(this->maxObj()[i] - degenvec[i], tolerances()->floatingPointFeastol())) 2074 numDegenerate++; 2075 } 2076 else // primal simplex 2077 { 2078 assert(type() == ENTER); 2079 2080 if(isZero(degenvec[i], tolerances()->floatingPointFeastol())) 2081 numDegenerate++; 2082 } 2083 } 2084 2085 2086 if(type() == LEAVE) // dual simplex 2087 { 2088 R degenVars = this->nRows() > numDegenerate ? R(this->nRows() - numDegenerate) : 0.0; 2089 degeneracyLevel = degenVars / this->nCols(); 2090 } 2091 else // primal simplex 2092 { 2093 assert(type() == ENTER); 2094 R degenVars = (numDegenerate > (this->nCols() - this->nRows())) ? R(numDegenerate - 2095 (this->nCols() - this->nRows())) : 0.0; 2096 degeneracyLevel = degenVars / this->nRows(); 2097 } 2098 } 2099 2100 return degeneracyLevel; 2101 } 2102 2103 template <class R> 2104 void SPxSolverBase<R>::getNdualNorms(int& nnormsRow, int& nnormsCol) const 2105 { 2106 nnormsRow = 0; 2107 nnormsCol = 0; 2108 2109 if(weightsAreSetup) 2110 { 2111 if(type() == SPxSolverBase<R>::LEAVE && rep() == SPxSolverBase<R>::COLUMN) 2112 { 2113 nnormsRow = coWeights.dim(); 2114 nnormsCol = 0; 2115 2116 assert(nnormsRow == dim()); 2117 } 2118 else if(type() == SPxSolverBase<R>::ENTER && rep() == SPxSolverBase<R>::ROW) 2119 { 2120 nnormsRow = weights.dim(); 2121 nnormsCol = coWeights.dim(); 2122 2123 assert(nnormsRow == coDim()); 2124 assert(nnormsCol == dim()); 2125 } 2126 } 2127 } 2128 2129 template <class R> 2130 bool SPxSolverBase<R>::getDualNorms(int& nnormsRow, int& nnormsCol, R * norms) const 2131 { 2132 nnormsRow = 0; 2133 nnormsCol = 0; 2134 2135 if(!weightsAreSetup) 2136 return false; 2137 2138 if(type() == SPxSolverBase<R>::LEAVE && rep() == SPxSolverBase<R>::COLUMN) 2139 { 2140 nnormsCol = 0; 2141 nnormsRow = coWeights.dim(); 2142 2143 assert(nnormsRow == dim()); 2144 2145 for(int i = 0; i < nnormsRow; ++i) 2146 norms[i] = coWeights[i]; 2147 } 2148 else if(type() == SPxSolverBase<R>::ENTER && rep() == SPxSolverBase<R>::ROW) 2149 { 2150 nnormsRow = weights.dim(); 2151 nnormsCol = coWeights.dim(); 2152 2153 assert(nnormsCol == dim()); 2154 assert(nnormsRow == coDim()); 2155 2156 for(int i = 0; i < nnormsRow; ++i) 2157 norms[i] = weights[i]; 2158 2159 for(int i = 0; i < nnormsCol; ++i) 2160 norms[nnormsRow + i] = coWeights[i]; 2161 } 2162 else 2163 return false; 2164 2165 return true; 2166 } 2167 2168 template <class R> 2169 bool SPxSolverBase<R>::setDualNorms(int nnormsRow, int nnormsCol, R * norms) 2170 { 2171 weightsAreSetup = false; 2172 2173 if(type() == SPxSolverBase<R>::LEAVE && rep() == SPxSolverBase<R>::COLUMN) 2174 { 2175 coWeights.reDim(dim(), false); 2176 assert(coWeights.dim() >= nnormsRow); 2177 2178 for(int i = 0; i < nnormsRow; ++i) 2179 coWeights[i] = norms[i]; 2180 2181 weightsAreSetup = true; 2182 } 2183 else if(type() == SPxSolverBase<R>::ENTER && rep() == SPxSolverBase<R>::ROW) 2184 { 2185 weights.reDim(coDim(), false); 2186 coWeights.reDim(dim(), false); 2187 assert(weights.dim() >= nnormsRow); 2188 assert(coWeights.dim() >= nnormsCol); 2189 2190 for(int i = 0; i < nnormsRow; ++i) 2191 weights[i] = norms[i]; 2192 2193 for(int i = 0; i < nnormsCol; ++i) 2194 coWeights[i] = norms[nnormsRow + i]; 2195 2196 weightsAreSetup = true; 2197 } 2198 else 2199 return false; 2200 2201 return true; 2202 } 2203 2204 template <class R> 2205 void SPxSolverBase<R>::setIntegralityInformation(int ncols, int* intInfo) 2206 { 2207 assert(ncols == this->nCols() || (ncols == 0 && intInfo == NULL)); 2208 2209 integerVariables.reSize(ncols); 2210 2211 for(int i = 0; i < ncols; ++i) 2212 { 2213 integerVariables[i] = intInfo[i]; 2214 } 2215 } 2216 2217 2218 2219 // 2220 // Auxiliary functions. 2221 // 2222 2223 // Pretty-printing of variable status. 2224 template <class R> 2225 std::ostream& operator<<(std::ostream & os, 2226 const typename SPxSolverBase<R>::VarStatus & status) 2227 { 2228 switch(status) 2229 { 2230 case SPxSolverBase<R>::BASIC: 2231 os << "BASIC"; 2232 break; 2233 2234 case SPxSolverBase<R>::FIXED: 2235 os << "FIXED"; 2236 break; 2237 2238 case SPxSolverBase<R>::ON_LOWER: 2239 os << "ON_LOWER"; 2240 break; 2241 2242 case SPxSolverBase<R>::ON_UPPER: 2243 os << "ON_UPPER"; 2244 break; 2245 2246 case SPxSolverBase<R>::ZERO: 2247 os << "ZERO"; 2248 break; 2249 2250 case SPxSolverBase<R>::UNDEFINED: 2251 os << "UNDEFINED"; 2252 break; 2253 2254 default: 2255 os << "?invalid?"; 2256 break; 2257 } 2258 2259 return os; 2260 } 2261 2262 // Pretty-printing of solver status. 2263 template <class R> 2264 std::ostream& operator<<(std::ostream & os, 2265 const typename SPxSolverBase<R>::Status & status) 2266 { 2267 switch(status) 2268 { 2269 case SPxSolverBase<R>::ERROR: 2270 os << "ERROR"; 2271 break; 2272 2273 case SPxSolverBase<R>::NO_RATIOTESTER: 2274 os << "NO_RATIOTESTER"; 2275 break; 2276 2277 case SPxSolverBase<R>::NO_PRICER: 2278 os << "NO_PRICER"; 2279 break; 2280 2281 case SPxSolverBase<R>::NO_SOLVER: 2282 os << "NO_SOLVER"; 2283 break; 2284 2285 case SPxSolverBase<R>::NOT_INIT: 2286 os << "NOT_INIT"; 2287 break; 2288 2289 case SPxSolverBase<R>::ABORT_CYCLING: 2290 os << "ABORT_CYCLING"; 2291 break; 2292 2293 case SPxSolverBase<R>::ABORT_TIME: 2294 os << "ABORT_TIME"; 2295 break; 2296 2297 case SPxSolverBase<R>::ABORT_ITER: 2298 os << "ABORT_ITER"; 2299 break; 2300 2301 case SPxSolverBase<R>::ABORT_VALUE: 2302 os << "ABORT_VALUE"; 2303 break; 2304 2305 case SPxSolverBase<R>::SINGULAR: 2306 os << "SINGULAR"; 2307 break; 2308 2309 case SPxSolverBase<R>::NO_PROBLEM: 2310 os << "NO_PROBLEM"; 2311 break; 2312 2313 case SPxSolverBase<R>::REGULAR: 2314 os << "REGULAR"; 2315 break; 2316 2317 case SPxSolverBase<R>::RUNNING: 2318 os << "RUNNING"; 2319 break; 2320 2321 case SPxSolverBase<R>::UNKNOWN: 2322 os << "UNKNOWN"; 2323 break; 2324 2325 case SPxSolverBase<R>::OPTIMAL: 2326 os << "OPTIMAL"; 2327 break; 2328 2329 case SPxSolverBase<R>::UNBOUNDED: 2330 os << "UNBOUNDED"; 2331 break; 2332 2333 case SPxSolverBase<R>::INFEASIBLE: 2334 os << "INFEASIBLE"; 2335 break; 2336 2337 default: 2338 os << "?other?"; 2339 break; 2340 } 2341 2342 return os; 2343 } 2344 2345 // Pretty-printing of algorithm. 2346 template <class R> 2347 std::ostream& operator<<(std::ostream & os, 2348 const typename SPxSolverBase<R>::Type & status) 2349 { 2350 switch(status) 2351 { 2352 case SPxSolverBase<R>::ENTER: 2353 os << "ENTER"; 2354 break; 2355 2356 case SPxSolverBase<R>::LEAVE: 2357 os << "LEAVE"; 2358 break; 2359 2360 default: 2361 os << "?other?"; 2362 break; 2363 } 2364 2365 return os; 2366 } 2367 2368 // Pretty-printing of representation. 2369 template <class R> 2370 std::ostream& operator<<(std::ostream & os, 2371 const typename SPxSolverBase<R>::Representation & status) 2372 { 2373 switch(status) 2374 { 2375 case SPxSolverBase<R>::ROW: 2376 os << "ROW"; 2377 break; 2378 2379 case SPxSolverBase<R>::COLUMN: 2380 os << "COLUMN"; 2381 break; 2382 2383 default: 2384 os << "?other?"; 2385 break; 2386 } 2387 2388 return os; 2389 } 2390 2391 2392 } // namespace soplex 2393