#include <iostream>
#include <assert.h>
#include "soplex/spxdefines.h"
#include "soplex.h"
#include "soplex/statistics.h"
#include "soplex/sorter.h"
#define USE_FEASTOL
#define MAX_DEGENCHECK 20
#define DEGENCHECK_OFFSET 50
#define SLACKCOEFF 1.0
#define TIMELIMIT_FRAC 0.5
namespace soplex
{
template <class R>
void SoPlexBase<R>::_solveDecompositionDualSimplex()
{
assert(_solver.rep() == SPxSolverBase<R>::ROW);
assert(_solver.type() == SPxSolverBase<R>::LEAVE);
bool stop = false;
_statistics->redProbStatus = SPxSolverBase<R>::NO_PROBLEM;
_statistics->solvingTime->start();
_lastSolveMode = SOLVEMODE_REAL;
_currentProb = DECOMP_ORIG;
if(intParam(SoPlexBase<R>::OBJSENSE) == SoPlexBase<R>::OBJSENSE_MINIMIZE)
{
assert(_solver.spxSense() == SPxLPBase<R>::MINIMIZE);
_solver.changeObj(_solver.maxObj());
_solver.changeSense(SPxLPBase<R>::MAXIMIZE);
}
_solver.setDecompStatus(SPxSolverBase<R>::FINDSTARTBASIS);
_solver.setDecompIterationLimit(intParam(SoPlexBase<R>::DECOMP_ITERLIMIT));
int numDegenCheck = 0;
R degeneracyLevel = 0;
_decompFeasVector.reDim(_solver.nCols());
bool initSolveFromScratch = true;
DataArray< typename SPxSolverBase<R>::VarStatus > basisStatusRows;
DataArray< typename SPxSolverBase<R>::VarStatus > basisStatusCols;
do
{
_decompSimplifyAndSolve(_solver, _slufactor, initSolveFromScratch, initSolveFromScratch);
initSolveFromScratch = false;
if(_solver.type() == SPxSolverBase<R>::LEAVE || _solver.status() >= SPxSolverBase<R>::OPTIMAL
|| _solver.status() == SPxSolverBase<R>::ABORT_EXDECOMP || numDegenCheck > MAX_DEGENCHECK)
{
if(intParam(SoPlexBase<R>::OBJSENSE) == SoPlexBase<R>::OBJSENSE_MINIMIZE)
{
assert(_solver.spxSense() == SPxLPBase<R>::MAXIMIZE);
_solver.changeObj(-(_solver.maxObj()));
_solver.changeSense(SPxLPBase<R>::MINIMIZE);
}
_solver.setDecompStatus(SPxSolverBase<R>::DONTFINDSTARTBASIS);
if(_solver.status() == SPxSolverBase<R>::UNBOUNDED
|| _solver.status() == SPxSolverBase<R>::INFEASIBLE)
_hasBasis = false;
_decompSimplifyAndSolve(_solver, _slufactor, true, false);
getOriginalProblemStatistics();
_storeSolutionReal();
_statistics->solvingTime->stop();
return;
}
else if(_solver.status() == SPxSolverBase<R>::ABORT_TIME
|| _solver.status() == SPxSolverBase<R>::ABORT_ITER
|| _solver.status() == SPxSolverBase<R>::ABORT_VALUE)
{
if(!_isRealLPLoaded)
{
_solver.loadLP(*_decompLP);
spx_free(_decompLP);
_decompLP = &_solver;
_isRealLPLoaded = true;
}
if(intParam(SoPlexBase<R>::OBJSENSE) == SoPlexBase<R>::OBJSENSE_MINIMIZE)
{
assert(_solver.spxSense() == SPxLPBase<R>::MAXIMIZE);
_solver.changeObj(-(_solver.maxObj()));
_solver.changeSense(SPxLPBase<R>::MINIMIZE);
}
_preprocessAndSolveReal(false);
_storeSolutionReal();
_statistics->solvingTime->stop();
return;
}
_solver.basis().solve(_decompFeasVector, _solver.maxObj());
degeneracyLevel = _solver.getDegeneracyLevel(_decompFeasVector);
_solver.setDegenCompOffset(DEGENCHECK_OFFSET);
numDegenCheck++;
}
while((degeneracyLevel > 0.9 || degeneracyLevel < 0.1)
|| !checkBasisDualFeasibility(_decompFeasVector));
_solver.setDecompStatus(SPxSolverBase<R>::DONTFINDSTARTBASIS);
if(_hasBasis)
{
basisStatusRows.reSize(numRows());
basisStatusCols.reSize(numCols());
_solver.getBasis(basisStatusRows.get_ptr(), basisStatusCols.get_ptr(), basisStatusRows.size(),
basisStatusCols.size());
}
_statistics->callsReducedProb++;
numDecompIter = 0;
numRedProbIter = _solver.iterations();
numCompProbIter = 0;
_decompDisplayLine = 0;
MSG_INFO1(spxout,
spxout << "======== Degeneracy Detected ========" << std::endl
<< std::endl
<< "======== Commencing decomposition solve ========" << std::endl
);
MSG_INFO2(spxout, spxout << "Creating the Reduced and Complementary problems." << std::endl);
const SPxOut::Verbosity orig_verbosity = spxout.getVerbosity();
const SPxOut::Verbosity decomp_verbosity = (SPxOut::Verbosity)intParam(
SoPlexBase<R>::DECOMP_VERBOSITY);
if(decomp_verbosity < orig_verbosity)
spxout.setVerbosity(decomp_verbosity);
_createDecompReducedAndComplementaryProblems();
_formDecompReducedProblem(stop);
_hasBasis = false;
bool hasRedBasis = false;
bool redProbError = false;
bool noRedprobIter = false;
bool explicitviol = boolParam(SoPlexBase<R>::EXPLICITVIOL);
int algIterCount = 0;
if(stop)
{
MSG_INFO1(spxout, spxout << "==== Error constructing the reduced problem ====" << std::endl);
redProbError = true;
_statistics->redProbStatus = SPxSolverBase<R>::NOT_INIT;
}
while(!stop)
{
int previter = _statistics->iterations;
_currentProb = DECOMP_RED;
MSG_INFO2(spxout,
spxout << std::endl
<< "=========================" << std::endl
<< "Solving: Reduced Problem." << std::endl
<< "=========================" << std::endl
<< std::endl);
_hasBasis = hasRedBasis;
_decompSimplifyAndSolve(_solver, _slufactor, !algIterCount, !algIterCount);
stop = decompTerminate(realParam(
SoPlexBase<R>::TIMELIMIT));
_statistics->callsReducedProb++;
_statistics->redProbStatus = _solver.status();
assert(_isRealLPLoaded);
hasRedBasis = _hasBasis;
_hasBasis = false;
if(_solver.status() != SPxSolverBase<R>::OPTIMAL)
{
if(_solver.status() == SPxSolverBase<R>::UNBOUNDED)
MSG_INFO2(spxout, spxout << "Unbounded reduced problem." << std::endl);
if(_solver.status() == SPxSolverBase<R>::INFEASIBLE)
MSG_INFO2(spxout, spxout << "Infeasible reduced problem." << std::endl);
MSG_INFO2(spxout, spxout << "Reduced problem status: " << static_cast<int>
(_solver.status()) << std::endl);
redProbError = true;
break;
}
if(_statistics->iterations == previter)
{
MSG_WARNING(spxout,
spxout << "WIMDSM02: reduced problem performed zero iterations. Terminating." << std::endl;);
noRedprobIter = true;
stop = true;
break;
}
printDecompDisplayLine(_solver, orig_verbosity, !algIterCount, !algIterCount);
VectorBase<R> reducedLPDualVector(_solver.nRows());
VectorBase<R> reducedLPRedcostVector(_solver.nCols());
_solver.getDualSol(reducedLPDualVector);
_solver.getRedCostSol(reducedLPRedcostVector);
if(algIterCount == 0)
_formDecompComplementaryProblem();
else
{
if(boolParam(SoPlexBase<R>::USECOMPDUAL))
_updateDecompComplementaryDualProblem(false);
else
_updateDecompComplementaryPrimalProblem(false);
}
_currentProb = DECOMP_COMP;
MSG_INFO2(spxout,
spxout << std::endl
<< "=========================" << std::endl
<< "Solving: Complementary Problem." << std::endl
<< "=========================" << std::endl
<< std::endl);
if(!explicitviol)
{
_decompSimplifyAndSolve(_compSolver, _compSlufactor, true, true);
MSG_INFO2(spxout, spxout << "Iteration " << algIterCount
<< "Objective Value: " << std::setprecision(10) << _compSolver.objValue()
<< std::endl);
}
assert(_isRealLPLoaded);
if(!explicitviol && (GE(_compSolver.objValue(), R(0.0), R(1e-20))
|| _compSolver.status() == SPxSolverBase<R>::INFEASIBLE
|| _compSolver.status() == SPxSolverBase<R>::UNBOUNDED))
{
_statistics->compProbStatus = _compSolver.status();
_statistics->finalCompObj = _compSolver.objValue();
if(_compSolver.status() == SPxSolverBase<R>::UNBOUNDED)
MSG_INFO2(spxout, spxout << "Unbounded complementary problem." << std::endl);
if(_compSolver.status() == SPxSolverBase<R>::INFEASIBLE)
MSG_INFO2(spxout, spxout << "Infeasible complementary problem." << std::endl);
if(_compSolver.status() == SPxSolverBase<R>::INFEASIBLE
|| _compSolver.status() == SPxSolverBase<R>::UNBOUNDED)
explicitviol = true;
stop = true;
}
if(!stop && !explicitviol)
{
VectorBase<R> compLPPrimalVector(_compSolver.nCols());
_compSolver.getPrimalSol(compLPPrimalVector);
VectorBase<R> compLPDualVector(_compSolver.nRows());
_compSolver.getDualSol(compLPDualVector);
_updateDecompReducedProblem(_compSolver.objValue(), reducedLPDualVector, reducedLPRedcostVector,
compLPPrimalVector, compLPDualVector);
}
else if(_compSolver.status() == SPxSolverBase<R>::INFEASIBLE
|| _compSolver.status() == SPxSolverBase<R>::UNBOUNDED
|| explicitviol)
{
VectorBase<R> reducedLPPrimalVector(_solver.nCols());
_solver.getPrimalSol(reducedLPPrimalVector);
_checkOriginalProblemOptimality(reducedLPPrimalVector, true);
if(_nDecompViolBounds > 0 || _nDecompViolRows > 0)
stop = false;
if(_nDecompViolBounds == 0 && _nDecompViolRows == 0)
stop = true;
if(!stop)
_updateDecompReducedProblemViol(false);
}
numDecompIter++;
algIterCount++;
}
if(!redProbError)
{
#ifndef NDEBUG
VectorBase<R> reducedLPPrimalVector(_solver.nCols());
_solver.getPrimalSol(reducedLPPrimalVector);
_checkOriginalProblemOptimality(reducedLPPrimalVector, true);
spxout.setVerbosity(orig_verbosity);
#endif
#ifdef PERFORM_COMPPROB_CHECK
if(boolParam(SoPlexBase<R>::USECOMPDUAL))
_setComplementaryDualOriginalObjective();
else
_setComplementaryPrimalOriginalObjective();
_hasBasis = false;
if(boolParam(SoPlexBase<R>::USECOMPDUAL))
{
SPxLPBase<R> compDualLP;
_compSolver.buildDualProblem(compDualLP, _decompPrimalRowIDs.get_ptr(),
_decompPrimalColIDs.get_ptr(),
_decompDualRowIDs.get_ptr(), _decompDualColIDs.get_ptr(), &_nPrimalRows, &_nPrimalCols, &_nDualRows,
&_nDualCols);
_compSolver.loadLP(compDualLP);
}
_decompSimplifyAndSolve(_compSolver, _compSlufactor, true, true);
_solReal._hasPrimal = true;
_hasSolReal = true;
VectorBase<R> testPrimalVector(_compSolver.nCols());
_compSolver.getPrimalSol(testPrimalVector);
_solReal._primal.reDim(_compSolver.nCols());
_solReal._primal = testPrimalVector;
R maxviol = 0;
R sumviol = 0;
if(getDecompBoundViolation(maxviol, sumviol))
MSG_INFO1(spxout, spxout << "Bound violation - "
<< "Max: " << std::setprecision(20) << maxviol << " "
<< "Sum: " << sumviol << std::endl);
if(getDecompRowViolation(maxviol, sumviol))
MSG_INFO1(spxout, spxout << "Row violation - "
<< "Max: " << std::setprecision(21) << maxviol << " "
<< "Sum: " << sumviol << std::endl);
MSG_INFO1(spxout, spxout << "Objective Value: " << _compSolver.objValue() << std::endl);
#endif
}
spxout.setVerbosity(orig_verbosity);
MSG_INFO1(spxout,
spxout << "======== Decomposition solve completed ========" << std::endl
<< std::endl
<< "======== Resolving original problem ========" << std::endl
);
if((!redProbError && !noRedprobIter) || algIterCount > 0)
{
spx_free(_decompCompProbColIDsIdx);
spx_free(_fixedOrigVars);
}
spx_free(_decompViolatedRows);
spx_free(_decompViolatedBounds);
spx_free(_decompReducedProbCols);
spx_free(_decompReducedProbRows);
getOriginalProblemStatistics();
_statistics->numRedProbRows = numIncludedRows;
_statistics->numRedProbCols = _solver.nCols();
_solver.printDisplayLine(false, true);
if(redProbError)
{
MSG_INFO1(spxout, spxout << "=== Reduced problem error - Solving original ===" << std::endl);
_solver.loadLP(*_realLP);
spx_free(_realLP);
_realLP = &_solver;
_isRealLPLoaded = true;
if(intParam(SoPlexBase<R>::OBJSENSE) == SoPlexBase<R>::OBJSENSE_MINIMIZE)
{
assert(_solver.spxSense() == SPxLPBase<R>::MAXIMIZE);
_solver.changeObj(-(_solver.maxObj()));
_solver.changeSense(SPxLPBase<R>::MINIMIZE);
}
_preprocessAndSolveReal(true);
}
else
{
_realLP->~SPxLPBase<R>();
spx_free(_realLP);
_realLP = &_solver;
_isRealLPLoaded = true;
if(intParam(SoPlexBase<R>::OBJSENSE) == SoPlexBase<R>::OBJSENSE_MINIMIZE)
{
assert(_solver.spxSense() == SPxLPBase<R>::MAXIMIZE);
_solver.changeObj(-(_solver.maxObj()));
_solver.changeSense(SPxLPBase<R>::MINIMIZE);
}
_preprocessAndSolveReal(false);
}
_statistics->solvingTime->stop();
}
template <class R>
void SoPlexBase<R>::_createDecompReducedAndComplementaryProblems()
{
_realLP = nullptr;
spx_alloc(_realLP);
_realLP = new(_realLP) SPxLPBase<R>(_solver);
_decompReducedProbRows = nullptr;
spx_alloc(_decompReducedProbRows, numRows());
_decompReducedProbCols = nullptr;
spx_alloc(_decompReducedProbCols, numCols());
_compSolver = _solver;
_compSolver.setOutstream(spxout);
_compSolver.setBasisSolver(&_compSlufactor);
_decompViolatedBounds = nullptr;
_decompViolatedRows = nullptr;
spx_alloc(_decompViolatedBounds, numCols());
spx_alloc(_decompViolatedRows, numRows());
_nDecompViolBounds = 0;
_nDecompViolRows = 0;
}
template <class R>
void SoPlexBase<R>::_formDecompReducedProblem(bool& stop)
{
MSG_INFO2(spxout, spxout << "Forming the Reduced problem" << std::endl);
int* nonposind = 0;
int* compatind = 0;
int* rowsforremoval = 0;
int* colsforremoval = 0;
int nnonposind = 0;
int ncompatind = 0;
assert(_solver.nCols() == numCols());
assert(_solver.nRows() == numRows());
_decompTransBasis = _solver.basis();
numIncludedRows = 0;
_decompLP = 0;
spx_alloc(_decompLP);
_decompLP = new(_decompLP) SPxLPBase<R>(_solver);
_basisStatusRows.reSize(numRows());
_basisStatusCols.reSize(numCols());
_solver.getBasis(_basisStatusRows.get_ptr(), _basisStatusCols.get_ptr());
spx_alloc(nonposind, numCols());
spx_alloc(colsforremoval, numCols());
if(!stop)
_getZeroDualMultiplierIndices(_decompFeasVector, nonposind, colsforremoval, &nnonposind, stop);
MSG_INFO2(spxout, spxout << "Computing the compatible columns" << std::endl
<< "Solving time: " << solveTime() << std::endl);
spx_alloc(compatind, _solver.nRows());
spx_alloc(rowsforremoval, _solver.nRows());
if(!stop)
_getCompatibleColumns(_decompFeasVector, nonposind, compatind, rowsforremoval, colsforremoval,
nnonposind,
&ncompatind, true, stop);
int* compatboundcons = 0;
int ncompatboundcons = 0;
spx_alloc(compatboundcons, numCols());
LPRowSetBase<R> boundcons;
if(!stop)
_getCompatibleBoundCons(boundcons, compatboundcons, nonposind, &ncompatboundcons, nnonposind, stop);
MSG_INFO2(spxout, spxout << "Deleting rows and columns to form the reduced problem" << std::endl
<< "Solving time: " << solveTime() << std::endl);
SPxRowId* addedrowids = 0;
spx_alloc(addedrowids, ncompatboundcons);
if(!stop)
{
_computeReducedProbObjCoeff(stop);
_solver.loadLP(*_decompLP);
_solver.removeRows(rowsforremoval);
_solver.addRows(addedrowids, boundcons);
for(int i = 0; i < ncompatboundcons; i++)
_decompReducedProbColRowIDs[compatboundcons[i]] = addedrowids[i];
}
spx_free(addedrowids);
spx_free(compatboundcons);
spx_free(rowsforremoval);
spx_free(compatind);
spx_free(colsforremoval);
spx_free(nonposind);
_decompLP->~SPxLPBase<R>();
spx_free(_decompLP);
}
template <class R>
void SoPlexBase<R>::_formDecompComplementaryProblem()
{
_nElimPrimalRows = 0;
_decompElimPrimalRowIDs.reSize(
_realLP->nRows()); _decompCompProbColIDsIdx = 0;
spx_alloc(_decompCompProbColIDsIdx, _realLP->nCols());
_fixedOrigVars = 0;
spx_alloc(_fixedOrigVars, _realLP->nCols());
for(int i = 0; i < _realLP->nCols(); i++)
{
_decompCompProbColIDsIdx[i] = -1;
_fixedOrigVars[i] = -2; }
int naddedrows = 0;
DataArray < SPxRowId > rangedRowIds(numRows());
_deleteAndUpdateRowsComplementaryProblem(rangedRowIds.get_ptr(), naddedrows);
if(boolParam(
SoPlexBase<R>::USECOMPDUAL)) {
_decompPrimalRowIDs.reSize(3 * _compSolver.nRows());
_decompPrimalColIDs.reSize(3 * _compSolver.nCols());
_decompDualRowIDs.reSize(3 * _compSolver.nCols());
_decompDualColIDs.reSize(3 * _compSolver.nRows());
_nPrimalRows = 0;
_nPrimalCols = 0;
_nDualRows = 0;
_nDualCols = 0;
SPxLPBase<R> compDualLP;
_compSolver.buildDualProblem(compDualLP, _decompPrimalRowIDs.get_ptr(),
_decompPrimalColIDs.get_ptr(),
_decompDualRowIDs.get_ptr(), _decompDualColIDs.get_ptr(), &_nPrimalRows, &_nPrimalCols, &_nDualRows,
&_nDualCols);
compDualLP.setOutstream(spxout);
for(int i = 0; i < _nPrimalRows; i++)
{
if(i + 1 < _nPrimalRows &&
_realLP->number(SPxRowId(_decompPrimalRowIDs[i])) == _realLP->number(SPxRowId(
_decompPrimalRowIDs[i + 1])))
i++;
}
for(int i = 0; i < _nPrimalCols; i++)
{
if(_decompPrimalColIDs[i].getIdx() != _compSlackColId.getIdx())
_decompCompProbColIDsIdx[_realLP->number(_decompPrimalColIDs[i])] = i;
}
assert(_nPrimalCols == _nDualRows);
assert(_compSolver.nCols() == compDualLP.nRows());
_compSlackDualRowId = compDualLP.rId(_compSolver.number(_compSlackColId));
_compSolver.loadLP(compDualLP);
_compSolver.init();
_updateComplementaryDualSlackColCoeff();
_decompFixedVarDualIDs.reSize(_realLP->nCols());
_decompVarBoundDualIDs.reSize(2 * _realLP->nCols());
_updateDecompComplementaryDualProblem(false);
}
else {
_decompPrimalRowIDs.reSize(_compSolver.nRows() * 2);
_decompPrimalColIDs.reSize(_compSolver.nCols());
_decompCompPrimalRowIDs.reSize(_compSolver.nRows() * 2);
_decompCompPrimalColIDs.reSize(_compSolver.nCols());
_nPrimalRows = 0;
_nPrimalCols = 0;
int addedrangedrows = 0;
_nCompPrimalRows = 0;
_nCompPrimalCols = 0;
for(int i = 0; i < _realLP->nRows(); i++)
{
assert(_nCompPrimalRows < _compSolver.nRows());
_decompPrimalRowIDs[_nPrimalRows] = _realLP->rId(i);
_decompCompPrimalRowIDs[_nCompPrimalRows] = _compSolver.rId(i);
_nPrimalRows++;
_nCompPrimalRows++;
if(_realLP->rowType(i) == LPRowBase<R>::RANGE || _realLP->rowType(i) == LPRowBase<R>::EQUAL)
{
assert(EQ(_compSolver.lhs(rangedRowIds[addedrangedrows]), _realLP->lhs(i)));
assert(LE(_compSolver.rhs(rangedRowIds[addedrangedrows]), R(infinity)));
assert(LE(_compSolver.lhs(i), R(-infinity)));
assert(LT(_compSolver.rhs(i), R(infinity)));
_decompPrimalRowIDs[_nPrimalRows] = _realLP->rId(i);
_decompCompPrimalRowIDs[_nCompPrimalRows] = rangedRowIds[addedrangedrows];
_nPrimalRows++;
_nCompPrimalRows++;
addedrangedrows++;
}
}
for(int i = 0; i < _compSolver.nCols(); i++)
{
if(_compSolver.cId(i).getIdx() != _compSlackColId.getIdx())
{
_decompPrimalColIDs[i] = _realLP->cId(i);
_decompCompPrimalColIDs[i] = _compSolver.cId(i);
_nPrimalCols++;
_nCompPrimalCols++;
_decompCompProbColIDsIdx[_realLP->number(_decompPrimalColIDs[i])] = i;
}
}
_updateDecompComplementaryPrimalProblem(false);
}
}
template <class R>
void SoPlexBase<R>::_decompSimplifyAndSolve(SPxSolverBase<R>& solver, SLUFactor<R>& sluFactor,
bool fromScratch, bool applyPreprocessing)
{
if(realParam(SoPlexBase<R>::TIMELIMIT) < realParam(SoPlexBase<R>::INFTY))
solver.setTerminationTime(Real(realParam(SoPlexBase<R>::TIMELIMIT)) -
_statistics->solvingTime->time());
solver.changeObjOffset(realParam(SoPlexBase<R>::OBJ_OFFSET));
_statistics->preprocessingTime->start();
typename SPxSimplifier<R>::Result result = SPxSimplifier<R>::OKAY;
if(fromScratch)
{
try
{
solver.reLoad();
}
catch(const SPxException& E)
{
MSG_ERROR(spxout << "Caught exception <" << E.what() << "> during simplify and solve.\n");
}
}
if(applyPreprocessing)
{
_enableSimplifierAndScaler();
solver.setTerminationValue(realParam(SoPlexBase<R>::INFTY));
}
else
{
_disableSimplifierAndScaler();
solver.setTerminationValue(solver.spxSense() == SPxLPBase<R>::MINIMIZE
? realParam(SoPlexBase<R>::OBJLIMIT_UPPER) : realParam(SoPlexBase<R>::INFTY));
}
applyPreprocessing = (_scaler != nullptr || _simplifier != NULL);
if(_isRealLPLoaded)
{
if(applyPreprocessing)
{
_decompLP = 0;
spx_alloc(_decompLP);
_decompLP = new(_decompLP) SPxLPBase<R>(solver);
_isRealLPLoaded = false;
}
else
_decompLP = &solver;
}
else
{
assert(_decompLP != &solver);
solver.loadLP(*_decompLP);
if(_hasBasis)
{
assert(_basisStatusRows.size() == solver.nRows());
assert(_basisStatusCols.size() == solver.nCols());
solver.setBasis(_basisStatusRows.get_const_ptr(), _basisStatusCols.get_const_ptr());
}
if(!applyPreprocessing)
{
_decompLP->~SPxLPBase<R>();
spx_free(_decompLP);
_decompLP = &solver;
_isRealLPLoaded = true;
}
else
{
_decompLP = 0;
spx_alloc(_decompLP);
_decompLP = new(_decompLP) SPxLPBase<R>(solver);
}
}
assert(_decompLP == &solver || applyPreprocessing);
assert(_decompLP != &solver || !applyPreprocessing);
if(_simplifier != 0)
{
Real remainingTime = _solver.getMaxTime() - _solver.time();
result = _simplifier->simplify(solver, realParam(SoPlexBase<R>::EPSILON_ZERO),
realParam(SoPlexBase<R>::FEASTOL),
realParam(SoPlexBase<R>::OPTTOL),
remainingTime);
solver.changeObjOffset(_simplifier->getObjoffset() + realParam(SoPlexBase<R>::OBJ_OFFSET));
}
_statistics->preprocessingTime->stop();
if(result == SPxSimplifier<R>::OKAY)
{
if(_scaler != nullptr)
_scaler->scale(solver);
bool _hadBasis = _hasBasis;
_statistics->simplexTime->start();
try
{
solver.solve();
}
catch(const SPxException& E)
{
MSG_ERROR(std::cerr << "Caught exception <" << E.what() << "> while solving real LP.\n");
_status = SPxSolverBase<R>::ERROR;
}
catch(...)
{
MSG_ERROR(std::cerr << "Caught unknown exception while solving real LP.\n");
_status = SPxSolverBase<R>::ERROR;
}
_statistics->simplexTime->stop();
if(_currentProb == DECOMP_ORIG || _currentProb == DECOMP_RED)
{
_statistics->iterations += solver.iterations();
_statistics->iterationsPrimal += solver.primalIterations();
_statistics->iterationsFromBasis += _hadBasis ? solver.iterations() : 0;
_statistics->boundflips += solver.boundFlips();
_statistics->luFactorizationTimeReal += sluFactor.getFactorTime();
_statistics->luSolveTimeReal += sluFactor.getSolveTime();
_statistics->luFactorizationsReal += sluFactor.getFactorCount();
_statistics->luSolvesReal += sluFactor.getSolveCount();
sluFactor.resetCounters();
_statistics->degenPivotsPrimal += solver.primalDegeneratePivots();
_statistics->degenPivotsDual += solver.dualDegeneratePivots();
_statistics->sumDualDegen += _solver.sumDualDegeneracy();
_statistics->sumPrimalDegen += _solver.sumPrimalDegeneracy();
if(_currentProb == DECOMP_ORIG)
_statistics->iterationsInit += solver.iterations();
else
_statistics->iterationsRedProb += solver.iterations();
}
if(_currentProb == DECOMP_COMP)
_statistics->iterationsCompProb += solver.iterations();
}
_evaluateSolutionDecomp(solver, sluFactor, result);
}
template <class R>
void SoPlexBase<R>::_decompResolveWithoutPreprocessing(SPxSolverBase<R>& solver,
SLUFactor<R>& sluFactor, typename SPxSimplifier<R>::Result result)
{
assert(_simplifier != 0 || _scaler != nullptr);
assert(result == SPxSimplifier<R>::VANISHED
|| (result == SPxSimplifier<R>::OKAY
&& (solver.status() == SPxSolverBase<R>::OPTIMAL
|| solver.status() == SPxSolverBase<R>::ABORT_DECOMP
|| solver.status() == SPxSolverBase<R>::ABORT_EXDECOMP)));
if(_simplifier != 0)
{
assert(!_simplifier->isUnsimplified());
bool vanished = result == SPxSimplifier<R>::VANISHED;
VectorBase<R> primal(vanished ? 0 : solver.nCols());
VectorBase<R> slacks(vanished ? 0 : solver.nRows());
VectorBase<R> dual(vanished ? 0 : solver.nRows());
VectorBase<R> redCost(vanished ? 0 : solver.nCols());
assert(!_isRealLPLoaded);
_basisStatusRows.reSize(_decompLP->nRows());
_basisStatusCols.reSize(_decompLP->nCols());
assert(vanished || _basisStatusRows.size() >= solver.nRows());
assert(vanished || _basisStatusCols.size() >= solver.nCols());
if(!vanished)
{
assert(solver.status() == SPxSolverBase<R>::OPTIMAL
|| solver.status() == SPxSolverBase<R>::ABORT_DECOMP
|| solver.status() == SPxSolverBase<R>::ABORT_EXDECOMP);
solver.getPrimalSol(primal);
solver.getSlacks(slacks);
solver.getDualSol(dual);
solver.getRedCostSol(redCost);
if(_scaler && solver.isScaled())
{
_scaler->unscalePrimal(solver, primal);
_scaler->unscaleSlacks(solver, slacks);
_scaler->unscaleDual(solver, dual);
_scaler->unscaleRedCost(solver, redCost);
}
solver.getBasis(_basisStatusRows.get_ptr(), _basisStatusCols.get_ptr());
}
try
{
_simplifier->unsimplify(primal, dual, slacks, redCost, _basisStatusRows.get_ptr(),
_basisStatusCols.get_ptr(), solver.status() == SPxSolverBase<R>::OPTIMAL);
_simplifier->getBasis(_basisStatusRows.get_ptr(), _basisStatusCols.get_ptr());
_hasBasis = true;
}
catch(const SPxException& E)
{
MSG_ERROR(spxout << "Caught exception <" << E.what() <<
"> during unsimplification. Resolving without simplifier and scaler.\n");
}
catch(...)
{
MSG_ERROR(spxout <<
"Caught unknown exception during unsimplification. Resolving without simplifier and scaler.\n");
_status = SPxSolverBase<R>::ERROR;
}
}
else if(_scaler != nullptr)
{
_basisStatusRows.reSize(numRows());
_basisStatusCols.reSize(numCols());
assert(_basisStatusRows.size() == solver.nRows());
assert(_basisStatusCols.size() == solver.nCols());
solver.getBasis(_basisStatusRows.get_ptr(), _basisStatusCols.get_ptr());
_hasBasis = true;
}
_decompSimplifyAndSolve(solver, sluFactor, false, false);
return;
}
template <class R>
void SoPlexBase<R>::_updateDecompReducedProblem(R objValue, VectorBase<R> dualVector,
VectorBase<R> redcostVector,
VectorBase<R> compPrimalVector, VectorBase<R> compDualVector)
{
R feastol = realParam(SoPlexBase<R>::FEASTOL);
R maxDualRatio = R(infinity);
bool usecompdual = boolParam(SoPlexBase<R>::USECOMPDUAL);
for(int i = 0; i < _nPrimalRows; i++)
{
R reducedProbDual = 0;
R compProbPrimal = 0;
R dualRatio = 0;
int rownumber = _realLP->number(SPxRowId(_decompPrimalRowIDs[i]));
if(_decompReducedProbRows[rownumber] && _solver.isBasic(_decompReducedProbRowIDs[rownumber]))
{
int solverRowNum = _solver.number(_decompReducedProbRowIDs[rownumber]);
reducedProbDual = dualVector[solverRowNum];
if(usecompdual)
compProbPrimal = compPrimalVector[_compSolver.number(SPxColId(_decompDualColIDs[i]))]; else
compProbPrimal = compDualVector[_compSolver.number(SPxRowId(_decompCompPrimalRowIDs[i]))];
if(EQ(reducedProbDual, R(0.0), feastol))
{
MSG_WARNING(spxout,
spxout << "WIMDSM01: reduced problem dual value is very close to zero." << std::endl;);
continue;
}
if(usecompdual && i < _nPrimalRows - 1 &&
_realLP->number(SPxRowId(_decompPrimalRowIDs[i])) == _realLP->number(SPxRowId(
_decompPrimalRowIDs[i + 1])))
{
i++;
compProbPrimal += compPrimalVector[_compSolver.number(SPxColId(_decompDualColIDs[i]))]; }
SoPlexBase<R>::DualSign varSign = getExpectedDualVariableSign(solverRowNum);
if(varSign == SoPlexBase<R>::IS_FREE || (varSign == SoPlexBase<R>::IS_POS
&& LE(compProbPrimal, (R)0, feastol)) ||
(varSign == SoPlexBase<R>::IS_NEG && GE(compProbPrimal, (R)0, feastol)))
{
dualRatio = R(infinity);
}
else
{
dualRatio = reducedProbDual / compProbPrimal;
}
if(LT(dualRatio, maxDualRatio, feastol))
maxDualRatio = dualRatio;
}
else
{
if(usecompdual)
compProbPrimal = compPrimalVector[_compSolver.number(SPxColId(_decompDualColIDs[i]))]; else
compProbPrimal = compDualVector[_compSolver.number(SPxRowId(_decompCompPrimalRowIDs[i]))];
}
}
if(maxDualRatio > 1.0)
maxDualRatio = 1.0;
VectorBase<R> compProbRedcost(
_compSolver.nCols());
_compSolver.getRedCostSol(compProbRedcost);
LPRowSetBase<R> updaterows;
Array<RowViolation> violatedrows;
int nviolatedrows = 0;
int* newrowidx = 0;
int nnewrowidx = 0;
spx_alloc(newrowidx, _nPrimalRows);
violatedrows.reSize(_nPrimalRows);
bool ratioTest = true;
for(int i = 0; i < _nPrimalRows; i++)
{
LPRowBase<R> origlprow;
DSVectorBase<R> rowtoaddVec(_realLP->nCols());
R compProbPrimal = 0;
R compRowRedcost = 0;
int rownumber = _realLP->number(SPxRowId(_decompPrimalRowIDs[i]));
if(!_decompReducedProbRows[_realLP->number(SPxRowId(_decompPrimalRowIDs[i]))])
{
int compRowNumber;
if(usecompdual)
{
compRowNumber = _compSolver.number(_decompDualColIDs[i]);
compProbPrimal = compPrimalVector[compRowNumber]; compRowRedcost = compProbRedcost[compRowNumber];
}
else
{
compRowNumber = _compSolver.number(_decompCompPrimalRowIDs[i]);
compProbPrimal = compDualVector[compRowNumber]; }
if(usecompdual && i < _nPrimalRows - 1 &&
_realLP->number(SPxRowId(_decompPrimalRowIDs[i])) == _realLP->number(SPxRowId(
_decompPrimalRowIDs[i + 1])))
{
i++;
compRowNumber = _compSolver.number(SPxColId(_decompDualColIDs[i]));
compProbPrimal += compPrimalVector[compRowNumber]; compRowRedcost += compProbRedcost[compRowNumber];
}
SoPlexBase<R>::DualSign varSign = getOrigProbDualVariableSign(rownumber);
if(ratioTest && ((varSign == SoPlexBase<R>::IS_FREE && !isZero(compProbPrimal, feastol)) ||
(varSign == SoPlexBase<R>::IS_POS && GT(compProbPrimal * maxDualRatio, (R) 0, feastol)) ||
(varSign == SoPlexBase<R>::IS_NEG && LT(compProbPrimal * maxDualRatio, (R) 0, feastol))))
{
if(!_decompReducedProbRows[rownumber])
{
numIncludedRows++;
assert(numIncludedRows <= _realLP->nRows());
}
violatedrows[nviolatedrows].idx = rownumber;
violatedrows[nviolatedrows].violation = spxAbs(compProbPrimal * maxDualRatio);
nviolatedrows++;
}
}
}
RowViolationCompare compare;
compare.entry = violatedrows.get_const_ptr();
if(!ratioTest || nviolatedrows == 0)
{
_findViolatedRows(objValue, violatedrows, nviolatedrows);
}
int sorted = 0;
int sortsize = MINIMUM(intParam(SoPlexBase<R>::DECOMP_MAXADDEDROWS), nviolatedrows);
if(sortsize > 0 && sortsize < nviolatedrows)
sorted = SPxQuicksortPart(violatedrows.get_ptr(), compare, sorted + 1, nviolatedrows, sortsize);
for(int i = 0; i < sortsize; i++)
{
updaterows.add(_transformedRows.lhs(violatedrows[i].idx),
_transformedRows.rowVector(violatedrows[i].idx),
_transformedRows.rhs(violatedrows[i].idx));
_decompReducedProbRows[violatedrows[i].idx] = true;
newrowidx[nnewrowidx] = violatedrows[i].idx;
nnewrowidx++;
}
SPxRowId* addedrowids = 0;
spx_alloc(addedrowids, nnewrowidx);
_solver.addRows(addedrowids, updaterows);
for(int i = 0; i < nnewrowidx; i++)
_decompReducedProbRowIDs[newrowidx[i]] = addedrowids[i];
spx_free(addedrowids);
spx_free(newrowidx);
}
template <class R>
void SoPlexBase<R>::_updateDecompReducedProblemViol(bool allrows)
{
#ifdef NO_TOL
R feastol = 0.0;
#else
#ifdef USE_FEASTOL
R feastol = realParam(SoPlexBase<R>::FEASTOL);
#else
R feastol = realParam(SoPlexBase<R>::EPSILON_ZERO);
#endif
#endif
LPRowSetBase<R> updaterows;
int* newrowidx = 0;
int nnewrowidx = 0;
spx_alloc(newrowidx, _nPrimalRows);
int rowNumber;
int bestrow = -1;
R bestrownorm = R(infinity);
R percenttoadd = 1;
int nrowstoadd = MINIMUM(intParam(SoPlexBase<R>::DECOMP_MAXADDEDROWS), _nDecompViolRows);
if(allrows)
nrowstoadd = _nDecompViolRows;
SSVectorBase<R> y(_solver.nCols());
y.unSetup();
for(int i = 0; i < nrowstoadd; i++)
{
rowNumber = _decompViolatedRows[i];
if(!allrows)
{
R norm = 0;
try
{
_solver.basis().solve(y, _solver.vector(rowNumber));
}
catch(const SPxException& E)
{
MSG_ERROR(spxout << "Caught exception <" << E.what() << "> while computing compatability.\n");
}
if(y.isSetup())
{
for(int j = 0; j < y.size(); j++)
{
if(isZero(_solver.fVec()[i], feastol))
norm += spxAbs(y.value(j)) * spxAbs(y.value(j));
}
}
else
{
for(int j = 0; j < numCols(); j++)
{
if(isZero(_solver.fVec()[i], feastol))
norm += spxAbs(y[j]) * spxAbs(y[j]);
}
}
norm = soplex::spxSqrt(norm);
if(LT(norm, bestrownorm))
{
bestrow = rowNumber;
bestrownorm = norm;
}
if(isZero(norm, feastol) && LT(nnewrowidx / R(numRows()), percenttoadd))
{
updaterows.add(_transformedRows.lhs(rowNumber), _transformedRows.rowVector(rowNumber),
_transformedRows.rhs(rowNumber));
_decompReducedProbRows[rowNumber] = true;
newrowidx[nnewrowidx] = rowNumber;
nnewrowidx++;
}
}
else
{
updaterows.add(_transformedRows.lhs(rowNumber), _transformedRows.rowVector(rowNumber),
_transformedRows.rhs(rowNumber));
_decompReducedProbRows[rowNumber] = true;
newrowidx[nnewrowidx] = rowNumber;
nnewrowidx++;
}
}
if(nnewrowidx == 0)
{
for(int i = 0; i < nrowstoadd; i++)
{
rowNumber = _decompViolatedRows[i];
updaterows.add(_transformedRows.lhs(rowNumber), _transformedRows.rowVector(rowNumber),
_transformedRows.rhs(rowNumber));
_decompReducedProbRows[rowNumber] = true;
newrowidx[nnewrowidx] = rowNumber;
nnewrowidx++;
}
}
if(!allrows && bestrow >= 0)
{
updaterows.add(_transformedRows.lhs(bestrow), _transformedRows.rowVector(bestrow),
_transformedRows.rhs(bestrow));
_decompReducedProbRows[bestrow] = true;
newrowidx[nnewrowidx] = bestrow;
nnewrowidx++;
}
SPxRowId* addedrowids = 0;
spx_alloc(addedrowids, nnewrowidx);
_solver.addRows(addedrowids, updaterows);
for(int i = 0; i < nnewrowidx; i++)
_decompReducedProbRowIDs[newrowidx[i]] = addedrowids[i];
spx_free(addedrowids);
spx_free(newrowidx);
}
template <class R>
void SoPlexBase<R>::_findViolatedRows(R compObjValue, Array<RowViolation>& violatedrows,
int& nviolatedrows)
{
R feastol = realParam(SoPlexBase<R>::FEASTOL);
VectorBase<R> compProbRedcost(
_compSolver.nCols()); VectorBase<R> compProbPrimal(
_compSolver.nCols()); VectorBase<R> compProbActivity(
_compSolver.nRows()); R compProbSlackVal = 0;
if(boolParam(SoPlexBase<R>::USECOMPDUAL))
{
_compSolver.getRedCostSol(compProbRedcost);
}
else
{
_compSolver.getPrimalSol(compProbPrimal);
_compSolver.computePrimalActivity(compProbPrimal, compProbActivity);
compProbSlackVal = compProbPrimal[_compSolver.number(_compSlackColId)];
}
for(int i = 0; i < _nPrimalRows; i++)
{
LPRowBase<R> origlprow;
DSVectorBase<R> rowtoaddVec(_realLP->nCols());
R compProbViol = 0;
R compSlackCoeff = 0;
int rownumber = _realLP->number(SPxRowId(_decompPrimalRowIDs[i]));
int comprownum = _compSolver.number(SPxRowId(_decompPrimalRowIDs[i]));
if(!_decompReducedProbRows[rownumber])
{
if(boolParam(SoPlexBase<R>::USECOMPDUAL))
{
compSlackCoeff = getCompSlackVarCoeff(i);
compProbViol = compProbRedcost[_compSolver.number(SPxColId(
_decompDualColIDs[i]))]; compProbViol += compObjValue * compSlackCoeff; compProbViol *= compSlackCoeff; }
else
{
R viol = _compSolver.rhs(comprownum) - (compProbActivity[comprownum] + compProbSlackVal);
if(viol < 0.0)
compProbViol = viol;
viol = (compProbActivity[comprownum] - compProbSlackVal) - _compSolver.lhs(comprownum);
if(viol < 0.0)
compProbViol = viol;
}
if(boolParam(SoPlexBase<R>::USECOMPDUAL) && i < _nPrimalRows - 1 &&
_realLP->number(SPxRowId(_decompPrimalRowIDs[i])) == _realLP->number(SPxRowId(
_decompPrimalRowIDs[i + 1])))
{
i++;
compSlackCoeff = getCompSlackVarCoeff(i);
R tempViol = compProbRedcost[_compSolver.number(SPxColId(_decompDualColIDs[i]))]; tempViol += compObjValue * compSlackCoeff;
tempViol *= compSlackCoeff;
if(tempViol < compProbViol)
compProbViol = tempViol;
}
if(LT(compProbViol, (R) 0, feastol))
{
if(!_decompReducedProbRows[rownumber])
{
numIncludedRows++;
assert(numIncludedRows <= _realLP->nRows());
}
violatedrows[nviolatedrows].idx = rownumber;
violatedrows[nviolatedrows].violation = spxAbs(compProbViol);
nviolatedrows++;
}
}
}
}
template <class R>
void SoPlexBase<R>::_getZeroDualMultiplierIndices(VectorBase<R> feasVector, int* nonposind,
int* colsforremoval,
int* nnonposind, bool& stop)
{
assert(_solver.rep() == SPxSolverBase<R>::ROW);
#ifdef NO_TOL
R feastol = 0.0;
#else
#ifdef USE_FEASTOL
R feastol = realParam(SoPlexBase<R>::FEASTOL);
#else
R feastol = realParam(SoPlexBase<R>::EPSILON_ZERO);
#endif
#endif
bool delCol;
_decompReducedProbColIDs.reSize(numCols());
*nnonposind = 0;
for(int i = 0; i < _solver.nCols(); ++i)
{
_decompReducedProbCols[i] = true;
_decompReducedProbColIDs[i].inValidate();
colsforremoval[i] = i;
delCol = false;
if(_solver.basis().baseId(i).isSPxRowId()) {
if(isZero(feasVector[i], feastol))
{
nonposind[*nnonposind] = i;
(*nnonposind)++;
}
}
else if(_solver.basis().baseId(
i).isSPxColId()) {
if(isZero(feasVector[i], feastol))
{
nonposind[*nnonposind] = i;
(*nnonposind)++;
delCol = true;
}
}
if(delCol)
{
colsforremoval[i] = -1;
_decompReducedProbCols[i] = false;
}
else if(_solver.basis().baseId(i).isSPxColId())
{
if(_solver.basis().baseId(i).isSPxColId())
_decompReducedProbColIDs[_solver.number(_solver.basis().baseId(i))] = SPxColId(
_solver.basis().baseId(i));
else
_decompReducedProbCols[_solver.number(_solver.basis().baseId(i))] = false;
}
}
stop = decompTerminate(realParam(SoPlexBase<R>::TIMELIMIT) * TIMELIMIT_FRAC);
}
template <class R>
void SoPlexBase<R>::_getCompatibleColumns(VectorBase<R> feasVector, int* nonposind, int* compatind,
int* rowsforremoval,
int* colsforremoval, int nnonposind, int* ncompatind, bool formRedProb, bool& stop)
{
#ifdef NO_TOL
R feastol = 0.0;
#else
#ifdef USE_FEASTOL
R feastol = realParam(SoPlexBase<R>::FEASTOL);
#else
R feastol = realParam(SoPlexBase<R>::EPSILON_ZERO);
#endif
#endif
bool compatible;
SSVectorBase<R> y(_solver.nCols());
y.unSetup();
*ncompatind = 0;
#ifndef NDEBUG
int bind = 0;
bool* activerows = 0;
spx_alloc(activerows, numRows());
for(int i = 0; i < numRows(); ++i)
activerows[i] = false;
for(int i = 0; i < numCols(); ++i)
{
if(_solver.basis().baseId(i).isSPxRowId()) {
if(!isZero(feasVector[i], feastol))
{
bind = _realLP->number(SPxRowId(_solver.basis().baseId(i))); assert(bind >= 0 && bind < numRows());
activerows[bind] = true;
}
}
}
#endif
if(formRedProb)
{
_decompReducedProbRowIDs.reSize(_solver.nRows());
_decompReducedProbColRowIDs.reSize(_solver.nRows());
}
for(int i = 0; i < numRows(); ++i)
{
rowsforremoval[i] = i;
if(formRedProb)
_decompReducedProbRows[i] = true;
numIncludedRows++;
try
{
_solver.basis().solve(y, _solver.vector(i));
}
catch(const SPxException& E)
{
MSG_ERROR(spxout << "Caught exception <" << E.what() << "> while computing compatability.\n");
}
compatible = true;
for(int j = 0; j < nnonposind; ++j)
{
if(!isZero(y[nonposind[j]], feastol))
{
compatible = false;
break;
}
}
assert(!activerows[i] || compatible);
DSVectorBase<R> newRowVector;
LPRowBase<R> rowtoupdate;
if(y.isSetup())
{
for(int j = 0; j < y.size(); j++)
newRowVector.add(y.index(j), y.value(j));
}
else
{
for(int j = 0; j < numCols(); j++)
{
if(!isZero(y[j], feastol))
newRowVector.add(j, y[j]);
}
}
_solver.getRow(i, rowtoupdate);
#ifndef NO_TRANSFORM
rowtoupdate.setRowVector(newRowVector);
#endif
if(formRedProb)
_transformedRows.add(rowtoupdate);
if(EQ(rowtoupdate.lhs(), rowtoupdate.rhs()))
compatible = true;
if(compatible)
{
compatind[*ncompatind] = i;
(*ncompatind)++;
if(formRedProb)
{
_decompReducedProbRowIDs[i] = _solver.rowId(i);
_decompLP->changeRow(i, rowtoupdate);
}
}
else
{
rowsforremoval[i] = -1;
numIncludedRows--;
if(formRedProb)
_decompReducedProbRows[i] = false;
}
stop = decompTerminate(realParam(SoPlexBase<R>::TIMELIMIT) * TIMELIMIT_FRAC);
if(stop)
break;
}
assert(numIncludedRows <= _solver.nRows());
#ifndef NDEBUG
spx_free(activerows);
#endif
}
template <class R>
void SoPlexBase<R>::_computeReducedProbObjCoeff(bool& stop)
{
#ifdef NO_TOL
R feastol = 0.0;
#else
#ifdef USE_FEASTOL
R feastol = realParam(SoPlexBase<R>::FEASTOL);
#else
R feastol = realParam(SoPlexBase<R>::EPSILON_ZERO);
#endif
#endif
SSVectorBase<R> y(numCols());
y.unSetup();
try
{
_solver.basis().solve(y, _solver.maxObj());
}
catch(const SPxException& E)
{
MSG_ERROR(spxout << "Caught exception <" << E.what() << "> while computing compatability.\n");
}
_transformedObj.reDim(numCols());
if(y.isSetup())
{
int ycount = 0;
for(int i = 0; i < numCols(); i++)
{
if(ycount < y.size() && i == y.index(ycount))
{
_transformedObj[i] = y.value(ycount);
ycount++;
}
else
_transformedObj[i] = 0.0;
}
}
else
{
for(int i = 0; i < numCols(); i++)
{
if(isZero(y[i], feastol))
_transformedObj[i] = 0.0;
else
_transformedObj[i] = y[i];
}
}
#ifndef NO_TRANSFORM
_decompLP->changeObj(_transformedObj);
#endif
stop = decompTerminate(realParam(SoPlexBase<R>::TIMELIMIT) * TIMELIMIT_FRAC);
}
template <class R>
void SoPlexBase<R>::_getCompatibleBoundCons(LPRowSetBase<R>& boundcons, int* compatboundcons,
int* nonposind,
int* ncompatboundcons, int nnonposind, bool& stop)
{
#ifdef NO_TOL
R feastol = 0.0;
#else
#ifdef USE_FEASTOL
R feastol = realParam(SoPlexBase<R>::FEASTOL);
#else
R feastol = realParam(SoPlexBase<R>::EPSILON_ZERO);
#endif
#endif
bool compatible;
int ncols = numCols();
SSVectorBase<R> y(ncols);
y.unSetup();
_decompReducedProbColRowIDs.reSize(numCols());
for(int i = 0; i < ncols; i++)
{
_decompReducedProbColRowIDs[i].inValidate();
_decompLP->changeUpper(i, R(infinity));
_decompLP->changeLower(i, R(-infinity));
try
{
_solver.basis().solve(y, _solver.unitVector(i));
}
catch(const SPxException& E)
{
MSG_ERROR(spxout << "Caught exception <" << E.what() << "> while computing compatability.\n");
}
compatible = true;
for(int j = 0; j < nnonposind; ++j)
{
if(!isZero(y[nonposind[j]]))
{
compatible = false;
break;
}
}
DSVectorBase<R> newRowVector;
LPRowBase<R> rowtoupdate;
#ifndef NO_TRANSFORM
if(y.isSetup())
{
for(int j = 0; j < y.size(); j++)
newRowVector.add(y.index(j), y.value(j));
}
else
{
for(int j = 0; j < ncols; j++)
{
if(!isZero(y[j], feastol))
{
newRowVector.add(j, y[j]);
}
}
}
#else
newRowVector.add(i, 1.0);
#endif
_transformedRows.add(_solver.lower(i), newRowVector, _solver.upper(i));
compatible = true;
if(compatible)
{
R lhs = R(-infinity);
R rhs = R(infinity);
if(GT(_solver.lower(i), R(-infinity)))
lhs = _solver.lower(i);
if(LT(_solver.upper(i), R(infinity)))
rhs = _solver.upper(i);
if(GT(lhs, R(-infinity)) || LT(rhs, R(infinity)))
{
compatboundcons[(*ncompatboundcons)] = i;
(*ncompatboundcons)++;
boundcons.add(lhs, newRowVector, rhs);
}
}
stop = decompTerminate(realParam(SoPlexBase<R>::TIMELIMIT) * TIMELIMIT_FRAC);
if(stop)
break;
}
}
template <class R>
void SoPlexBase<R>::_getRowsForRemovalComplementaryProblem(int* nonposind, int* bind,
int* rowsforremoval,
int* nrowsforremoval, int nnonposind)
{
*nrowsforremoval = 0;
for(int i = 0; i < nnonposind; i++)
{
if(bind[nonposind[i]] < 0)
{
rowsforremoval[*nrowsforremoval] = -1 - bind[nonposind[i]];
(*nrowsforremoval)++;
}
}
}
template <class R>
void SoPlexBase<R>::_deleteAndUpdateRowsComplementaryProblem(SPxRowId rangedRowIds[],
int& naddedrows)
{
DSVectorBase<R> slackColCoeff;
VectorBase<R> newObjCoeff(numCols());
for(int i = 0; i < numCols(); i++)
{
_compSolver.changeBounds(_realLP->cId(i), R(-infinity), R(infinity));
newObjCoeff[i] = 0;
}
_compSolver.changeObj(newObjCoeff);
SPxColId* addedcolid = 0;
if(boolParam(SoPlexBase<R>::USECOMPDUAL))
{
spx_alloc(addedcolid, 1);
LPColSetBase<R> compSlackCol;
compSlackCol.add(R(1.0), R(-infinity), slackColCoeff, R(infinity));
_compSolver.addCols(addedcolid, compSlackCol);
_compSlackColId = addedcolid[0];
}
else
{
LPRowSetBase<R>
addrangedrows; naddedrows = 0;
for(int i = 0; i < numRows(); i++)
{
if(_realLP->rowType(i) == LPRowBase<R>::RANGE || _realLP->rowType(i) == LPRowBase<R>::EQUAL)
{
assert(GT(_compSolver.lhs(i), R(-infinity)) && LT(_compSolver.rhs(i), R(infinity)));
assert(_compSolver.rowType(i) == LPRowBase<R>::RANGE
|| _compSolver.rowType(i) == LPRowBase<R>::EQUAL);
_compSolver.changeLhs(i, R(-infinity));
addrangedrows.add(_realLP->lhs(i), _realLP->rowVector(i), R(infinity));
naddedrows++;
}
}
SPxRowId* addedrowid = 0;
spx_alloc(addedrowid, naddedrows);
_compSolver.addRows(addedrowid, addrangedrows);
for(int i = 0; i < naddedrows; i++)
rangedRowIds[i] = addedrowid[i];
spx_free(addedrowid);
spx_alloc(addedcolid, 1);
LPColSetBase<R> compSlackCol;
compSlackCol.add(R(-1.0), R(0.0), slackColCoeff, R(infinity));
_compSolver.addCols(addedcolid, compSlackCol);
_compSlackColId = addedcolid[0];
}
spx_free(addedcolid);
}
template <class R>
void SoPlexBase<R>::_updateDecompComplementaryDualProblem(bool origObj)
{
R feastol = realParam(SoPlexBase<R>::FEASTOL);
int prevNumCols =
_compSolver.nCols(); int prevNumRows = _compSolver.nRows();
int prevPrimalRowIds = _nPrimalRows;
int prevDualColIds = _nDualCols;
LPColSetBase<R> addElimCols(_nElimPrimalRows); int numElimColsAdded = 0;
int currnumrows = prevNumRows;
for(int i = 0; i < _nElimPrimalRows; i++)
{
int rowNumber = _realLP->number(_decompElimPrimalRowIDs[i]);
int solverRowNum = _solver.number(_decompReducedProbRowIDs[rowNumber]);
assert(solverRowNum >= 0 && solverRowNum < _solver.nRows());
if(_solver.basis().desc().rowStatus(solverRowNum) == SPxBasisBase<R>::Desc::P_ON_UPPER ||
_solver.basis().desc().rowStatus(solverRowNum) == SPxBasisBase<R>::Desc::P_ON_LOWER ||
_solver.basis().desc().rowStatus(solverRowNum) == SPxBasisBase<R>::Desc::P_FIXED ||
_solver.basis().desc().rowStatus(solverRowNum) == SPxBasisBase<R>::Desc::D_FREE ||
(_solver.basis().desc().rowStatus(solverRowNum) == SPxBasisBase<R>::Desc::D_ON_LOWER &&
LE(_solver.rhs(solverRowNum) - _solver.pVec()[solverRowNum], R(0.0), feastol)) ||
(_solver.basis().desc().rowStatus(solverRowNum) == SPxBasisBase<R>::Desc::D_ON_UPPER &&
LE(_solver.pVec()[solverRowNum] - _solver.lhs(solverRowNum), R(0.0), feastol)))
{
LPRowBase<R> origlprow;
DSVectorBase<R> coltoaddVec(_realLP->nCols());
LPRowSetBase<R> additionalrows;
int nnewrows = 0;
_realLP->getRow(rowNumber, origlprow);
for(int j = 0; j < origlprow.rowVector().size(); j++)
{
int colNumber = origlprow.rowVector().index(j);
if(_decompCompProbColIDsIdx[colNumber] == -1)
{
assert(!_decompReducedProbColIDs[colNumber].isValid());
_decompPrimalColIDs[_nPrimalCols] = _realLP->cId(colNumber);
_decompCompProbColIDsIdx[colNumber] = _nPrimalCols;
_fixedOrigVars[colNumber] = -2;
_nPrimalCols++;
additionalrows.create(1, _realLP->maxObj(colNumber), _realLP->maxObj(colNumber));
nnewrows++;
coltoaddVec.add(currnumrows, origlprow.rowVector().value(j));
currnumrows++;
}
else
coltoaddVec.add(_compSolver.number(_decompDualRowIDs[_decompCompProbColIDsIdx[colNumber]]),
origlprow.rowVector().value(j));
}
SPxRowId* addedrowids = 0;
spx_alloc(addedrowids, nnewrows);
_compSolver.addRows(addedrowids, additionalrows);
for(int j = 0; j < nnewrows; j++)
{
_decompDualRowIDs[_nDualRows] = addedrowids[j];
_nDualRows++;
}
spx_free(addedrowids);
if(_solver.basis().desc().rowStatus(solverRowNum) == SPxBasisBase<R>::Desc::P_ON_UPPER ||
_solver.basis().desc().rowStatus(solverRowNum) == SPxBasisBase<R>::Desc::P_FIXED ||
_solver.basis().desc().rowStatus(solverRowNum) == SPxBasisBase<R>::Desc::D_FREE ||
(_solver.basis().desc().rowStatus(solverRowNum) == SPxBasisBase<R>::Desc::D_ON_LOWER &&
LE(_solver.rhs(solverRowNum) - _solver.pVec()[solverRowNum], R(0.0), feastol)))
{
assert(LT(_realLP->rhs(_decompElimPrimalRowIDs[i]), R(infinity)));
addElimCols.add(_realLP->rhs(_decompElimPrimalRowIDs[i]), R(-infinity), coltoaddVec, R(infinity));
if(_nPrimalRows >= _decompPrimalRowIDs.size())
{
_decompPrimalRowIDs.reSize(_nPrimalRows * 2);
_decompDualColIDs.reSize(_nPrimalRows * 2);
}
_decompPrimalRowIDs[_nPrimalRows] = _decompElimPrimalRowIDs[i];
_nPrimalRows++;
_decompElimPrimalRowIDs.remove(i);
_nElimPrimalRows--;
i--;
numElimColsAdded++;
}
else if(_solver.basis().desc().rowStatus(solverRowNum) == SPxBasisBase<R>::Desc::P_ON_LOWER ||
(_solver.basis().desc().rowStatus(solverRowNum) == SPxBasisBase<R>::Desc::D_ON_UPPER &&
LE(_solver.pVec()[solverRowNum] - _solver.lhs(solverRowNum), R(0.0), feastol)))
{
assert(GT(_realLP->lhs(_decompElimPrimalRowIDs[i]), R(-infinity)));
addElimCols.add(_realLP->lhs(_decompElimPrimalRowIDs[i]), R(-infinity), coltoaddVec, R(infinity));
_decompPrimalRowIDs[_nPrimalRows] = _decompElimPrimalRowIDs[i];
_nPrimalRows++;
_decompElimPrimalRowIDs.remove(i);
_nElimPrimalRows--;
i--;
numElimColsAdded++;
}
}
}
MSG_INFO2(spxout, spxout << "Number of eliminated columns added to complementary problem: "
<< numElimColsAdded << std::endl);
_compSolver.addCols(addElimCols);
for(int i = prevNumCols; i < _compSolver.nCols(); i++)
{
_decompDualColIDs[prevDualColIds + i - prevNumCols] = _compSolver.colId(i);
_nDualCols++;
}
assert(_nDualCols == _nPrimalRows);
DSVectorBase<R> slackRowCoeff(_compSolver.nCols());
int* colsforremoval = 0;
int ncolsforremoval = 0;
spx_alloc(colsforremoval, prevPrimalRowIds);
for(int i = 0; i < prevPrimalRowIds; i++)
{
int rowNumber = _realLP->number(_decompPrimalRowIDs[i]);
if(_decompReducedProbRows[rowNumber])
{
#ifdef KEEP_ALL_ROWS_IN_COMP_PROB
bool incrementI = false;
#endif
if(i + 1 < prevPrimalRowIds
&& _realLP->number(_decompPrimalRowIDs[i]) == _realLP->number(_decompPrimalRowIDs[i + 1]))
{
assert(_decompPrimalRowIDs[i].idx == _decompPrimalRowIDs[i + 1].idx);
#ifdef KEEP_ALL_ROWS_IN_COMP_PROB
if(_realLP->rowType(_decompPrimalRowIDs[i]) == LPRowBase<R>::RANGE)
{
_compSolver.changeObj(_decompDualColIDs[i + 1], 0.0);
_compSolver.changeBounds(_decompDualColIDs[i + 1], 0.0, 0.0);
}
incrementI = true;
#else
colsforremoval[ncolsforremoval] = _compSolver.number(SPxColId(_decompDualColIDs[i + 1]));
ncolsforremoval++;
_decompPrimalRowIDs.remove(i + 1);
_nPrimalRows--;
_decompDualColIDs.remove(i + 1);
_nDualCols--;
prevPrimalRowIds--;
#endif
}
int solverRowNum = _solver.number(_decompReducedProbRowIDs[rowNumber]);
assert(solverRowNum >= 0 && solverRowNum < _solver.nRows());
if(_solver.basis().desc().rowStatus(solverRowNum) == SPxBasisBase<R>::Desc::P_ON_UPPER ||
_solver.basis().desc().rowStatus(solverRowNum) == SPxBasisBase<R>::Desc::P_FIXED ||
_solver.basis().desc().rowStatus(solverRowNum) == SPxBasisBase<R>::Desc::D_FREE ||
(_solver.basis().desc().rowStatus(solverRowNum) == SPxBasisBase<R>::Desc::D_ON_LOWER &&
LE(_solver.rhs(solverRowNum) - _solver.pVec()[solverRowNum], R(0.0), feastol)))
{
_compSolver.changeObj(_decompDualColIDs[i], _realLP->rhs(SPxRowId(_decompPrimalRowIDs[i])));
_compSolver.changeBounds(_decompDualColIDs[i], R(-infinity), R(infinity));
}
else if(_solver.basis().desc().rowStatus(solverRowNum) == SPxBasisBase<R>::Desc::P_ON_LOWER ||
(_solver.basis().desc().rowStatus(solverRowNum) == SPxBasisBase<R>::Desc::D_ON_UPPER &&
LE(_solver.pVec()[solverRowNum] - _solver.lhs(solverRowNum), R(0.0), feastol)))
{
_compSolver.changeObj(_decompDualColIDs[i], _realLP->lhs(SPxRowId(_decompPrimalRowIDs[i])));
_compSolver.changeBounds(_decompDualColIDs[i], R(-infinity), R(infinity));
}
else {
#ifdef KEEP_ALL_ROWS_IN_COMP_PROB
switch(_realLP->rowType(_decompPrimalRowIDs[i]))
{
case LPRowBase<R>::RANGE:
assert(_realLP->number(SPxColId(_decompPrimalRowIDs[i])) ==
_realLP->number(SPxColId(_decompPrimalRowIDs[i + 1])));
assert(_compSolver.obj(_compSolver.number(SPxColId(_decompDualColIDs[i]))) !=
_compSolver.obj(_compSolver.number(SPxColId(_decompDualColIDs[i + 1]))));
_compSolver.changeObj(_decompDualColIDs[i], _realLP->rhs(_decompPrimalRowIDs[i]));
_compSolver.changeBounds(_decompDualColIDs[i], 0.0, R(infinity));
_compSolver.changeObj(_decompDualColIDs[i + 1], _realLP->lhs(_decompPrimalRowIDs[i]));
_compSolver.changeBounds(_decompDualColIDs[i + 1], R(-infinity), 0.0);
i++;
break;
case LPRowBase<R>::GREATER_EQUAL:
_compSolver.changeObj(_decompDualColIDs[i], _realLP->lhs(_decompPrimalRowIDs[i]));
_compSolver.changeBounds(_decompDualColIDs[i], R(-infinity), 0.0);
break;
case LPRowBase<R>::LESS_EQUAL:
_compSolver.changeObj(_decompDualColIDs[i], _realLP->rhs(_decompPrimalRowIDs[i]));
_compSolver.changeBounds(_decompDualColIDs[i], 0.0, R(infinity));
break;
default:
throw SPxInternalCodeException("XDECOMPSL01 This should never happen.");
}
#else
colsforremoval[ncolsforremoval] = _compSolver.number(SPxColId(_decompDualColIDs[i]));
ncolsforremoval++;
if(_nElimPrimalRows >= _decompElimPrimalRowIDs.size())
_decompElimPrimalRowIDs.reSize(_realLP->nRows());
_decompElimPrimalRowIDs[_nElimPrimalRows] = _decompPrimalRowIDs[i];
_nElimPrimalRows++;
_decompPrimalRowIDs.remove(i);
_nPrimalRows--;
_decompDualColIDs.remove(i);
_nDualCols--;
i--;
prevPrimalRowIds--;
#endif
}
#ifdef KEEP_ALL_ROWS_IN_COMP_PROB
if(incrementI)
i++;
#endif
}
else
{
switch(_realLP->rowType(_decompPrimalRowIDs[i]))
{
case LPRowBase<R>::RANGE:
assert(_realLP->number(SPxColId(_decompPrimalRowIDs[i])) ==
_realLP->number(SPxColId(_decompPrimalRowIDs[i + 1])));
assert(_compSolver.obj(_compSolver.number(SPxColId(_decompDualColIDs[i]))) !=
_compSolver.obj(_compSolver.number(SPxColId(_decompDualColIDs[i + 1]))));
if(_compSolver.obj(_compSolver.number(SPxColId(_decompDualColIDs[i]))) <
_compSolver.obj(_compSolver.number(SPxColId(_decompDualColIDs[i + 1]))))
{
slackRowCoeff.add(_compSolver.number(SPxColId(_decompDualColIDs[i])), -SLACKCOEFF);
slackRowCoeff.add(_compSolver.number(SPxColId(_decompDualColIDs[i + 1])), SLACKCOEFF);
}
else
{
slackRowCoeff.add(_compSolver.number(SPxColId(_decompDualColIDs[i])), SLACKCOEFF);
slackRowCoeff.add(_compSolver.number(SPxColId(_decompDualColIDs[i + 1])), -SLACKCOEFF);
}
i++;
break;
case LPRowBase<R>::EQUAL:
assert(_realLP->number(SPxColId(_decompPrimalRowIDs[i])) ==
_realLP->number(SPxColId(_decompPrimalRowIDs[i + 1])));
slackRowCoeff.add(_compSolver.number(SPxColId(_decompDualColIDs[i])), SLACKCOEFF);
slackRowCoeff.add(_compSolver.number(SPxColId(_decompDualColIDs[i + 1])), SLACKCOEFF);
i++;
break;
case LPRowBase<R>::GREATER_EQUAL:
slackRowCoeff.add(_compSolver.number(SPxColId(_decompDualColIDs[i])), -SLACKCOEFF);
break;
case LPRowBase<R>::LESS_EQUAL:
slackRowCoeff.add(_compSolver.number(SPxColId(_decompDualColIDs[i])), SLACKCOEFF);
break;
default:
throw SPxInternalCodeException("XDECOMPSL01 This should never happen.");
}
if(origObj)
{
int numRemove = 1;
int removeCount = 0;
if(_realLP->number(SPxColId(_decompPrimalRowIDs[i])) ==
_realLP->number(SPxColId(_decompPrimalRowIDs[i + 1])))
numRemove++;
do
{
colsforremoval[ncolsforremoval] = _compSolver.number(SPxColId(_decompDualColIDs[i]));
ncolsforremoval++;
if(_nElimPrimalRows >= _decompElimPrimalRowIDs.size())
_decompElimPrimalRowIDs.reSize(_realLP->nRows());
_decompElimPrimalRowIDs[_nElimPrimalRows] = _decompPrimalRowIDs[i];
_nElimPrimalRows++;
_decompPrimalRowIDs.remove(i);
_nPrimalRows--;
_decompDualColIDs.remove(i);
_nDualCols--;
i--;
prevPrimalRowIds--;
removeCount++;
}
while(removeCount < numRemove);
}
}
}
R lhs = 1.0;
R rhs = 1.0;
if(slackRowCoeff.size() == 0)
{
lhs = 0.0;
rhs = 0.0;
}
LPRowBase<R> compSlackRow(lhs, slackRowCoeff, rhs);
_compSolver.changeRow(_compSlackDualRowId, compSlackRow);
int* perm = 0;
spx_alloc(perm, _compSolver.nCols() + numElimColsAdded);
_compSolver.removeCols(colsforremoval, ncolsforremoval, perm);
int* currFixedVars = 0;
spx_alloc(currFixedVars, _realLP->nCols());
_identifyComplementaryDualFixedPrimalVars(currFixedVars);
_removeComplementaryDualFixedPrimalVars(currFixedVars);
_updateComplementaryDualFixedPrimalVars(currFixedVars);
spx_free(currFixedVars);
spx_free(perm);
spx_free(colsforremoval);
}
template <class R>
void SoPlexBase<R>::_updateDecompComplementaryPrimalProblem(bool origObj)
{
R feastol = realParam(SoPlexBase<R>::FEASTOL);
int prevNumRows = _compSolver.nRows();
int prevPrimalRowIds = _nPrimalRows;
assert(_nPrimalRows == _nCompPrimalRows);
LPRowSetBase<R> addElimRows(_nElimPrimalRows); int numElimRowsAdded = 0;
for(int i = 0; i < _nElimPrimalRows; i++)
{
int rowNumber = _realLP->number(_decompElimPrimalRowIDs[i]);
int solverRowNum = _solver.number(_decompReducedProbRowIDs[rowNumber]);
assert(solverRowNum >= 0 && solverRowNum < _solver.nRows());
if(_solver.basis().desc().rowStatus(solverRowNum) == SPxBasisBase<R>::Desc::P_ON_UPPER
|| _solver.basis().desc().rowStatus(solverRowNum) == SPxBasisBase<R>::Desc::P_ON_LOWER
|| _solver.basis().desc().rowStatus(solverRowNum) == SPxBasisBase<R>::Desc::P_FIXED
|| _solver.basis().desc().rowStatus(solverRowNum) == SPxBasisBase<R>::Desc::D_FREE
|| (_solver.basis().desc().rowStatus(solverRowNum) == SPxBasisBase<R>::Desc::D_ON_LOWER &&
EQ(_solver.rhs(solverRowNum) - _solver.pVec()[solverRowNum], R(0.0), feastol))
|| (_solver.basis().desc().rowStatus(solverRowNum) == SPxBasisBase<R>::Desc::D_ON_UPPER &&
EQ(_solver.pVec()[solverRowNum] - _solver.lhs(solverRowNum), R(0.0), feastol)))
{
LPRowBase<R> origlprow;
_realLP->getRow(rowNumber, origlprow);
if(_solver.basis().desc().rowStatus(solverRowNum) == SPxBasisBase<R>::Desc::P_ON_UPPER
|| _solver.basis().desc().rowStatus(solverRowNum) == SPxBasisBase<R>::Desc::P_FIXED
|| _solver.basis().desc().rowStatus(solverRowNum) == SPxBasisBase<R>::Desc::D_FREE
|| (_solver.basis().desc().rowStatus(solverRowNum) == SPxBasisBase<R>::Desc::D_ON_LOWER &&
EQ(_solver.rhs(solverRowNum) - _solver.pVec()[solverRowNum], R(0.0), feastol)))
{
assert(LT(_realLP->rhs(_decompElimPrimalRowIDs[i]), R(infinity)));
if(_nPrimalRows >= _decompPrimalRowIDs.size())
{
_decompPrimalRowIDs.reSize(_nPrimalRows * 2);
_decompCompPrimalRowIDs.reSize(_nPrimalRows * 2);
}
addElimRows.add(_realLP->rhs(_decompElimPrimalRowIDs[i]), origlprow.rowVector(),
_realLP->rhs(_decompElimPrimalRowIDs[i]));
_decompPrimalRowIDs[_nPrimalRows] = _decompElimPrimalRowIDs[i];
_nPrimalRows++;
_decompElimPrimalRowIDs.remove(i);
_nElimPrimalRows--;
i--;
numElimRowsAdded++;
}
else if(_solver.basis().desc().rowStatus(solverRowNum) == SPxBasisBase<R>::Desc::P_ON_LOWER
|| (_solver.basis().desc().rowStatus(solverRowNum) == SPxBasisBase<R>::Desc::D_ON_UPPER &&
EQ(_solver.pVec()[solverRowNum] - _solver.lhs(solverRowNum), R(0.0), feastol)))
{
assert(GT(_realLP->lhs(_decompElimPrimalRowIDs[i]), R(-infinity)));
if(_nPrimalRows >= _decompPrimalRowIDs.size())
{
_decompPrimalRowIDs.reSize(_nPrimalRows * 2);
_decompCompPrimalRowIDs.reSize(_nPrimalRows * 2);
}
addElimRows.add(_realLP->lhs(_decompElimPrimalRowIDs[i]), origlprow.rowVector(),
_realLP->lhs(_decompElimPrimalRowIDs[i]));
_decompPrimalRowIDs[_nPrimalRows] = _decompElimPrimalRowIDs[i];
_nPrimalRows++;
_decompElimPrimalRowIDs.remove(i);
_nElimPrimalRows--;
i--;
numElimRowsAdded++;
}
}
}
MSG_INFO2(spxout, spxout << "Number of eliminated rows added to the complementary problem: "
<< numElimRowsAdded << std::endl);
_compSolver.addRows(addElimRows);
for(int i = prevNumRows; i < _compSolver.nRows(); i++)
{
_decompCompPrimalRowIDs[prevPrimalRowIds + i - prevNumRows] = _compSolver.rowId(i);
_nCompPrimalRows++;
}
assert(_nPrimalRows == _nCompPrimalRows);
DSVectorBase<R> slackColCoeff(_compSolver.nRows());
int* rowsforremoval = 0;
int nrowsforremoval = 0;
spx_alloc(rowsforremoval, prevPrimalRowIds);
for(int i = 0; i < prevPrimalRowIds; i++)
{
int rowNumber = _realLP->number(_decompPrimalRowIDs[i]);
if(_decompReducedProbRows[rowNumber])
{
int solverRowNum = _solver.number(_decompReducedProbRowIDs[rowNumber]);
assert(solverRowNum >= 0 && solverRowNum < _solver.nRows());
if(_solver.basis().desc().rowStatus(solverRowNum) == SPxBasisBase<R>::Desc::P_ON_UPPER
|| _solver.basis().desc().rowStatus(solverRowNum) == SPxBasisBase<R>::Desc::P_FIXED
|| _solver.basis().desc().rowStatus(solverRowNum) == SPxBasisBase<R>::Desc::D_FREE
|| (_solver.basis().desc().rowStatus(solverRowNum) == SPxBasisBase<R>::Desc::D_ON_LOWER &&
EQ(_solver.rhs(solverRowNum) - _solver.pVec()[solverRowNum], R(0.0), feastol)))
{
_compSolver.changeLhs(_decompCompPrimalRowIDs[i], _realLP->rhs(SPxRowId(_decompPrimalRowIDs[i])));
_compSolver.changeRhs(_decompCompPrimalRowIDs[i], _realLP->rhs(SPxRowId(_decompPrimalRowIDs[i])));
}
else if(_solver.basis().desc().rowStatus(solverRowNum) == SPxBasisBase<R>::Desc::P_ON_LOWER
|| (_solver.basis().desc().rowStatus(solverRowNum) == SPxBasisBase<R>::Desc::D_ON_UPPER &&
EQ(_solver.pVec()[solverRowNum] - _solver.lhs(solverRowNum), R(0.0), feastol)))
{
_compSolver.changeRhs(_decompCompPrimalRowIDs[i], _realLP->lhs(SPxRowId(_decompPrimalRowIDs[i])));
_compSolver.changeLhs(_decompCompPrimalRowIDs[i], _realLP->lhs(SPxRowId(_decompPrimalRowIDs[i])));
}
else {
rowsforremoval[nrowsforremoval] = _compSolver.number(SPxRowId(_decompCompPrimalRowIDs[i]));
nrowsforremoval++;
if(_nElimPrimalRows >= _decompElimPrimalRowIDs.size())
_decompElimPrimalRowIDs.reSize(_realLP->nRows());
_decompElimPrimalRowIDs[_nElimPrimalRows] = _decompPrimalRowIDs[i];
_nElimPrimalRows++;
_decompPrimalRowIDs.remove(i);
_nPrimalRows--;
_decompCompPrimalRowIDs.remove(i);
_nCompPrimalRows--;
i--;
prevPrimalRowIds--;
}
}
else
{
switch(_compSolver.rowType(_decompCompPrimalRowIDs[i]))
{
case LPRowBase<R>::RANGE:
assert(false);
break;
case LPRowBase<R>::EQUAL:
assert(false);
break;
case LPRowBase<R>::LESS_EQUAL:
slackColCoeff.add(_compSolver.number(SPxRowId(_decompCompPrimalRowIDs[i])), -SLACKCOEFF);
break;
case LPRowBase<R>::GREATER_EQUAL:
slackColCoeff.add(_compSolver.number(SPxRowId(_decompCompPrimalRowIDs[i])), SLACKCOEFF);
break;
default:
throw SPxInternalCodeException("XDECOMPSL01 This should never happen.");
}
if(origObj)
{
rowsforremoval[nrowsforremoval] = _compSolver.number(SPxRowId(_decompCompPrimalRowIDs[i]));
nrowsforremoval++;
if(_nElimPrimalRows >= _decompElimPrimalRowIDs.size())
_decompElimPrimalRowIDs.reSize(_realLP->nRows());
_decompElimPrimalRowIDs[_nElimPrimalRows] = _decompPrimalRowIDs[i];
_nElimPrimalRows++;
_decompPrimalRowIDs.remove(i);
_nPrimalRows--;
_decompCompPrimalRowIDs.remove(i);
_nCompPrimalRows--;
i--;
prevPrimalRowIds--;
}
}
}
LPColBase<R> compSlackCol(-1, slackColCoeff, R(infinity), 0.0);
_compSolver.changeCol(_compSlackColId, compSlackCol);
int* perm = 0;
spx_alloc(perm, _compSolver.nRows() + numElimRowsAdded);
_compSolver.removeRows(rowsforremoval, nrowsforremoval, perm);
int* currFixedVars = 0;
spx_alloc(currFixedVars, _realLP->nCols());
_identifyComplementaryPrimalFixedPrimalVars(currFixedVars);
_updateComplementaryPrimalFixedPrimalVars(currFixedVars);
spx_free(currFixedVars);
spx_free(perm);
spx_free(rowsforremoval);
}
template <class R>
void SoPlexBase<R>::_checkOriginalProblemOptimality(VectorBase<R> primalVector, bool printViol)
{
SSVectorBase<R> x(_solver.nCols());
x.unSetup();
_decompTransBasis.coSolve(x, primalVector);
if(printViol)
{
MSG_INFO1(spxout, spxout << std::endl
<< "Checking consistency between the reduced problem and the original problem." << std::endl);
}
R redObjVal = 0;
R objectiveVal = 0;
for(int i = 0; i < _solver.nCols(); i++)
{
redObjVal += _solver.maxObj(i) * primalVector[i];
objectiveVal += _realLP->maxObj(i) * x[i];
}
if(printViol)
{
MSG_INFO1(spxout, spxout << "Reduced Problem Objective Value: " << redObjVal << std::endl
<< "Original Problem Objective Value: " << objectiveVal << std::endl);
}
_solReal._isPrimalFeasible = true;
_hasSolReal = true;
_solReal._primal.reDim(_solver.nCols());
_solReal._primal = x;
R maxviol = 0;
R sumviol = 0;
if(getDecompBoundViolation(maxviol, sumviol))
{
if(printViol)
MSG_INFO1(spxout, spxout << "Bound violation - "
<< "Max violation: " << maxviol << " Sum violation: " << sumviol << std::endl);
}
_statistics->totalBoundViol = sumviol;
_statistics->maxBoundViol = maxviol;
if(getDecompRowViolation(maxviol, sumviol))
{
if(printViol)
MSG_INFO1(spxout, spxout << "Row violation - "
<< "Max violation: " << maxviol << " Sum violation: " << sumviol << std::endl);
}
_statistics->totalRowViol = sumviol;
_statistics->maxRowViol = maxviol;
if(printViol)
MSG_INFO1(spxout, spxout << std::endl);
}
template <class R>
void SoPlexBase<R>::_updateComplementaryDualSlackColCoeff()
{
for(int i = 0; i < _nPrimalRows; i++)
{
int rowNumber = _realLP->number(SPxRowId(_decompPrimalRowIDs[i]));
if(!_decompReducedProbRows[rowNumber])
{
if(_realLP->rowType(_decompPrimalRowIDs[i]) == LPRowBase<R>::EQUAL)
{
assert(_realLP->lhs(_decompPrimalRowIDs[i]) == _realLP->rhs(_decompPrimalRowIDs[i]));
_compSolver.changeLower(_decompDualColIDs[i],
0.0);
LPColBase<R> addEqualityCol(-_realLP->rhs(_decompPrimalRowIDs[i]),
R(-1.0)*_compSolver.colVector(_decompDualColIDs[i]), R(infinity),
0.0);
SPxColId newDualCol;
_compSolver.addCol(newDualCol, addEqualityCol);
_decompPrimalRowIDs.insert(i + 1, 1, _decompPrimalRowIDs[i]);
_decompDualColIDs.insert(i + 1, 1, newDualCol);
assert(_realLP->number(_decompPrimalRowIDs[i]) == _realLP->number(_decompPrimalRowIDs[i + 1]));
i++;
_nPrimalRows++;
_nDualCols++;
}
}
}
}
template <class R>
void SoPlexBase<R>::_identifyComplementaryDualFixedPrimalVars(int* currFixedVars)
{
R feastol = realParam(SoPlexBase<R>::FEASTOL);
int numFixedVar = 0;
for(int i = 0; i < _realLP->nCols(); i++)
{
currFixedVars[i] = 0;
if(!_decompReducedProbColRowIDs[i].isValid())
continue;
int rowNumber = _solver.number(_decompReducedProbColRowIDs[i]);
if(_decompReducedProbColRowIDs[i].isValid())
{
if(_solver.basis().desc().rowStatus(rowNumber) == SPxBasisBase<R>::Desc::P_ON_UPPER ||
_solver.basis().desc().rowStatus(rowNumber) == SPxBasisBase<R>::Desc::P_ON_LOWER ||
_solver.basis().desc().rowStatus(rowNumber) == SPxBasisBase<R>::Desc::P_FIXED ||
_solver.basis().desc().rowStatus(rowNumber) == SPxBasisBase<R>::Desc::D_FREE)
{
currFixedVars[i] = getOrigVarFixedDirection(i);
numFixedVar++;
}
else
{
if(_solver.basis().desc().rowStatus(rowNumber) == SPxBasisBase<R>::Desc::D_ON_LOWER &&
EQ(_solver.rhs(rowNumber) - _solver.pVec()[rowNumber], R(0.0), feastol))
currFixedVars[i] = 1;
else if(_solver.basis().desc().rowStatus(rowNumber) == SPxBasisBase<R>::Desc::D_ON_UPPER &&
EQ(_solver.pVec()[rowNumber] - _solver.lhs(rowNumber), R(0.0), feastol))
currFixedVars[i] = -1;
}
}
}
MSG_INFO3(spxout, spxout << "Number of fixed primal variables in the complementary (dual) problem: "
<< numFixedVar << std::endl);
}
template <class R>
void SoPlexBase<R>::_removeComplementaryDualFixedPrimalVars(int* currFixedVars)
{
SPxColId tempId;
int ncolsforremoval = 0;
int* colsforremoval = 0;
spx_alloc(colsforremoval, _realLP->nCols() * 2);
tempId.inValidate();
for(int i = 0; i < _realLP->nCols(); i++)
{
assert(_decompCompProbColIDsIdx[i] != -1);
if(_decompCompProbColIDsIdx[i] != -1
&& _fixedOrigVars[i] != -2) {
if(_fixedOrigVars[i] != 0)
{
assert(_compSolver.number(SPxColId(_decompFixedVarDualIDs[i])) >= 0);
assert(_fixedOrigVars[i] == -1 || _fixedOrigVars[i] == 1);
assert(_decompFixedVarDualIDs[i].isValid());
colsforremoval[ncolsforremoval] = _compSolver.number(SPxColId(_decompFixedVarDualIDs[i]));
ncolsforremoval++;
_decompFixedVarDualIDs[i] = tempId;
}
else {
assert((LE(_realLP->lower(i), R(-infinity)) && GE(_realLP->upper(i), R(infinity))) ||
_compSolver.number(SPxColId(_decompVarBoundDualIDs[i * 2])) >= 0);
int varcount = 0;
if(GT(_realLP->lower(i), R(-infinity)))
{
colsforremoval[ncolsforremoval] = _compSolver.number(SPxColId(_decompVarBoundDualIDs[i * 2 +
varcount]));
ncolsforremoval++;
_decompVarBoundDualIDs[i * 2 + varcount] = tempId;
varcount++;
}
if(LT(_realLP->upper(i), R(infinity)))
{
colsforremoval[ncolsforremoval] = _compSolver.number(SPxColId(_decompVarBoundDualIDs[i * 2 +
varcount]));
ncolsforremoval++;
_decompVarBoundDualIDs[i * 2 + varcount] = tempId;
}
}
}
}
int* perm = 0;
spx_alloc(perm, _compSolver.nCols());
_compSolver.removeCols(colsforremoval, ncolsforremoval, perm);
spx_free(perm);
spx_free(colsforremoval);
}
template <class R>
void SoPlexBase<R>::_updateComplementaryDualFixedPrimalVars(int* currFixedVars)
{
DSVectorBase<R> col(1);
LPColSetBase<R> boundConsCols;
LPColSetBase<R> fixedVarsDualCols(_nPrimalCols);
int numFixedVars = 0;
int numBoundConsCols = 0;
int* boundConsColsAdded = 0;
spx_alloc(boundConsColsAdded, _realLP->nCols());
for(int i = 0; i < _realLP->nCols(); i++)
{
boundConsColsAdded[i] = 0;
assert(_decompCompProbColIDsIdx[i] != -1);
if(_decompCompProbColIDsIdx[i] != -1)
{
int idIndex = _decompCompProbColIDsIdx[i];
assert(_compSolver.number(SPxRowId(_decompDualRowIDs[idIndex])) >= 0);
col.add(_compSolver.number(SPxRowId(_decompDualRowIDs[idIndex])), 1.0);
if(currFixedVars[i] != 0)
{
assert(currFixedVars[i] == -1 || currFixedVars[i] == 1);
assert(_realLP->lower(i) == _solver.lhs(_decompReducedProbColRowIDs[i]));
assert(_realLP->upper(i) == _solver.rhs(_decompReducedProbColRowIDs[i]));
R colObjCoeff = 0;
if(currFixedVars[i] == -1)
colObjCoeff = _solver.lhs(_decompReducedProbColRowIDs[i]);
else
colObjCoeff = _solver.rhs(_decompReducedProbColRowIDs[i]);
fixedVarsDualCols.add(colObjCoeff, R(-infinity), col, R(infinity));
numFixedVars++;
}
else {
bool isRedProbCol = _decompReducedProbColRowIDs[i].isValid();
if(GT(_realLP->lower(i), R(-infinity)))
{
if(!isRedProbCol)
col.add(_compSolver.number(SPxRowId(_compSlackDualRowId)), -SLACKCOEFF);
boundConsCols.add(_realLP->lower(i), R(-infinity), col, 0.0);
if(!isRedProbCol)
col.remove(col.size() - 1);
boundConsColsAdded[i]++;
numBoundConsCols++;
}
if(LT(_realLP->upper(i), R(infinity)))
{
if(!isRedProbCol)
col.add(_compSolver.number(SPxRowId(_compSlackDualRowId)), SLACKCOEFF);
boundConsCols.add(_realLP->upper(i), 0.0, col, R(infinity));
if(!isRedProbCol)
col.remove(col.size() - 1);
boundConsColsAdded[i]++;
numBoundConsCols++;
}
}
col.clear();
_fixedOrigVars[i] = currFixedVars[i];
}
}
SPxColId* addedcolids = 0;
spx_alloc(addedcolids, numFixedVars);
_compSolver.addCols(addedcolids, fixedVarsDualCols);
SPxColId tempId;
int addedcolcount = 0;
tempId.inValidate();
for(int i = 0; i < _realLP->nCols(); i++)
{
if(_fixedOrigVars[i] != 0)
{
assert(_fixedOrigVars[i] == -1 || _fixedOrigVars[i] == 1);
_decompFixedVarDualIDs[i] = addedcolids[addedcolcount];
addedcolcount++;
}
else
_decompFixedVarDualIDs[i] = tempId;
}
SPxColId* addedbndcolids = 0;
spx_alloc(addedbndcolids, numBoundConsCols);
_compSolver.addCols(addedbndcolids, boundConsCols);
addedcolcount = 0;
for(int i = 0; i < _realLP->nCols(); i++)
{
if(boundConsColsAdded[i] > 0)
{
for(int j = 0; j < boundConsColsAdded[i]; j++)
{
_decompVarBoundDualIDs[i * 2 + j] = addedbndcolids[addedcolcount];
addedcolcount++;
}
}
switch(boundConsColsAdded[i])
{
case 0:
_decompVarBoundDualIDs[i * 2] = tempId;
case 1:
_decompVarBoundDualIDs[i * 2 + 1] = tempId;
break;
}
}
spx_free(addedbndcolids);
spx_free(addedcolids);
spx_free(boundConsColsAdded);
}
template <class R>
void SoPlexBase<R>::_identifyComplementaryPrimalFixedPrimalVars(int* currFixedVars)
{
int numFixedVar = 0;
for(int i = 0; i < _realLP->nCols(); i++)
{
currFixedVars[i] = 0;
if(!_decompReducedProbColRowIDs[i].isValid())
continue;
int rowNumber = _solver.number(_decompReducedProbColRowIDs[i]);
if(_decompReducedProbColRowIDs[i].isValid() &&
(_solver.basis().desc().rowStatus(rowNumber) == SPxBasisBase<R>::Desc::P_ON_UPPER ||
_solver.basis().desc().rowStatus(rowNumber) == SPxBasisBase<R>::Desc::P_ON_LOWER ||
_solver.basis().desc().rowStatus(rowNumber) == SPxBasisBase<R>::Desc::P_FIXED))
{
currFixedVars[i] = getOrigVarFixedDirection(i);
numFixedVar++;
}
}
MSG_INFO3(spxout, spxout <<
"Number of fixed primal variables in the complementary (primal) problem: "
<< numFixedVar << std::endl);
}
template <class R>
void SoPlexBase<R>::_updateComplementaryPrimalFixedPrimalVars(int* currFixedVars)
{
int numFixedVars = 0;
for(int i = 0; i < _nCompPrimalCols; i++)
{
int colNumber = _compSolver.number(SPxColId(_decompCompPrimalColIDs[i]));
if(_fixedOrigVars[colNumber] != currFixedVars[colNumber])
{
if(currFixedVars[colNumber] != 0)
{
assert(currFixedVars[colNumber] == -1 || currFixedVars[colNumber] == 1);
if(currFixedVars[colNumber] == -1)
_compSolver.changeBounds(colNumber, _realLP->lower(SPxColId(_decompPrimalColIDs[i])),
_realLP->lower(SPxColId(_decompPrimalColIDs[i])));
else
_compSolver.changeBounds(colNumber, _realLP->upper(SPxColId(_decompPrimalColIDs[i])),
_realLP->upper(SPxColId(_decompPrimalColIDs[i])));
numFixedVars++;
}
else
{
_compSolver.changeBounds(colNumber, R(-infinity), R(infinity));
}
}
_fixedOrigVars[colNumber] = currFixedVars[colNumber];
}
}
template <class R>
void SoPlexBase<R>::_setComplementaryDualOriginalObjective()
{
for(int i = 0; i < _realLP->nCols(); i++)
{
assert(_decompCompProbColIDsIdx[i] != -1); int idIndex = _decompCompProbColIDsIdx[i];
int compRowNumber = _compSolver.number(_decompDualRowIDs[idIndex]);
if(_decompCompProbColIDsIdx[i] != -1)
{
if(LE(_realLP->lower(i), R(-infinity)) && GE(_realLP->upper(i), R(infinity)))
{
_compSolver.changeLhs(compRowNumber, _realLP->obj(i));
_compSolver.changeRhs(compRowNumber, _realLP->obj(i));
assert(LE(_compSolver.lhs(compRowNumber), _compSolver.rhs(compRowNumber)));
}
else if(LE(_realLP->lower(i), R(-infinity)))
{
_compSolver.changeRhs(compRowNumber, _realLP->obj(i));
if(isZero(_realLP->upper(i)))
_compSolver.changeLhs(compRowNumber, R(-infinity));
else
_compSolver.changeLhs(compRowNumber, _realLP->obj(i));
}
else if(GE(_realLP->upper(i), R(infinity)))
{
_compSolver.changeLhs(compRowNumber, _realLP->obj(i));
if(isZero(_realLP->upper(i)))
_compSolver.changeRhs(compRowNumber, R(infinity));
else
_compSolver.changeRhs(compRowNumber, _realLP->obj(i));
}
else if(NE(_realLP->lower(i), _realLP->upper(i)))
{
if(isZero(_realLP->upper(i)))
{
_compSolver.changeLhs(compRowNumber, _realLP->obj(i));
_compSolver.changeRhs(compRowNumber, R(infinity));
}
else if(isZero(_realLP->upper(i)))
{
_compSolver.changeLhs(compRowNumber, R(-infinity));
_compSolver.changeRhs(compRowNumber, _realLP->obj(i));
}
else
{
_compSolver.changeLhs(compRowNumber, _realLP->obj(i));
_compSolver.changeRhs(compRowNumber, _realLP->obj(i));
}
}
else
{
_compSolver.changeLhs(compRowNumber, _realLP->obj(i));
_compSolver.changeRhs(compRowNumber, _realLP->obj(i));
}
}
}
_compSolver.removeRow(_compSlackDualRowId);
}
template <class R>
void SoPlexBase<R>::_setComplementaryPrimalOriginalObjective()
{
assert(_realLP->nCols() == _compSolver.nCols() - 1);
for(int i = 0; i < _realLP->nCols(); i++)
{
int colNumber = _realLP->number(_decompPrimalColIDs[i]);
int compColNumber = _compSolver.number(_decompCompPrimalColIDs[i]);
_compSolver.changeObj(compColNumber, _realLP->maxObj(colNumber));
}
_compSolver.removeCol(_compSlackColId);
}
template <class R>
int SoPlexBase<R>::getOrigVarFixedDirection(int colNum)
{
if(!_decompReducedProbColRowIDs[colNum].isValid())
return 0;
int rowNumber = _solver.number(_decompReducedProbColRowIDs[colNum]);
if(_solver.basis().desc().rowStatus(rowNumber) == SPxBasisBase<R>::Desc::P_ON_UPPER ||
_solver.basis().desc().rowStatus(rowNumber) == SPxBasisBase<R>::Desc::P_FIXED ||
_solver.basis().desc().rowStatus(rowNumber) == SPxBasisBase<R>::Desc::D_FREE)
{
assert(_solver.rhs(rowNumber) < R(infinity));
return 1;
}
else if(_solver.basis().desc().rowStatus(rowNumber) == SPxBasisBase<R>::Desc::P_ON_LOWER)
{
assert(_solver.lhs(rowNumber) > R(-infinity));
return -1;
}
return 0;
}
template <class R>
void SoPlexBase<R>::_evaluateSolutionDecomp(SPxSolverBase<R>& solver, SLUFactor<R>& sluFactor,
typename SPxSimplifier<R>::Result result)
{
typename SPxSolverBase<R>::Status solverStat = SPxSolverBase<R>::UNKNOWN;
if(result == SPxSimplifier<R>::INFEASIBLE)
solverStat = SPxSolverBase<R>::INFEASIBLE;
else if(result == SPxSimplifier<R>::DUAL_INFEASIBLE)
solverStat = SPxSolverBase<R>::INForUNBD;
else if(result == SPxSimplifier<R>::UNBOUNDED)
solverStat = SPxSolverBase<R>::UNBOUNDED;
else if(result == SPxSimplifier<R>::VANISHED)
solverStat = SPxSolverBase<R>::OPTIMAL;
else if(result == SPxSimplifier<R>::OKAY)
solverStat = solver.status();
if(_currentProb == DECOMP_ORIG || _currentProb == DECOMP_RED)
_status = solverStat;
switch(solverStat)
{
case SPxSolverBase<R>::OPTIMAL:
if(!_isRealLPLoaded)
{
solver.changeObjOffset(realParam(SoPlexBase<R>::OBJ_OFFSET));
_decompResolveWithoutPreprocessing(solver, sluFactor, result);
return;
}
else
_hasBasis = true;
break;
case SPxSolverBase<R>::UNBOUNDED:
case SPxSolverBase<R>::INFEASIBLE:
case SPxSolverBase<R>::INForUNBD:
if(!_isRealLPLoaded)
{
solver.changeObjOffset(realParam(SoPlexBase<R>::OBJ_OFFSET));
_decompSimplifyAndSolve(solver, sluFactor, false, false);
return;
}
else
_hasBasis = (solver.basis().status() > SPxBasisBase<R>::NO_PROBLEM);
break;
case SPxSolverBase<R>::ABORT_DECOMP:
case SPxSolverBase<R>::ABORT_EXDECOMP:
if(!_isRealLPLoaded)
{
solver.changeObjOffset(realParam(SoPlexBase<R>::OBJ_OFFSET));
_decompResolveWithoutPreprocessing(solver, sluFactor, result);
return;
}
else
_hasBasis = (solver.basis().status() > SPxBasisBase<R>::NO_PROBLEM);
break;
case SPxSolverBase<R>::SINGULAR:
case SPxSolverBase<R>::ABORT_CYCLING:
if(!_isRealLPLoaded)
{
solver.changeObjOffset(realParam(SoPlexBase<R>::OBJ_OFFSET));
_decompSimplifyAndSolve(solver, sluFactor, false, false);
return;
}
break;
case SPxSolverBase<R>::ABORT_TIME:
case SPxSolverBase<R>::ABORT_ITER:
case SPxSolverBase<R>::ABORT_VALUE:
case SPxSolverBase<R>::REGULAR:
case SPxSolverBase<R>::RUNNING:
if(_simplifier == 0 && solver.basis().status() > SPxBasisBase<R>::NO_PROBLEM)
{
_basisStatusRows.reSize(_decompLP->nRows());
_basisStatusCols.reSize(_decompLP->nCols());
assert(_basisStatusRows.size() == solver.nRows());
assert(_basisStatusCols.size() == solver.nCols());
solver.getBasis(_basisStatusRows.get_ptr(), _basisStatusCols.get_ptr());
_hasBasis = true;
}
else
_hasBasis = false;
break;
default:
_hasBasis = false;
break;
}
}
template <class R>
bool SoPlexBase<R>::checkBasisDualFeasibility(VectorBase<R> feasVec)
{
assert(_solver.rep() == SPxSolverBase<R>::ROW);
assert(_solver.spxSense() == SPxLPBase<R>::MAXIMIZE);
R feastol = realParam(SoPlexBase<R>::FEASTOL);
for(int i = 0; i < _solver.nCols(); i++)
{
if(_solver.basis().baseId(i).isSPxRowId()) {
int rownumber = _solver.number(_solver.basis().baseId(i));
if(_solver.basis().desc().rowStatus(rownumber) != SPxBasisBase<R>::Desc::P_ON_UPPER &&
_solver.basis().desc().rowStatus(rownumber) != SPxBasisBase<R>::Desc::P_FIXED)
{
if(GT(feasVec[i], (R) 0, feastol))
return false;
}
if(_solver.basis().desc().rowStatus(rownumber) != SPxBasisBase<R>::Desc::P_ON_LOWER &&
_solver.basis().desc().rowStatus(rownumber) != SPxBasisBase<R>::Desc::P_FIXED)
{
if(LT(feasVec[i], (R) 0, feastol))
return false;
}
}
else if(_solver.basis().baseId(
i).isSPxColId()) {
int colnumber = _solver.number(_solver.basis().baseId(i));
if(_solver.basis().desc().colStatus(colnumber) != SPxBasisBase<R>::Desc::P_ON_UPPER &&
_solver.basis().desc().colStatus(colnumber) != SPxBasisBase<R>::Desc::P_FIXED)
{
if(GT(feasVec[i], (R) 0, feastol))
return false;
}
if(_solver.basis().desc().colStatus(colnumber) != SPxBasisBase<R>::Desc::P_ON_LOWER &&
_solver.basis().desc().colStatus(colnumber) != SPxBasisBase<R>::Desc::P_FIXED)
{
if(LT(feasVec[i], (R) 0, feastol))
return false;
}
}
}
return true;
}
template <class R>
typename SoPlexBase<R>::DualSign SoPlexBase<R>::getExpectedDualVariableSign(int rowNumber)
{
if(_solver.isRowBasic(rowNumber))
{
if(_solver.basis().desc().rowStatus(rowNumber) != SPxBasisBase<R>::Desc::P_ON_UPPER &&
_solver.basis().desc().rowStatus(rowNumber) != SPxBasisBase<R>::Desc::P_FIXED)
return SoPlexBase<R>::IS_NEG;
if(_solver.basis().desc().rowStatus(rowNumber) != SPxBasisBase<R>::Desc::P_ON_LOWER &&
_solver.basis().desc().rowStatus(rowNumber) != SPxBasisBase<R>::Desc::P_FIXED)
return SoPlexBase<R>::IS_POS;
}
return SoPlexBase<R>::IS_FREE;
}
template <class R>
typename SoPlexBase<R>::DualSign SoPlexBase<R>::getOrigProbDualVariableSign(int rowNumber)
{
if(_realLP->rowType(rowNumber) == LPRowBase<R>::LESS_EQUAL)
return IS_POS;
if(_realLP->rowType(rowNumber) == LPRowBase<R>::GREATER_EQUAL)
return IS_NEG;
if(_realLP->rowType(rowNumber) == LPRowBase<R>::EQUAL)
return IS_FREE;
if(_realLP->rowType(rowNumber) == LPRowBase<R>::RANGE)
return IS_FREE;
return IS_FREE;
}
template <class R>
void SoPlexBase<R>::printDecompDisplayLine(SPxSolverBase<R>& solver,
const SPxOut::Verbosity origVerb, bool force, bool forceHead)
{
const SPxOut::Verbosity currVerb = spxout.getVerbosity();
spxout.setVerbosity(origVerb);
int displayFreq = intParam(SoPlexBase<R>::DECOMP_DISPLAYFREQ);
MSG_INFO1(spxout,
if(forceHead || (_decompDisplayLine % (displayFreq * 30) == 0))
{
spxout << "type | time | iters | red iter | alg iter | rows | cols | shift | value\n";
}
if(force || (_decompDisplayLine % displayFreq == 0))
{
Real currentTime = _statistics->solvingTime->time();
(solver.type() == SPxSolverBase<R>::LEAVE) ? spxout << " L |" : spxout << " E |";
spxout << std::fixed << std::setw(7) << std::setprecision(1) << currentTime << " |";
spxout << std::scientific << std::setprecision(2);
spxout << std::setw(8) << _statistics->iterations << " | ";
spxout << std::scientific << std::setprecision(2);
spxout << std::setw(8) << _statistics->iterationsRedProb << " | ";
spxout << std::scientific << std::setprecision(2);
spxout << std::setw(8) << _statistics->callsReducedProb << " | ";
spxout << std::scientific << std::setprecision(2);
spxout << std::setw(8) << numIncludedRows << " | ";
spxout << std::scientific << std::setprecision(2);
spxout << std::setw(8) << solver.nCols() << " | "
<< solver.shift() << " | "
<< std::setprecision(8) << solver.value() + solver.objOffset()
<< std::endl;
}
_decompDisplayLine++;
);
spxout.setVerbosity(currVerb);
}
template <class R>
void SoPlexBase<R>::getOriginalProblemStatistics()
{
numProbRows = _realLP->nRows();
numProbCols = _realLP->nCols();
nNonzeros = _realLP->nNzos();
minAbsNonzero = _realLP->minAbsNzo();
maxAbsNonzero = _realLP->maxAbsNzo();
origCountLower = 0;
origCountUpper = 0;
origCountBoxed = 0;
origCountFreeCol = 0;
origCountLhs = 0;
origCountRhs = 0;
origCountRanged = 0;
origCountFreeRow = 0;
for(int i = 0; i < _realLP->nCols(); i++)
{
bool hasLower = false;
bool hasUpper = false;
if(_realLP->lower(i) > R(-infinity))
{
origCountLower++;
hasLower = true;
}
if(_realLP->upper(i) < R(infinity))
{
origCountUpper++;
hasUpper = true;
}
if(hasUpper && hasLower)
{
origCountBoxed++;
origCountUpper--;
origCountLower--;
}
if(!hasUpper && !hasLower)
origCountFreeCol++;
}
for(int i = 0; i < _realLP->nRows(); i++)
{
bool hasRhs = false;
bool hasLhs = false;
if(_realLP->lhs(i) > R(-infinity))
{
origCountLhs++;
hasLhs = true;
}
if(_realLP->rhs(i) < R(infinity))
{
origCountRhs++;
hasRhs = true;
}
if(hasRhs && hasLhs)
{
if(EQ(_realLP->rhs(i), _realLP->lhs(i)))
origCountEqual++;
else
origCountRanged++;
origCountLhs--;
origCountRhs--;
}
if(!hasRhs && !hasLhs)
origCountFreeRow++;
}
}
template <class R>
void SoPlexBase<R>::printOriginalProblemStatistics(std::ostream& os)
{
os << " Columns : " << numProbCols << "\n"
<< " boxed : " << origCountBoxed << "\n"
<< " lower bound : " << origCountLower << "\n"
<< " upper bound : " << origCountUpper << "\n"
<< " free : " << origCountFreeCol << "\n"
<< " Rows : " << numProbRows << "\n"
<< " equal : " << origCountEqual << "\n"
<< " ranged : " << origCountRanged << "\n"
<< " lhs : " << origCountLhs << "\n"
<< " rhs : " << origCountRhs << "\n"
<< " free : " << origCountFreeRow << "\n"
<< " Nonzeros : " << nNonzeros << "\n"
<< " per column : " << R(nNonzeros) / R(numProbCols) << "\n"
<< " per row : " << R(nNonzeros) / R(numProbRows) << "\n"
<< " sparsity : " << R(nNonzeros) / R(numProbCols) / R(numProbRows) << "\n"
<< " min. abs. value : " << R(minAbsNonzero) << "\n"
<< " max. abs. value : " << R(maxAbsNonzero) << "\n";
}
template <class R>
R SoPlexBase<R>::getCompSlackVarCoeff(int primalRowNum)
{
int indDir = 1;
switch(_realLP->rowType(_decompPrimalRowIDs[primalRowNum]))
{
case LPRowBase<R>::RANGE:
assert((primalRowNum < _nPrimalRows - 1
&& _realLP->number(SPxColId(_decompPrimalRowIDs[primalRowNum])) ==
_realLP->number(SPxColId(_decompPrimalRowIDs[primalRowNum + 1]))) ||
(primalRowNum > 0 && _realLP->number(SPxColId(_decompPrimalRowIDs[primalRowNum - 1])) ==
_realLP->number(SPxColId(_decompPrimalRowIDs[primalRowNum]))));
if(_realLP->number(SPxColId(_decompPrimalRowIDs[primalRowNum - 1])) ==
_realLP->number(SPxColId(_decompPrimalRowIDs[primalRowNum])))
indDir = -1;
if(_compSolver.obj(_compSolver.number(SPxColId(_decompDualColIDs[primalRowNum]))) <
_compSolver.obj(_compSolver.number(SPxColId(_decompDualColIDs[primalRowNum + indDir]))))
return -SLACKCOEFF;
else
return SLACKCOEFF;
break;
case LPRowBase<R>::GREATER_EQUAL:
return -SLACKCOEFF;
break;
case LPRowBase<R>::EQUAL:
assert((primalRowNum < _nPrimalRows - 1
&& _realLP->number(SPxColId(_decompPrimalRowIDs[primalRowNum])) ==
_realLP->number(SPxColId(_decompPrimalRowIDs[primalRowNum + 1]))) ||
(primalRowNum > 0 && _realLP->number(SPxColId(_decompPrimalRowIDs[primalRowNum - 1])) ==
_realLP->number(SPxColId(_decompPrimalRowIDs[primalRowNum]))));
case LPRowBase<R>::LESS_EQUAL:
return SLACKCOEFF;
break;
default:
throw SPxInternalCodeException("XDECOMPSL01 This should never happen.");
}
}
template <class R>
bool SoPlexBase<R>::getDecompBoundViolation(R& maxviol, R& sumviol)
{
R feastol = realParam(SoPlexBase<R>::FEASTOL);
VectorBase<R>& primal = _solReal._primal;
assert(primal.dim() == _realLP->nCols());
_nDecompViolBounds = 0;
maxviol = 0.0;
sumviol = 0.0;
bool isViol = false;
bool isMaxViol = false;
for(int i = _realLP->nCols() - 1; i >= 0; i--)
{
R currviol = 0.0;
R viol = _realLP->lower(i) - primal[i];
isViol = false;
isMaxViol = false;
if(viol > 0.0)
{
sumviol += viol;
if(viol > maxviol)
{
maxviol = viol;
isMaxViol = true;
}
if(currviol < viol)
currviol = viol;
}
if(GT(viol, R(0.0), feastol))
isViol = true;
viol = primal[i] - _realLP->upper(i);
if(viol > 0.0)
{
sumviol += viol;
if(viol > maxviol)
{
maxviol = viol;
isMaxViol = true;
}
if(currviol < viol)
currviol = viol;
}
if(GT(viol, R(0.0), feastol))
isViol = true;
if(isViol)
{
if(isMaxViol)
{
_decompViolatedBounds[_nDecompViolBounds] = _decompViolatedBounds[0];
_decompViolatedBounds[0] = i;
}
else
_decompViolatedBounds[_nDecompViolBounds] = i;
_nDecompViolBounds++;
}
}
return true;
}
template <class R>
bool SoPlexBase<R>::getDecompRowViolation(R& maxviol, R& sumviol)
{
R feastol = realParam(SoPlexBase<R>::FEASTOL);
VectorBase<R>& primal = _solReal._primal;
assert(primal.dim() == _realLP->nCols());
VectorBase<R> activity(_realLP->nRows());
_realLP->computePrimalActivity(primal, activity);
_nDecompViolRows = 0;
maxviol = 0.0;
sumviol = 0.0;
bool isViol = false;
bool isMaxViol = false;
for(int i = _realLP->nRows() - 1; i >= 0; i--)
{
R currviol = 0.0;
isViol = false;
isMaxViol = false;
R viol = _realLP->lhs(i) - activity[i];
if(viol > 0.0)
{
sumviol += viol;
if(viol > maxviol)
{
maxviol = viol;
isMaxViol = true;
}
if(viol > currviol)
currviol = viol;
}
if(GT(viol, R(0.0), feastol))
isViol = true;
viol = activity[i] - _realLP->rhs(i);
if(viol > 0.0)
{
sumviol += viol;
if(viol > maxviol)
{
maxviol = viol;
isMaxViol = true;
}
if(viol > currviol)
currviol = viol;
}
if(GT(viol, R(0.0), feastol))
isViol = true;
if(isViol)
{
if(isMaxViol)
{
_decompViolatedRows[_nDecompViolRows] = _decompViolatedRows[0];
_decompViolatedRows[0] = i;
}
else
_decompViolatedRows[_nDecompViolRows] = i;
_nDecompViolRows++;
}
}
return true;
}
template <class R>
bool SoPlexBase<R>::decompTerminate(R timeLimit)
{
R maxTime = timeLimit;
if(maxTime < 0 || maxTime >= R(infinity))
return false;
Real currentTime = _statistics->solvingTime->time();
if(currentTime >= maxTime)
{
MSG_INFO2(spxout, spxout << " --- timelimit (" << _solver.getMaxTime()
<< ") reached" << std::endl;)
_solver.setSolverStatus(SPxSolverBase<R>::ABORT_TIME);
return true;
}
return false;
}
template <class R>
void SoPlexBase<R>::getOriginalProblemBasisRowStatus(DataArray< int >& degenerateRowNums,
DataArray< typename SPxSolverBase<R>::VarStatus >& degenerateRowStatus, int& nDegenerateRows,
int& nNonBasicRows)
{
R feastol = realParam(SoPlexBase<R>::FEASTOL);
int basicRow = 0;
for(int i = 0; i < _nElimPrimalRows; i++)
{
int rowNumber = _realLP->number(_decompElimPrimalRowIDs[i]);
int solverRowNum = _solver.number(_decompReducedProbRowIDs[rowNumber]);
assert(solverRowNum >= 0 && solverRowNum < _solver.nRows());
if(_solver.basis().desc().rowStatus(solverRowNum) == SPxBasisBase<R>::Desc::P_ON_UPPER)
{
_basisStatusRows[rowNumber] = SPxSolverBase<R>::ON_UPPER;
}
else if(_solver.basis().desc().rowStatus(solverRowNum) == SPxBasisBase<R>::Desc::P_ON_LOWER)
{
_basisStatusRows[rowNumber] = SPxSolverBase<R>::ON_LOWER;
}
else if(_solver.basis().desc().rowStatus(solverRowNum) == SPxBasisBase<R>::Desc::P_FIXED)
{
_basisStatusRows[rowNumber] = SPxSolverBase<R>::FIXED;
}
else if(_solver.basis().desc().rowStatus(solverRowNum) == SPxBasisBase<R>::Desc::P_FREE)
{
_basisStatusRows[rowNumber] = SPxSolverBase<R>::ZERO;
}
else
{
_basisStatusRows[rowNumber] = SPxSolverBase<R>::BASIC;
basicRow++;
}
}
for(int i = 0; i < _nPrimalRows; i++)
{
int rowNumber = _realLP->number(_decompPrimalRowIDs[i]);
if(_decompReducedProbRows[rowNumber])
{
int solverRowNum = _solver.number(_decompReducedProbRowIDs[rowNumber]);
assert(solverRowNum >= 0 && solverRowNum < _solver.nRows());
if(_solver.basis().desc().rowStatus(solverRowNum) == SPxBasisBase<R>::Desc::P_ON_UPPER)
{
_basisStatusRows[rowNumber] = SPxSolverBase<R>::ON_UPPER;
}
else if(_solver.basis().desc().rowStatus(solverRowNum) == SPxBasisBase<R>::Desc::D_ON_LOWER &&
EQ(_solver.rhs(solverRowNum) - _solver.pVec()[solverRowNum], 0.0, feastol))
{
degenerateRowNums[nDegenerateRows] = rowNumber;
degenerateRowStatus[nDegenerateRows] = SPxSolverBase<R>::ON_UPPER;
nDegenerateRows++;
}
else if(_solver.basis().desc().rowStatus(solverRowNum) == SPxBasisBase<R>::Desc::P_ON_LOWER)
{
_basisStatusRows[rowNumber] = SPxSolverBase<R>::ON_LOWER;
}
else if(_solver.basis().desc().rowStatus(solverRowNum) == SPxBasisBase<R>::Desc::D_ON_UPPER &&
EQ(_solver.pVec()[solverRowNum] - _solver.lhs(solverRowNum), 0.0, feastol))
{
degenerateRowNums[nDegenerateRows] = rowNumber;
degenerateRowStatus[nDegenerateRows] = SPxSolverBase<R>::ON_LOWER;
nDegenerateRows++;
}
else if(_solver.basis().desc().rowStatus(solverRowNum) == SPxBasisBase<R>::Desc::P_FIXED)
{
_basisStatusRows[rowNumber] = SPxSolverBase<R>::FIXED;
}
else if(_solver.basis().desc().rowStatus(solverRowNum) == SPxBasisBase<R>::Desc::P_FREE)
{
_basisStatusRows[rowNumber] = SPxSolverBase<R>::ZERO;
}
else
{
_basisStatusRows[rowNumber] = SPxSolverBase<R>::BASIC;
basicRow++;
}
}
else
{
_basisStatusRows[rowNumber] = SPxSolverBase<R>::BASIC;
basicRow++;
switch(_realLP->rowType(_decompPrimalRowIDs[i]))
{
case LPRowBase<R>::RANGE:
i++;
break;
case LPRowBase<R>::EQUAL:
i++;
break;
case LPRowBase<R>::GREATER_EQUAL:
break;
case LPRowBase<R>::LESS_EQUAL:
break;
default:
throw SPxInternalCodeException("XDECOMPSL01 This should never happen.");
}
}
}
nNonBasicRows = _realLP->nRows() - basicRow - nDegenerateRows;
MSG_INFO2(spxout, spxout << "Number of non-basic rows: " << nNonBasicRows << " (from "
<< _realLP->nRows() << ")" << std::endl);
}
template <class R>
void SoPlexBase<R>::getOriginalProblemBasisColStatus(int& nNonBasicCols)
{
R feastol = realParam(SoPlexBase<R>::FEASTOL);
int basicCol = 0;
int numZeroDual = 0;
for(int i = 0; i < _realLP->nCols(); i++)
{
if(!_decompReducedProbColRowIDs[i].isValid())
continue;
int rowNumber = _solver.number(_decompReducedProbColRowIDs[i]);
if(_decompReducedProbColRowIDs[i].isValid())
{
if(_solver.basis().desc().rowStatus(rowNumber) == SPxBasisBase<R>::Desc::P_ON_UPPER)
{
_basisStatusCols[i] = SPxSolverBase<R>::ON_UPPER;
}
else if(_solver.basis().desc().rowStatus(rowNumber) == SPxBasisBase<R>::Desc::P_ON_LOWER)
{
_basisStatusCols[i] = SPxSolverBase<R>::ON_LOWER;
}
else if(_solver.basis().desc().rowStatus(rowNumber) == SPxBasisBase<R>::Desc::P_FIXED)
{
_basisStatusCols[i] = SPxSolverBase<R>::FIXED;
}
else if(_solver.basis().desc().rowStatus(rowNumber) == SPxBasisBase<R>::Desc::P_FREE)
{
_basisStatusCols[i] = SPxSolverBase<R>::ZERO;
}
else
{
_basisStatusCols[i] = SPxSolverBase<R>::BASIC;
basicCol++;
}
}
if(EQ(_solver.fVec()[i], 0.0, feastol))
numZeroDual++;
}
nNonBasicCols = _realLP->nCols() - basicCol;
MSG_INFO2(spxout, spxout << "Number of non-basic columns: "
<< nNonBasicCols << " (from " << _realLP->nCols() << ")" << std::endl
<< "Number of zero dual columns: " << numZeroDual << " (from " << _realLP->nCols() << ")" <<
std::endl);
}
template <class R>
void SoPlexBase<R>::_writeOriginalProblemBasis(const char* filename, NameSet* rowNames,
NameSet* colNames, bool cpxFormat)
{
int numrows = _realLP->nRows();
int numcols = _realLP->nCols();
int nNonBasicRows = 0;
int nNonBasicCols = 0;
int nDegenerateRows = 0;
DataArray< int > degenerateRowNums; DataArray< typename SPxSolverBase<R>::VarStatus >
degenerateRowStatus;
_basisStatusRows.reSize(numrows);
_basisStatusCols.reSize(numcols);
degenerateRowNums.reSize(numrows);
degenerateRowStatus.reSize(numrows);
getOriginalProblemBasisRowStatus(degenerateRowNums, degenerateRowStatus, nDegenerateRows,
nNonBasicRows);
getOriginalProblemBasisColStatus(nNonBasicCols);
assert(nDegenerateRows + nNonBasicRows + nNonBasicCols >= numcols);
int degenRowsSetNonBasic = 0;
for(int i = 0; i < nDegenerateRows; i++)
{
if(nNonBasicRows + nNonBasicCols + degenRowsSetNonBasic < numcols)
{
_basisStatusRows[degenerateRowNums[i]] = degenerateRowStatus[i];
degenRowsSetNonBasic++;
}
else
_basisStatusRows[degenerateRowNums[i]] = SPxSolverBase<R>::BASIC;
}
bool wasRealLPLoaded = _isRealLPLoaded;
_isRealLPLoaded = false;
writeBasisFile(filename, rowNames, colNames, cpxFormat);
_isRealLPLoaded = wasRealLPLoaded;
}
}