1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 2 /* */ 3 /* This file is part of the class library */ 4 /* SoPlex --- the Sequential object-oriented simPlex. */ 5 /* */ 6 /* Copyright (C) 1996-2021 Konrad-Zuse-Zentrum */ 7 /* fuer Informationstechnik Berlin */ 8 /* */ 9 /* SoPlex is distributed under the terms of the ZIB Academic Licence. */ 10 /* */ 11 /* You should have received a copy of the ZIB Academic License */ 12 /* along with SoPlex; see the file COPYING. If not email to soplex@zib.de. */ 13 /* */ 14 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 15 16 /**@file spxbasis.h 17 * @brief Simplex basis. 18 */ 19 #ifndef _SPXBASIS_H_ 20 #define _SPXBASIS_H_ 21 22 /* undefine SOPLEX_DEBUG flag from including files; if SOPLEX_DEBUG should be defined in this file, do so below */ 23 #ifdef SOPLEX_DEBUG 24 #define SOPLEX_DEBUG_SPXBASIS 25 #undef SOPLEX_DEBUG 26 #endif 27 28 #include <assert.h> 29 #include <iostream> 30 #include <iomanip> 31 #include <string.h> 32 #include <sstream> 33 34 #include "soplex/spxdefines.h" 35 #include "soplex/spxlp.h" 36 #include "soplex/svector.h" 37 #include "soplex/ssvector.h" 38 #include "soplex/dataarray.h" 39 #include "soplex/slinsolver.h" 40 #include "soplex/nameset.h" 41 #include "soplex/spxout.h" 42 #include "soplex/timerfactory.h" 43 44 //#define MEASUREUPDATETIME 45 46 namespace soplex 47 { 48 template <class R> 49 class SPxSolverBase; 50 51 /**@class SPxBasisBase 52 @brief Simplex basis. 53 @ingroup Algo 54 55 Consider the linear program as provided from class SPxLP: 56 \f[ 57 \begin{array}{rl} 58 \hbox{max} & c^T x \\ 59 \hbox{s.t.} & l_r \le Ax \le u_r \\ 60 & l_c \le x \le u_c 61 \end{array} 62 \f] 63 where \f$c, l_c, u_c, x \in {\bf R}^n\f$, \f$l_r, u_r \in {\bf R}^m\f$ and 64 \f$A \in {\bf R}^{m \times n}\f$. Solving this LP with the simplex algorithm 65 requires the definition of a \em basis. Such can be defined as a set of 66 column vectors or a set of row vectors building a non-singular matrix. We 67 will refer to the first case as the \em columnwise \em representation and 68 the latter case will be called the \em rowwise \em representation. In both 69 cases, a \em basis is a set of vectors forming a non-singular matrix. The 70 dimension of the vectors is referred to as the basis' \em dimension, 71 whereas the number of vectors belonging to the LP is called the basis' 72 \em codimension. 73 74 Class SPxBasisBase is designed to represent a generic simplex basis, suitable 75 for both representations. At any time the representation can be changed by 76 calling method setRep(). 77 78 Class SPxBasisBase provides methods for solving linear systems with the basis 79 matrix. However, SPxBasisBase does not provide a linear solver by its own. 80 Instead, a SLinSolver object must be #load%ed to a SPxBasisBase which will 81 be called for solving linear systems. 82 */ 83 template <class R> // theLP gets templated 84 class SPxBasisBase 85 { 86 public: 87 88 /// basis status. 89 /** Each SPxBasisBase is assigned a status flag, which can take on of the 90 above values. 91 */ 92 enum SPxStatus 93 { 94 NO_PROBLEM = -2, ///< No Problem has been loaded to the basis. 95 SINGULAR = -1, ///< Basis is singular. 96 REGULAR = 0, ///< Basis is not known to be dual nor primal feasible. 97 DUAL = 1, ///< Basis is dual feasible. 98 PRIMAL = 2, ///< Basis is primal feasible. 99 OPTIMAL = 3, ///< Basis is optimal, i.e. dual and primal feasible. 100 UNBOUNDED = 4, ///< LP has been proven to be primal unbounded. 101 INFEASIBLE = 5 ///< LP has been proven to be primal infeasible. 102 }; 103 104 105 /// Basis descriptor. 106 class Desc 107 { 108 public: 109 110 //------------------------------------ 111 ///@name Status 112 ///@{ 113 /// Status of a variable. 114 /** A basis is described by assigning a Status to all of the LP 115 variables and covariables. This assignment is maintained by the 116 basis #Desc%riptor. 117 118 Variables and covariables (slackvariables) may have a primal or dual Status. The 119 first type specifies that a variable is set on a primal bound, while 120 the latter type indicates a dual variable to be set on a bound. 121 If a row variable has a primal status, say #P_ON_UPPER, this means 122 that the upper bound of the inequality is set to be tight. Hence, 123 in this case the upper bound must not be infinity. 124 125 Equivalently, if the status of a variable is dual, say #D_ON_UPPER, 126 it means that the dual variable corresponding to the upper bound 127 inequality of this variable is set to 0. 128 129 For a column basis, primal #Status%es correspond to nonbasic 130 variables, while dual ones are basic. This is reversed for a row 131 basis. We will now reveal in more detail the significance of 132 variable #Status%es. 133 134 <b>Primal Variables</b> 135 136 Consider a range inequality \f$l_r \le a^T x \le u_r\f$ or bounds on 137 a variable \f$l_c \le x_c \le u_c\f$. The following table reveals 138 what is implied if the corresponding variable or covariable is 139 assigned to a primal #Status: 140 141 \f[ 142 \begin{array}{lcl} 143 l_c \le x_c \le u_c & \mbox{Status}(x_i) & l_r \le a^T x \le u_r \\ 144 \hline 145 x_c = u_c < \infty & \mbox{P\_ON\_UPPER} & a^T x = u_r < \infty \\ 146 x_c = l_c > -\infty & \mbox{P\_ON\_LOWER} & a^T x = l_r > -\infty \\ 147 -\infty < l_c = x_c = u_c < \infty 148 & \mbox{P\_FIXED} & 149 -\infty < l_r = a^T x = u_r < \infty \\ 150 -\infty = l_i < x_i=0 < u_i = \infty 151 & \mbox{P\_FREE} & 152 -\infty = l_r < a^T x = 0 < u_r = \infty \\ 153 \end{array} 154 \f] 155 156 Note that to determine whether a variable with #Status stat is set to 157 its upper bound, one can compute the test (-stat | -#P_ON_UPPER). 158 This will yield true even if the variable is fixed, i.e., sitting on 159 both bounds at the same time. 160 161 <b>Dual Variables</b> 162 163 In principle for implementing the Simplex algorithm it would suffice 164 to use only one dual #Status. However, for performance reasons it 165 is advisable to introduce various dual status types, reflecting 166 the structure of the bounds. Given an upper bound \f$u\f$ and a lower 167 bound \f$l\f$ of a constraint or variable, the following table 168 indicates the setting of the dual Status of this variable. 169 170 \f[ 171 \begin{array}{cl} 172 l \le ... \le u & \mbox{Status} \\ 173 \hline 174 -\infty < l \ne u < \infty & \mbox{D\_ON\_BOTH} \\ 175 -\infty < l \ne u = \infty & \mbox{D\_ON\_UPPER} \\ 176 -\infty = l \ne u < \infty & \mbox{D\_ON\_LOWER} \\ 177 -\infty < l = u < \infty & \mbox{D\_FREE} \\ 178 -\infty = l \ne u = \infty & \mbox{D\_UNDEFINED} \\ 179 \end{array} 180 \f] 181 182 Note that unbounded primal variables are reflected by an #D_UNDEFINED 183 dual variable, since no reduced costs exist for them. To facilitate 184 the assignment of dual #Status%es, class SPxBasisBase provides methods 185 #dualStatus(), #dualColStatus() and #dualRowStatus)(). 186 */ 187 enum Status 188 { 189 P_ON_LOWER = -4, ///< primal variable is set to its lower bound 190 P_ON_UPPER = -2, ///< primal variable is set to its upper bound 191 P_FREE = -1, ///< primal variable is left free, but unset 192 P_FIXED = P_ON_UPPER + P_ON_LOWER, ///< primal variable is fixed to both bounds 193 D_FREE = 1, ///< dual variable is left free, but unset 194 D_ON_UPPER = 2, ///< dual variable is set to its upper bound 195 D_ON_LOWER = 4, ///< dual variable is set to its lower bound 196 D_ON_BOTH = D_ON_LOWER + D_ON_UPPER, ///< dual variable has two bounds 197 D_UNDEFINED = 8 ///< primal or dual variable is undefined 198 }; 199 ///@} 200 201 friend SPxBasisBase<R>; 202 template <class T> friend std::ostream& operator<< (std::ostream& os, 203 const Status& stat); //@todo is the <> required here? 204 205 private: 206 207 //------------------------------------ 208 ///@name Data 209 ///@{ 210 DataArray < Status > rowstat; ///< status of rows. 211 DataArray < Status > colstat; ///< status of columns. 212 DataArray < Status >* stat; ///< basis' status. 213 DataArray < Status >* costat; ///< cobasis' status. 214 ///@} 215 216 public: 217 218 //------------------------------------ 219 ///@name Access / modification 220 ///@{ 221 /// returns number of columns. 222 int nCols() const 223 { 224 return colstat.size(); 225 } 226 /// returns number of rows. 227 int nRows() const 228 { 229 return rowstat.size(); 230 } 231 /// returns dimension. 232 int dim() const 233 { 234 return stat->size(); 235 } 236 /// returns codimension. 237 int coDim() const 238 { 239 return costat->size(); 240 } 241 /// 242 Status& rowStatus(int i) 243 { 244 return rowstat[i]; 245 } 246 /// returns status of row \p i. 247 Status rowStatus(int i) const 248 { 249 return rowstat[i]; 250 } 251 /// returns the array of row \ref soplex::SPxBasisBase<R>::Desc::Status "Status"es. 252 const Status* rowStatus(void) const 253 { 254 return rowstat.get_const_ptr(); 255 } 256 /// 257 Status& colStatus(int i) 258 { 259 return colstat[i]; 260 } 261 /// returns status of column \p i. 262 Status colStatus(int i) const 263 { 264 return colstat[i]; 265 } 266 /// returns the array of column \ref soplex::SPxBasisBase<R>::Desc::Status "Status"es. 267 const Status* colStatus(void) const 268 { 269 return colstat.get_const_ptr(); 270 } 271 /// 272 Status& status(int i) 273 { 274 return (*stat)[i]; 275 } 276 /// returns status of variable \p i. 277 Status status(int i) const 278 { 279 return (*stat)[i]; 280 } 281 /// returns the array of variable \ref soplex::SPxBasisBase<R>::Desc::Status "Status"es. 282 const Status* status(void) const 283 { 284 return stat->get_const_ptr(); 285 } 286 /// 287 Status& coStatus(int i) 288 { 289 return (*costat)[i]; 290 } 291 /// returns status of covariable \p i. 292 Status coStatus(int i) const 293 { 294 return (*costat)[i]; 295 } 296 /// returns the array of covariable \ref soplex::SPxBasisBase<R>::Desc::Status "Status"es. 297 const Status* coStatus(void) const 298 { 299 return costat->get_const_ptr(); 300 } 301 /// resets dimensions. 302 void reSize(int rowDim, int colDim); 303 ///@} 304 305 //------------------------------------ 306 ///@name Debugging 307 ///@{ 308 /// Prints out status. 309 void dump() const; 310 311 /// consistency check. 312 bool isConsistent() const; 313 ///@} 314 315 //------------------------------------ 316 ///@name Construction / destruction 317 ///@{ 318 /// default constructor 319 Desc() 320 : stat(0) 321 , costat(0) 322 {} 323 explicit Desc(const SPxSolverBase<R>& base); 324 325 /// copy constructor 326 Desc(const Desc& old); 327 /// assignment operator 328 Desc& operator=(const Desc& rhs); 329 ///@} 330 }; 331 332 protected: 333 334 //------------------------------------ 335 //**@name Protected data 336 /** 337 For storing the basis matrix we keep two arrays: Array #theBaseId 338 contains the SPxId%s of the basis vectors, and #matrix the pointers to 339 the vectors themselfes. Method #loadMatrixVecs() serves for loading 340 #matrix according to the SPxId%s stored in #theBaseId. This method must 341 be called whenever the VectorBase<R> pointers may have 342 changed due to manipulations of the LP. 343 */ 344 ///@{ 345 /// the LP 346 SPxSolverBase<R>* theLP; 347 /// SPxId%s of basic vectors. 348 DataArray < SPxId > theBaseId; 349 /// pointers to the vectors of the basis matrix. 350 DataArray < const SVectorBase<R>* > matrix; 351 /// \c true iff the pointers in \ref soplex::SPxBasisBase<R>::matrix "matrix" are set up correctly. 352 bool matrixIsSetup; 353 354 /* @brief LU factorization of basis matrix 355 The factorization of the matrix is stored in #factor if #factorized != 0. 356 Otherwise #factor is undefined. 357 */ 358 SLinSolver<R>* factor; 359 /// \c true iff \ref soplex::SPxBasisBase<R>::factor "factor" = \ref soplex::SPxBasisBase<R>::matrix "matrix" \f$^{-1}\f$. 360 bool factorized; 361 362 /// number of updates before refactorization. 363 /** When a vector of the basis matrix is exchanged by a call to method 364 #change(), the LU factorization of the matrix is updated 365 accordingly. However, after atmost #maxUpdates updates of the 366 factorization, it is recomputed in order to regain numerical 367 stability and reduce fill in. 368 */ 369 int maxUpdates; 370 371 /// allowed increase of nonzeros before refactorization. 372 /** When the number of nonzeros in LU factorization exceeds 373 #nonzeroFactor times the number of nonzeros in B, the 374 basis matrix is refactorized. 375 */ 376 R nonzeroFactor; 377 378 /// allowed increase in relative fill before refactorization 379 /** When the real relative fill is bigger than fillFactor times lastFill 380 * the Basis will be refactorized. 381 */ 382 R fillFactor; 383 384 /// allowed total increase in memory consumption before refactorization 385 R memFactor; 386 387 /* Rank-1-updates to the basis may be performed via method #change(). In 388 this case, the factorization is updated, and the following members are 389 reset. 390 */ 391 int iterCount; ///< number of calls to change() since last manipulation 392 int lastIterCount; ///< number of calls to change() before halting the simplex 393 int iterDegenCheck;///< number of calls to change() since last degeneracy check 394 int updateCount; ///< number of calls to change() since last factorize() 395 int totalUpdateCount; ///< number of updates 396 int nzCount; ///< number of nonzeros in basis matrix 397 int lastMem; ///< memory needed after last fresh factorization 398 R lastFill; ///< fill ratio that occured during last factorization 399 int lastNzCount; ///< number of nonzeros in basis matrix after last fresh factorization 400 401 Timer* theTime; ///< time spent in updates 402 Timer::TYPE timerType; ///< type of timer (user or wallclock) 403 404 SPxId lastin; ///< lastEntered(): variable entered the base last 405 SPxId lastout; ///< lastLeft(): variable left the base last 406 int lastidx; ///< lastIndex(): basis index where last update was done 407 R minStab; ///< minimum stability 408 ///@} 409 410 private: 411 412 //------------------------------------ 413 //**@name Private data */ 414 ///@{ 415 SPxStatus thestatus; ///< current status of the basis. 416 Desc thedesc; ///< the basis' Descriptor 417 bool freeSlinSolver; ///< true iff factor should be freed inside of this object 418 SPxOut* spxout; ///< message handler 419 420 ///@} 421 422 public: 423 424 //------------------------------------------------ 425 /**@name Status and Descriptor related Methods */ 426 ///@{ 427 /// returns current SPxStatus. 428 SPxStatus status() const 429 { 430 return thestatus; 431 } 432 433 /// sets basis SPxStatus to \p stat. 434 void setStatus(SPxStatus stat) 435 { 436 437 if(thestatus != stat) 438 { 439 #ifdef SOPLEX_DEBUG 440 MSG_DEBUG(std::cout << "DBSTAT01 SPxBasisBase<R>::setStatus(): status: " 441 << int(thestatus) << " (" << thestatus << ") -> " 442 << int(stat) << " (" << stat << ")" << std::endl;) 443 #endif 444 445 thestatus = stat; 446 447 if(stat == NO_PROBLEM) 448 invalidate(); 449 } 450 } 451 452 // TODO control factorization frequency dynamically 453 /// change maximum number of iterations until a refactorization is performed 454 void setMaxUpdates(int maxUp) 455 { 456 assert(maxUp >= 0); 457 maxUpdates = maxUp; 458 } 459 460 /// returns maximum number of updates before a refactorization is performed 461 int getMaxUpdates() const 462 { 463 return maxUpdates; 464 } 465 466 /// 467 const Desc& desc() const 468 { 469 return thedesc; 470 } 471 /// returns current basis Descriptor. 472 Desc& desc() 473 { 474 return thedesc; 475 } 476 477 /// dual Status for the \p i'th column variable of the loaded LP. 478 typename Desc::Status dualColStatus(int i) const; 479 480 /// dual Status for the column variable with ID \p id of the loaded LP. 481 typename Desc::Status dualStatus(const SPxColId& id) const; 482 483 /// dual Status for the \p i'th row variable of the loaded LP. 484 typename Desc::Status dualRowStatus(int i) const; 485 486 /// dual Status for the row variable with ID \p id of the loaded LP. 487 typename Desc::Status dualStatus(const SPxRowId& id) const; 488 489 /// dual Status for the variable with ID \p id of the loaded LP. 490 /** It is automatically detected, whether the \p id is one of a 491 row or a column variable, and the correct row or column status 492 is returned. 493 */ 494 typename Desc::Status dualStatus(const SPxId& id) const 495 { 496 return id.isSPxRowId() 497 ? dualStatus(SPxRowId(id)) 498 : dualStatus(SPxColId(id)); 499 } 500 ///@} 501 502 503 //----------------------------------- 504 /**@name Inquiry Methods */ 505 ///@{ 506 /// 507 inline SPxId& baseId(int i) 508 { 509 return theBaseId[i]; 510 } 511 /// returns the Id of the \p i'th basis vector. 512 inline SPxId baseId(int i) const 513 { 514 return theBaseId[i]; 515 } 516 517 /// returns the \p i'th basic vector. 518 const SVectorBase<R>& baseVec(int i) const 519 { 520 assert(matrixIsSetup); 521 return *matrix[i]; 522 } 523 524 /// returns SPxId of last VectorBase<R> included to the basis. 525 inline SPxId lastEntered() const 526 { 527 return lastin; 528 } 529 530 /// returns SPxId of last vector that left the basis. 531 inline SPxId lastLeft() const 532 { 533 return lastout; 534 } 535 536 /// returns index in basis where last update was done. 537 inline int lastIndex() const 538 { 539 return lastidx; 540 } 541 542 /// returns number of basis changes since last refactorization. 543 inline int lastUpdate() const 544 { 545 return updateCount; 546 } 547 548 /// returns number of basis changes since last \ref soplex::SPxBasisBase<R>::load() "load()". 549 inline int iteration() const 550 { 551 return iterCount; 552 } 553 554 /// returns the number of iterations prior to the last break in execution 555 inline int prevIteration() const 556 { 557 return lastIterCount; 558 } 559 560 /// returns the number of iterations since the last degeneracy check 561 inline int lastDegenCheck() const 562 { 563 return iterDegenCheck; 564 } 565 566 /// returns loaded solver. 567 inline SPxSolverBase<R>* solver() const 568 { 569 return theLP; 570 } 571 ///@} 572 573 //----------------------------------- 574 /**@name Linear Algebra */ 575 ///@{ 576 /// Basis-vector product. 577 /** Depending on the representation, for an SPxBasisBase B, 578 B.multBaseWith(x) computes 579 - \f$x \leftarrow Bx\f$ in the columnwise case, and 580 - \f$x \leftarrow x^TB\f$ in the rowwise case. 581 582 Both can be seen uniformly as multiplying the basis matrix \p B with 583 a vector \p x aligned the same way as the \em vectors of \p B. 584 */ 585 VectorBase<R>& multBaseWith(VectorBase<R>& x) const; 586 587 /// Basis-vector product 588 void multBaseWith(SSVectorBase<R>& x, SSVectorBase<R>& result) const; 589 590 /// Vector-basis product. 591 /** Depending on the representation, for a #SPxBasisBase B, 592 B.multWithBase(x) computes 593 - \f$x \leftarrow x^TB\f$ in the columnwise case and 594 - \f$x \leftarrow Bx\f$ in the rowwise case. 595 596 Both can be seen uniformly as multiplying the basis matrix \p B with 597 a vector \p x aligned the same way as the \em covectors of \p B. 598 */ 599 VectorBase<R>& multWithBase(VectorBase<R>& x) const; 600 601 /// VectorBase<R>-basis product 602 void multWithBase(SSVectorBase<R>& x, SSVectorBase<R>& result) const; 603 604 /* compute an estimated condition number for the current basis matrix 605 * by computing estimates of the norms of B and B^-1 using the power method. 606 * maxiters and tolerance control the accuracy of the estimate. 607 */ 608 R condition(int maxiters = 10, R tolerance = 1e-6); 609 610 /* wrapper to compute an estimate of the condition number of the current basis matrix */ 611 R getEstimatedCondition() 612 { 613 return condition(20, 1e-6); 614 } 615 616 /* wrapper to compute the exact condition number of the current basis matrix */ 617 R getExactCondition() 618 { 619 return condition(1000, 1e-9); 620 } 621 622 /** compute one of several matrix metrics based on the diagonal of the LU factorization 623 * type = 0: max/min ratio 624 * type = 1: trace of U (sum of diagonal elements) 625 * type = 2: determinant (product of diagonal elements) 626 */ 627 R getMatrixMetric(int type = 0); 628 629 /// returns the stability of the basis matrix. 630 R stability() const 631 { 632 return factor->stability(); 633 } 634 /// 635 void solve(VectorBase<R>& x, const VectorBase<R>& rhs) 636 { 637 if(rhs.dim() == 0) 638 { 639 x.clear(); 640 return; 641 } 642 643 if(!factorized) 644 SPxBasisBase<R>::factorize(); 645 646 factor->solveRight(x, rhs); 647 } 648 /// 649 void solve(SSVectorBase<R>& x, const SVectorBase<R>& rhs) 650 { 651 if(rhs.size() == 0) 652 { 653 x.clear(); 654 return; 655 } 656 657 if(!factorized) 658 SPxBasisBase<R>::factorize(); 659 660 factor->solveRight(x, rhs); 661 } 662 /// solves linear system with basis matrix. 663 /** Depending on the representation, for a SPxBasisBase B, 664 B.solve(x) computes 665 - \f$x \leftarrow B^{-1}rhs\f$ in the columnwise case and 666 - \f$x \leftarrow rhs^TB^{-1}\f$ in the rowwise case. 667 668 Both can be seen uniformly as solving a linear system with the basis 669 matrix \p B and a right handside vector \p x aligned the same way as 670 the \em vectors of \p B. 671 */ 672 void solve4update(SSVectorBase<R>& x, const SVectorBase<R>& rhs) 673 { 674 if(rhs.size() == 0) 675 { 676 x.clear(); 677 return; 678 } 679 680 if(!factorized) 681 SPxBasisBase<R>::factorize(); 682 683 factor->solveRight4update(x, rhs); 684 } 685 /// solves two systems in one call. 686 void solve4update(SSVectorBase<R>& x, VectorBase<R>& y, const SVectorBase<R>& rhsx, 687 SSVectorBase<R>& rhsy) 688 { 689 if(!factorized) 690 SPxBasisBase<R>::factorize(); 691 692 factor->solve2right4update(x, y, rhsx, rhsy); 693 } 694 /// solves two systems in one call using only sparse data structures 695 void solve4update(SSVectorBase<R>& x, SSVectorBase<R>& y, const SVectorBase<R>& rhsx, 696 SSVectorBase<R>& rhsy) 697 { 698 if(!factorized) 699 SPxBasisBase<R>::factorize(); 700 701 factor->solve2right4update(x, y, rhsx, rhsy); 702 } 703 /// solves three systems in one call. 704 void solve4update(SSVectorBase<R>& x, VectorBase<R>& y, VectorBase<R>& y2, 705 const SVectorBase<R>& rhsx, SSVectorBase<R>& rhsy, SSVectorBase<R>& rhsy2) 706 { 707 if(!factorized) 708 SPxBasisBase<R>::factorize(); 709 710 assert(rhsy.isSetup()); 711 assert(rhsy2.isSetup()); 712 factor->solve3right4update(x, y, y2, rhsx, rhsy, rhsy2); 713 } 714 /// solves three systems in one call using only sparse data structures 715 void solve4update(SSVectorBase<R>& x, SSVectorBase<R>& y, SSVectorBase<R>& y2, 716 const SVectorBase<R>& rhsx, SSVectorBase<R>& rhsy, SSVectorBase<R>& rhsy2) 717 { 718 if(!factorized) 719 SPxBasisBase<R>::factorize(); 720 721 assert(rhsy.isSetup()); 722 assert(rhsy2.isSetup()); 723 factor->solve3right4update(x, y, y2, rhsx, rhsy, rhsy2); 724 } 725 /// Cosolves linear system with basis matrix. 726 /** Depending on the representation, for a SPxBasisBase B, 727 B.coSolve(x) computes 728 - \f$x \leftarrow rhs^TB^{-1}\f$ in the columnwise case and 729 - \f$x \leftarrow B^{-1}rhs\f$ in the rowwise case. 730 731 Both can be seen uniformly as solving a linear system with the basis 732 matrix \p B and a right handside vector \p x aligned the same way as 733 the \em covectors of \p B. 734 */ 735 void coSolve(VectorBase<R>& x, const VectorBase<R>& rhs) 736 { 737 if(rhs.dim() == 0) 738 { 739 x.clear(); 740 return; 741 } 742 743 if(!factorized) 744 SPxBasisBase<R>::factorize(); 745 746 factor->solveLeft(x, rhs); 747 } 748 /// Sparse version of coSolve 749 void coSolve(SSVectorBase<R>& x, const SVectorBase<R>& rhs) 750 { 751 if(rhs.size() == 0) 752 { 753 x.clear(); 754 return; 755 } 756 757 if(!factorized) 758 SPxBasisBase<R>::factorize(); 759 760 factor->solveLeft(x, rhs); 761 } 762 /// solves two systems in one call. 763 void coSolve(SSVectorBase<R>& x, VectorBase<R>& y, const SVectorBase<R>& rhsx, 764 SSVectorBase<R>& rhsy) 765 { 766 if(!factorized) 767 SPxBasisBase<R>::factorize(); 768 769 factor->solveLeft(x, y, rhsx, rhsy); 770 } 771 /// Sparse version of solving two systems in one call. 772 void coSolve(SSVectorBase<R>& x, SSVectorBase<R>& y, const SVectorBase<R>& rhsx, 773 SSVectorBase<R>& rhsy) 774 { 775 if(!factorized) 776 SPxBasisBase<R>::factorize(); 777 778 factor->solveLeft(x, y, rhsx, rhsy); 779 } 780 /// solves three systems in one call. May be improved by using just one pass through the basis. 781 void coSolve(SSVectorBase<R>& x, VectorBase<R>& y, VectorBase<R>& z, const SVectorBase<R>& rhsx, 782 SSVectorBase<R>& rhsy, SSVectorBase<R>& rhsz) 783 { 784 if(!factorized) 785 SPxBasisBase<R>::factorize(); 786 787 factor->solveLeft(x, y, z, rhsx, rhsy, rhsz); 788 } 789 /// Sparse version of solving three systems in one call. 790 void coSolve(SSVectorBase<R>& x, SSVectorBase<R>& y, SSVectorBase<R>& z, const SVectorBase<R>& rhsx, 791 SSVectorBase<R>& rhsy, SSVectorBase<R>& rhsz) 792 { 793 if(!factorized) 794 SPxBasisBase<R>::factorize(); 795 796 factor->solveLeft(x, y, z, rhsx, rhsy, rhsz); 797 } 798 ///@} 799 800 801 //------------------------------------ 802 /**@name Modification notification. 803 These methods must be called after the loaded LP has been modified. 804 */ 805 ///@{ 806 /// inform SPxBasisBase, that \p n new rows had been added. 807 void addedRows(int n); 808 /// inform SPxBasisBase that row \p i had been removed. 809 void removedRow(int i); 810 /// inform SPxBasisBase that rows in \p perm with negative entry were removed. 811 void removedRows(const int perm[]); 812 /// inform SPxBasisBase that \p n new columns had been added. 813 void addedCols(int n); 814 /// inform SPxBasisBase that column \p i had been removed. 815 void removedCol(int i); 816 /// inform SPxBasisBase that columns in \p perm with negative entry were removed. 817 void removedCols(const int perm[]); 818 /// inform SPxBasisBase that a row had been changed. 819 void changedRow(int); 820 /// inform SPxBasisBase that a column had been changed. 821 void changedCol(int); 822 /// inform SPxBasisBase that a matrix entry had been changed. 823 void changedElement(int, int); 824 ///@} 825 826 827 //-------------------------------- 828 /**@name Miscellaneous */ 829 ///@{ 830 /// performs basis update. 831 /** Changes the \p i 'th vector of the basis with the vector associated to 832 \p id. This includes: 833 - updating the factorization, or recomputing it from scratch by 834 calling \ref soplex::SPxSolverBase<R>::factorize() "factorize()", 835 - resetting \ref soplex::SPxSolverBase<R>::lastEntered() "lastEntered()", 836 - resetting \ref soplex::SPxSolverBase<R>::lastIndex() "lastIndex()", 837 - resetting \ref soplex::SPxSolverBase<R>::lastLeft() "lastLeft()", 838 - resetting \ref soplex::SPxSolverBase<R>::lastUpdate() "lastUpdate()", 839 - resetting \ref soplex::SPxSolverBase<R>::iterations() "iterations()". 840 841 The basis descriptor is \em not \em modified, since #factor() 842 cannot know about how to set up the status of the involved variables 843 correctly. 844 845 A vector \p enterVec may be passed for a fast ETA update of the LU 846 factorization associated to the basis. It must be initialized with 847 the solution vector \f$x\f$ of the right linear system \f$Bx = b\f$ 848 with the entering vector as right-hand side vector \f$b\f$, where \f$B\f$ 849 denotes the basis matrix. This can be computed using method #solve(). 850 When using FAST updates, a vector \p eta may be passed for 851 improved performance. It must be initialized by a call to 852 factor->solveRightUpdate() as described in SLinSolver. The 853 implementation hidden behind FAST updates depends on the 854 SLinSolver implementation class. 855 */ 856 virtual void change(int i, SPxId& id, 857 const SVectorBase<R>* enterVec, const SSVectorBase<R>* eta = 0); 858 859 /** Load basis from \p in in MPS format. If \p rowNames and \p colNames 860 * are \c NULL, default names are used for the constraints and variables. 861 */ 862 virtual bool readBasis(std::istream& in, 863 const NameSet* rowNames, const NameSet* colNames); 864 865 /** Write basis to \p os in MPS format. If \p rowNames and \p colNames are 866 * \c NULL, default names are used for the constraints and variables. 867 */ 868 virtual void writeBasis(std::ostream& os, 869 const NameSet* rownames, const NameSet* colnames, const bool cpxFormat = false) const; 870 871 virtual void printMatrix() const; 872 873 /** Prints current basis matrix to a file using the MatrixMarket format: 874 * row col value 875 * The filename is basis/basis[number].mtx where number is a parameter. 876 */ 877 void printMatrixMTX(int number); 878 879 /// checks if a Descriptor is valid for the current LP w.r.t. its bounds 880 virtual bool isDescValid(const Desc& ds); 881 882 /// sets up basis. 883 /** Loads a Descriptor to the basis and sets up the basis matrix and 884 all vectors accordingly. The Descriptor must have the same number of 885 rows and columns as the currently loaded LP. 886 */ 887 virtual void loadDesc(const Desc&); 888 889 /// sets up linear solver to use. 890 /** If destroy is true, solver will be freed inside this object, e.g. in the destructor. 891 */ 892 virtual void loadBasisSolver(SLinSolver<R>* solver, const bool destroy = false); 893 894 /// loads the LP \p lp to the basis. 895 /** This involves resetting all counters to 0 and setting up a regular 896 default basis consisting of slacks, artificial variables or bounds. 897 */ 898 virtual void load(SPxSolverBase<R>* lp, bool initSlackBasis = true); 899 900 /// unloads the LP from the basis. 901 virtual void unLoad() 902 { 903 theLP = 0; 904 setStatus(NO_PROBLEM); 905 } 906 907 /// invalidates actual basis. 908 /** This method makes the basis matrix and vectors invalid. The basis will 909 be reinitialized if needed. 910 */ 911 void invalidate(); 912 913 /// Restores initial basis. 914 /** This method changes the basis to that present just after loading the LP 915 (see addedRows() and addedCols()). This may be necessary if a row or a 916 column is changed, since then the current basis may become singular. 917 */ 918 void restoreInitialBasis(); 919 920 /// output basis entries. 921 void dump(); 922 923 /// consistency check. 924 bool isConsistent() const; 925 926 /// time spent in updates 927 Real getTotalUpdateTime() const 928 { 929 return theTime->time(); 930 } 931 /// number of updates performed 932 int getTotalUpdateCount() const 933 { 934 return totalUpdateCount; 935 } 936 937 /// returns statistical information in form of a string. 938 std::string statistics() const 939 { 940 std::stringstream s; 941 s << factor->statistics() 942 #ifdef MEASUREUPDATETIME 943 << "Updates : " << std::setw(10) << getTotalUpdateCount() << std::endl 944 << " Time spent : " << std::setw(10) << getTotalUpdateTime() << std::endl 945 #endif 946 ; 947 948 return s.str(); 949 } 950 951 void setOutstream(SPxOut& newOutstream) 952 { 953 spxout = &newOutstream; 954 } 955 ///@} 956 957 //-------------------------------------- 958 /**@name Constructors / Destructors */ 959 ///@{ 960 /// default constructor. 961 SPxBasisBase<R>(Timer::TYPE ttype = Timer::USER_TIME); 962 /// copy constructor 963 SPxBasisBase<R>(const SPxBasisBase<R>& old); 964 /// assignment operator 965 SPxBasisBase<R>& operator=(const SPxBasisBase<R>& rhs); 966 /// destructor. 967 virtual ~SPxBasisBase<R>(); 968 ///@} 969 970 971 protected: 972 973 //-------------------------------------- 974 /**@name Protected helpers */ 975 ///@{ 976 /// loads \ref soplex::SPxBasisBase<R>::matrix "matrix" according to the SPxId%s stored in \ref soplex::SPxBasisBase<R>::theBaseId "theBaseId". 977 /** This method must be called whenever there is a chance, that the vector 978 pointers may have changed due to manipulations of the LP. 979 */ 980 void loadMatrixVecs(); 981 982 /// resizes internal arrays. 983 /** When a new LP is loaded, the basis matrix and vectors become invalid 984 and possibly also of the wrong dimension. Hence, after loading an 985 LP, #reDim() is called to reset all arrays etc. accoriding to the 986 dimensions of the loaded LP. 987 */ 988 void reDim(); 989 990 /// factorizes the basis matrix. 991 virtual void factorize(); 992 993 /// sets descriptor representation according to loaded LP. 994 void setRep(); 995 ///@} 996 997 }; 998 999 1000 // 1001 // Auxiliary functions. 1002 // 1003 1004 /// Pretty-printing of basis status. 1005 template <class R> 1006 std::ostream& operator<<(std::ostream& os, 1007 const typename SPxBasisBase<R>::SPxStatus& status); 1008 1009 1010 /* For backwards compatibility */ 1011 typedef SPxBasisBase<Real> SPxBasis; 1012 1013 } // namespace soplex 1014 1015 // General templated definitions 1016 #include "spxbasis.hpp" 1017 #include "spxdesc.hpp" 1018 1019 /* reset the SOPLEX_DEBUG flag to its original value */ 1020 #undef SOPLEX_DEBUG 1021 #ifdef SOPLEX_DEBUG_SPXBASIS 1022 #define SOPLEX_DEBUG 1023 #undef SOPLEX_DEBUG_SPXBASIS 1024 #endif 1025 1026 #endif // _SPXBASIS_H_ 1027