Scippy

SoPlex

Sequential object-oriented simPlex

spxpapilo.h
Go to the documentation of this file.
1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2 /* */
3 /* This file is part of the class library */
4 /* SoPlex --- the Sequential object-oriented simPlex. */
5 /* */
6 /* Copyright (C) 1996-2022 Konrad-Zuse-Zentrum */
7 /* fuer Informationstechnik Berlin */
8 /* */
9 /* SoPlex is distributed under the terms of the ZIB Academic Licence. */
10 /* */
11 /* You should have received a copy of the ZIB Academic License */
12 /* along with SoPlex; see the file COPYING. If not email to soplex@zib.de. */
13 /* */
14 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
15 
16 
17 #ifndef SOPLEX_WITH_PAPILO
18 
19 namespace soplex
20 {
21 
22 template <class R> class Presol : public SPxSimplifier<R>
23 {
24 
25 public:
26 
27  //------------------------------------
28  ///@name Constructors / destructors
29  ///@{
30  /// default constructor.
31  explicit Presol(Timer::TYPE ttype = Timer::USER_TIME) : SPxSimplifier<R>("PaPILO", ttype)
32  { ; };
33 
34  /// copy constructor.
35  Presol(const Presol& old) : SPxSimplifier<R>(old) { ; }
36 
37  /// assignment operator
38  Presol& operator=(const Presol& rhs)
39  {
40  return *this;
41  }
42 
43  /// destructor.
44  virtual ~Presol()
45  {
46  ;
47  }
48 
50  {
51  return new Presol(*this);
52  }
53 
54  virtual typename SPxSimplifier<R>::Result simplify(SPxLPBase<R>& lp, R eps, R delta,
55  Real remainingTime)
56  {
58  }
59 
60  virtual typename SPxSimplifier<R>::Result simplify(SPxLPBase<R>& lp, R eps, R ftol, R otol,
61  Real remainingTime,
62  bool keepbounds, uint32_t seed)
63  {
64  assert(false);
66  };
67 
68  virtual void unsimplify(const VectorBase<R>&, const VectorBase<R>&,
69  const VectorBase<R>&, const VectorBase<R>&,
70  const typename SPxSolverBase<R>::VarStatus[],
71  const typename SPxSolverBase<R>::VarStatus[],
72  bool isOptimal)
73  {
74  assert(false);
75  };
76 
77  /// returns result status of the simplification
78  virtual typename SPxSimplifier<R>::Result result() const
79  {
80  assert(false);
82  }
83 
84  /// specifies whether an optimal solution has already been unsimplified.
85  virtual bool isUnsimplified() const
86  {
87  assert(false);
88  return false;
89  }
90 
91  /// returns a reference to the unsimplified primal solution.
93  {
94  assert(false);
95  static const VectorBase<R>& emptyVector = VectorBase<R>();
96  return emptyVector;
97  }
98 
99  /// returns a reference to the unsimplified dual solution.
101  {
102  assert(false);
103  static const VectorBase<R>& emptyVector = VectorBase<R>();
104  return emptyVector;
105  }
106 
107  /// returns a reference to the unsimplified slack values.
109  {
110  assert(false);
111  static const VectorBase<R>& emptyVector = VectorBase<R>();
112  return emptyVector;
113  }
114 
115  /// returns a reference to the unsimplified reduced costs.
117  {
118  assert(false);
119  static const VectorBase<R>& emptyVector = VectorBase<R>();
120  return emptyVector;
121  }
122 
123  /// gets basis status for a single row.
124  virtual typename SPxSolverBase<R>::VarStatus getBasisRowStatus(int i) const
125  {
126  assert(false);
128  }
129 
130  /// gets basis status for a single column.
131  virtual typename SPxSolverBase<R>::VarStatus getBasisColStatus(int j) const
132  {
133  assert(false);
135  }
136 
137  /// get optimal basis.
138  virtual void getBasis(typename SPxSolverBase<R>::VarStatus rows[],
139  typename SPxSolverBase<R>::VarStatus cols[], const int rowsSize = -1,
140  const int colsSize = -1) const
141  {
142  assert(false);
143  }
144 
145 };
146 
147 }
148 
149 
150 #else
151 
152 #include <memory>
153 
154 #include "papilo/core/Presolve.hpp"
155 #include "papilo/core/ProblemBuilder.hpp"
156 #include "papilo/Config.hpp"
157 
158 #include "soplex/spxsimplifier.h"
159 
160 #include "soplex/spxdefines.h"
161 #include "soplex/spxsimplifier.h"
162 #include "soplex/array.h"
163 #include "soplex/exceptions.h"
164 #include "soplex/spxdefines.h"
165 
166 
167 namespace soplex
168 {
169 
170 template<class R>
171 class Presol : public SPxSimplifier<R>
172 {
173 private:
174 
175 #ifdef SOPLEX_DEBUG
176  const papilo::VerbosityLevel verbosityLevel = papilo::VerbosityLevel::kInfo;
177 #else
178  const papilo::VerbosityLevel verbosityLevel = papilo::VerbosityLevel::kQuiet;
179 #endif
180 
181  VectorBase<R> m_prim; ///< unsimplified primal solution VectorBase<R>.
182  VectorBase<R> m_slack; ///< unsimplified slack VectorBase<R>.
183  VectorBase<R> m_dual; ///< unsimplified dual solution VectorBase<R>.
184  VectorBase<R> m_redCost; ///< unsimplified reduced cost VectorBase<R>.
185  DataArray<typename SPxSolverBase<R>::VarStatus> m_cBasisStat; ///< basis status of columns.
186  DataArray<typename SPxSolverBase<R>::VarStatus> m_rBasisStat; ///< basis status of rows.
187 
188 
189  papilo::PostsolveStorage<R>
190  postsolveStorage; ///< stored postsolve to recalculate the original solution
191  bool noChanges = false; ///< did PaPILO reduce the problem?
192 
193  bool postsolved; ///< was the solution already postsolve?
194  bool vanished = false;
195  R m_epsilon; ///< epsilon zero.
196  R m_feastol; ///< primal feasibility tolerance.
197  R m_opttol; ///< dual feasibility tolerance.
198  R modifyRowsFac; ///<
199  DataArray<int> m_stat; ///< preprocessing history.
200  typename SPxLPBase<R>::SPxSense m_thesense; ///< optimization sense.
201 
202  // TODO: the following parameters were ignored? Maybe I don't exactly know what they suppose to be
203  bool m_keepbounds; ///< keep some bounds (for boundflipping)
204  typename SPxSimplifier<R>::Result m_result; ///< result of the simplification.
205 
206 protected:
207 
208  R epsZero() const
209  {
210  return m_epsilon;
211  }
212 
213  R feastol() const
214  {
215  return m_feastol;
216  }
217 
218  R opttol() const
219  {
220  return m_opttol;
221  }
222 
223 public:
224 
225  //------------------------------------
226  ///@name Constructors / destructors
227  ///@{
228  /// default constructor.
229  explicit Presol(Timer::TYPE ttype = Timer::USER_TIME)
230  : SPxSimplifier<R>("PaPILO", ttype), postsolved(false), m_epsilon(DEFAULT_EPS_ZERO),
231  m_feastol(DEFAULT_BND_VIOL), m_opttol(DEFAULT_BND_VIOL), modifyRowsFac(1.0),
232  m_thesense(SPxLPBase<R>::MAXIMIZE),
233  m_keepbounds(false), m_result(this->OKAY)
234  { ; };
235 
236  /// copy constructor.
237  Presol(const Presol& old)
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)
244  {
245  ;
246  }
247 
248  /// assignment operator
249  Presol& operator=(const Presol& rhs)
250  {
251  if(this != &rhs)
252  {
254  m_prim = rhs.m_prim;
255  m_slack = rhs.m_slack;
256  m_dual = rhs.m_dual;
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;
269  }
270 
271  return *this;
272  }
273 
274  /// destructor.
275  virtual ~Presol()
276  {
277  ;
278  }
279 
280  SPxSimplifier<R>* clone() const
281  {
282  return new Presol(*this);
283  }
284 
285  void
286  setModifyConsFrac(R value)
287  {
288  modifyRowsFac = value;
289  }
290 
291  virtual typename SPxSimplifier<R>::Result simplify(SPxLPBase<R>& lp, R eps, R delta,
292  Real remainingTime)
293  {
294  return simplify(lp, eps, delta, delta, remainingTime, false, 0);
295  }
296 
297  virtual typename SPxSimplifier<R>::Result simplify(SPxLPBase<R>& lp, R eps, R ftol, R otol,
298  Real remainingTime,
299  bool keepbounds, uint32_t seed);
300 
301  virtual void unsimplify(const VectorBase<R>&, const VectorBase<R>&, const VectorBase<R>&,
302  const VectorBase<R>&,
303  const typename SPxSolverBase<R>::VarStatus[],
304  const typename SPxSolverBase<R>::VarStatus[],
305  bool isOptimal);
306 
307  /// returns result status of the simplification
308  virtual typename SPxSimplifier<R>::Result result() const
309  {
310  return m_result;
311  }
312 
313  /// specifies whether an optimal solution has already been unsimplified.
314  virtual bool isUnsimplified() const
315  {
316  return postsolved;
317  }
318 
319  /// returns a reference to the unsimplified primal solution.
320  virtual const VectorBase<R>& unsimplifiedPrimal()
321  {
322  assert(postsolved);
323  return m_prim;
324  }
325 
326  /// returns a reference to the unsimplified dual solution.
327  virtual const VectorBase<R>& unsimplifiedDual()
328  {
329  assert(postsolved);
330  return m_dual;
331  }
332 
333  /// returns a reference to the unsimplified slack values.
334  virtual const VectorBase<R>& unsimplifiedSlacks()
335  {
336  assert(postsolved);
337  return m_slack;
338  }
339 
340  /// returns a reference to the unsimplified reduced costs.
341  virtual const VectorBase<R>& unsimplifiedRedCost()
342  {
343  assert(postsolved);
344  return m_redCost;
345  }
346 
347  /// gets basis status for a single row.
348  virtual typename SPxSolverBase<R>::VarStatus getBasisRowStatus(int i) const
349  {
350  assert(postsolved);
351  return m_rBasisStat[i];
352  }
353 
354  /// gets basis status for a single column.
355  virtual typename SPxSolverBase<R>::VarStatus getBasisColStatus(int j) const
356  {
357  assert(postsolved);
358  return m_cBasisStat[j];
359  }
360 
361  /// get optimal basis.
362  virtual void getBasis(typename SPxSolverBase<R>::VarStatus rows[],
363  typename SPxSolverBase<R>::VarStatus cols[], const int rowsSize = -1,
364  const int colsSize = -1) const
365  {
366  assert(postsolved);
367  assert(rowsSize < 0 || rowsSize >= m_rBasisStat.size());
368  assert(colsSize < 0 || colsSize >= m_cBasisStat.size());
369 
370  for(int i = 0; i < m_rBasisStat.size(); ++i)
371  rows[i] = m_rBasisStat[i];
372 
373  for(int j = 0; j < m_cBasisStat.size(); ++j)
374  cols[j] = m_cBasisStat[j];
375  }
376 
377 private:
378 
379  void initLocalVariables(const SPxLPBase <R>& lp);
380 
381  void configurePapilo(papilo::Presolve<R>& presolve, R feasTolerance, R epsilon, uint32_t seed,
382  Real remainingTime) const;
383 
384  void applyPresolveResultsToColumns(SPxLPBase <R>& lp, const papilo::Problem<R>& problem,
385  const papilo::PresolveResult<R>& res) const;
386 
387  void applyPresolveResultsToRows(SPxLPBase <R>& lp, const papilo::Problem<R>& problem,
388  const papilo::PresolveResult<R>& res) const;
389 
390  papilo::VarBasisStatus
391  convertToPapiloStatus(typename SPxSolverBase<R>::VarStatus status) const;
392 
394  convertToSoplexStatus(papilo::VarBasisStatus status) const ;
395 };
396 
397 template <class R>
398 void Presol<R>::unsimplify(const VectorBase<R>& x, const VectorBase<R>& y,
399  const VectorBase<R>& s, const VectorBase<R>& r,
400  const typename SPxSolverBase<R>::VarStatus rows[],
401  const typename SPxSolverBase<R>::VarStatus cols[],
402  bool isOptimal)
403 {
404 
405  MSG_INFO1((*this->spxout), (*this->spxout)
406  << " --- unsimplifying solution and basis"
407  << std::endl;
408  )
409 
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());
414 
415  //if presolving made no changes then copy the reduced solution to the original
416  if(noChanges)
417  {
418  for(int j = 0; j < x.dim(); ++j)
419  {
420  m_prim[j] = x[j];
421  m_redCost[j] = r[j];
422  m_cBasisStat[j] = cols[j];
423  }
424 
425  for(int i = 0; i < y.dim(); ++i)
426  {
427  m_dual[i] = y[i];
428  m_slack[i] = s[i];
429  m_rBasisStat[i] = rows[i];
430  }
431 
432  postsolved = true;
433  return;
434  }
435 
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);
440 
441  papilo::Solution<R> originalSolution{};
442  papilo::Solution<R> reducedSolution{};
443  reducedSolution.type = papilo::SolutionType::kPrimalDual;
444  reducedSolution.basisAvailabe = true;
445 
446  reducedSolution.primal.clear();
447  reducedSolution.reducedCosts.clear();
448  reducedSolution.varBasisStatus.clear();
449  reducedSolution.dual.clear();
450  reducedSolution.rowBasisStatus.clear();
451 
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);
457 
458  postsolved = true;
459 
460  // NOTE: for maximization problems, we have to switch signs of dual and
461  // reduced cost values, since simplifier assumes minimization problem
462  R switch_sign = m_thesense == SPxLPBase<R>::MAXIMIZE ? -1 : 1;
463 
464  // assign values of variables in reduced LP
465  for(int j = 0; j < nColsReduced; ++j)
466  {
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]);
471  }
472 
473  for(int i = 0; i < nRowsReduced; ++i)
474  {
475  reducedSolution.dual[i] = isZero(y[i], this->epsZero()) ? 0.0 : switch_sign * y[i];
476  reducedSolution.rowBasisStatus[i] = convertToPapiloStatus(rows[i]);
477  }
478 
479  papilo::Num<R> num {};
480  num.setEpsilon(m_epsilon);
481  num.setFeasTol(m_feastol);
482  /* since PaPILO verbosity is quiet it's irrelevant what the messenger is */
483  papilo::Message msg{};
484  msg.setVerbosityLevel(verbosityLevel);
485 
486  papilo::Postsolve<R> postsolve {msg, num};
487  auto status = postsolve.undo(reducedSolution, originalSolution, postsolveStorage, isOptimal);
488 
489  if(status == PostsolveStatus::kFailed && isOptimal)
490  {
491  MSG_ERROR(std::cerr << "PaPILO did not pass validation" << std::endl;)
492  assert(false);
493  }
494 
495  for(int j = 0; j < (int)postsolveStorage.nColsOriginal; ++j)
496  {
497  m_prim[j] = originalSolution.primal[j];
498  m_redCost[j] = switch_sign * originalSolution.reducedCosts[j];
499  m_cBasisStat[j] = convertToSoplexStatus(originalSolution.varBasisStatus[j]);
500  }
501 
502  for(int i = 0; i < (int)postsolveStorage.nRowsOriginal; ++i)
503  {
504  m_dual[i] = switch_sign * originalSolution.dual[i];
505  m_slack[i] = originalSolution.slack[i];
506  m_rBasisStat[i] = convertToSoplexStatus(originalSolution.rowBasisStatus[i]);
507  }
508 
509 }
510 
511 template <class R>
512 papilo::VarBasisStatus
514 {
515  switch(status)
516  {
518  return papilo::VarBasisStatus::ON_UPPER;
519 
521  return papilo::VarBasisStatus::ON_LOWER;
522 
524  return papilo::VarBasisStatus::FIXED;
525 
527  return papilo::VarBasisStatus::BASIC;
528 
530  return papilo::VarBasisStatus::UNDEFINED;
531 
533  return papilo::VarBasisStatus::ZERO;
534  }
535 
536  return papilo::VarBasisStatus::UNDEFINED;
537 }
538 
539 template <class R>
541 Presol<R>::convertToSoplexStatus(papilo::VarBasisStatus status) const
542 {
543  switch(status)
544  {
545  case papilo::VarBasisStatus::ON_UPPER:
547 
548  case papilo::VarBasisStatus::ON_LOWER:
550 
551  case papilo::VarBasisStatus::ZERO:
552  return SPxSolverBase<R>::ZERO;
553 
554  case papilo::VarBasisStatus::FIXED:
556 
557  case papilo::VarBasisStatus::UNDEFINED:
559 
560  case papilo::VarBasisStatus::BASIC:
562  }
563 
565 }
566 
567 
568 template<class R>
569 papilo::Problem<R> buildProblem(SPxLPBase<R>& lp)
570 {
571  papilo::ProblemBuilder<R> builder;
572 
573  /* build problem from matrix */
574  int nnz = lp.nNzos();
575  int ncols = lp.nCols();
576  int nrows = lp.nRows();
577  builder.reserve(nnz, nrows, ncols);
578 
579  /* set up columns */
580  builder.setNumCols(ncols);
581 
582  R switch_sign = lp.spxSense() == SPxLPBase<R>::MAXIMIZE ? -1 : 1;
583 
584  for(int i = 0; i < ncols; ++i)
585  {
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));
593 
594  builder.setColIntegral(i, false);
595  builder.setObj(i, objective * switch_sign);
596  }
597 
598  /* set up rows */
599  builder.setNumRows(nrows);
600 
601  for(int i = 0; i < nrows; ++i)
602  {
603  const SVectorBase<R> rowVector = lp.rowVector(i);
604  int rowlength = rowVector.size();
605  int* indices = new int[rowlength];
606  R* rowValues = new R[rowlength];
607 
608  for(int j = 0; j < rowlength; j++)
609  {
610  const Nonzero<R> element = rowVector.element(j);
611  indices[j] = element.idx;
612  rowValues[j] = element.val;
613  }
614 
615  builder.addRowEntries(i, rowlength, indices, rowValues);
616 
617  R lhs = lp.lhs(i);
618  R rhs = lp.rhs(i);
619  builder.setRowLhs(i, lhs);
620  builder.setRowRhs(i, rhs);
621  builder.setRowLhsInf(i, lhs <= -R(infinity));
622  builder.setRowRhsInf(i, rhs >= R(infinity));
623  }
624 
625  return builder.build();
626 }
627 
628 
629 template<class R>
631 Presol<R>::simplify(SPxLPBase<R>& lp, R eps, R ftol, R otol,
632  Real remainingTime, bool keepbounds, uint32_t seed)
633 {
634 
635  //TODO: how to use the keepbounds parameter?
636  m_keepbounds = keepbounds;
637 
638  if(m_keepbounds)
639  MSG_WARNING((*this->spxout), (*this->spxout) << "==== PaPILO doesn't handle parameter keepbounds" <<
640  std::endl;)
641 
642  initLocalVariables(lp);
643 
644  papilo::Problem<R> problem = buildProblem(lp);
645  papilo::Presolve<R> presolve;
646 
647  configurePapilo(presolve, ftol, eps, seed, remainingTime);
648  MSG_INFO1((*this->spxout), (*this->spxout)
649  << " --- starting PaPILO" << std::endl;
650  )
651 
652  papilo::PresolveResult<R> res = presolve.apply(problem);
653 
654  switch(res.status)
655  {
656  case papilo::PresolveStatus::kInfeasible:
657  m_result = SPxSimplifier<R>::INFEASIBLE;
658  MSG_INFO1((*this->spxout), (*this->spxout)
659  << " --- presolving detected infeasibility" << std::endl;
660  )
662 
663  case papilo::PresolveStatus::kUnbndOrInfeas:
664  case papilo::PresolveStatus::kUnbounded:
665  m_result = SPxSimplifier<R>::UNBOUNDED;
666  MSG_INFO1((*this->spxout), (*this->spxout) <<
667  "==== Presolving detected unboundedness of the problem" << std::endl;
668  )
670 
671  case papilo::PresolveStatus::kUnchanged:
672  // since Soplex has no state unchanged store the value in a new variable
673  noChanges = true;
674  MSG_INFO1((*this->spxout), (*this->spxout)
675  << "==== Presolving found nothing " << std::endl;
676  )
677  return SPxSimplifier<R>::OKAY;
678 
679  case papilo::PresolveStatus::kReduced:
680  break;
681  }
682 
683 
684  int newNonzeros = problem.getConstraintMatrix().getNnz();
685 
686  if(newNonzeros == 0 || ((problem.getNRows() <= modifyRowsFac * lp.nRows() ||
687  newNonzeros <= modifyRowsFac * lp.nNzos())))
688  {
689  MSG_INFO1((*this->spxout), (*this->spxout)
690  << " --- presolved problem has " << problem.getNRows() <<
691  " rows, "
692  << problem.getNCols() << " cols and "
693  << newNonzeros << " non-zeros and "
694  << presolve.getStatistics().nboundchgs << " boundchanges and "
695  << presolve.getStatistics().nsidechgs << " sidechanges"
696  << std::endl;
697  )
698  postsolveStorage = res.postsolve;
699 
700  // remove all constraints and variables
701  for(int j = lp.nCols() - 1; j >= 0; j--)
702  lp.removeCol(j);
703 
704  for(int i = lp.nRows() - 1; i >= 0; i--)
705  lp.removeRow(i);
706 
707  applyPresolveResultsToColumns(lp, problem, res);
708  applyPresolveResultsToRows(lp, problem, res);
709  assert(newNonzeros == lp.nNzos());
710  }
711  else
712  {
713  noChanges = true;
714  MSG_INFO1((*this->spxout),
715  (*this->spxout)
716 
717  << " --- presolve results smaller than the modifyconsfac"
718  << std::endl;
719  )
720  }
721 
722  if(newNonzeros == 0)
723  {
724  vanished = true;
725  m_result = SPxSimplifier<R>::VANISHED;
726  }
727 
728  return m_result;
729 }
730 
731 template<class R>
733 {
734  m_result = SPxSimplifier<R>::OKAY;
735 
736  m_thesense = lp.spxSense();
737  postsolved = false;
738 
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());
745 
746  this->m_timeUsed->reset();
747  this->m_timeUsed->start();
748 }
749 
750 template<class R>
751 void Presol<R>::configurePapilo(papilo::Presolve<R>& presolve, R feasTolerance, R epsilon,
752  uint32_t seed, Real remainingTime) const
753 {
754  /* communicate the SOPLEX parameters to the presolve libary */
755 
756  /* communicate the random seed */
757  presolve.getPresolveOptions().randomseed = (unsigned int) seed;
758 
759  /* set number of threads to be used for presolve */
760  /* TODO: set threads for PaPILO? Can Soplex be run with multiple threads?*/
761  // presolve.getPresolveOptions().threads = data->threads;
762 
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;
769 
770  presolve.setVerbosityLevel(verbosityLevel);
771 
772  /* enable lp presolvers with dual postsolve*/
773  using uptr = std::unique_ptr<papilo::PresolveMethod<R>>;
774 
775  /* fast presolvers*/
776  presolve.addPresolveMethod(uptr(new papilo::SingletonCols<R>()));
777  presolve.addPresolveMethod(uptr(new papilo::ConstraintPropagation<R>()));
778 
779  /* medium presolver */
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>()));
785 
786  /* exhaustive presolvers*/
787  presolve.addPresolveMethod(uptr(new papilo::DominatedCols<R>()));
788 
789  /**
790  * TODO: PaPILO doesn't support dualpostsolve for those presolvers
791  * presolve.addPresolveMethod(uptr(new papilo::SimpleSubstitution<R>()));
792  * presolve.addPresolveMethod(uptr(new papilo::DualInfer<R>()));
793  * presolve.addPresolveMethod(uptr(new papilo::Substitution<R>()));
794  * presolve.addPresolveMethod(uptr(new papilo::Sparsify<R>()));
795  * presolve.getPresolveOptions().removeslackvars = false;
796  * presolve.getPresolveOptions().maxfillinpersubstitution
797  * =data->maxfillinpersubstitution;
798  * presolve.getPresolveOptions().maxshiftperrow = data->maxshiftperrow;
799  */
800 
801 
802 }
803 
804 template<class R>
805 void Presol<R>::applyPresolveResultsToColumns(SPxLPBase <R>& lp, const papilo::Problem<R>& problem,
806  const papilo::PresolveResult<R>& res) const
807 {
808 
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();
813 
814  R switch_sign = lp.spxSense() == SPxLPBase<R>::MAXIMIZE ? -1 : 1;
815 
816  for(int col = 0; col < problem.getNCols(); col++)
817  {
818  DSVectorBase<R> emptyVector{0};
819  R lb = lowerBounds[col];
820 
821  if(colFlags[col].test(papilo::ColFlag::kLbInf))
822  lb = -R(infinity);
823 
824  R ub = upperBounds[col];
825 
826  if(colFlags[col].test(papilo::ColFlag::kUbInf))
827  ub = R(infinity);
828 
829  LPColBase<R> column(objective.coefficients[col]* switch_sign, emptyVector, ub, lb);
830  lp.addCol(column);
831  assert(lp.lower(col) == lb);
832  assert(lp.upper(col) == ub);
833  }
834 
835  lp.changeObjOffset(objective.offset);
836 
837  assert(problem.getNCols() == lp.nCols());
838 }
839 
840 template<class R>
841 void Presol<R>::applyPresolveResultsToRows(SPxLPBase <R>& lp, const papilo::Problem<R>& problem,
842  const papilo::PresolveResult<R>& res) const
843 {
844  int size = res.postsolve.origrow_mapping.size();
845 
846  //add the adjusted constraints
847  for(int row = 0; row < size; row++)
848  {
849  R rhs = problem.getConstraintMatrix().getRightHandSides()[row];
850 
851  if(problem.getRowFlags()[row].test(papilo::RowFlag::kRhsInf))
852  rhs = R(infinity);
853 
854  R lhs = problem.getConstraintMatrix().getLeftHandSides()[row];
855 
856  if(problem.getRowFlags()[row].test(papilo::RowFlag::kLhsInf))
857  lhs = -R(infinity);
858 
859  const papilo::SparseVectorView<R> papiloRowVector =
860  problem.getConstraintMatrix().getRowCoefficients(row);
861  const int* indices = papiloRowVector.getIndices();
862  const R* values = papiloRowVector.getValues();
863 
864  int length = papiloRowVector.getLength();
865  DSVectorBase<R> soplexRowVector{length};
866 
867  for(int i = 0; i < length; i++)
868  {
869  soplexRowVector.add(indices[i], values[i]);
870  }
871 
872  LPRowBase<R> lpRowBase(lhs, soplexRowVector, rhs);
873  lp.addRow(lpRowBase);
874  assert(lp.lhs(row) == lhs);
875  assert(lp.rhs(row) == rhs);
876  }
877 
878  assert(problem.getNRows() == lp.nRows());
879 }
880 
881 } // namespace soplex
882 
883 #endif
const VectorBase< R > & rhs() const
Returns right hand side vector.
Definition: spxlpbase.h:239
virtual void removeRow(int i)
Removes i &#39;th row.
Definition: spxlpbase.h:951
Safe arrays of data objects.Class DataArray provides safe arrays of Data Objects. For general C++ obj...
Definition: dataarray.h:65
Sparse vector nonzero element.
Definition: svectorbase.h:37
const VectorBase< R > & upper() const
Returns upper bound vector.
Definition: spxlpbase.h:479
#define DEFAULT_BND_VIOL
default allowed bound violation
Definition: spxdefines.h:264
THREADLOCAL const Real infinity
Definition: spxdefines.cpp:32
Result
Result of the simplification.
Definition: spxsimplifier.h:82
virtual bool isUnsimplified() const
specifies whether an optimal solution has already been unsimplified.
Definition: spxpapilo.h:85
Dense vector.Class VectorBase provides dense linear algebra vectors. Internally, VectorBase wraps std...
Definition: dsvectorbase.h:28
int size() const
Number of used indices.
Definition: svectorbase.h:155
Nonzero< R > & element(int n)
Reference to the n &#39;th nonzero element.
Definition: svectorbase.h:219
Sequential object-oriented SimPlex.SPxSolverBase is an LP solver class using the revised Simplex algo...
Definition: spxbasis.h:49
Exception classes for SoPlex.
Dynamic sparse vectors.Class DSVectorBase implements dynamic sparse vectors, i.e. SVectorBases with a...
Definition: dsvectorbase.h:43
Presol(Timer::TYPE ttype=Timer::USER_TIME)
Definition: spxpapilo.h:31
virtual void removeCol(int i)
Removes i &#39;th column.
Definition: spxlpbase.h:1051
virtual SPxSimplifier< R >::Result simplify(SPxLPBase< R > &lp, R eps, R ftol, R otol, Real remainingTime, bool keepbounds, uint32_t seed)
Definition: spxpapilo.h:60
int idx
Index of nonzero element.
Definition: svectorbase.h:42
LP simplification base class.
virtual ~Presol()
destructor.
Definition: spxpapilo.h:44
virtual const VectorBase< R > & unsimplifiedRedCost()
returns a reference to the unsimplified reduced costs.
Definition: spxpapilo.h:116
int nRows() const
Returns number of rows in LP.
Definition: spxlpbase.h:170
void add(const SVectorBase< S > &vec)
Append nonzeros of sv.
Definition: dsvectorbase.h:219
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)
Definition: spxpapilo.h:68
simplification could be done
Definition: spxsimplifier.h:84
int nNzos() const
Returns number of nonzeros in LP.
Definition: spxlpbase.h:182
Timer * m_timeUsed
user time used for simplification
Definition: spxsimplifier.h:52
SPxSimplifier & operator=(const SPxSimplifier &rhs)
assignment operator
SPxSense
Optimization sense.
Definition: spxlpbase.h:115
double Real
Definition: spxdefines.h:256
virtual SPxSimplifier< R >::Result simplify(SPxLPBase< R > &lp, R eps, R delta, Real remainingTime)
Definition: spxpapilo.h:54
SPxSense spxSense() const
Returns the optimization sense.
Definition: spxlpbase.h:533
Presol(const Presol &old)
copy constructor.
Definition: spxpapilo.h:35
LP simplification abstract base class.Instances of classes derived from SPxSimplifier may be loaded t...
Definition: spxsimplifier.h:42
#define MSG_ERROR(x)
Prints out message x if the verbosity level is at least SPxOut::ERROR.
Definition: spxdefines.h:152
int size() const
Returns number of elements.
Definition: classarray.h:208
#define DEFAULT_EPS_ZERO
default allowed additive zero: 1.0 + EPS_ZERO == 1.0
Definition: spxdefines.h:268
R obj(int i) const
Returns objective value of column i.
Definition: spxlpbase.h:425
const VectorBase< R > & lhs() const
Returns left hand side vector.
Definition: spxlpbase.h:273
SPxSimplifier< R > * clone() const
Definition: spxpapilo.h:49
virtual SPxSolverBase< R >::VarStatus getBasisColStatus(int j) const
gets basis status for a single column.
Definition: spxpapilo.h:131
(In)equality for LPs.Class LPRowBase provides constraints for linear programs in the form where a is...
Definition: lprowbase.h:45
Debugging, floating point type and parameter definitions.
virtual void addCol(const LPColBase< R > &col, bool scale=false)
Definition: spxlpbase.h:775
int dim() const
Dimension of vector.
Definition: vectorbase.h:262
virtual const VectorBase< R > & unsimplifiedSlacks()
returns a reference to the unsimplified slack values.
Definition: spxpapilo.h:108
virtual const VectorBase< R > & unsimplifiedDual()
returns a reference to the unsimplified dual solution.
Definition: spxpapilo.h:100
Everything should be within this namespace.
TYPE
types of timers
Definition: timer.h:99
Saving LPs in a form suitable for SoPlex.Class SPxLPBase provides the data structures required for sa...
Definition: spxlpbase.h:56
#define MSG_WARNING(spxout, x)
Prints out message x if the verbosity level is at least SPxOut::WARNING.
Definition: spxdefines.h:154
Presol & operator=(const Presol &rhs)
assignment operator
Definition: spxpapilo.h:38
Save arrays of arbitrary types.
void changeObjOffset(const T &o)
Definition: spxlpbase.h:1910
const SVectorBase< R > & rowVector(int i) const
Gets row vector of row i.
Definition: spxlpbase.h:224
virtual void addRow(const LPRowBase< R > &row, bool scale=false)
Definition: spxlpbase.h:603
int size() const
return nr. of elements.
Definition: dataarray.h:218
R val
Value of nonzero element.
Definition: svectorbase.h:41
#define MSG_INFO1(spxout, x)
Prints out message x if the verbosity level is at least SPxOut::INFO1.
Definition: spxdefines.h:156
int nCols() const
Returns number of columns in LP.
Definition: spxlpbase.h:176
virtual SPxSimplifier< R >::Result result() const
returns result status of the simplification
Definition: spxpapilo.h:78
Sparse vectors.Class SVectorBase provides packed sparse vectors. Such are a sparse vectors...
Definition: ssvectorbase.h:34
virtual SPxSolverBase< R >::VarStatus getBasisRowStatus(int i) const
gets basis status for a single row.
Definition: spxpapilo.h:124
virtual void reset()=0
initialize timer, set timing accounts to zero.
SPxOut * spxout
message handler
Definition: spxsimplifier.h:73
virtual const VectorBase< R > & unsimplifiedPrimal()
returns a reference to the unsimplified primal solution.
Definition: spxpapilo.h:92
const VectorBase< R > & lower() const
Returns (internal and possibly scaled) lower bound vector.
Definition: spxlpbase.h:506
LP column.Class LPColBase provides a datatype for storing the column of an LP a the form similar to ...
Definition: lpcolbase.h:45
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.
Definition: spxpapilo.h:138