#include <assert.h>
#include "soplex/spxdefines.h"
#include "soplex/spxratiotester.h"
#include "soplex/spxpricer.h"
#include "soplex/spxout.h"
#include "soplex/exceptions.h"
namespace soplex
{
template <class R>
R SPxSolverBase<R>::test(int i, typename SPxBasisBase<R>::Desc::Status stat) const
{
assert(type() == ENTER);
assert(!isBasic(stat));
R x;
switch(stat)
{
case SPxBasisBase<R>::Desc::D_FREE:
case SPxBasisBase<R>::Desc::D_ON_BOTH:
assert(rep() == ROW);
x = (*thePvec)[i] - this->lhs(i);
if(x < 0)
return x;
case SPxBasisBase<R>::Desc::D_ON_LOWER:
assert(rep() == ROW);
return this->rhs(i) - (*thePvec)[i];
case SPxBasisBase<R>::Desc::D_ON_UPPER:
assert(rep() == ROW);
return (*thePvec)[i] - this->lhs(i);
case SPxBasisBase<R>::Desc::P_ON_UPPER:
assert(rep() == COLUMN);
return this->maxObj(i) - (*thePvec)[i];
case SPxBasisBase<R>::Desc::P_ON_LOWER:
assert(rep() == COLUMN);
return (*thePvec)[i] - this->maxObj(i);
case SPxBasisBase<R>::Desc::P_FREE :
x = this->maxObj(i) - (*thePvec)[i];
return (x < 0) ? x : -x;
default:
return 0;
}
}
template <class R>
void SPxSolverBase<R>::computeTest()
{
const typename SPxBasisBase<R>::Desc& ds = this->desc();
R pricingTol = leavetol();
m_pricingViolCoUpToDate = true;
m_pricingViolCo = 0;
infeasibilitiesCo.clear();
int sparsitythreshold = (int)(sparsePricingFactor * coDim());
for(int i = 0; i < coDim(); ++i)
{
typename SPxBasisBase<R>::Desc::Status stat = ds.status(i);
if(isBasic(stat))
{
theTest[i] = 0.0;
if(remainingRoundsEnterCo == 0)
isInfeasibleCo[i] = SPxPricer<R>::NOT_VIOLATED;
}
else
{
assert(!isBasic(stat));
theTest[i] = test(i, stat);
if(remainingRoundsEnterCo == 0)
{
if(theTest[i] < -pricingTol)
{
assert(infeasibilitiesCo.size() < infeasibilitiesCo.max());
m_pricingViolCo -= theTest[i];
infeasibilitiesCo.addIdx(i);
isInfeasibleCo[i] = SPxPricer<R>::VIOLATED;
++m_numViol;
}
else
isInfeasibleCo[i] = SPxPricer<R>::NOT_VIOLATED;
if(infeasibilitiesCo.size() > sparsitythreshold)
{
MSG_INFO2((*this->spxout), (*this->spxout) << " --- using dense pricing"
<< std::endl;)
remainingRoundsEnterCo = DENSEROUNDS;
sparsePricingEnterCo = false;
infeasibilitiesCo.clear();
}
}
else if(theTest[i] < -pricingTol)
{
m_pricingViolCo -= theTest[i];
++m_numViol;
}
}
}
if(infeasibilitiesCo.size() == 0 && !sparsePricingEnterCo)
--remainingRoundsEnterCo;
else if(infeasibilitiesCo.size() <= sparsitythreshold && !sparsePricingEnterCo)
{
MSG_INFO2((*this->spxout),
std::streamsize prec = spxout->precision();
if(hyperPricingEnter)
(*this->spxout) << " --- using hypersparse pricing, ";
else
(*this->spxout) << " --- using sparse pricing, ";
(*this->spxout) << "sparsity: "
<< std::setw(6) << std::fixed << std::setprecision(4)
<< (R) infeasibilitiesCo.size() / coDim()
<< std::scientific << std::setprecision(int(prec))
<< std::endl;
)
sparsePricingEnterCo = true;
}
}
template <class R>
R SPxSolverBase<R>::computePvec(int i)
{
return (*thePvec)[i] = vector(i) * (*theCoPvec);
}
template <class R>
R SPxSolverBase<R>::computeTest(int i)
{
typename SPxBasisBase<R>::Desc::Status stat = this->desc().status(i);
if(isBasic(stat))
return theTest[i] = 0;
else
return theTest[i] = test(i, stat);
}
template <class R>
R SPxSolverBase<R>::coTest(int i, typename SPxBasisBase<R>::Desc::Status stat) const
{
assert(type() == ENTER);
assert(!isBasic(stat));
R x;
switch(stat)
{
case SPxBasisBase<R>::Desc::D_FREE:
case SPxBasisBase<R>::Desc::D_ON_BOTH :
assert(rep() == ROW);
x = (*theCoPvec)[i] - SPxLPBase<R>::lower(i);
if(x < 0)
return x;
case SPxBasisBase<R>::Desc::D_ON_LOWER:
assert(rep() == ROW);
return SPxLPBase<R>::upper(i) - (*theCoPvec)[i];
case SPxBasisBase<R>::Desc::D_ON_UPPER:
assert(rep() == ROW);
return (*theCoPvec)[i] - SPxLPBase<R>::lower(i);
case SPxBasisBase<R>::Desc::P_ON_UPPER:
assert(rep() == COLUMN);
return (*theCoPvec)[i] - this->maxRowObj(i);
case SPxBasisBase<R>::Desc::P_ON_LOWER:
assert(rep() == COLUMN);
return this->maxRowObj(i) - (*theCoPvec)[i];
default:
return 0;
}
}
template <class R>
void SPxSolverBase<R>::computeCoTest()
{
int i;
R pricingTol = leavetol();
m_pricingViolUpToDate = true;
m_pricingViol = 0;
m_numViol = 0;
infeasibilities.clear();
int sparsitythreshold = (int)(sparsePricingFactor * dim());
const typename SPxBasisBase<R>::Desc& ds = this->desc();
for(i = dim() - 1; i >= 0; --i)
{
typename SPxBasisBase<R>::Desc::Status stat = ds.coStatus(i);
if(isBasic(stat))
{
theCoTest[i] = 0;
if(remainingRoundsEnter == 0)
isInfeasible[i] = SPxPricer<R>::NOT_VIOLATED;
}
else
{
theCoTest[i] = coTest(i, stat);
if(remainingRoundsEnter == 0)
{
if(theCoTest[i] < -pricingTol)
{
assert(infeasibilities.size() < infeasibilities.max());
m_pricingViol -= theCoTest[i];
infeasibilities.addIdx(i);
isInfeasible[i] = SPxPricer<R>::VIOLATED;
++m_numViol;
}
else
isInfeasible[i] = SPxPricer<R>::NOT_VIOLATED;
if(infeasibilities.size() > sparsitythreshold)
{
MSG_INFO2((*this->spxout), (*this->spxout) << " --- using dense pricing"
<< std::endl;)
remainingRoundsEnter = DENSEROUNDS;
sparsePricingEnter = false;
infeasibilities.clear();
}
}
else if(theCoTest[i] < -pricingTol)
{
m_pricingViol -= theCoTest[i];
++m_numViol;
}
}
}
if(infeasibilities.size() == 0 && !sparsePricingEnter)
--remainingRoundsEnter;
else if(infeasibilities.size() <= sparsitythreshold && !sparsePricingEnter)
{
MSG_INFO2((*this->spxout),
std::streamsize prec = spxout->precision();
if(hyperPricingEnter)
(*this->spxout) << " --- using hypersparse pricing, ";
else
(*this->spxout) << " --- using sparse pricing, ";
(*this->spxout) << "sparsity: "
<< std::setw(6) << std::fixed << std::setprecision(4)
<< (R) infeasibilities.size() / dim()
<< std::scientific << std::setprecision(int(prec))
<< std::endl;
)
sparsePricingEnter = true;
}
}
template <class R>
void SPxSolverBase<R>::updateTest()
{
thePvec->delta().setup();
const IdxSet& idx = thePvec->idx();
const typename SPxBasisBase<R>::Desc& ds = this->desc();
R pricingTol = leavetol();
int i;
updateViolsCo.clear();
for(i = idx.size() - 1; i >= 0; --i)
{
int j = idx.index(i);
typename SPxBasisBase<R>::Desc::Status stat = ds.status(j);
if(!isBasic(stat))
{
if(m_pricingViolCoUpToDate && theTest[j] < -pricingTol)
m_pricingViolCo += theTest[j];
theTest[j] = test(j, stat);
if(sparsePricingEnterCo)
{
if(theTest[j] < -pricingTol)
{
assert(remainingRoundsEnterCo == 0);
m_pricingViolCo -= theTest[j];
if(isInfeasibleCo[j] == SPxPricer<R>::NOT_VIOLATED)
{
infeasibilitiesCo.addIdx(j);
isInfeasibleCo[j] = SPxPricer<R>::VIOLATED;
}
if(hyperPricingEnter)
updateViolsCo.addIdx(j);
}
else
{
isInfeasibleCo[j] = SPxPricer<R>::NOT_VIOLATED;
}
}
else if(theTest[j] < -pricingTol)
m_pricingViolCo -= theTest[j];
}
else
{
isInfeasibleCo[j] = SPxPricer<R>::NOT_VIOLATED;
theTest[j] = 0;
}
}
}
template <class R>
void SPxSolverBase<R>::updateCoTest()
{
theCoPvec->delta().setup();
const IdxSet& idx = theCoPvec->idx();
const typename SPxBasisBase<R>::Desc& ds = this->desc();
R pricingTol = leavetol();
int i;
updateViols.clear();
for(i = idx.size() - 1; i >= 0; --i)
{
int j = idx.index(i);
typename SPxBasisBase<R>::Desc::Status stat = ds.coStatus(j);
if(!isBasic(stat))
{
if(m_pricingViolUpToDate && theCoTest[j] < -pricingTol)
m_pricingViol += theCoTest[j];
theCoTest[j] = coTest(j, stat);
if(sparsePricingEnter)
{
if(theCoTest[j] < -pricingTol)
{
assert(remainingRoundsEnter == 0);
m_pricingViol -= theCoTest[j];
if(isInfeasible[j] == SPxPricer<R>::NOT_VIOLATED)
{
infeasibilities.addIdx(j);
isInfeasible[j] = SPxPricer<R>::VIOLATED;
}
if(hyperPricingEnter)
updateViols.addIdx(j);
}
else
{
isInfeasible[j] = SPxPricer<R>::NOT_VIOLATED;
}
}
else if(theCoTest[j] < -pricingTol)
m_pricingViol -= theCoTest[j];
}
else
{
isInfeasible[j] = SPxPricer<R>::NOT_VIOLATED;
theCoTest[j] = 0;
}
}
}
template <class R>
void SPxSolverBase<R>::getEnterVals
(
SPxId enterId,
R& enterTest,
R& enterUB,
R& enterLB,
R& enterVal,
R& enterMax,
R& enterPric,
typename SPxBasisBase<R>::Desc::Status& enterStat,
R& enterRO,
StableSum<R>& objChange
)
{
int enterIdx;
typename SPxBasisBase<R>::Desc& ds = this->desc();
if(enterId.isSPxColId())
{
enterIdx = this->number(SPxColId(enterId));
enterStat = ds.colStatus(enterIdx);
assert(!isBasic(enterStat));
if(rep() == COLUMN)
{
computePvec(enterIdx);
enterTest = computeTest(enterIdx);
theTest[enterIdx] = 0;
}
else
{
enterTest = coTest()[enterIdx];
theCoTest[enterIdx] = 0;
}
switch(enterStat)
{
case SPxBasisBase<R>::Desc::P_ON_UPPER :
assert(rep() == COLUMN);
enterUB = theUCbound[enterIdx];
enterLB = theLCbound[enterIdx];
enterVal = enterUB;
enterMax = enterLB - enterUB;
enterPric = (*thePvec)[enterIdx];
enterRO = this->maxObj(enterIdx);
objChange -= enterVal * enterRO;
if(enterLB <= R(-infinity))
ds.colStatus(enterIdx) = SPxBasisBase<R>::Desc::D_ON_LOWER;
else if(EQ(enterLB, enterUB))
ds.colStatus(enterIdx) = SPxBasisBase<R>::Desc::D_FREE;
else
ds.colStatus(enterIdx) = SPxBasisBase<R>::Desc::D_ON_BOTH;
break;
case SPxBasisBase<R>::Desc::P_ON_LOWER :
assert(rep() == COLUMN);
enterUB = theUCbound[enterIdx];
enterLB = theLCbound[enterIdx];
enterVal = enterLB;
enterMax = enterUB - enterLB;
enterPric = (*thePvec)[enterIdx];
enterRO = this->maxObj(enterIdx);
objChange -= enterVal * enterRO;
if(enterUB >= R(infinity))
ds.colStatus(enterIdx) = SPxBasisBase<R>::Desc::D_ON_UPPER;
else if(EQ(enterLB, enterUB))
ds.colStatus(enterIdx) = SPxBasisBase<R>::Desc::D_FREE;
else
ds.colStatus(enterIdx) = SPxBasisBase<R>::Desc::D_ON_BOTH;
break;
case SPxBasisBase<R>::Desc::P_FREE :
assert(rep() == COLUMN);
enterUB = theUCbound[enterIdx];
enterLB = theLCbound[enterIdx];
enterVal = 0;
enterPric = (*thePvec)[enterIdx];
enterRO = this->maxObj(enterIdx);
ds.colStatus(enterIdx) = SPxBasisBase<R>::Desc::D_UNDEFINED;
enterMax = (enterRO - enterPric > 0) ? R(infinity) : R(-infinity);
break;
case SPxBasisBase<R>::Desc::D_ON_UPPER :
assert(rep() == ROW);
assert(theUCbound[enterIdx] < R(infinity));
enterUB = theUCbound[enterIdx];
enterLB = R(-infinity);
enterMax = R(-infinity);
enterVal = enterUB;
enterPric = (*theCoPvec)[enterIdx];
enterRO = SPxLPBase<R>::lower(enterIdx);
objChange -= enterRO * enterVal;
ds.colStatus(enterIdx) = SPxBasisBase<R>::Desc::P_ON_LOWER;
break;
case SPxBasisBase<R>::Desc::D_ON_LOWER :
assert(rep() == ROW);
assert(theLCbound[enterIdx] > R(-infinity));
enterLB = theLCbound[enterIdx];
enterUB = R(infinity);
enterMax = R(infinity);
enterVal = enterLB;
enterPric = (*theCoPvec)[enterIdx];
enterRO = SPxLPBase<R>::upper(enterIdx);
objChange -= enterRO * enterVal;
ds.colStatus(enterIdx) = SPxBasisBase<R>::Desc::P_ON_UPPER;
break;
case SPxBasisBase<R>::Desc::D_FREE:
assert(rep() == ROW);
assert(SPxLPBase<R>::lower(enterIdx) == SPxLPBase<R>::upper(enterIdx));
enterUB = R(infinity);
enterLB = R(-infinity);
enterVal = 0;
enterRO = SPxLPBase<R>::upper(enterIdx);
enterPric = (*theCoPvec)[enterIdx];
if(enterPric > enterRO)
enterMax = R(infinity);
else
enterMax = R(-infinity);
ds.colStatus(enterIdx) = SPxBasisBase<R>::Desc::P_FIXED;
break;
case SPxBasisBase<R>::Desc::D_ON_BOTH :
assert(rep() == ROW);
enterPric = (*theCoPvec)[enterIdx];
if(enterPric > SPxLPBase<R>::upper(enterIdx))
{
enterLB = theLCbound[enterIdx];
enterUB = R(infinity);
enterMax = R(infinity);
enterVal = enterLB;
enterRO = SPxLPBase<R>::upper(enterIdx);
ds.colStatus(enterIdx) = SPxBasisBase<R>::Desc::P_ON_UPPER;
}
else
{
enterUB = theUCbound[enterIdx];
enterVal = enterUB;
enterRO = SPxLPBase<R>::lower(enterIdx);
enterLB = R(-infinity);
enterMax = R(-infinity);
ds.colStatus(enterIdx) = SPxBasisBase<R>::Desc::P_ON_LOWER;
}
objChange -= theLCbound[enterIdx] * SPxLPBase<R>::upper(enterIdx);
objChange -= theUCbound[enterIdx] * SPxLPBase<R>::lower(enterIdx);
break;
default:
throw SPxInternalCodeException("XENTER01 This should never happen.");
}
MSG_DEBUG(std::cout << "DENTER03 SPxSolverBase::getEnterVals() : col " << enterIdx
<< ": " << enterStat
<< " -> " << ds.colStatus(enterIdx)
<< " objChange: " << objChange
<< std::endl;)
}
else
{
assert(enterId.isSPxRowId());
enterIdx = this->number(SPxRowId(enterId));
enterStat = ds.rowStatus(enterIdx);
assert(!isBasic(enterStat));
if(rep() == ROW)
{
computePvec(enterIdx);
enterTest = computeTest(enterIdx);
theTest[enterIdx] = 0;
}
else
{
enterTest = coTest()[enterIdx];
theCoTest[enterIdx] = 0;
}
switch(enterStat)
{
case SPxBasisBase<R>::Desc::P_ON_UPPER :
assert(rep() == COLUMN);
enterUB = theURbound[enterIdx];
enterLB = theLRbound[enterIdx];
enterVal = enterLB;
enterMax = enterUB - enterLB;
enterPric = (*theCoPvec)[enterIdx];
enterRO = this->maxRowObj(enterIdx);
objChange -= enterRO * enterVal;
if(enterUB >= R(infinity))
ds.rowStatus(enterIdx) = SPxBasisBase<R>::Desc::D_ON_LOWER;
else if(EQ(enterLB, enterUB))
ds.rowStatus(enterIdx) = SPxBasisBase<R>::Desc::D_FREE;
else
ds.rowStatus(enterIdx) = SPxBasisBase<R>::Desc::D_ON_BOTH;
break;
case SPxBasisBase<R>::Desc::P_ON_LOWER :
assert(rep() == COLUMN);
enterUB = theURbound[enterIdx];
enterLB = theLRbound[enterIdx];
enterVal = enterUB;
enterMax = enterLB - enterUB;
enterPric = (*theCoPvec)[enterIdx];
enterRO = this->maxRowObj(enterIdx);
objChange -= enterRO * enterVal;
if(enterLB <= R(-infinity))
ds.rowStatus(enterIdx) = SPxBasisBase<R>::Desc::D_ON_UPPER;
else if(EQ(enterLB, enterUB))
ds.rowStatus(enterIdx) = SPxBasisBase<R>::Desc::D_FREE;
else
ds.rowStatus(enterIdx) = SPxBasisBase<R>::Desc::D_ON_BOTH;
break;
case SPxBasisBase<R>::Desc::P_FREE :
assert(rep() == COLUMN);
#if 1
throw SPxInternalCodeException("XENTER02 This should never happen.");
#else#endif
break;
case SPxBasisBase<R>::Desc::D_ON_UPPER :
assert(rep() == ROW);
assert(theURbound[enterIdx] < R(infinity));
enterUB = theURbound[enterIdx];
enterLB = R(-infinity);
enterVal = enterUB;
enterMax = R(-infinity);
enterPric = (*thePvec)[enterIdx];
enterRO = this->lhs(enterIdx);
objChange -= enterRO * enterVal;
ds.rowStatus(enterIdx) = SPxBasisBase<R>::Desc::P_ON_LOWER;
break;
case SPxBasisBase<R>::Desc::D_ON_LOWER :
assert(rep() == ROW);
assert(theLRbound[enterIdx] > R(-infinity));
enterLB = theLRbound[enterIdx];
enterUB = R(infinity);
enterVal = enterLB;
enterMax = R(infinity);
enterPric = (*thePvec)[enterIdx];
enterRO = this->rhs(enterIdx);
objChange -= enterRO * enterVal;
ds.rowStatus(enterIdx) = SPxBasisBase<R>::Desc::P_ON_UPPER;
break;
case SPxBasisBase<R>::Desc::D_FREE:
assert(rep() == ROW);
assert(this->rhs(enterIdx) == this->lhs(enterIdx));
enterUB = R(infinity);
enterLB = R(-infinity);
enterVal = 0;
enterPric = (*thePvec)[enterIdx];
enterRO = this->rhs(enterIdx);
enterMax = (enterPric > enterRO) ? R(infinity) : R(-infinity);
ds.rowStatus(enterIdx) = SPxBasisBase<R>::Desc::P_FIXED;
break;
case SPxBasisBase<R>::Desc::D_ON_BOTH :
assert(rep() == ROW);
enterPric = (*thePvec)[enterIdx];
if(enterPric > this->rhs(enterIdx))
{
enterLB = theLRbound[enterIdx];
enterVal = enterLB;
enterUB = R(infinity);
enterMax = R(infinity);
enterRO = this->rhs(enterIdx);
ds.rowStatus(enterIdx) = SPxBasisBase<R>::Desc::P_ON_UPPER;
}
else
{
enterUB = theURbound[enterIdx];
enterVal = enterUB;
enterLB = R(-infinity);
enterMax = R(-infinity);
enterRO = this->lhs(enterIdx);
ds.rowStatus(enterIdx) = SPxBasisBase<R>::Desc::P_ON_LOWER;
}
objChange -= theLRbound[enterIdx] * this->rhs(enterIdx);
objChange -= theURbound[enterIdx] * this->lhs(enterIdx);
break;
default:
throw SPxInternalCodeException("XENTER03 This should never happen.");
}
MSG_DEBUG(std::cout << "DENTER05 SPxSolverBase::getEnterVals() : row "
<< enterIdx << ": " << enterStat
<< " -> " << ds.rowStatus(enterIdx)
<< " objChange: " << objChange
<< std::endl;)
}
}
template <class R>
void SPxSolverBase<R>::getEnterVals2
(
int leaveIdx,
R enterMax,
R& leavebound,
StableSum<R>& objChange
)
{
int idx;
typename SPxBasisBase<R>::Desc& ds = this->desc();
SPxId leftId = this->baseId(leaveIdx);
if(leftId.isSPxRowId())
{
idx = this->number(SPxRowId(leftId));
typename SPxBasisBase<R>::Desc::Status leaveStat = ds.rowStatus(idx);
switch(leaveStat)
{
case SPxBasisBase<R>::Desc::P_FIXED :
assert(rep() == ROW);
throw SPxInternalCodeException("XENTER04 This should never happen.");
break;
case SPxBasisBase<R>::Desc::P_ON_UPPER :
assert(rep() == ROW);
leavebound = theLBbound[leaveIdx];
theLRbound[idx] = leavebound;
ds.rowStatus(idx) = this->dualRowStatus(idx);
switch(ds.rowStatus(idx))
{
case SPxBasisBase<R>::Desc::D_ON_UPPER :
objChange += theURbound[idx] * this->lhs(idx);
break;
case SPxBasisBase<R>::Desc::D_ON_LOWER :
objChange += theLRbound[idx] * this->rhs(idx);
break;
case SPxBasisBase<R>::Desc::D_ON_BOTH :
objChange += theURbound[idx] * this->lhs(idx);
objChange += theLRbound[idx] * this->rhs(idx);
break;
default:
break;
}
break;
case SPxBasisBase<R>::Desc::P_ON_LOWER :
assert(rep() == ROW);
leavebound = theUBbound[leaveIdx];
theURbound[idx] = leavebound;
ds.rowStatus(idx) = this->dualRowStatus(idx);
switch(ds.rowStatus(idx))
{
case SPxBasisBase<R>::Desc::D_ON_UPPER :
objChange += theURbound[idx] * this->lhs(idx);
break;
case SPxBasisBase<R>::Desc::D_ON_LOWER :
objChange += theLRbound[idx] * this->rhs(idx);
break;
case SPxBasisBase<R>::Desc::D_ON_BOTH :
objChange += theURbound[idx] * this->lhs(idx);
objChange += theLRbound[idx] * this->rhs(idx);
break;
default:
break;
}
break;
case SPxBasisBase<R>::Desc::P_FREE :
assert(rep() == ROW);
#if 1
throw SPxInternalCodeException("XENTER05 This should never happen.");
#else#endif
break;
case SPxBasisBase<R>::Desc::D_UNDEFINED :
assert(rep() == COLUMN);
throw SPxInternalCodeException("XENTER06 This should never happen.");
break;
case SPxBasisBase<R>::Desc::D_FREE :
assert(rep() == COLUMN);
if(theFvec->delta()[leaveIdx] * enterMax < 0)
leavebound = theUBbound[leaveIdx];
else
leavebound = theLBbound[leaveIdx];
theLRbound[idx] = leavebound;
theURbound[idx] = leavebound;
objChange += leavebound * this->maxRowObj(leaveIdx);
ds.rowStatus(idx) = SPxBasisBase<R>::Desc::P_FIXED;
break;
case SPxBasisBase<R>::Desc::D_ON_UPPER :
assert(rep() == COLUMN);
leavebound = theUBbound[leaveIdx];
theURbound[idx] = leavebound;
objChange += leavebound * this->maxRowObj(leaveIdx);
ds.rowStatus(idx) = SPxBasisBase<R>::Desc::P_ON_LOWER;
break;
case SPxBasisBase<R>::Desc::D_ON_LOWER :
assert(rep() == COLUMN);
leavebound = theLBbound[leaveIdx];
theLRbound[idx] = leavebound;
objChange += leavebound * this->maxRowObj(leaveIdx);
ds.rowStatus(idx) = SPxBasisBase<R>::Desc::P_ON_UPPER;
break;
case SPxBasisBase<R>::Desc::D_ON_BOTH :
assert(rep() == COLUMN);
if(enterMax * theFvec->delta()[leaveIdx] < 0)
{
leavebound = theUBbound[leaveIdx];
theURbound[idx] = leavebound;
objChange += leavebound * this->maxRowObj(leaveIdx);
ds.rowStatus(idx) = SPxBasisBase<R>::Desc::P_ON_LOWER;
}
else
{
leavebound = theLBbound[leaveIdx];
theLRbound[idx] = leavebound;
objChange += leavebound * this->maxRowObj(leaveIdx);
ds.rowStatus(idx) = SPxBasisBase<R>::Desc::P_ON_UPPER;
}
break;
default:
throw SPxInternalCodeException("XENTER07 This should never happen.");
}
MSG_DEBUG(std::cout << "DENTER06 SPxSolverBase::getEnterVals2(): row "
<< idx << ": " << leaveStat
<< " -> " << ds.rowStatus(idx)
<< " objChange: " << objChange
<< std::endl;)
}
else
{
assert(leftId.isSPxColId());
idx = this->number(SPxColId(leftId));
typename SPxBasisBase<R>::Desc::Status leaveStat = ds.colStatus(idx);
switch(leaveStat)
{
case SPxBasisBase<R>::Desc::P_ON_UPPER :
assert(rep() == ROW);
leavebound = theLBbound[leaveIdx];
theLCbound[idx] = leavebound;
ds.colStatus(idx) = this->dualColStatus(idx);
switch(ds.colStatus(idx))
{
case SPxBasisBase<R>::Desc::D_ON_UPPER :
objChange += theUCbound[idx] * this->lower(idx);
break;
case SPxBasisBase<R>::Desc::D_ON_LOWER :
objChange += theLCbound[idx] * this->upper(idx);
break;
case SPxBasisBase<R>::Desc::D_ON_BOTH :
objChange += theLCbound[idx] * this->upper(idx);
objChange += theUCbound[idx] * this->lower(idx);
break;
default:
break;
}
break;
case SPxBasisBase<R>::Desc::P_ON_LOWER :
assert(rep() == ROW);
leavebound = theUBbound[leaveIdx];
theUCbound[idx] = leavebound;
ds.colStatus(idx) = this->dualColStatus(idx);
switch(ds.colStatus(idx))
{
case SPxBasisBase<R>::Desc::D_ON_UPPER :
objChange += theUCbound[idx] * this->lower(idx);
break;
case SPxBasisBase<R>::Desc::D_ON_LOWER :
objChange += theLCbound[idx] * this->upper(idx);
break;
case SPxBasisBase<R>::Desc::D_ON_BOTH :
objChange += theLCbound[idx] * this->upper(idx);
objChange += theUCbound[idx] * this->lower(idx);
break;
default:
break;
}
break;
case SPxBasisBase<R>::Desc::P_FREE :
assert(rep() == ROW);
if(theFvec->delta()[leaveIdx] * enterMax > 0)
{
leavebound = theLBbound[leaveIdx];
theLCbound[idx] = leavebound;
}
else
{
leavebound = theUBbound[leaveIdx];
theUCbound[idx] = leavebound;
}
ds.colStatus(idx) = SPxBasisBase<R>::Desc::D_UNDEFINED;
break;
case SPxBasisBase<R>::Desc::P_FIXED:
assert(rep() == ROW);
throw SPxInternalCodeException("XENTER08 This should never happen.");
break;
case SPxBasisBase<R>::Desc::D_FREE :
assert(rep() == COLUMN);
if(theFvec->delta()[leaveIdx] * enterMax > 0)
leavebound = theLBbound[leaveIdx];
else
leavebound = theUBbound[leaveIdx];
theUCbound[idx] =
theLCbound[idx] = leavebound;
objChange += this->maxObj(idx) * leavebound;
ds.colStatus(idx) = SPxBasisBase<R>::Desc::P_FIXED;
break;
case SPxBasisBase<R>::Desc::D_ON_UPPER :
assert(rep() == COLUMN);
leavebound = theLBbound[leaveIdx];
theLCbound[idx] = leavebound;
objChange += this->maxObj(idx) * leavebound;
ds.colStatus(idx) = SPxBasisBase<R>::Desc::P_ON_LOWER;
break;
case SPxBasisBase<R>::Desc::D_ON_LOWER :
assert(rep() == COLUMN);
leavebound = theUBbound[leaveIdx];
theUCbound[idx] = leavebound;
objChange += this->maxObj(idx) * leavebound;
ds.colStatus(idx) = SPxBasisBase<R>::Desc::P_ON_UPPER;
break;
case SPxBasisBase<R>::Desc::D_ON_BOTH :
case SPxBasisBase<R>::Desc::D_UNDEFINED :
assert(rep() == COLUMN);
if(enterMax * theFvec->delta()[leaveIdx] < 0)
{
leavebound = theUBbound[leaveIdx];
theUCbound[idx] = leavebound;
objChange += this->maxObj(idx) * leavebound;
ds.colStatus(idx) = SPxBasisBase<R>::Desc::P_ON_UPPER;
}
else
{
leavebound = theLBbound[leaveIdx];
theLCbound[idx] = leavebound;
objChange += this->maxObj(idx) * leavebound;
ds.colStatus(idx) = SPxBasisBase<R>::Desc::P_ON_LOWER;
}
break;
default:
throw SPxInternalCodeException("XENTER09 This should never happen.");
}
MSG_DEBUG(std::cout << "DENTER07 SPxSolverBase::getEnterVals2(): col "
<< idx << ": " << leaveStat
<< " -> " << ds.colStatus(idx)
<< " objChange: " << objChange
<< std::endl;)
}
}
template <class R>
void
SPxSolverBase<R>::ungetEnterVal(
SPxId enterId,
typename SPxBasisBase<R>::Desc::Status enterStat,
R leaveVal,
const SVectorBase<R>& vec,
StableSum<R>& objChange
)
{
assert(rep() == COLUMN);
int enterIdx;
typename SPxBasisBase<R>::Desc& ds = this->desc();
if(enterId.isSPxColId())
{
enterIdx = this->number(SPxColId(enterId));
if(enterStat == SPxBasisBase<R>::Desc::P_ON_UPPER)
{
ds.colStatus(enterIdx) = SPxBasisBase<R>::Desc::P_ON_LOWER;
objChange += theLCbound[enterIdx] * this->maxObj(enterIdx);
}
else
{
ds.colStatus(enterIdx) = SPxBasisBase<R>::Desc::P_ON_UPPER;
objChange += theUCbound[enterIdx] * this->maxObj(enterIdx);
}
theFrhs->multAdd(leaveVal, vec);
}
else
{
enterIdx = this->number(SPxRowId(enterId));
assert(enterId.isSPxRowId());
if(enterStat == SPxBasisBase<R>::Desc::P_ON_UPPER)
{
ds.rowStatus(enterIdx) = SPxBasisBase<R>::Desc::P_ON_LOWER;
objChange += (theURbound[enterIdx]) * this->maxRowObj(enterIdx);
}
else
{
ds.rowStatus(enterIdx) = SPxBasisBase<R>::Desc::P_ON_UPPER;
objChange += (theLRbound[enterIdx]) * this->maxRowObj(enterIdx);
}
(*theFrhs)[enterIdx] += leaveVal;
}
if(isId(enterId))
{
theTest[enterIdx] = 0;
isInfeasibleCo[enterIdx] = SPxPricer<R>::NOT_VIOLATED;
}
else
{
theCoTest[enterIdx] = 0;
isInfeasible[enterIdx] = SPxPricer<R>::NOT_VIOLATED;
}
}
template <class R>
void SPxSolverBase<R>::rejectEnter(
SPxId enterId,
R enterTest,
typename SPxBasisBase<R>::Desc::Status enterStat
)
{
int enterIdx = this->number(enterId);
if(isId(enterId))
{
theTest[enterIdx] = enterTest;
this->desc().status(enterIdx) = enterStat;
}
else
{
theCoTest[enterIdx] = enterTest;
this->desc().coStatus(enterIdx) = enterStat;
}
}
template <class R>
void SPxSolverBase<R>::computePrimalray4Col(R direction, SPxId enterId)
{
R sign = (direction > 0 ? 1.0 : -1.0);
primalRay.clear();
primalRay.setMax(fVec().delta().size() + 1);
for(int j = 0; j < fVec().delta().size(); ++j)
{
SPxId i = this->baseId(fVec().idx().index(j));
if(i.isSPxColId())
primalRay.add(this->number(SPxColId(i)), sign * fVec().delta().value(j));
}
if(enterId.isSPxColId())
primalRay.add(this->number(SPxColId(enterId)), -sign);
}
template <class R>
void SPxSolverBase<R>::computeDualfarkas4Row(R direction, SPxId enterId)
{
R sign = (direction > 0 ? -1.0 : 1.0);
dualFarkas.clear();
dualFarkas.setMax(fVec().delta().size() + 1);
for(int j = 0; j < fVec().delta().size(); ++j)
{
SPxId spxid = this->baseId(fVec().idx().index(j));
if(spxid.isSPxRowId())
dualFarkas.add(this->number(SPxRowId(spxid)), sign * fVec().delta().value(j));
}
if(enterId.isSPxRowId())
dualFarkas.add(this->number(SPxRowId(enterId)), -sign);
}
template <class R>
bool SPxSolverBase<R>::enter(SPxId& enterId, bool polish)
{
assert(enterId.isValid());
assert(type() == ENTER);
assert(initialized);
SPxId none; R enterTest; R enterUB; R enterLB; R enterVal; R enterMax; R enterPric; typename SPxBasisBase<R>::Desc::Status enterStat; R enterRO; StableSum<R> objChange;
const SVectorBase<R>* enterVec = enterVector(enterId);
bool instable = instableEnter;
assert(!instable || instableEnterId.isValid());
getEnterVals(enterId, enterTest, enterUB, enterLB,
enterVal, enterMax, enterPric, enterStat, enterRO, objChange);
if(!polish && enterTest > -epsilon())
{
rejectEnter(enterId, enterTest, enterStat);
this->change(-1, none, 0);
MSG_DEBUG(std::cout << "DENTER08 rejecting false enter pivot" << std::endl;)
return false;
}
if(theFvec->delta().isSetup() && theFvec->delta().size() == 0)
SPxBasisBase<R>::solve4update(theFvec->delta(), *enterVec);
#ifdef ENABLE_ADDITIONAL_CHECKS
else
{
VectorBase<R> tmp(dim());
tmp = reinterpret_cast<VectorBase<R>&>(theFvec->delta());
this->multBaseWith(tmp);
tmp -= *enterVec;
if(tmp.length() > entertol())
{
MSG_INFO2((*this->spxout), (*this->spxout) << "WENTER09 fVec updated error = "
<< tmp.length() << std::endl;)
}
}
#endif
if(!polish && m_numCycle > m_maxCycle)
{
if(-enterMax > 0)
perturbMaxEnter();
else
perturbMinEnter();
}
R leaveVal = -enterMax;
boundflips = 0;
int leaveIdx = theratiotester->selectLeave(leaveVal, enterTest, polish);
assert(leaveIdx < 0 || !this->baseId(leaveIdx).isSPxColId()
|| this->desc().colStatus(this->number(SPxColId(this->baseId(leaveIdx)))) !=
SPxBasisBase<R>::Desc::P_FIXED);
assert(leaveIdx < 0 || !this->baseId(leaveIdx).isSPxRowId()
|| this->desc().rowStatus(this->number(SPxRowId(this->baseId(leaveIdx)))) !=
SPxBasisBase<R>::Desc::P_FIXED);
instableEnterVal = 0;
instableEnterId = SPxId();
instableEnter = false;
if(leaveIdx >= 0)
{
if(spxAbs(leaveVal) < entertol())
{
if(NE(theUBbound[leaveIdx], theLBbound[leaveIdx])
&& enterStat != SPxBasisBase<R>::Desc::P_FREE && enterStat != SPxBasisBase<R>::Desc::D_FREE)
{
m_numCycle++;
enterCycles++;
}
}
else
m_numCycle /= 2;
if(coSolveVector3 && coSolveVector2)
{
assert(coSolveVector2->isConsistent());
assert(coSolveVector2rhs->isSetup());
assert(coSolveVector3->isConsistent());
assert(coSolveVector3rhs->isSetup());
assert(boundflips > 0);
SPxBasisBase<R>::coSolve(theCoPvec->delta(), *coSolveVector2, *coSolveVector3
, unitVecs[leaveIdx], *coSolveVector2rhs, *coSolveVector3rhs);
(*theCoPvec) -= (*coSolveVector3);
}
else if(coSolveVector3)
{
assert(coSolveVector3->isConsistent());
assert(coSolveVector3rhs->isSetup());
assert(boundflips > 0);
SPxBasisBase<R>::coSolve(theCoPvec->delta(), *coSolveVector3, unitVecs[leaveIdx],
*coSolveVector3rhs);
(*theCoPvec) -= (*coSolveVector3);
}
else if(coSolveVector2)
SPxBasisBase<R>::coSolve(theCoPvec->delta(), *coSolveVector2, unitVecs[leaveIdx],
*coSolveVector2rhs);
else
SPxBasisBase<R>::coSolve(theCoPvec->delta(), unitVecs[leaveIdx]);
if(boundflips > 0)
{
for(int i = coSolveVector3->dim() - 1; i >= 0; --i)
{
if(spxAbs((*coSolveVector3)[i]) > epsilon())
(*thePvec).multAdd(-(*coSolveVector3)[i], (*thecovectors)[i]);
}
if(enterId.isSPxColId())
enterPric = (*theCoPvec)[this->number(SPxColId(enterId))];
else
enterPric = (*thePvec)[this->number(SPxRowId(enterId))];
MSG_DEBUG(std::cout << "IEBFRT02 breakpoints passed / bounds flipped = " << boundflips << std::endl;
)
totalboundflips += boundflips;
}
(*theCoPrhs)[leaveIdx] = enterRO;
theCoPvec->value() = (enterRO - enterPric) / theFvec->delta()[leaveIdx];
if(theCoPvec->value() > epsilon() || theCoPvec->value() < -epsilon())
{
if(pricing() == FULL)
{
thePvec->value() = theCoPvec->value();
setupPupdate();
}
doPupdate();
}
assert(thePvec->isConsistent());
assert(theCoPvec->isConsistent());
assert(!this->baseId(leaveIdx).isSPxRowId()
|| this->desc().rowStatus(this->number(SPxRowId(this->baseId(leaveIdx)))) !=
SPxBasisBase<R>::Desc::P_FIXED);
assert(!this->baseId(leaveIdx).isSPxColId()
|| this->desc().colStatus(this->number(SPxColId(this->baseId(leaveIdx)))) !=
SPxBasisBase<R>::Desc::P_FIXED);
R leavebound;
try
{
getEnterVals2(leaveIdx, enterMax, leavebound, objChange);
}
catch(const SPxException& F)
{
rejectEnter(enterId, enterTest, enterStat);
this->change(-1, none, 0);
throw F;
}
theUBbound[leaveIdx] = enterUB;
theLBbound[leaveIdx] = enterLB;
updateCoTest();
if(pricing() == FULL)
updateTest();
theFvec->value() = leaveVal;
theFvec->update();
(*theFvec)[leaveIdx] = enterVal - leaveVal;
if(leavebound > epsilon() || leavebound < -epsilon())
theFrhs->multAdd(-leavebound, this->baseVec(leaveIdx));
if(enterVal > epsilon() || enterVal < -epsilon())
theFrhs->multAdd(enterVal, *enterVec);
updateNonbasicValue(objChange);
this->change(leaveIdx, enterId, enterVec, &(theFvec->delta()));
return true;
}
else if(NE(leaveVal, -enterMax))
{
if(!instable)
{
instableEnterId = enterId;
instableEnterVal = enterTest;
MSG_DEBUG(std::cout << "DENTER09 rejecting enter pivot and looking for others" << std::endl;)
rejectEnter(enterId, enterTest / 10.0, enterStat);
this->change(-1, none, 0);
}
else
{
MSG_DEBUG(std::cout << "DENTER10 rejecting enter pivot in instable state, resetting values" <<
std::endl;)
rejectEnter(enterId, enterTest, enterStat);
this->change(-1, none, 0);
}
return false;
}
else if(!polish && leaveVal < R(infinity) && leaveVal > R(-infinity))
{
assert(rep() == COLUMN);
assert(EQ(leaveVal, -enterMax));
this->change(-1, enterId, enterVec);
theFvec->value() = leaveVal;
theFvec->update();
ungetEnterVal(enterId, enterStat, leaveVal, *enterVec, objChange);
updateNonbasicValue(objChange);
MSG_DEBUG(std::cout << "DENTER11 moving entering variable from one bound to the other" << std::endl;
)
return false;
}
else
{
rejectEnter(enterId, enterTest, enterStat);
this->change(-1, none, 0);
if(polish)
return false;
else if(this->lastUpdate() > 1)
{
MSG_INFO3((*this->spxout), (*this->spxout) << "IENTER01 factorization triggered in "
<< "enter() for feasibility test" << std::endl;)
try
{
factorize();
}
catch(const SPxStatusException& E)
{
assert(SPxBasisBase<R>::status() == SPxBasisBase<R>::SINGULAR);
MSG_INFO3((*this->spxout), (*this->spxout) << "Caught exception in factorization: " << E.what() <<
std::endl;)
}
return false;
}
else if(spxAbs(enterTest) < entertol())
{
MSG_INFO3((*this->spxout), (*this->spxout) << "IENTER11 clean up step to reduce numerical errors" <<
std::endl;)
SPxBasisBase<R>::coSolve(*theCoPvec, *theCoPrhs);
computePvec();
computeCoTest();
computeTest();
return false;
}
MSG_INFO3((*this->spxout), (*this->spxout) << "IENTER02 unboundedness/infeasibility found in "
<< "enter()" << std::endl;)
if(rep() == ROW)
{
computeDualfarkas4Row(leaveVal, enterId);
setBasisStatus(SPxBasisBase<R>::INFEASIBLE);
}
else
{
computePrimalray4Col(leaveVal, enterId);
setBasisStatus(SPxBasisBase<R>::UNBOUNDED);
}
return false;
}
}
}