17 #ifndef SOPLEX_WITH_PAPILO 62 bool keepbounds, uint32_t seed)
140 const int colsSize = -1)
const 154 #include "papilo/core/Presolve.hpp" 155 #include "papilo/core/ProblemBuilder.hpp" 156 #include "papilo/Config.hpp" 176 const papilo::VerbosityLevel verbosityLevel = papilo::VerbosityLevel::kInfo;
178 const papilo::VerbosityLevel verbosityLevel = papilo::VerbosityLevel::kQuiet;
189 papilo::PostsolveStorage<R>
191 bool noChanges =
false;
194 bool vanished =
false;
233 m_keepbounds(
false), m_result(this->
OKAY)
238 :
SPxSimplifier<R>(old), m_prim(old.m_prim), m_slack(old.m_slack), m_dual(old.m_dual),
239 m_redCost(old.m_redCost), m_cBasisStat(old.m_cBasisStat), m_rBasisStat(old.m_rBasisStat),
240 postsolveStorage(old.postsolveStorage), postsolved(old.postsolved), m_epsilon(old.m_epsilon),
241 m_feastol(old.m_feastol), m_opttol(old.m_opttol),
242 modifyRowsFac(old.modifyRowsFac), m_thesense(old.m_thesense),
243 m_keepbounds(old.m_keepbounds), m_result(old.m_result)
255 m_slack = rhs.m_slack;
257 m_redCost = rhs.m_redCost;
258 m_cBasisStat = rhs.m_cBasisStat;
259 m_rBasisStat = rhs.m_rBasisStat;
260 postsolved = rhs.postsolved;
261 m_epsilon = rhs.m_epsilon;
262 m_feastol = rhs.m_feastol;
263 m_opttol = rhs.m_opttol;
264 m_thesense = rhs.m_thesense;
265 m_keepbounds = rhs.m_keepbounds;
266 m_result = rhs.m_result;
267 postsolveStorage = rhs.postsolveStorage;
268 modifyRowsFac = rhs.modifyRowsFac;
286 setModifyConsFrac(R value)
288 modifyRowsFac = value;
294 return simplify(lp, eps, delta, delta, remainingTime,
false, 0);
299 bool keepbounds, uint32_t seed);
351 return m_rBasisStat[i];
358 return m_cBasisStat[j];
364 const int colsSize = -1)
const 367 assert(rowsSize < 0 || rowsSize >= m_rBasisStat.
size());
368 assert(colsSize < 0 || colsSize >= m_cBasisStat.
size());
370 for(
int i = 0; i < m_rBasisStat.
size(); ++i)
371 rows[i] = m_rBasisStat[i];
373 for(
int j = 0; j < m_cBasisStat.
size(); ++j)
374 cols[j] = m_cBasisStat[j];
381 void configurePapilo(papilo::Presolve<R>& presolve, R feasTolerance, R epsilon, uint32_t seed,
382 Real remainingTime)
const;
384 void applyPresolveResultsToColumns(
SPxLPBase <R>& lp,
const papilo::Problem<R>& problem,
385 const papilo::PresolveResult<R>& res)
const;
387 void applyPresolveResultsToRows(
SPxLPBase <R>& lp,
const papilo::Problem<R>& problem,
388 const papilo::PresolveResult<R>& res)
const;
390 papilo::VarBasisStatus
394 convertToSoplexStatus(papilo::VarBasisStatus status)
const ;
406 <<
" --- unsimplifying solution and basis" 410 assert(x.
dim() <= m_prim.dim());
411 assert(y.
dim() <= m_dual.dim());
412 assert(x.
dim() == r.
dim());
413 assert(y.
dim() == s.
dim());
418 for(
int j = 0; j < x.
dim(); ++j)
422 m_cBasisStat[j] = cols[j];
425 for(
int i = 0; i < y.
dim(); ++i)
429 m_rBasisStat[i] = rows[i];
436 int nColsReduced = (int)postsolveStorage.origcol_mapping.
size();
437 int nRowsReduced = (int)postsolveStorage.origrow_mapping.size();
438 assert(x.
dim() == (int)postsolveStorage.origcol_mapping.size() || vanished);
439 assert(y.
dim() == (int)postsolveStorage.origrow_mapping.size() || vanished);
441 papilo::Solution<R> originalSolution{};
442 papilo::Solution<R> reducedSolution{};
443 reducedSolution.type = papilo::SolutionType::kPrimalDual;
444 reducedSolution.basisAvailabe =
true;
446 reducedSolution.primal.clear();
447 reducedSolution.reducedCosts.clear();
448 reducedSolution.varBasisStatus.clear();
449 reducedSolution.dual.clear();
450 reducedSolution.rowBasisStatus.clear();
452 reducedSolution.primal.resize(nColsReduced);
453 reducedSolution.reducedCosts.resize(nColsReduced);
454 reducedSolution.varBasisStatus.resize(nColsReduced);
455 reducedSolution.dual.resize(nRowsReduced);
456 reducedSolution.rowBasisStatus.resize(nRowsReduced);
465 for(
int j = 0; j < nColsReduced; ++j)
467 reducedSolution.primal[j] = isZero(x[j], this->epsZero()) ? 0.0 : x[j];
468 reducedSolution.reducedCosts[j] =
469 isZero(r[j], this->epsZero()) ? 0.0 : switch_sign * r[j];
470 reducedSolution.varBasisStatus[j] = convertToPapiloStatus(cols[j]);
473 for(
int i = 0; i < nRowsReduced; ++i)
475 reducedSolution.dual[i] = isZero(y[i], this->epsZero()) ? 0.0 : switch_sign * y[i];
476 reducedSolution.rowBasisStatus[i] = convertToPapiloStatus(rows[i]);
479 papilo::Num<R> num {};
480 num.setEpsilon(m_epsilon);
481 num.setFeasTol(m_feastol);
483 papilo::Message msg{};
484 msg.setVerbosityLevel(verbosityLevel);
486 papilo::Postsolve<R> postsolve {msg, num};
487 auto status = postsolve.undo(reducedSolution, originalSolution, postsolveStorage, isOptimal);
489 if(status == PostsolveStatus::kFailed && isOptimal)
491 MSG_ERROR(std::cerr <<
"PaPILO did not pass validation" << std::endl;)
495 for(
int j = 0; j < (int)postsolveStorage.nColsOriginal; ++j)
497 m_prim[j] = originalSolution.primal[j];
498 m_redCost[j] = switch_sign * originalSolution.reducedCosts[j];
499 m_cBasisStat[j] = convertToSoplexStatus(originalSolution.varBasisStatus[j]);
502 for(
int i = 0; i < (int)postsolveStorage.nRowsOriginal; ++i)
504 m_dual[i] = switch_sign * originalSolution.dual[i];
505 m_slack[i] = originalSolution.slack[i];
506 m_rBasisStat[i] = convertToSoplexStatus(originalSolution.rowBasisStatus[i]);
512 papilo::VarBasisStatus
518 return papilo::VarBasisStatus::ON_UPPER;
521 return papilo::VarBasisStatus::ON_LOWER;
524 return papilo::VarBasisStatus::FIXED;
527 return papilo::VarBasisStatus::BASIC;
530 return papilo::VarBasisStatus::UNDEFINED;
533 return papilo::VarBasisStatus::ZERO;
536 return papilo::VarBasisStatus::UNDEFINED;
545 case papilo::VarBasisStatus::ON_UPPER:
548 case papilo::VarBasisStatus::ON_LOWER:
551 case papilo::VarBasisStatus::ZERO:
554 case papilo::VarBasisStatus::FIXED:
557 case papilo::VarBasisStatus::UNDEFINED:
560 case papilo::VarBasisStatus::BASIC:
571 papilo::ProblemBuilder<R> builder;
574 int nnz = lp.
nNzos();
575 int ncols = lp.
nCols();
576 int nrows = lp.
nRows();
577 builder.reserve(nnz, nrows, ncols);
580 builder.setNumCols(ncols);
584 for(
int i = 0; i < ncols; ++i)
586 R lowerbound = lp.
lower(i);
587 R upperbound = lp.
upper(i);
588 R objective = lp.
obj(i);
589 builder.setColLb(i, lowerbound);
590 builder.setColUb(i, upperbound);
591 builder.setColLbInf(i, lowerbound <= -R(
infinity));
592 builder.setColUbInf(i, upperbound >= R(
infinity));
594 builder.setColIntegral(i,
false);
595 builder.setObj(i, objective * switch_sign);
599 builder.setNumRows(nrows);
601 for(
int i = 0; i < nrows; ++i)
604 int rowlength = rowVector.
size();
605 int* indices =
new int[rowlength];
606 R* rowValues =
new R[rowlength];
608 for(
int j = 0; j < rowlength; j++)
611 indices[j] = element.
idx;
612 rowValues[j] = element.
val;
615 builder.addRowEntries(i, rowlength, indices, rowValues);
619 builder.setRowLhs(i, lhs);
620 builder.setRowRhs(i, rhs);
621 builder.setRowLhsInf(i, lhs <= -R(
infinity));
622 builder.setRowRhsInf(i, rhs >= R(
infinity));
625 return builder.build();
632 Real remainingTime,
bool keepbounds, uint32_t seed)
636 m_keepbounds = keepbounds;
642 initLocalVariables(lp);
644 papilo::Problem<R> problem = buildProblem(lp);
645 papilo::Presolve<R> presolve;
647 configurePapilo(presolve, ftol, eps, seed, remainingTime);
649 <<
" --- starting PaPILO" << std::endl;
652 papilo::PresolveResult<R> res = presolve.apply(problem);
656 case papilo::PresolveStatus::kInfeasible:
659 <<
" --- presolving detected infeasibility" << std::endl;
663 case papilo::PresolveStatus::kUnbndOrInfeas:
664 case papilo::PresolveStatus::kUnbounded:
667 "==== Presolving detected unboundedness of the problem" << std::endl;
671 case papilo::PresolveStatus::kUnchanged:
675 <<
"==== Presolving found nothing " << std::endl;
679 case papilo::PresolveStatus::kReduced:
684 int newNonzeros = problem.getConstraintMatrix().getNnz();
686 if(newNonzeros == 0 || ((problem.getNRows() <= modifyRowsFac * lp.
nRows() ||
687 newNonzeros <= modifyRowsFac * lp.
nNzos())))
690 <<
" --- presolved problem has " << problem.getNRows() <<
692 << problem.getNCols() <<
" cols and " 693 << newNonzeros <<
" non-zeros and " 694 << presolve.getStatistics().nboundchgs <<
" boundchanges and " 695 << presolve.getStatistics().nsidechgs <<
" sidechanges" 698 postsolveStorage = res.postsolve;
701 for(
int j = lp.
nCols() - 1; j >= 0; j--)
704 for(
int i = lp.
nRows() - 1; i >= 0; i--)
707 applyPresolveResultsToColumns(lp, problem, res);
708 applyPresolveResultsToRows(lp, problem, res);
709 assert(newNonzeros == lp.
nNzos());
717 <<
" --- presolve results smaller than the modifyconsfac" 739 m_prim.reDim(lp.
nCols());
740 m_slack.reDim(lp.
nRows());
741 m_dual.reDim(lp.
nRows());
742 m_redCost.reDim(lp.
nCols());
743 m_cBasisStat.reSize(lp.
nCols());
744 m_rBasisStat.reSize(lp.
nRows());
752 uint32_t seed,
Real remainingTime)
const 757 presolve.getPresolveOptions().randomseed = (
unsigned int) seed;
763 presolve.getPresolveOptions().tlim = remainingTime;
764 presolve.getPresolveOptions().feastol = double(feasTolerance);
765 presolve.getPresolveOptions().epsilon = double(epsilon);
766 presolve.getPresolveOptions().detectlindep = 0;
767 presolve.getPresolveOptions().componentsmaxint = -1;
768 presolve.getPresolveOptions().calculate_basis_for_dual =
true;
770 presolve.setVerbosityLevel(verbosityLevel);
773 using uptr = std::unique_ptr<papilo::PresolveMethod<R>>;
776 presolve.addPresolveMethod(uptr(
new papilo::SingletonCols<R>()));
777 presolve.addPresolveMethod(uptr(
new papilo::ConstraintPropagation<R>()));
780 presolve.addPresolveMethod(uptr(
new papilo::ParallelRowDetection<R>()));
781 presolve.addPresolveMethod(uptr(
new papilo::ParallelColDetection<R>()));
782 presolve.addPresolveMethod(uptr(
new papilo::SingletonStuffing<R>()));
783 presolve.addPresolveMethod(uptr(
new papilo::DualFix<R>()));
784 presolve.addPresolveMethod(uptr(
new papilo::FixContinuous<R>()));
787 presolve.addPresolveMethod(uptr(
new papilo::DominatedCols<R>()));
806 const papilo::PresolveResult<R>& res)
const 809 const papilo::Objective<R>& objective = problem.getObjective();
810 const papilo::Vec<R>& upperBounds = problem.getUpperBounds();
811 const papilo::Vec<R>& lowerBounds = problem.getLowerBounds();
812 const papilo::Vec<papilo::ColFlags>& colFlags = problem.getColFlags();
816 for(
int col = 0; col < problem.getNCols(); col++)
819 R lb = lowerBounds[col];
821 if(colFlags[col].test(papilo::ColFlag::kLbInf))
824 R ub = upperBounds[col];
826 if(colFlags[col].test(papilo::ColFlag::kUbInf))
829 LPColBase<R> column(objective.coefficients[col]* switch_sign, emptyVector, ub, lb);
831 assert(lp.
lower(col) == lb);
832 assert(lp.
upper(col) == ub);
837 assert(problem.getNCols() == lp.
nCols());
842 const papilo::PresolveResult<R>& res)
const 844 int size = res.postsolve.origrow_mapping.size();
847 for(
int row = 0; row < size; row++)
849 R rhs = problem.getConstraintMatrix().getRightHandSides()[row];
851 if(problem.getRowFlags()[row].test(papilo::RowFlag::kRhsInf))
854 R lhs = problem.getConstraintMatrix().getLeftHandSides()[row];
856 if(problem.getRowFlags()[row].test(papilo::RowFlag::kLhsInf))
859 const papilo::SparseVectorView<R> papiloRowVector =
860 problem.getConstraintMatrix().getRowCoefficients(row);
861 const int* indices = papiloRowVector.getIndices();
862 const R* values = papiloRowVector.getValues();
864 int length = papiloRowVector.getLength();
867 for(
int i = 0; i < length; i++)
869 soplexRowVector.
add(indices[i], values[i]);
874 assert(lp.
lhs(row) == lhs);
875 assert(lp.
rhs(row) == rhs);
878 assert(problem.getNRows() == lp.
nRows());
const VectorBase< R > & rhs() const
Returns right hand side vector.
virtual void removeRow(int i)
Removes i 'th row.
Safe arrays of data objects.Class DataArray provides safe arrays of Data Objects. For general C++ obj...
Sparse vector nonzero element.
const VectorBase< R > & upper() const
Returns upper bound vector.
#define DEFAULT_BND_VIOL
default allowed bound violation
THREADLOCAL const Real infinity
Result
Result of the simplification.
virtual bool isUnsimplified() const
specifies whether an optimal solution has already been unsimplified.
Dense vector.Class VectorBase provides dense linear algebra vectors. Internally, VectorBase wraps std...
int size() const
Number of used indices.
Nonzero< R > & element(int n)
Reference to the n 'th nonzero element.
Sequential object-oriented SimPlex.SPxSolverBase is an LP solver class using the revised Simplex algo...
Exception classes for SoPlex.
Dynamic sparse vectors.Class DSVectorBase implements dynamic sparse vectors, i.e. SVectorBases with a...
Presol(Timer::TYPE ttype=Timer::USER_TIME)
virtual void removeCol(int i)
Removes i 'th column.
virtual SPxSimplifier< R >::Result simplify(SPxLPBase< R > &lp, R eps, R ftol, R otol, Real remainingTime, bool keepbounds, uint32_t seed)
int idx
Index of nonzero element.
LP simplification base class.
virtual ~Presol()
destructor.
virtual const VectorBase< R > & unsimplifiedRedCost()
returns a reference to the unsimplified reduced costs.
int nRows() const
Returns number of rows in LP.
void add(const SVectorBase< S > &vec)
Append nonzeros of sv.
virtual void start()=0
start timer, resume accounting user, system and real time.
virtual void unsimplify(const VectorBase< R > &, const VectorBase< R > &, const VectorBase< R > &, const VectorBase< R > &, const typename SPxSolverBase< R >::VarStatus[], const typename SPxSolverBase< R >::VarStatus[], bool isOptimal)
simplification could be done
int nNzos() const
Returns number of nonzeros in LP.
Timer * m_timeUsed
user time used for simplification
SPxSimplifier & operator=(const SPxSimplifier &rhs)
assignment operator
SPxSense
Optimization sense.
virtual SPxSimplifier< R >::Result simplify(SPxLPBase< R > &lp, R eps, R delta, Real remainingTime)
SPxSense spxSense() const
Returns the optimization sense.
Presol(const Presol &old)
copy constructor.
LP simplification abstract base class.Instances of classes derived from SPxSimplifier may be loaded t...
#define MSG_ERROR(x)
Prints out message x if the verbosity level is at least SPxOut::ERROR.
int size() const
Returns number of elements.
#define DEFAULT_EPS_ZERO
default allowed additive zero: 1.0 + EPS_ZERO == 1.0
R obj(int i) const
Returns objective value of column i.
const VectorBase< R > & lhs() const
Returns left hand side vector.
SPxSimplifier< R > * clone() const
virtual SPxSolverBase< R >::VarStatus getBasisColStatus(int j) const
gets basis status for a single column.
(In)equality for LPs.Class LPRowBase provides constraints for linear programs in the form where a is...
Debugging, floating point type and parameter definitions.
virtual void addCol(const LPColBase< R > &col, bool scale=false)
int dim() const
Dimension of vector.
virtual const VectorBase< R > & unsimplifiedSlacks()
returns a reference to the unsimplified slack values.
virtual const VectorBase< R > & unsimplifiedDual()
returns a reference to the unsimplified dual solution.
Everything should be within this namespace.
Saving LPs in a form suitable for SoPlex.Class SPxLPBase provides the data structures required for sa...
#define MSG_WARNING(spxout, x)
Prints out message x if the verbosity level is at least SPxOut::WARNING.
Presol & operator=(const Presol &rhs)
assignment operator
Save arrays of arbitrary types.
void changeObjOffset(const T &o)
const SVectorBase< R > & rowVector(int i) const
Gets row vector of row i.
virtual void addRow(const LPRowBase< R > &row, bool scale=false)
int size() const
return nr. of elements.
R val
Value of nonzero element.
#define MSG_INFO1(spxout, x)
Prints out message x if the verbosity level is at least SPxOut::INFO1.
int nCols() const
Returns number of columns in LP.
virtual SPxSimplifier< R >::Result result() const
returns result status of the simplification
Sparse vectors.Class SVectorBase provides packed sparse vectors. Such are a sparse vectors...
virtual SPxSolverBase< R >::VarStatus getBasisRowStatus(int i) const
gets basis status for a single row.
virtual void reset()=0
initialize timer, set timing accounts to zero.
SPxOut * spxout
message handler
virtual const VectorBase< R > & unsimplifiedPrimal()
returns a reference to the unsimplified primal solution.
const VectorBase< R > & lower() const
Returns (internal and possibly scaled) lower bound vector.
LP column.Class LPColBase provides a datatype for storing the column of an LP a the form similar to ...
virtual void getBasis(typename SPxSolverBase< R >::VarStatus rows[], typename SPxSolverBase< R >::VarStatus cols[], const int rowsSize=-1, const int colsSize=-1) const
get optimal basis.