Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/bugfix-70'
Browse files Browse the repository at this point in the history
  • Loading branch information
svigerske committed Jun 18, 2024
2 parents c1e6764 + bfb7671 commit 2b00e24
Show file tree
Hide file tree
Showing 4 changed files with 60 additions and 42 deletions.
1 change: 1 addition & 0 deletions CHANGELOG
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ code quality:
fixed bugs:
- remove unused and incorrect SOPLEX_VERSION_API in cmake, SOPLEX_APIVERSION now always set in `spxdefines.h`
- disable objective limits once if exceeding unscaled and unsimplified solution is not dual feasible
- recompute solution from fresh factorization if objective limit is reached to avoid incorrect terminations

miscellaneous:
- remove `gzstream.h/hpp` (L-GPL) and replace it with `zstr` (MIT License) for `.gz` file handling
Expand Down
63 changes: 21 additions & 42 deletions src/soplex/spxsolve.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -445,23 +445,8 @@ typename SPxSolverBase<R>::Status SPxSolverBase<R>::solve(volatile bool* interru
{
R newpricertol = minpricertol;

// refactorize to eliminate accumulated errors from LU updates
if(this->lastUpdate() > 0)
factorize();

// recompute Fvec, Pvec and CoPvec to get a more precise solution and obj value
computeFrhs();
SPxBasisBase<R>::solve(*theFvec, *theFrhs);

computeEnterCoPrhs();
SPxBasisBase<R>::coSolve(*theCoPvec, *theCoPrhs);
computePvec();

forceRecompNonbasicValue();

SPX_MSG_INFO2((*this->spxout), (*this->spxout) << " --- checking feasibility and optimality\n")
computeCoTest();
computeTest();
// ensure that solution is accurate
factorizeAndRecompute();

// is the solution good enough ?
// max three times reduced
Expand Down Expand Up @@ -802,22 +787,8 @@ typename SPxSolverBase<R>::Status SPxSolverBase<R>::solve(volatile bool* interru
{
R newpricertol = minpricertol;

// refactorize to eliminate accumulated errors from LU updates
if(this->lastUpdate() > 0)
factorize();

// recompute Fvec, Pvec and CoPvec to get a more precise solution and obj value
computeFrhs();
SPxBasisBase<R>::solve(*theFvec, *theFrhs);

computeLeaveCoPrhs();
SPxBasisBase<R>::coSolve(*theCoPvec, *theCoPrhs);
computePvec();

forceRecompNonbasicValue();

SPX_MSG_INFO2((*this->spxout), (*this->spxout) << " --- checking feasibility and optimality\n")
computeFtest();
// ensure that solution is accurate
factorizeAndRecompute();

// is the solution good enough ?
// max three times reduced
Expand Down Expand Up @@ -1863,15 +1834,23 @@ bool SPxSolverBase<R>::terminate()
// SPxSense::MINIMIZE == -1, so we have sign = 1 on minimizing
if(int(this->spxSense()) * value() <= int(this->spxSense()) * objLimit)
{
SPX_MSG_INFO2((*this->spxout), (*this->spxout) << " --- objective value limit (" << objLimit
<< ") reached" << std::endl;)
SPxOut::debug(this, " --- objective value limit reached\n (value:{} limit:{})\n", value(),
objLimit);
SPxOut::debug(this, " (spxSense:{} rep:{} type:{})\n", int(this->spxSense()), int(rep()),
int(type()));

m_status = ABORT_VALUE;
return true;
// ensure that solution is accurate
factorizeAndRecompute();

// check no violations and objective limit again
if(shift() < epsilon() && noViols(tolerances()->floatingPointOpttol() - shift())
&& int(this->spxSense()) * value() <= int(this->spxSense()) * objLimit)
{
SPX_MSG_INFO2((*this->spxout), (*this->spxout) << " --- objective value limit (" << objLimit
<< ") reached" << std::endl;)
SPxOut::debug(this, " --- objective value limit reached\n (value:{} limit:{})\n", value(),
objLimit);
SPxOut::debug(this, " (spxSense:{} rep:{} type:{})\n", int(this->spxSense()), int(rep()),
int(type()));

m_status = ABORT_VALUE;
return true;
}
}
}
}
Expand Down
11 changes: 11 additions & 0 deletions src/soplex/spxsolver.h
Original file line number Diff line number Diff line change
Expand Up @@ -728,6 +728,17 @@ class SPxSolverBase : public SPxLPBase<R>, protected SPxBasisBase<R>
m_nonbasicValueUpToDate = false;
}

/** helper method that computes a fresh factorization of the basis matrix
* (if at least one update has been performed)
* and recomputes Frhs, Fvec, CoPrhs, Pvec, and the nonbasic values.
* In LEAVE the Ftest is recomputed, in ENTER the CoTest and Test are recomputed.
*
* This method is called to eliminate accumulated errors from LU updates
* especially required before checking if the solver can terminate
* (optimality or objective limit)
*/
virtual void factorizeAndRecompute();

/// get solution vector for primal variables.
/** This method returns the Status of the basis.
* If it is #REGULAR or better,
Expand Down
27 changes: 27 additions & 0 deletions src/soplex/spxsolver.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -1025,6 +1025,33 @@ void SPxSolverBase<R>::setType(Type tp)
return m_nonbasicValueUpToDate;
}

template <class R>
void SPxSolverBase<R>::factorizeAndRecompute()
{
// refactorize to eliminate accumulated errors from LU updates
if(this->lastUpdate() > 0)
factorize();

computeFrhs();
SPxBasisBase<R>::solve(*theFvec, *theFrhs);
type() == LEAVE ? computeLeaveCoPrhs() : computeEnterCoPrhs();

SPxBasisBase<R>::coSolve(*theCoPvec, *theCoPrhs);
computePvec();

forceRecompNonbasicValue();

SPX_MSG_INFO2((*this->spxout), (*this->spxout) << " --- checking feasibility and optimality\n")

if(type() == LEAVE)
computeFtest();
else
{
computeCoTest();
computeTest();
}
}

template <class R>
void SPxSolverBase<R>::hyperPricing(bool h)
{
Expand Down

0 comments on commit 2b00e24

Please sign in to comment.