Scippy

SoPlex

Sequential object-oriented simPlex

solverational.cpp
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-2019 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 #include <iostream>
17 #include <assert.h>
18 
19 #include "soplex.h"
20 #include "soplex/statistics.h"
22 #include "soplex/ratrecon.h"
23 
24 namespace soplex
25 {
26 /// solves rational LP
28 {
29  bool hasUnboundedRay = false;
30  bool infeasibilityNotCertified = false;
31  bool unboundednessNotCertified = false;
32 
33  // start timing
36 
37  // remember that last solve was rational
39 
40  // ensure that the solver has the original problem
41  if(!_isRealLPLoaded)
42  {
43  assert(_realLP != &_solver);
44 
47  _realLP = &_solver;
48  _isRealLPLoaded = true;
49  }
50  // during the rational solve, we always store basis information in the basis arrays
51  else if(_hasBasis)
52  {
57  }
58 
59  // store objective, bounds, and sides of real LP in case they will be modified during iterative refinement
60  _storeLPReal();
61 
62  // deactivate objective limit in floating-point solver
65  {
66  MSG_INFO2(spxout, spxout << "Deactivating objective limit.\n");
67  }
68 
70 
72 
73  // apply lifting to reduce range of nonzero matrix coefficients
75  _lift();
76 
77  // force column representation
78  ///@todo implement row objectives with row representation
79  int oldRepresentation = intParam(SoPlex::REPRESENTATION);
81 
82  // force ratio test (avoid bound flipping)
83  int oldRatiotester = intParam(SoPlex::RATIOTESTER);
85 
86  ///@todo implement handling of row objectives in Cplex interface
87 #ifdef SOPLEX_WITH_CPX
88  int oldEqtrans = boolParam(SoPlex::EQTRANS);
90 #endif
91 
92  // introduce slack variables to transform inequality constraints into equations
95 
96  _storedBasis = false;
97 
98  bool stoppedTime;
99  bool stoppedIter;
100 
101  do
102  {
103  bool primalFeasible = false;
104  bool dualFeasible = false;
105  bool infeasible = false;
106  bool unbounded = false;
107  bool error = false;
108  stoppedTime = false;
109  stoppedIter = false;
110 
111  // solve problem with iterative refinement and recovery mechanism
112  _performOptIRStable(_solRational, !unboundednessNotCertified, !infeasibilityNotCertified, 0,
113  primalFeasible, dualFeasible, infeasible, unbounded, stoppedTime, stoppedIter, error);
114 
115  // case: an unrecoverable error occured
116  if(error)
117  {
119  break;
120  }
121  // case: stopped due to some limit
122  else if(stoppedTime)
123  {
125  break;
126  }
127  else if(stoppedIter)
128  {
130  break;
131  }
132  // case: unboundedness detected for the first time
133  else if(unbounded && !unboundednessNotCertified)
134  {
135  SolRational solUnbounded;
136 
137  _performUnboundedIRStable(solUnbounded, hasUnboundedRay, stoppedTime, stoppedIter, error);
138 
139  assert(!hasUnboundedRay || solUnbounded.hasPrimalRay());
140  assert(!solUnbounded.hasPrimalRay() || hasUnboundedRay);
141 
142  if(error)
143  {
144  MSG_INFO1(spxout, spxout << "Error while testing for unboundedness.\n");
146  break;
147  }
148 
149  if(hasUnboundedRay)
150  {
151  MSG_INFO1(spxout, spxout << "Dual infeasible. Primal unbounded ray available.\n");
152  }
153  else
154  {
155  MSG_INFO1(spxout, spxout << "Dual feasible. Rejecting primal unboundedness.\n");
156  }
157 
158  unboundednessNotCertified = !hasUnboundedRay;
159 
160  if(stoppedTime)
161  {
163  break;
164  }
165  else if(stoppedIter)
166  {
168  break;
169  }
170 
171  _performFeasIRStable(_solRational, infeasible, stoppedTime, stoppedIter, error);
172 
173  ///@todo this should be stored already earlier, possible switch use solRational above and solFeas here
174  if(hasUnboundedRay)
175  {
176  _solRational._primalRay = solUnbounded._primalRay;
178  }
179 
180  if(error)
181  {
182  MSG_INFO1(spxout, spxout << "Error while testing for feasibility.\n");
184  break;
185  }
186  else if(stoppedTime)
187  {
189  break;
190  }
191  else if(stoppedIter)
192  {
194  break;
195  }
196  else if(infeasible)
197  {
198  MSG_INFO1(spxout, spxout << "Primal infeasible. Dual Farkas ray available.\n");
200  break;
201  }
202  else if(hasUnboundedRay)
203  {
204  MSG_INFO1(spxout, spxout << "Primal feasible and unbounded.\n");
206  break;
207  }
208  else
209  {
210  MSG_INFO1(spxout, spxout << "Primal feasible and bounded.\n");
211  continue;
212  }
213  }
214  // case: infeasibility detected
215  else if(infeasible && !infeasibilityNotCertified)
216  {
217  _storeBasis();
218 
219  _performFeasIRStable(_solRational, infeasible, stoppedTime, stoppedIter, error);
220 
221  if(error)
222  {
223  MSG_INFO1(spxout, spxout << "Error while testing for infeasibility.\n");
225  _restoreBasis();
226  break;
227  }
228 
229  infeasibilityNotCertified = !infeasible;
230 
231  if(stoppedTime)
232  {
234  _restoreBasis();
235  break;
236  }
237  else if(stoppedIter)
238  {
240  _restoreBasis();
241  break;
242  }
243 
244  if(infeasible && boolParam(SoPlex::TESTDUALINF))
245  {
246  SolRational solUnbounded;
247 
248  _performUnboundedIRStable(solUnbounded, hasUnboundedRay, stoppedTime, stoppedIter, error);
249 
250  assert(!hasUnboundedRay || solUnbounded.hasPrimalRay());
251  assert(!solUnbounded.hasPrimalRay() || hasUnboundedRay);
252 
253  if(error)
254  {
255  MSG_INFO1(spxout, spxout << "Error while testing for dual infeasibility.\n");
257  _restoreBasis();
258  break;
259  }
260 
261  if(hasUnboundedRay)
262  {
263  MSG_INFO1(spxout, spxout << "Dual infeasible. Primal unbounded ray available.\n");
264  _solRational._primalRay = solUnbounded._primalRay;
266  }
267  else if(solUnbounded._isDualFeasible)
268  {
269  MSG_INFO1(spxout, spxout << "Dual feasible. Storing dual multipliers.\n");
270  _solRational._dual = solUnbounded._dual;
271  _solRational._redCost = solUnbounded._redCost;
273  }
274  else
275  {
276  assert(false);
277  MSG_INFO1(spxout, spxout << "Not dual infeasible.\n");
278  }
279  }
280 
281  _restoreBasis();
282 
283  if(infeasible)
284  {
285  MSG_INFO1(spxout, spxout << "Primal infeasible. Dual Farkas ray available.\n");
287  break;
288  }
289  else if(hasUnboundedRay)
290  {
291  MSG_INFO1(spxout, spxout << "Primal feasible and unbounded.\n");
293  break;
294  }
295  else
296  {
297  MSG_INFO1(spxout, spxout << "Primal feasible. Optimizing again.\n");
298  continue;
299  }
300  }
301  else if(primalFeasible && dualFeasible)
302  {
303  MSG_INFO1(spxout, spxout << "Solved to optimality.\n");
305  break;
306  }
307  else
308  {
309  MSG_INFO1(spxout, spxout << "Terminating without success.\n");
310  break;
311  }
312  }
313  while(!_isSolveStopped(stoppedTime, stoppedIter));
314 
315  ///@todo set status to ABORT_VALUE if optimal solution exceeds objective limit
316 
319  _hasSolRational = true;
320 
321  // restore original problem
324 
325 #ifdef SOPLEX_WITH_CPX
326  setBoolParam(SoPlex::EQTRANS, oldEqtrans);
327 #endif
328 
329  // reset representation and ratio test
330  setIntParam(SoPlex::REPRESENTATION, oldRepresentation);
331  setIntParam(SoPlex::RATIOTESTER, oldRatiotester);
332 
333  // undo lifting
336 
337  // restore objective, bounds, and sides of real LP in case they have been modified during iterative refinement
338  _restoreLPReal();
339 
340  // since the real LP is loaded in the solver, we need to also pass the basis information to the solver if
341  // available
342  if(_hasBasis)
343  {
344  assert(_isRealLPLoaded);
347  // since setBasis always sets the basis status to regular, we need to set it manually here
348  switch(_status)
349  {
350  case SPxSolver::OPTIMAL:
352  break;
355  break;
358  break;
359  default:
360  break;
361  }
362  }
363 
364  // stop timing
366 }
367 
368 
369 
370 /// solves current problem with iterative refinement and recovery mechanism
372  SolRational& sol,
373  bool acceptUnbounded,
374  bool acceptInfeasible,
375  int minRounds,
376  bool& primalFeasible,
377  bool& dualFeasible,
378  bool& infeasible,
379  bool& unbounded,
380  bool& stoppedTime,
381  bool& stoppedIter,
382  bool& error)
383 {
384  // start rational solving timing
386 
387  primalFeasible = false;
388  dualFeasible = false;
389  infeasible = false;
390  unbounded = false;
391  stoppedTime = false;
392  stoppedIter = false;
393  error = false;
394 
395  // set working tolerances in floating-point solver
398 
399  // declare vectors and variables
401 
402  _modLower.reDim(numColsRational(), false);
403  _modUpper.reDim(numColsRational(), false);
404  _modLhs.reDim(numRowsRational(), false);
405  _modRhs.reDim(numRowsRational(), false);
406  _modObj.reDim(numColsRational(), false);
407 
408  DVectorReal primalReal(numColsRational());
409  DVectorReal dualReal(numRowsRational());
410 
411  Rational boundsViolation;
412  Rational sideViolation;
413  Rational redCostViolation;
414  Rational dualViolation;
415  Rational primalScale;
416  Rational dualScale;
417  Rational maxScale;
418 
419  // solve original LP
420  MSG_INFO1(spxout, spxout << "Initial floating-point solve . . .\n");
421 
422  if(_hasBasis)
423  {
424  assert(_basisStatusRows.size() == numRowsRational());
425  assert(_basisStatusCols.size() == numColsRational());
428  }
429 
430  for(int r = numRowsRational() - 1; r >= 0; r--)
431  {
432  assert(_solver.maxRowObj(r) == 0.0);
433  }
434 
436  result = _solveRealStable(acceptUnbounded, acceptInfeasible, primalReal, dualReal, _basisStatusRows,
438 
439  // evaluate result
440  switch(result)
441  {
442  case SPxSolver::OPTIMAL:
443  MSG_INFO1(spxout, spxout << "Floating-point optimal.\n");
444  break;
445 
447  MSG_INFO1(spxout, spxout << "Floating-point infeasible.\n");
448 
449  // the floating-point solve returns a Farkas ray if and only if the simplifier was not used, which is exactly
450  // the case when a basis could be returned
451  if(_hasBasis)
452  {
453  sol._dualFarkas = dualReal;
454  sol._hasDualFarkas = true;
455  }
456  else
457  sol._hasDualFarkas = false;
458 
459  infeasible = true;
460  return;
461 
463  MSG_INFO1(spxout, spxout << "Floating-point unbounded.\n");
464  unbounded = true;
465  return;
466 
468  stoppedTime = true;
469  return;
470 
472  stoppedIter = true;
473  return;
474 
475  default:
476  error = true;
477  return;
478  }
479 
481 
482  // store floating-point solution of original LP as current rational solution and ensure that solution vectors have
483  // right dimension; ensure that solution is aligned with basis
484  sol._primal.reDim(numColsRational(), false);
485  sol._slacks.reDim(numRowsRational(), false);
486  sol._dual.reDim(numRowsRational(), false);
487  sol._redCost.reDim(numColsRational(), false);
488  sol._isPrimalFeasible = true;
489  sol._isDualFeasible = true;
490 
491  for(int c = numColsRational() - 1; c >= 0; c--)
492  {
493  SPxSolver::VarStatus& basisStatusCol = _basisStatusCols[c];
494 
495  if(basisStatusCol == SPxSolver::ON_LOWER)
496  sol._primal[c] = lowerRational(c);
497  else if(basisStatusCol == SPxSolver::ON_UPPER)
498  sol._primal[c] = upperRational(c);
499  else if(basisStatusCol == SPxSolver::FIXED)
500  {
501  // it may happen that lower and upper are only equal in the real LP but different in the rational LP; we do
502  // not check this to avoid rational comparisons, but simply switch the basis status to the lower bound; this
503  // is necessary, because for fixed variables any reduced cost is feasible
504  sol._primal[c] = lowerRational(c);
505  basisStatusCol = SPxSolver::ON_LOWER;
506  }
507  else if(basisStatusCol == SPxSolver::ZERO)
508  sol._primal[c] = 0;
509  else
510  sol._primal[c] = primalReal[c];
511  }
512 
514 
515  int dualSize = 0;
516 
517  for(int r = numRowsRational() - 1; r >= 0; r--)
518  {
519  SPxSolver::VarStatus& basisStatusRow = _basisStatusRows[r];
520 
521  // it may happen that left-hand and right-hand side are different in the rational, but equal in the real LP,
522  // leading to a fixed basis status; this is critical because rows with fixed basis status are ignored in the
523  // computation of the dual violation; to avoid rational comparisons we do not check this but simply switch to
524  // the left-hand side status
525  if(basisStatusRow == SPxSolver::FIXED)
526  basisStatusRow = SPxSolver::ON_LOWER;
527 
528  {
529  sol._dual[r] = dualReal[r];
530 
531  if(dualReal[r] != 0.0)
532  dualSize++;
533  }
534  }
535 
536  // we assume that the objective function vector has less nonzeros than the reduced cost vector, and so multiplying
537  // with -1 first and subtracting the dual activity should be faster than adding the dual activity and negating
538  // afterwards
541 
542  // initial scaling factors are one
543  primalScale = _rationalPosone;
544  dualScale = _rationalPosone;
545 
546  // control progress
547  Rational maxViolation;
548  Rational bestViolation = _rationalPosInfty;
549  const Rational violationImprovementFactor = 0.9;
550  const Rational errorCorrectionFactor = 1.1;
551  Rational errorCorrection = 2;
552  int numFailedRefinements = 0;
553 
554  // store basis status in case solving modified problem failed
555  DataArray< SPxSolver::VarStatus > basisStatusRowsFirst;
556  DataArray< SPxSolver::VarStatus > basisStatusColsFirst;
557 
558  // refinement loop
559  const bool maximizing = (intParam(SoPlex::OBJSENSE) == SoPlex::OBJSENSE_MAXIMIZE);
560  const int maxDimRational = numColsRational() > numRowsRational() ? numColsRational() :
561  numRowsRational();
562  SolRational factorSol;
563  bool factorSolNewBasis = true;
564  int lastStallRefinements = 0;
565  int nextRatrecRefinement = 0;
566 
567  do
568  {
569  // decrement minRounds counter
570  minRounds--;
571 
572  MSG_DEBUG(std::cout << "Computing primal violations.\n");
573 
574  // compute violation of bounds
575  boundsViolation = 0;
576 
577  for(int c = numColsRational() - 1; c >= 0; c--)
578  {
579  // lower bound
581 
582  if(_lowerFinite(_colTypes[c]))
583  {
584  if(lowerRational(c) == 0)
585  {
586  _modLower[c] = sol._primal[c];
587  _modLower[c] *= -1;
588 
589  if(_modLower[c] > boundsViolation)
590  boundsViolation = _modLower[c];
591  }
592  else
593  {
594  _modLower[c] = lowerRational(c);
595  _modLower[c] -= sol._primal[c];
596 
597  if(_modLower[c] > boundsViolation)
598  boundsViolation = _modLower[c];
599  }
600  }
601 
602  // upper bound
604 
605  if(_upperFinite(_colTypes[c]))
606  {
607  if(upperRational(c) == 0)
608  {
609  _modUpper[c] = sol._primal[c];
610  _modUpper[c] *= -1;
611 
612  if(_modUpper[c] < -boundsViolation)
613  boundsViolation = -_modUpper[c];
614  }
615  else
616  {
617  _modUpper[c] = upperRational(c);
618  _modUpper[c] -= sol._primal[c];
619 
620  if(_modUpper[c] < -boundsViolation)
621  boundsViolation = -_modUpper[c];
622  }
623  }
624  }
625 
626  // compute violation of sides
627  sideViolation = 0;
628 
629  for(int r = numRowsRational() - 1; r >= 0; r--)
630  {
631  const SPxSolver::VarStatus& basisStatusRow = _basisStatusRows[r];
632 
633  // left-hand side
634  assert((lhsRational(r) > _rationalNegInfty) == _lowerFinite(_rowTypes[r]));
635 
636  if(_lowerFinite(_rowTypes[r]))
637  {
638  if(lhsRational(r) == 0)
639  {
640  _modLhs[r] = sol._slacks[r];
641  _modLhs[r] *= -1;
642  }
643  else
644  {
645  _modLhs[r] = lhsRational(r);
646  _modLhs[r] -= sol._slacks[r];
647  }
648 
649  if(_modLhs[r] > sideViolation)
650  sideViolation = _modLhs[r];
651  // if the activity is feasible, but too far from the bound, this violates complementary slackness; we
652  // count it as side violation here
653  else if(basisStatusRow == SPxSolver::ON_LOWER && _modLhs[r] < -sideViolation)
654  sideViolation = -_modLhs[r];
655  }
656 
657  // right-hand side
658  assert((rhsRational(r) < _rationalPosInfty) == _upperFinite(_rowTypes[r]));
659 
660  if(_upperFinite(_rowTypes[r]))
661  {
662  if(rhsRational(r) == 0)
663  {
664  _modRhs[r] = sol._slacks[r];
665  _modRhs[r] *= -1;
666  }
667  else
668  {
669  _modRhs[r] = rhsRational(r);
670  _modRhs[r] -= sol._slacks[r];
671  }
672 
673  if(_modRhs[r] < -sideViolation)
674  sideViolation = -_modRhs[r];
675  // if the activity is feasible, but too far from the bound, this violates complementary slackness; we
676  // count it as side violation here
677  else if(basisStatusRow == SPxSolver::ON_UPPER && _modRhs[r] > sideViolation)
678  sideViolation = _modRhs[r];
679  }
680  }
681 
682  MSG_DEBUG(std::cout << "Computing dual violations.\n");
683 
684  // compute reduced cost violation
685  redCostViolation = 0;
686 
687  for(int c = numColsRational() - 1; c >= 0; c--)
688  {
689  if(_colTypes[c] == RANGETYPE_FIXED)
690  continue;
691 
692  const SPxSolver::VarStatus& basisStatusCol = _basisStatusCols[c];
693  assert(basisStatusCol != SPxSolver::FIXED);
694 
695  if(((maximizing && basisStatusCol != SPxSolver::ON_LOWER) || (!maximizing
696  && basisStatusCol != SPxSolver::ON_UPPER))
697  && sol._redCost[c] < -redCostViolation)
698  {
699  MSG_DEBUG(std::cout << "basisStatusCol = " << basisStatusCol
700  << ", lower tight = " << bool(sol._primal[c] <= lowerRational(c))
701  << ", upper tight = " << bool(sol._primal[c] >= upperRational(c))
702  << ", sol._redCost[c] = " << rationalToString(sol._redCost[c])
703  << "\n");
704  redCostViolation = -sol._redCost[c];
705  }
706 
707  if(((maximizing && basisStatusCol != SPxSolver::ON_UPPER) || (!maximizing
708  && basisStatusCol != SPxSolver::ON_LOWER))
709  && sol._redCost[c] > redCostViolation)
710  {
711  MSG_DEBUG(std::cout << "basisStatusCol = " << basisStatusCol
712  << ", lower tight = " << bool(sol._primal[c] <= lowerRational(c))
713  << ", upper tight = " << bool(sol._primal[c] >= upperRational(c))
714  << ", sol._redCost[c] = " << rationalToString(sol._redCost[c])
715  << "\n");
716  redCostViolation = sol._redCost[c];
717  }
718  }
719 
720  // compute dual violation
721  dualViolation = 0;
722 
723  for(int r = numRowsRational() - 1; r >= 0; r--)
724  {
725  if(_rowTypes[r] == RANGETYPE_FIXED)
726  continue;
727 
728  const SPxSolver::VarStatus& basisStatusRow = _basisStatusRows[r];
729  assert(basisStatusRow != SPxSolver::FIXED);
730 
731  if(((maximizing && basisStatusRow != SPxSolver::ON_LOWER) || (!maximizing
732  && basisStatusRow != SPxSolver::ON_UPPER))
733  && sol._dual[r] < -dualViolation)
734  {
735  MSG_DEBUG(std::cout << "basisStatusRow = " << basisStatusRow
736  << ", lower tight = " << bool(sol._slacks[r] <= lhsRational(r))
737  << ", upper tight = " << bool(sol._slacks[r] >= rhsRational(r))
738  << ", sol._dual[r] = " << rationalToString(sol._dual[r])
739  << "\n");
740  dualViolation = -sol._dual[r];
741  }
742 
743  if(((maximizing && basisStatusRow != SPxSolver::ON_UPPER) || (!maximizing
744  && basisStatusRow != SPxSolver::ON_LOWER))
745  && sol._dual[r] > dualViolation)
746  {
747  MSG_DEBUG(std::cout << "basisStatusRow = " << basisStatusRow
748  << ", lower tight = " << bool(sol._slacks[r] <= lhsRational(r))
749  << ", upper tight = " << bool(sol._slacks[r] >= rhsRational(r))
750  << ", sol._dual[r] = " << rationalToString(sol._dual[r])
751  << "\n");
752  dualViolation = sol._dual[r];
753  }
754  }
755 
756  _modObj = sol._redCost;
757 
758  // output violations; the reduced cost violations for artificially introduced slack columns are actually violations of the dual multipliers
760  << "Max. bound violation = " << rationalToString(boundsViolation) << "\n"
761  << "Max. row violation = " << rationalToString(sideViolation) << "\n"
762  << "Max. reduced cost violation = " << rationalToString(redCostViolation) << "\n"
763  << "Max. dual violation = " << rationalToString(dualViolation) << "\n");
764 
766  << std::fixed << std::setprecision(2) << std::setw(10)
767  << "Progress table: "
768  << std::setw(10) << _statistics->refinements << " & "
769  << std::setw(10) << _statistics->iterations << " & "
770  << std::setw(10) << _statistics->solvingTime->time() << " & "
771  << std::setw(10) << _statistics->rationalTime->time() << " & "
772  << std::setw(10) << rationalToString(boundsViolation > sideViolation ? boundsViolation :
773  sideViolation, 2) << " & "
774  << std::setw(10) << rationalToString(redCostViolation > dualViolation ? redCostViolation :
775  dualViolation, 2) << "\n");
776 
777  // terminate if tolerances are satisfied
778  primalFeasible = (boundsViolation <= _rationalFeastol && sideViolation <= _rationalFeastol);
779  dualFeasible = (redCostViolation <= _rationalOpttol && dualViolation <= _rationalOpttol);
780 
781  if(primalFeasible && dualFeasible)
782  {
783  if(minRounds < 0)
784  {
785  MSG_INFO1(spxout, spxout << "Tolerances reached.\n");
786  break;
787  }
788  else
789  {
791  "Tolerances reached but minRounds forcing additional refinement rounds.\n");
792  }
793  }
794 
795  // terminate if some limit is reached
796  if(_isSolveStopped(stoppedTime, stoppedIter))
797  break;
798 
799  // check progress
800  maxViolation = boundsViolation;
801 
802  if(sideViolation > maxViolation)
803  maxViolation = sideViolation;
804 
805  if(redCostViolation > maxViolation)
806  maxViolation = redCostViolation;
807 
808  if(dualViolation > maxViolation)
809  maxViolation = dualViolation;
810 
811  bestViolation *= violationImprovementFactor;
812 
813  if(maxViolation > bestViolation)
814  {
815  MSG_INFO2(spxout, spxout << "Failed to reduce violation significantly.\n");
816  numFailedRefinements++;
817  }
818  else
819  bestViolation = maxViolation;
820 
821  // decide whether to perform rational reconstruction and/or factorization
822  bool performRatfac = boolParam(SoPlex::RATFAC)
823  && lastStallRefinements >= intParam(SoPlex::RATFAC_MINSTALLS) && _hasBasis && factorSolNewBasis;
824  bool performRatrec = boolParam(SoPlex::RATREC)
825  && (_statistics->refinements >= nextRatrecRefinement || performRatfac);
826 
827  // attempt rational reconstruction
828  errorCorrection *= errorCorrectionFactor;
829 
830  if(performRatrec && maxViolation > 0)
831  {
832  MSG_INFO1(spxout, spxout << "Performing rational reconstruction . . .\n");
833 
834  maxViolation *= errorCorrection; // only used for sign check later
835  maxViolation.invert();
836 
838  {
839  MSG_INFO1(spxout, spxout << "Tolerances reached.\n");
840  primalFeasible = true;
841  dualFeasible = true;
842  break;
843  }
844 
845  nextRatrecRefinement = int(_statistics->refinements * realParam(SoPlex::RATREC_FREQ)) + 1;
846  MSG_DEBUG(spxout << "Next rational reconstruction after refinement " << nextRatrecRefinement <<
847  ".\n");
848  }
849 
850  // solve basis systems exactly
851  if(performRatfac && maxViolation > 0)
852  {
853  MSG_INFO1(spxout, spxout << "Performing rational factorization . . .\n");
854 
855  bool optimal;
856  _factorizeColumnRational(sol, _basisStatusRows, _basisStatusCols, stoppedTime, stoppedIter, error,
857  optimal);
858  factorSolNewBasis = false;
859 
860  if(stoppedTime)
861  {
862  MSG_INFO1(spxout, spxout << "Stopped rational factorization.\n");
863  }
864  else if(error)
865  {
866  // message was already printed; reset error flag and continue without factorization
867  error = false;
868  }
869  else if(optimal)
870  {
871  MSG_INFO1(spxout, spxout << "Tolerances reached.\n");
872  primalFeasible = true;
873  dualFeasible = true;
874  break;
875  }
876  else if(boolParam(SoPlex::RATFACJUMP))
877  {
878  MSG_INFO1(spxout, spxout << "Jumping to exact basic solution.\n");
879  minRounds++;
880  continue;
881  }
882  }
883 
884  // start refinement
885 
886  // compute primal scaling factor; limit increase in scaling by tolerance used in floating point solve
887  maxScale = primalScale;
888  maxScale *= _rationalMaxscaleincr;
889 
890  primalScale = boundsViolation > sideViolation ? boundsViolation : sideViolation;
891 
892  if(primalScale < redCostViolation)
893  primalScale = redCostViolation;
894 
895  assert(primalScale >= 0);
896 
897  if(primalScale > 0)
898  {
899  primalScale.invert();
900 
901  if(primalScale > maxScale)
902  primalScale = maxScale;
903  }
904  else
905  primalScale = maxScale;
906 
908  primalScale.powRound();
909 
910  // apply scaled bounds
911  if(primalScale <= 1)
912  {
913  if(primalScale < 1)
914  primalScale = 1;
915 
916  for(int c = numColsRational() - 1; c >= 0; c--)
917  {
918  if(_lowerFinite(_colTypes[c]))
919  {
920  if(_modLower[c] <= _rationalNegInfty)
922  else
924  }
925 
926  if(_upperFinite(_colTypes[c]))
927  {
928  if(_modUpper[c] >= _rationalPosInfty)
930  else
932  }
933  }
934  }
935  else
936  {
937  MSG_INFO2(spxout, spxout << "Scaling primal by " << rationalToString(primalScale) << ".\n");
938 
939  for(int c = numColsRational() - 1; c >= 0; c--)
940  {
941  if(_lowerFinite(_colTypes[c]))
942  {
943  _modLower[c] *= primalScale;
944 
945  if(_modLower[c] <= _rationalNegInfty)
947  else
949  }
950 
951  if(_upperFinite(_colTypes[c]))
952  {
953  _modUpper[c] *= primalScale;
954 
955  if(_modUpper[c] >= _rationalPosInfty)
957  else
959  }
960  }
961  }
962 
963  // apply scaled sides
964  assert(primalScale >= 1);
965 
966  if(primalScale == 1)
967  {
968  for(int r = numRowsRational() - 1; r >= 0; r--)
969  {
970  if(_lowerFinite(_rowTypes[r]))
971  {
972  if(_modLhs[r] <= _rationalNegInfty)
974  else
975  _solver.changeLhs(r, Real(_modLhs[r]));
976  }
977 
978  if(_upperFinite(_rowTypes[r]))
979  {
980  if(_modRhs[r] >= _rationalPosInfty)
982  else
983  _solver.changeRhs(r, Real(_modRhs[r]));
984  }
985  }
986  }
987  else
988  {
989  for(int r = numRowsRational() - 1; r >= 0; r--)
990  {
991  if(_lowerFinite(_rowTypes[r]))
992  {
993  _modLhs[r] *= primalScale;
994 
995  if(_modLhs[r] <= _rationalNegInfty)
997  else
998  _solver.changeLhs(r, Real(_modLhs[r]));
999  }
1000 
1001  if(_upperFinite(_rowTypes[r]))
1002  {
1003  _modRhs[r] *= primalScale;
1004 
1005  if(_modRhs[r] >= _rationalPosInfty)
1007  else
1008  _solver.changeRhs(r, Real(_modRhs[r]));
1009  }
1010  }
1011  }
1012 
1013  // compute dual scaling factor; limit increase in scaling by tolerance used in floating point solve
1014  maxScale = dualScale;
1015  maxScale *= _rationalMaxscaleincr;
1016 
1017  dualScale = redCostViolation > dualViolation ? redCostViolation : dualViolation;
1018  assert(dualScale >= 0);
1019 
1020  if(dualScale > 0)
1021  {
1022  dualScale.invert();
1023 
1024  if(dualScale > maxScale)
1025  dualScale = maxScale;
1026  }
1027  else
1028  dualScale = maxScale;
1029 
1031  dualScale.powRound();
1032 
1033  if(dualScale > primalScale)
1034  dualScale = primalScale;
1035 
1036  if(dualScale < 1)
1037  dualScale = 1;
1038  else
1039  {
1040  MSG_INFO2(spxout, spxout << "Scaling dual by " << rationalToString(dualScale) << ".\n");
1041 
1042  // perform dual scaling
1043  ///@todo remove _modObj and use dualScale * sol._redCost directly
1044  _modObj *= dualScale;
1045  }
1046 
1047  // apply scaled objective function
1048  for(int c = numColsRational() - 1; c >= 0; c--)
1049  {
1050  if(_modObj[c] >= _rationalPosInfty)
1052  else if(_modObj[c] <= _rationalNegInfty)
1054  else
1055  _solver.changeObj(c, Real(_modObj[c]));
1056  }
1057 
1058  for(int r = numRowsRational() - 1; r >= 0; r--)
1059  {
1060  Rational newRowObj;
1061 
1062  if(_rowTypes[r] == RANGETYPE_FIXED)
1063  _solver.changeRowObj(r, 0.0);
1064  else
1065  {
1066  newRowObj = sol._dual[r];
1067  newRowObj *= dualScale;
1068 
1069  if(newRowObj >= _rationalPosInfty)
1071  else if(newRowObj <= _rationalNegInfty)
1073  else
1074  _solver.changeRowObj(r, -Real(newRowObj));
1075  }
1076  }
1077 
1078  MSG_INFO1(spxout, spxout << "Refined floating-point solve . . .\n");
1079 
1080  // ensure that artificial slack columns are basic and inequality constraints are nonbasic; otherwise we may end
1081  // up with dual violation on inequality constraints after removing the slack columns; do not change this in the
1082  // floating-point solver, though, because the solver may require its original basis to detect optimality
1083  if(_slackCols.num() > 0 && _hasBasis)
1084  {
1085  int numOrigCols = numColsRational() - _slackCols.num();
1086  assert(_slackCols.num() <= 0 || boolParam(SoPlex::EQTRANS));
1087 
1088  for(int i = 0; i < _slackCols.num(); i++)
1089  {
1090  int row = _slackCols.colVector(i).index(0);
1091  int col = numOrigCols + i;
1092 
1093  assert(row >= 0);
1094  assert(row < numRowsRational());
1095 
1097  {
1098  _basisStatusRows[row] = _basisStatusCols[col];
1101  }
1102  }
1103  }
1104 
1105  // load basis
1107  {
1108  MSG_DEBUG(spxout << "basis (status = " << _solver.basis().status() << ") desc before set:\n";
1109  _solver.basis().desc().dump());
1111  MSG_DEBUG(spxout << "basis (status = " << _solver.basis().status() << ") desc after set:\n";
1112  _solver.basis().desc().dump());
1113 
1115  MSG_DEBUG(spxout << "setting basis in solver " << (_hasBasis ? "successful" : "failed") <<
1116  " (3)\n");
1117  }
1118 
1119  // solve modified problem
1120  int prevIterations = _statistics->iterations;
1122  result = _solveRealStable(acceptUnbounded, acceptInfeasible, primalReal, dualReal, _basisStatusRows,
1123  _basisStatusCols, _hasBasis, primalScale > 1e20 || dualScale > 1e20);
1124 
1125  // count refinements and remember whether we moved to a new basis
1127 
1128  if(_statistics->iterations <= prevIterations)
1129  {
1130  lastStallRefinements++;
1132  }
1133  else
1134  {
1135  factorSolNewBasis = true;
1136  lastStallRefinements = 0;
1138  }
1139 
1140  // evaluate result; if modified problem was not solved to optimality, stop refinement
1141  switch(result)
1142  {
1143  case SPxSolver::OPTIMAL:
1144  MSG_INFO1(spxout, spxout << "Floating-point optimal.\n");
1145  break;
1146 
1147  case SPxSolver::INFEASIBLE:
1148  MSG_INFO1(spxout, spxout << "Floating-point infeasible.\n");
1149  sol._dualFarkas = dualReal;
1150  sol._hasDualFarkas = true;
1151  infeasible = true;
1153  return;
1154 
1155  case SPxSolver::UNBOUNDED:
1156  MSG_INFO1(spxout, spxout << "Floating-point unbounded.\n");
1157  unbounded = true;
1159  return;
1160 
1161  case SPxSolver::ABORT_TIME:
1162  stoppedTime = true;
1163  return;
1164 
1165  case SPxSolver::ABORT_ITER:
1166  stoppedIter = true;
1168  return;
1169 
1170  default:
1171  error = true;
1173  return;
1174  }
1175 
1177 
1178  // correct primal solution and align with basis
1179  MSG_DEBUG(std::cout << "Correcting primal solution.\n");
1180 
1181  int primalSize = 0;
1182  Rational primalScaleInverse = primalScale;
1183  primalScaleInverse.invert();
1185 
1186  for(int c = numColsRational() - 1; c >= 0; c--)
1187  {
1188  // force values of nonbasic variables to bounds
1189  SPxSolver::VarStatus& basisStatusCol = _basisStatusCols[c];
1190 
1191  if(basisStatusCol == SPxSolver::ON_LOWER)
1192  {
1193  if(sol._primal[c] != lowerRational(c))
1194  {
1195  int i = _primalDualDiff.size();
1197  _primalDualDiff.add(c);
1199  _primalDualDiff.value(i) -= sol._primal[c];
1200  sol._primal[c] = lowerRational(c);
1201  }
1202  }
1203  else if(basisStatusCol == SPxSolver::ON_UPPER)
1204  {
1205  if(sol._primal[c] != upperRational(c))
1206  {
1207  int i = _primalDualDiff.size();
1209  _primalDualDiff.add(c);
1211  _primalDualDiff.value(i) -= sol._primal[c];
1212  sol._primal[c] = upperRational(c);
1213  }
1214  }
1215  else if(basisStatusCol == SPxSolver::FIXED)
1216  {
1217  // it may happen that lower and upper are only equal in the real LP but different in the rational LP; we
1218  // do not check this to avoid rational comparisons, but simply switch the basis status to the lower
1219  // bound; this is necessary, because for fixed variables any reduced cost is feasible
1220  basisStatusCol = SPxSolver::ON_LOWER;
1221 
1222  if(sol._primal[c] != lowerRational(c))
1223  {
1224  int i = _primalDualDiff.size();
1226  _primalDualDiff.add(c);
1228  _primalDualDiff.value(i) -= sol._primal[c];
1229  sol._primal[c] = lowerRational(c);
1230  }
1231  }
1232  else if(basisStatusCol == SPxSolver::ZERO)
1233  {
1234  if(sol._primal[c] != 0)
1235  {
1236  int i = _primalDualDiff.size();
1238  _primalDualDiff.add(c);
1239  _primalDualDiff.value(i) = sol._primal[c];
1240  _primalDualDiff.value(i) *= -1;
1241  sol._primal[c] = 0;
1242  }
1243  }
1244  else
1245  {
1246  if(primalReal[c] == 1.0)
1247  {
1248  int i = _primalDualDiff.size();
1250  _primalDualDiff.add(c);
1251  _primalDualDiff.value(i) = primalScaleInverse;
1252  sol._primal[c] += _primalDualDiff.value(i);
1253  }
1254  else if(primalReal[c] == -1.0)
1255  {
1256  int i = _primalDualDiff.size();
1258  _primalDualDiff.add(c);
1259  _primalDualDiff.value(i) = primalScaleInverse;
1260  _primalDualDiff.value(i) *= -1;
1261  sol._primal[c] += _primalDualDiff.value(i);
1262  }
1263  else if(primalReal[c] != 0.0)
1264  {
1265  int i = _primalDualDiff.size();
1267  _primalDualDiff.add(c);
1268  _primalDualDiff.value(i) = primalReal[c];
1269  _primalDualDiff.value(i) *= primalScaleInverse;
1270  sol._primal[c] += _primalDualDiff.value(i);
1271  }
1272  }
1273 
1274  if(sol._primal[c] != 0)
1275  primalSize++;
1276  }
1277 
1278  // update or recompute slacks depending on which looks faster
1279  if(_primalDualDiff.size() < primalSize)
1280  {
1282 #ifndef NDEBUG
1283 #ifdef SOPLEX_WITH_GMP
1284  {
1285  DVectorRational activity(numRowsRational());
1286  _rationalLP->computePrimalActivity(sol._primal, activity);
1287  assert(sol._slacks == activity);
1288  }
1289 #endif
1290 #endif
1291  }
1292  else
1294 
1295  const int numCorrectedPrimals = _primalDualDiff.size();
1296 
1297  // correct dual solution and align with basis
1298  MSG_DEBUG(std::cout << "Correcting dual solution.\n");
1299 
1300 #ifndef NDEBUG
1301  {
1302  // compute reduced cost violation
1303  DVectorRational debugRedCost(numColsRational());
1304  debugRedCost = DVectorRational(_realLP->maxObj());
1305  debugRedCost *= -1;
1306  _rationalLP->subDualActivity(DVectorRational(dualReal), debugRedCost);
1307 
1308  Rational debugRedCostViolation = 0;
1309 
1310  for(int c = numColsRational() - 1; c >= 0; c--)
1311  {
1312  if(_colTypes[c] == RANGETYPE_FIXED)
1313  continue;
1314 
1315  const SPxSolver::VarStatus& basisStatusCol = _basisStatusCols[c];
1316  assert(basisStatusCol != SPxSolver::FIXED);
1317 
1318  if(((maximizing && basisStatusCol != SPxSolver::ON_LOWER) || (!maximizing
1319  && basisStatusCol != SPxSolver::ON_UPPER))
1320  && debugRedCost[c] < -debugRedCostViolation)
1321  {
1322  MSG_DEBUG(std::cout << "basisStatusCol = " << basisStatusCol
1323  << ", lower tight = " << bool(sol._primal[c] <= lowerRational(c))
1324  << ", upper tight = " << bool(sol._primal[c] >= upperRational(c))
1325  << ", obj[c] = " << _realLP->obj(c)
1326  << ", debugRedCost[c] = " << rationalToString(debugRedCost[c])
1327  << "\n");
1328  debugRedCostViolation = -debugRedCost[c];
1329  }
1330 
1331  if(((maximizing && basisStatusCol != SPxSolver::ON_UPPER) || (!maximizing
1332  && basisStatusCol != SPxSolver::ON_LOWER))
1333  && debugRedCost[c] > debugRedCostViolation)
1334  {
1335  MSG_DEBUG(std::cout << "basisStatusCol = " << basisStatusCol
1336  << ", lower tight = " << bool(sol._primal[c] <= lowerRational(c))
1337  << ", upper tight = " << bool(sol._primal[c] >= upperRational(c))
1338  << ", obj[c] = " << _realLP->obj(c)
1339  << ", debugRedCost[c] = " << rationalToString(debugRedCost[c])
1340  << "\n");
1341  debugRedCostViolation = debugRedCost[c];
1342  }
1343  }
1344 
1345  // compute dual violation
1346  Rational debugDualViolation = 0;
1347  Rational debugBasicDualViolation = 0;
1348 
1349  for(int r = numRowsRational() - 1; r >= 0; r--)
1350  {
1351  if(_rowTypes[r] == RANGETYPE_FIXED)
1352  continue;
1353 
1354  const SPxSolver::VarStatus& basisStatusRow = _basisStatusRows[r];
1355  assert(basisStatusRow != SPxSolver::FIXED);
1356 
1357  Rational val = (-dualScale * sol._dual[r]) - Rational(dualReal[r]);
1358 
1359  if(((maximizing && basisStatusRow != SPxSolver::ON_LOWER) || (!maximizing
1360  && basisStatusRow != SPxSolver::ON_UPPER))
1361  && val > debugDualViolation)
1362  {
1363  MSG_DEBUG(std::cout << "basisStatusRow = " << basisStatusRow
1364  << ", lower tight = " << bool(sol._slacks[r] <= lhsRational(r))
1365  << ", upper tight = " << bool(sol._slacks[r] >= rhsRational(r))
1366  << ", dualReal[r] = " << rationalToString(val)
1367  << ", dualReal[r] = " << dualReal[r]
1368  << "\n");
1369  debugDualViolation = val;
1370  }
1371 
1372  if(((maximizing && basisStatusRow != SPxSolver::ON_UPPER) || (!maximizing
1373  && basisStatusRow != SPxSolver::ON_LOWER))
1374  && val < -debugDualViolation)
1375  {
1376  MSG_DEBUG(std::cout << "basisStatusRow = " << basisStatusRow
1377  << ", lower tight = " << bool(sol._slacks[r] <= lhsRational(r))
1378  << ", upper tight = " << bool(sol._slacks[r] >= rhsRational(r))
1379  << ", dualReal[r] = " << rationalToString(val)
1380  << ", dualReal[r] = " << dualReal[r]
1381  << "\n");
1382  debugDualViolation = -val;
1383  }
1384 
1385  if(basisStatusRow == SPxSolver::BASIC && spxAbs(val) > debugBasicDualViolation)
1386  {
1387  MSG_DEBUG(std::cout << "basisStatusRow = " << basisStatusRow
1388  << ", lower tight = " << bool(sol._slacks[r] <= lhsRational(r))
1389  << ", upper tight = " << bool(sol._slacks[r] >= rhsRational(r))
1390  << ", dualReal[r] = " << rationalToString(val)
1391  << ", dualReal[r] = " << dualReal[r]
1392  << "\n");
1393  debugBasicDualViolation = spxAbs(val);
1394  }
1395  }
1396 
1397  if(debugRedCostViolation > _solver.opttol() || debugDualViolation > _solver.opttol()
1398  || debugBasicDualViolation > 1e-9)
1399  {
1400  MSG_WARNING(spxout, spxout << "Warning: floating-point dual solution with violation "
1401  << rationalToString(debugRedCostViolation) << " / "
1402  << rationalToString(debugDualViolation) << " / "
1403  << rationalToString(debugBasicDualViolation)
1404  << " (red. cost, dual, basic).\n");
1405  }
1406  }
1407 #endif
1408 
1409  Rational dualScaleInverseNeg = dualScale;
1410  dualScaleInverseNeg.invert();
1411  dualScaleInverseNeg *= -1;
1413  dualSize = 0;
1414 
1415  for(int r = numRowsRational() - 1; r >= 0; r--)
1416  {
1417  SPxSolver::VarStatus& basisStatusRow = _basisStatusRows[r];
1418 
1419  // it may happen that left-hand and right-hand side are different in the rational, but equal in the real LP,
1420  // leading to a fixed basis status; this is critical because rows with fixed basis status are ignored in the
1421  // computation of the dual violation; to avoid rational comparisons we do not check this but simply switch
1422  // to the left-hand side status
1423  if(basisStatusRow == SPxSolver::FIXED)
1424  basisStatusRow = SPxSolver::ON_LOWER;
1425 
1426  {
1427  if(dualReal[r] != 0)
1428  {
1429  int i = _primalDualDiff.size();
1431  _primalDualDiff.add(r);
1432  _primalDualDiff.value(i) = dualReal[r];
1433  _primalDualDiff.value(i) *= dualScaleInverseNeg;
1434  sol._dual[r] -= _primalDualDiff.value(i);
1435 
1436  dualSize++;
1437  }
1438  else
1439  {
1440  // we do not check whether the dual value is nonzero, because it probably is; this gives us an
1441  // overestimation of the number of nonzeros in the dual solution
1442  dualSize++;
1443  }
1444  }
1445  }
1446 
1447  // update or recompute reduced cost values depending on which looks faster; adding one to the length of the
1448  // dual vector accounts for the objective function vector
1449  if(_primalDualDiff.size() < dualSize + 1)
1450  {
1452 #ifndef NDEBUG
1453  {
1454  DVectorRational activity(_rationalLP->maxObj());
1455  activity *= -1;
1456  _rationalLP->subDualActivity(sol._dual, activity);
1457  }
1458 #endif
1459  }
1460  else
1461  {
1462  // we assume that the objective function vector has less nonzeros than the reduced cost vector, and so multiplying
1463  // with -1 first and subtracting the dual activity should be faster than adding the dual activity and negating
1464  // afterwards
1465  _rationalLP->getObj(sol._redCost);
1467  }
1468 
1469  const int numCorrectedDuals = _primalDualDiff.size();
1470 
1471  if(numCorrectedPrimals + numCorrectedDuals > 0)
1472  {
1473  MSG_INFO2(spxout, spxout << "Corrected " << numCorrectedPrimals << " primal variables and " <<
1474  numCorrectedDuals << " dual values.\n");
1475  }
1476  }
1477  while(true);
1478 
1479  // correct basis status for restricted inequalities
1480  if(_hasBasis)
1481  {
1482  for(int r = numRowsRational() - 1; r >= 0; r--)
1483  {
1484  assert((lhsRational(r) == rhsRational(r)) == (_rowTypes[r] == RANGETYPE_FIXED));
1485 
1487  _basisStatusRows[r] = (maximizing == (sol._dual[r] < 0))
1490  }
1491  }
1492 
1493  // compute objective function values
1494  assert(sol._isPrimalFeasible == sol._isDualFeasible);
1495 
1496  if(sol._isPrimalFeasible)
1497  {
1498  sol._objVal = sol._primal * _rationalLP->maxObj();
1499 
1501  sol._objVal *= -1;
1502  }
1503 
1504  // set objective coefficients for all rows to zero
1506 
1507  // stop rational solving time
1509 }
1510 
1511 
1512 
1513 /// performs iterative refinement on the auxiliary problem for testing unboundedness
1515  SolRational& sol,
1516  bool& hasUnboundedRay,
1517  bool& stopped,
1518  bool& stoppedIter,
1519  bool& error)
1520 {
1521  bool primalFeasible;
1522  bool dualFeasible;
1523  bool infeasible;
1524  bool unbounded;
1525 
1526  // move objective function to constraints and adjust sides and bounds
1528 
1529  // invalidate solution
1530  sol.invalidate();
1531 
1532  // remember current number of refinements
1533  int oldRefinements = _statistics->refinements;
1534 
1535  // perform iterative refinement
1536  _performOptIRStable(sol, false, false, 0, primalFeasible, dualFeasible, infeasible, unbounded,
1537  stopped, stoppedIter, error);
1538 
1539  // update unbounded refinement counter
1540  _statistics->unbdRefinements += _statistics->refinements - oldRefinements;
1541 
1542  // stopped due to some limit
1543  if(stopped)
1544  {
1545  sol.invalidate();
1546  hasUnboundedRay = false;
1547  error = false;
1548  }
1549  // the unbounded problem should always be solved to optimality
1550  else if(error || unbounded || infeasible || !primalFeasible || !dualFeasible)
1551  {
1552  sol.invalidate();
1553  hasUnboundedRay = false;
1554  stopped = false;
1555  error = true;
1556  }
1557  else
1558  {
1559  const Rational& tau = sol._primal[numColsRational() - 1];
1560 
1561  MSG_DEBUG(std::cout << "tau = " << tau << " (roughly " << rationalToString(tau) << ")\n");
1562 
1563  assert(tau <= 1.0 + 2.0 * realParam(SoPlex::FEASTOL));
1564  assert(tau >= -realParam(SoPlex::FEASTOL));
1565 
1566  // because the right-hand side and all bounds (but tau's upper bound) are zero, tau should be approximately
1567  // zero if basic; otherwise at its upper bound 1
1568  error = !(tau >= _rationalPosone || tau <= _rationalFeastol);
1569  assert(!error);
1570 
1571  hasUnboundedRay = (tau >= 1);
1572  }
1573 
1574  // restore problem
1575  _untransformUnbounded(sol, hasUnboundedRay);
1576 }
1577 
1578 
1579 
1580 /// performs iterative refinement on the auxiliary problem for testing feasibility
1582  SolRational& sol,
1583  bool& withDualFarkas,
1584  bool& stopped,
1585  bool& stoppedIter,
1586  bool& error)
1587 {
1588  bool primalFeasible;
1589  bool dualFeasible;
1590  bool infeasible;
1591  bool unbounded;
1592  bool success = false;
1593  error = false;
1594 
1595 #if 0
1596  // if the problem has been found to be infeasible and an approximate Farkas proof is available, we compute a
1597  // scaled unit box around the origin that provably contains no feasible solution; this currently only works for
1598  // equality form
1599  ///@todo check whether approximate Farkas proof can be used
1601  ///@todo if approx Farkas proof is good enough then exit without doing any transformation
1602 #endif
1603 
1604  // remove objective function, shift, homogenize
1606 
1607  // invalidate solution
1608  sol.invalidate();
1609 
1610  do
1611  {
1612  // remember current number of refinements
1613  int oldRefinements = _statistics->refinements;
1614 
1615  // perform iterative refinement
1616  _performOptIRStable(sol, false, false, 0, primalFeasible, dualFeasible, infeasible, unbounded,
1617  stopped, stoppedIter, error);
1618 
1619  // update feasible refinement counter
1620  _statistics->feasRefinements += _statistics->refinements - oldRefinements;
1621 
1622  // stopped due to some limit
1623  if(stopped)
1624  {
1625  sol.invalidate();
1626  withDualFarkas = false;
1627  error = false;
1628  }
1629  // the feasibility problem should always be solved to optimality
1630  else if(error || unbounded || infeasible || !primalFeasible || !dualFeasible)
1631  {
1632  sol.invalidate();
1633  withDualFarkas = false;
1634  stopped = false;
1635  error = true;
1636  }
1637  // else we should have either a refined Farkas proof or an approximate feasible solution to the original
1638  else
1639  {
1640  const Rational& tau = sol._primal[numColsRational() - 1];
1641 
1642  MSG_DEBUG(std::cout << "tau = " << tau << " (roughly " << rationalToString(tau) << ")\n");
1643 
1644  assert(tau >= -realParam(SoPlex::FEASTOL));
1645  assert(tau <= 1.0 + realParam(SoPlex::FEASTOL));
1646 
1647  error = (tau < -_rationalFeastol || tau > _rationalPosone + _rationalFeastol);
1648  withDualFarkas = (tau < _rationalPosone);
1649 
1650  if(withDualFarkas)
1651  {
1654 
1655 #if 0
1656  // check if we can compute sufficiently large Farkas box
1658 #endif
1659 
1660  if(true) //@todo check if computeInfeasBox found a sufficient box
1661  {
1662 
1663  success = true;
1664  sol._isPrimalFeasible = false;
1665  }
1666  }
1667  else
1668  {
1669  sol._isDualFeasible = false;
1670  success = true; //successfully found approximate feasible solution
1671  }
1672  }
1673  }
1674  while(!error && !success && !stopped);
1675 
1676  // restore problem
1677  _untransformFeasibility(sol, withDualFarkas);
1678 }
1679 
1680 
1681 
1682 /// reduces matrix coefficient in absolute value by the lifting procedure of Thiele et al. 2013
1684 {
1685  MSG_DEBUG(std::cout << "Reducing matrix coefficients by lifting.\n");
1686 
1687  // start timing
1689 
1690  MSG_DEBUG(_realLP->writeFile("beforeLift.lp", 0, 0, 0));
1691 
1692  // remember unlifted state
1695 
1696  // allocate vector memory
1697  DSVectorRational colVector;
1698  SVectorRational::Element liftingRowMem[2];
1699  SVectorRational liftingRowVector(2, liftingRowMem);
1700 
1701  // search each column for large nonzeros entries
1702  const Rational maxValue = realParam(SoPlex::LIFTMAXVAL);
1703 
1704  for(int i = 0; i < numColsRational(); i++)
1705  {
1706  MSG_DEBUG(std::cout << "in lifting: examining column " << i << "\n");
1707 
1708  // get column vector
1709  colVector = colVectorRational(i);
1710 
1711  bool addedLiftingRow = false;
1712  int liftingColumnIndex = -1;
1713 
1714  // go through nonzero entries of the column
1715  for(int k = colVector.size() - 1; k >= 0; k--)
1716  {
1717  const Rational& value = colVector.value(k);
1718 
1719  if(spxAbs(value) > maxValue)
1720  {
1721  MSG_DEBUG(std::cout << " --> nonzero " << k << " has value " << rationalToString(
1722  value) << " in row " << colVector.index(k) << "\n");
1723 
1724  // add new column equal to maxValue times original column
1725  if(!addedLiftingRow)
1726  {
1727  MSG_DEBUG(std::cout << " --> adding lifting row\n");
1728 
1729  assert(liftingRowVector.size() == 0);
1730 
1731  liftingColumnIndex = numColsRational();
1732  liftingRowVector.add(i, maxValue);
1733  liftingRowVector.add(liftingColumnIndex, -1);
1734 
1735  _rationalLP->addRow(LPRowRational(0, liftingRowVector, 0));
1736  _realLP->addRow(LPRowReal(0.0, DSVectorReal(liftingRowVector), 0.0));
1737 
1738  assert(liftingColumnIndex == numColsRational() - 1);
1739  assert(liftingColumnIndex == numColsReal() - 1);
1740 
1743 
1744  liftingRowVector.clear();
1745  addedLiftingRow = true;
1746  }
1747 
1748  // get row index
1749  int rowIndex = colVector.index(k);
1750  assert(rowIndex >= 0);
1751  assert(rowIndex < _beforeLiftRows);
1752  assert(liftingColumnIndex == numColsRational() - 1);
1753 
1754  MSG_DEBUG(std::cout << " --> changing matrix\n");
1755 
1756  // remove nonzero from original column
1757  _rationalLP->changeElement(rowIndex, i, 0);
1758  _realLP->changeElement(rowIndex, i, 0.0);
1759 
1760  // add nonzero divided by maxValue to new column
1761  Rational newValue(value);
1762  newValue /= maxValue;
1763  _rationalLP->changeElement(rowIndex, liftingColumnIndex, newValue);
1764  _realLP->changeElement(rowIndex, liftingColumnIndex, Real(newValue));
1765  }
1766  }
1767  }
1768 
1769  // search each column for small nonzeros entries
1770  const Rational minValue = realParam(SoPlex::LIFTMINVAL);
1771 
1772  for(int i = 0; i < numColsRational(); i++)
1773  {
1774  MSG_DEBUG(std::cout << "in lifting: examining column " << i << "\n");
1775 
1776  // get column vector
1777  colVector = colVectorRational(i);
1778 
1779  bool addedLiftingRow = false;
1780  int liftingColumnIndex = -1;
1781 
1782  // go through nonzero entries of the column
1783  for(int k = colVector.size() - 1; k >= 0; k--)
1784  {
1785  const Rational& value = colVector.value(k);
1786 
1787  if(spxAbs(value) < minValue)
1788  {
1789  MSG_DEBUG(std::cout << " --> nonzero " << k << " has value " << rationalToString(
1790  value) << " in row " << colVector.index(k) << "\n");
1791 
1792  // add new column equal to maxValue times original column
1793  if(!addedLiftingRow)
1794  {
1795  MSG_DEBUG(std::cout << " --> adding lifting row\n");
1796 
1797  assert(liftingRowVector.size() == 0);
1798 
1799  liftingColumnIndex = numColsRational();
1800  liftingRowVector.add(i, minValue);
1801  liftingRowVector.add(liftingColumnIndex, -1);
1802 
1803  _rationalLP->addRow(LPRowRational(0, liftingRowVector, 0));
1804  _realLP->addRow(LPRowReal(0.0, DSVectorReal(liftingRowVector), 0.0));
1805 
1806  assert(liftingColumnIndex == numColsRational() - 1);
1807  assert(liftingColumnIndex == numColsReal() - 1);
1808 
1811 
1812  liftingRowVector.clear();
1813  addedLiftingRow = true;
1814  }
1815 
1816  // get row index
1817  int rowIndex = colVector.index(k);
1818  assert(rowIndex >= 0);
1819  assert(rowIndex < _beforeLiftRows);
1820  assert(liftingColumnIndex == numColsRational() - 1);
1821 
1822  MSG_DEBUG(std::cout << " --> changing matrix\n");
1823 
1824  // remove nonzero from original column
1825  _rationalLP->changeElement(rowIndex, i, 0);
1826  _realLP->changeElement(rowIndex, i, 0.0);
1827 
1828  // add nonzero divided by maxValue to new column
1829  Rational newValue(value);
1830  newValue /= minValue;
1831  _rationalLP->changeElement(rowIndex, liftingColumnIndex, newValue);
1832  _realLP->changeElement(rowIndex, liftingColumnIndex, Real(newValue));
1833  }
1834  }
1835  }
1836 
1837  // adjust basis
1838  if(_hasBasis)
1839  {
1840  assert(numColsRational() >= _beforeLiftCols);
1841  assert(numRowsRational() >= _beforeLiftRows);
1842 
1846  }
1847 
1848  MSG_DEBUG(_realLP->writeFile("afterLift.lp", 0, 0, 0));
1849 
1850  // stop timing
1852 
1853  if(numColsRational() > _beforeLiftCols || numRowsRational() > _beforeLiftRows)
1854  {
1855  MSG_INFO1(spxout, spxout << "Added " << numColsRational() - _beforeLiftCols << " columns and "
1856  << numRowsRational() - _beforeLiftRows << " rows to reduce large matrix coefficients\n.");
1857  }
1858 }
1859 
1860 
1861 
1862 /// undoes lifting
1864 {
1865  // start timing
1867 
1868  // print LP if in debug mode
1869  MSG_DEBUG(_realLP->writeFile("beforeProject.lp", 0, 0, 0));
1870 
1871  assert(numColsRational() >= _beforeLiftCols);
1872  assert(numRowsRational() >= _beforeLiftRows);
1873 
1874  // shrink rational LP to original size
1877 
1878  // shrink real LP to original size
1881 
1882  // adjust solution
1883  if(sol.isPrimalFeasible())
1884  {
1887  }
1888 
1889  if(sol.hasPrimalRay())
1890  {
1892  }
1893 
1894  ///@todo if we know the mapping between original and lifting columns, we simply need to add the reduced cost of
1895  /// the lifting column to the reduced cost of the original column; this is not implemented now, because for
1896  /// optimal solutions the reduced costs of the lifting columns are zero
1897  const Rational maxValue = realParam(SoPlex::LIFTMAXVAL);
1898 
1899  for(int i = _beforeLiftCols; i < numColsRational() && sol._isDualFeasible; i++)
1900  {
1901  if(spxAbs(maxValue * sol._redCost[i]) > _rationalOpttol)
1902  {
1903  MSG_INFO1(spxout, spxout << "Warning: lost dual solution during project phase.\n");
1904  sol._isDualFeasible = false;
1905  }
1906  }
1907 
1908  if(sol.isDualFeasible())
1909  {
1912  }
1913 
1914  if(sol.hasDualFarkas())
1915  {
1917  }
1918 
1919  // adjust basis
1920  for(int i = _beforeLiftCols; i < numColsRational() && _hasBasis; i++)
1921  {
1923  {
1924  MSG_INFO1(spxout, spxout <<
1925  "Warning: lost basis during project phase because of nonbasic lifting column.\n");
1926  _hasBasis = false;
1928  }
1929  }
1930 
1931  for(int i = _beforeLiftRows; i < numRowsRational() && _hasBasis; i++)
1932  {
1934  {
1935  MSG_INFO1(spxout, spxout <<
1936  "Warning: lost basis during project phase because of basic lifting row.\n");
1937  _hasBasis = false;
1939  }
1940  }
1941 
1942  if(_hasBasis)
1943  {
1947  }
1948 
1949  // print LP if in debug mode
1950  MSG_DEBUG(_realLP->writeFile("afterProject.lp", 0, 0, 0));
1951 
1952  // stop timing
1954 }
1955 
1956 
1957 
1958 /// stores objective, bounds, and sides of real LP
1960 {
1961 #ifndef SOPLEX_MANUAL_ALT
1962 
1964  {
1966  return;
1967  }
1968 
1969 #endif
1970 
1971  _manualLower = _realLP->lower();
1972  _manualUpper = _realLP->upper();
1973  _manualLhs = _realLP->lhs();
1974  _manualRhs = _realLP->rhs();
1977 }
1978 
1979 
1980 
1981 /// restores objective, bounds, and sides of real LP
1983 {
1985  {
1986 #ifndef SOPLEX_MANUAL_ALT
1988 #else
1994 #endif
1995 
1996  if(_hasBasis)
1997  {
1998  // in manual sync mode, if the right-hand side of an equality constraint is not floating-point
1999  // representable, the user might have constructed the constraint in the real LP by rounding down the
2000  // left-hand side and rounding up the right-hand side; if the basis status is fixed, we need to adjust it
2001  for(int i = 0; i < _solver.nRows(); i++)
2002  {
2003  if(_basisStatusRows[i] == SPxSolver::FIXED && _solver.lhs(i) != _solver.rhs(i))
2004  {
2005  assert(_solver.rhs(i) == spxNextafter(_solver.lhs(i), infinity));
2006 
2010  {
2012  }
2013  else
2014  {
2016  }
2017  }
2018  }
2019 
2022  }
2023  }
2024  else
2025  {
2031  }
2032 }
2033 
2034 
2035 
2036 /// introduces slack variables to transform inequality constraints into equations for both rational and real LP,
2037 /// which should be in sync
2039 {
2040  MSG_DEBUG(std::cout << "Transforming rows to equation form.\n");
2041 
2042  // start timing
2044 
2045  MSG_DEBUG(_realLP->writeFile("beforeTransEqu.lp", 0, 0, 0));
2046 
2047  // clear array of slack columns
2048  _slackCols.clear();
2049 
2050  // add artificial slack variables to convert inequality to equality constraints
2051  for(int i = 0; i < numRowsRational(); i++)
2052  {
2053  assert((lhsRational(i) == rhsRational(i)) == (_rowTypes[i] == RANGETYPE_FIXED));
2054 
2055  if(_rowTypes[i] != RANGETYPE_FIXED)
2056  {
2058 
2059  if(_rationalLP->lhs(i) != 0)
2061 
2062  if(_rationalLP->rhs(i) != 0)
2064 
2065  assert(_rationalLP->lhs(i) == 0);
2066  assert(_rationalLP->rhs(i) == 0);
2067  _realLP->changeRange(i, 0.0, 0.0);
2070  }
2071  }
2072 
2075 
2076  // adjust basis
2077  if(_hasBasis)
2078  {
2079  for(int i = 0; i < _slackCols.num(); i++)
2080  {
2081  int row = _slackCols.colVector(i).index(0);
2082 
2083  assert(row >= 0);
2084  assert(row < numRowsRational());
2085 
2086  switch(_basisStatusRows[row])
2087  {
2088  case SPxSolver::ON_LOWER:
2090  break;
2091 
2092  case SPxSolver::ON_UPPER:
2094  break;
2095 
2096  case SPxSolver::BASIC:
2097  case SPxSolver::FIXED:
2098  default:
2100  break;
2101  }
2102 
2104  }
2105 
2107  }
2108 
2109  MSG_DEBUG(_realLP->writeFile("afterTransEqu.lp", 0, 0, 0));
2110 
2111  // stop timing
2113 
2114  if(_slackCols.num() > 0)
2115  {
2116  MSG_INFO1(spxout, spxout << "Added " << _slackCols.num() <<
2117  " slack columns to transform rows to equality form.\n");
2118  }
2119 }
2120 
2121 
2122 
2123 /// restores original problem
2125 {
2126  // start timing
2128 
2129  // print LP if in debug mode
2130  MSG_DEBUG(_realLP->writeFile("beforeUntransEqu.lp", 0, 0, 0));
2131 
2132  int numCols = numColsRational();
2133  int numOrigCols = numColsRational() - _slackCols.num();
2134 
2135  // adjust solution
2136  if(sol.isPrimalFeasible())
2137  {
2138  for(int i = 0; i < _slackCols.num(); i++)
2139  {
2140  int col = numOrigCols + i;
2141  int row = _slackCols.colVector(i).index(0);
2142 
2143  assert(row >= 0);
2144  assert(row < numRowsRational());
2145 
2146  sol._slacks[row] -= sol._primal[col];
2147  }
2148 
2149  sol._primal.reDim(numOrigCols);
2150  }
2151 
2152  if(sol.hasPrimalRay())
2153  {
2154  sol._primalRay.reDim(numOrigCols);
2155  }
2156 
2157  // adjust basis
2158  if(_hasBasis)
2159  {
2160  for(int i = 0; i < _slackCols.num(); i++)
2161  {
2162  int col = numOrigCols + i;
2163  int row = _slackCols.colVector(i).index(0);
2164 
2165  assert(row >= 0);
2166  assert(row < numRowsRational());
2167  assert(_basisStatusRows[row] != SPxSolver::UNDEFINED);
2168  assert(_basisStatusRows[row] != SPxSolver::ZERO || lhsRational(row) == 0);
2169  assert(_basisStatusRows[row] != SPxSolver::ZERO || rhsRational(row) == 0);
2171 
2172  MSG_DEBUG(std::cout << "slack column " << col << " for row " << row
2173  << ": col status=" << _basisStatusCols[col]
2174  << ", row status=" << _basisStatusRows[row]
2175  << ", redcost=" << rationalToString(sol._redCost[col])
2176  << ", dual=" << rationalToString(sol._dual[row]) << "\n");
2177 
2179  {
2180  switch(_basisStatusCols[col])
2181  {
2182  case SPxSolver::ON_LOWER:
2184  break;
2185 
2186  case SPxSolver::ON_UPPER:
2188  break;
2189 
2190  case SPxSolver::BASIC:
2191  case SPxSolver::FIXED:
2192  default:
2193  _basisStatusRows[row] = _basisStatusCols[col];
2194  break;
2195  }
2196  }
2197  }
2198 
2199  _basisStatusCols.reSize(numOrigCols);
2200 
2201  if(_slackCols.num() > 0)
2203  }
2204 
2205  // not earlier because of debug message
2206  if(sol.isDualFeasible())
2207  {
2208  sol._redCost.reDim(numOrigCols);
2209  }
2210 
2211  // restore sides and remove slack columns
2212  for(int i = 0; i < _slackCols.num(); i++)
2213  {
2214  int col = numOrigCols + i;
2215  int row = _slackCols.colVector(i).index(0);
2216 
2217  if(upperRational(col) != 0)
2218  _rationalLP->changeLhs(row, -upperRational(col));
2219 
2220  if(lowerRational(col) != 0)
2221  _rationalLP->changeRhs(row, -lowerRational(col));
2222 
2223  assert(_rationalLP->lhs(row) == -upperRational(col));
2224  assert(_rationalLP->rhs(row) == -lowerRational(col));
2225  _rowTypes[row] = _switchRangeType(_colTypes[col]);
2226  }
2227 
2228  _rationalLP->removeColRange(numOrigCols, numCols - 1);
2229  _realLP->removeColRange(numOrigCols, numCols - 1);
2230  _colTypes.reSize(numOrigCols);
2231 
2232  // objective, bounds, and sides of real LP are restored only after _solveRational()
2233 
2234  // print LP if in debug mode
2235  MSG_DEBUG(_realLP->writeFile("afterUntransEqu.lp", 0, 0, 0));
2236 
2237  // stop timing
2239 }
2240 
2241 
2242 
2243 /// transforms LP to unboundedness problem by moving the objective function to the constraints, changing right-hand
2244 /// side and bounds to zero, and adding an auxiliary variable for the decrease in the objective function
2246 {
2247  MSG_INFO1(spxout, spxout << "Setting up LP to compute primal unbounded ray.\n");
2248 
2249  // start timing
2251 
2252  // print LP if in debug mode
2253  MSG_DEBUG(_realLP->writeFile("beforeTransUnbounded.lp", 0, 0, 0));
2254 
2255  // store bounds
2258 
2259  for(int c = numColsRational() - 1; c >= 0; c--)
2260  {
2261  if(_lowerFinite(_colTypes[c]))
2263 
2264  if(_upperFinite(_colTypes[c]))
2266  }
2267 
2268  // store sides
2271 
2272  for(int r = numRowsRational() - 1; r >= 0; r--)
2273  {
2274  if(_lowerFinite(_rowTypes[r]))
2275  _unboundedLhs[r] = lhsRational(r);
2276 
2277  if(_upperFinite(_rowTypes[r]))
2278  _unboundedRhs[r] = rhsRational(r);
2279  }
2280 
2281  // make right-hand side zero
2282  for(int r = numRowsRational() - 1; r >= 0; r--)
2283  {
2284  assert((lhsRational(r) > _rationalNegInfty) == _lowerFinite(_rowTypes[r]));
2285 
2286  if(_lowerFinite(_rowTypes[r]))
2287  {
2288  _rationalLP->changeLhs(r, 0);
2289  _realLP->changeLhs(r, 0.0);
2290  }
2291  else if(_realLP->lhs(r) > -realParam(SoPlex::INFTY))
2293 
2294  assert((rhsRational(r) < _rationalPosInfty) == _upperFinite(_rowTypes[r]));
2295 
2296  if(_upperFinite(_rowTypes[r]))
2297  {
2298  _rationalLP->changeRhs(r, 0);
2299  _realLP->changeRhs(r, 0.0);
2300  }
2301  else if(_realLP->rhs(r) < realParam(SoPlex::INFTY))
2303  }
2304 
2305  // transform objective function to constraint and add auxiliary variable
2306  int numOrigCols = numColsRational();
2307  DSVectorRational obj(numOrigCols + 1);
2308  ///@todo implement this without copying the objective function
2309  obj = _rationalLP->maxObj();
2310  obj.add(numOrigCols, -1);
2311  _rationalLP->addRow(LPRowRational(0, obj, 0));
2312  _realLP->addRow(LPRowReal(0, DSVectorReal(obj), 0));
2314 
2315  assert(numColsRational() == numOrigCols + 1);
2316 
2317  // set objective coefficient and bounds for auxiliary variable
2318  _rationalLP->changeMaxObj(numOrigCols, 1);
2319  _realLP->changeMaxObj(numOrigCols, 1.0);
2320 
2321  _rationalLP->changeBounds(numOrigCols, _rationalNegInfty, 1);
2322  _realLP->changeBounds(numOrigCols, -realParam(SoPlex::INFTY), 1.0);
2324 
2325  // set objective coefficients to zero and adjust bounds for problem variables
2326  for(int c = numColsRational() - 2; c >= 0; c--)
2327  {
2328  _rationalLP->changeObj(c, 0);
2329  _realLP->changeObj(c, 0.0);
2330 
2331  assert((lowerRational(c) > _rationalNegInfty) == _lowerFinite(_colTypes[c]));
2332 
2333  if(_lowerFinite(_colTypes[c]))
2334  {
2335  _rationalLP->changeLower(c, 0);
2336  _realLP->changeLower(c, 0.0);
2337  }
2338  else if(_realLP->lower(c) > -realParam(SoPlex::INFTY))
2340 
2341  assert((upperRational(c) < _rationalPosInfty) == _upperFinite(_colTypes[c]));
2342 
2343  if(_upperFinite(_colTypes[c]))
2344  {
2345  _rationalLP->changeUpper(c, 0);
2346  _realLP->changeUpper(c, 0.0);
2347  }
2348  else if(_realLP->upper(c) < realParam(SoPlex::INFTY))
2350  }
2351 
2352  // adjust basis
2353  if(_hasBasis)
2354  {
2358  }
2359 
2360  // print LP if in debug mode
2361  MSG_DEBUG(_realLP->writeFile("afterTransUnbounded.lp", 0, 0, 0));
2362 
2363  // stop timing
2365 }
2366 
2367 
2368 
2369 /// undoes transformation to unboundedness problem
2370 void SoPlex::_untransformUnbounded(SolRational& sol, bool unbounded)
2371 {
2372  // start timing
2374 
2375  // print LP if in debug mode
2376  MSG_DEBUG(_realLP->writeFile("beforeUntransUnbounded.lp", 0, 0, 0));
2377 
2378  int numOrigCols = numColsRational() - 1;
2379  int numOrigRows = numRowsRational() - 1;
2380  const Rational& tau = sol._primal[numOrigCols];
2381 
2382  // adjust solution and basis
2383  if(unbounded)
2384  {
2385  assert(tau >= _rationalPosone);
2386 
2387  sol._isPrimalFeasible = false;
2388  sol._hasPrimalRay = true;
2389  sol._isDualFeasible = false;
2390  sol._hasDualFarkas = false;
2391 
2392  if(tau != 1)
2393  sol._primal /= tau;
2394 
2395  sol._primalRay = sol._primal;
2396  sol._primalRay.reDim(numOrigCols);
2397 
2398  _hasBasis = (_basisStatusCols[numOrigCols] != SPxSolver::BASIC
2399  && _basisStatusRows[numOrigRows] == SPxSolver::BASIC);
2400  _basisStatusCols.reSize(numOrigCols);
2401  _basisStatusRows.reSize(numOrigRows);
2402  }
2404  {
2405  const Rational& alpha = sol._dual[numOrigRows];
2406 
2407  assert(sol._isDualFeasible);
2408  assert(alpha <= _rationalFeastol - _rationalPosone);
2409 
2410  sol._isPrimalFeasible = false;
2411  sol._hasPrimalRay = false;
2412  sol._hasDualFarkas = false;
2413 
2414  if(alpha != -1)
2415  {
2416  sol._dual /= -alpha;
2417  sol._redCost /= -alpha;
2418  }
2419 
2420  sol._dual.reDim(numOrigRows);
2421  sol._redCost.reDim(numOrigCols);
2422  }
2423  else
2424  {
2425  sol.invalidate();
2426  _hasBasis = false;
2427  _basisStatusCols.reSize(numOrigCols);
2428  _basisStatusCols.reSize(numOrigRows);
2429  }
2430 
2431  // recover objective function
2432  const SVectorRational& objRowVector = _rationalLP->rowVector(numOrigRows);
2433 
2434  for(int i = objRowVector.size() - 1; i >= 0; i--)
2435  {
2436  _rationalLP->changeMaxObj(objRowVector.index(i), objRowVector.value(i));
2437  _realLP->changeMaxObj(objRowVector.index(i), Real(objRowVector.value(i)));
2438  }
2439 
2440  // remove objective function constraint and auxiliary variable
2441  _rationalLP->removeRow(numOrigRows);
2442  _realLP->removeRow(numOrigRows);
2443  _rowTypes.reSize(numOrigRows);
2444 
2445  _rationalLP->removeCol(numOrigCols);
2446  _realLP->removeCol(numOrigCols);
2447  _colTypes.reSize(numOrigCols);
2448 
2449  // restore objective, sides and bounds
2450  for(int r = numRowsRational() - 1; r >= 0; r--)
2451  {
2452  if(_lowerFinite(_rowTypes[r]))
2453  {
2456  }
2457 
2458  if(_upperFinite(_rowTypes[r]))
2459  {
2462  }
2463 
2464  assert((lhsRational(r) > _rationalNegInfty) == _lowerFinite(_rowTypes[r]));
2465  assert((rhsRational(r) < _rationalPosInfty) == _upperFinite(_rowTypes[r]));
2466  assert((lhsReal(r) > -realParam(SoPlex::INFTY)) == _lowerFinite(_rowTypes[r]));
2467  assert((rhsReal(r) < realParam(SoPlex::INFTY)) == _upperFinite(_rowTypes[r]));
2468  }
2469 
2470  for(int c = numColsRational() - 1; c >= 0; c--)
2471  {
2472  if(_lowerFinite(_colTypes[c]))
2473  {
2476  }
2477 
2478  if(_upperFinite(_colTypes[c]))
2479  {
2482  }
2483 
2484  assert((lowerRational(c) > _rationalNegInfty) == _lowerFinite(_colTypes[c]));
2485  assert((upperRational(c) < _rationalPosInfty) == _upperFinite(_colTypes[c]));
2486  assert((lowerReal(c) > -realParam(SoPlex::INFTY)) == _lowerFinite(_colTypes[c]));
2487  assert((upperReal(c) < realParam(SoPlex::INFTY)) == _upperFinite(_colTypes[c]));
2488  }
2489 
2490  // invalidate rational basis factorization
2492 
2493  // print LP if in debug mode
2494  MSG_DEBUG(_realLP->writeFile("afterUntransUnbounded.lp", 0, 0, 0));
2495 
2496  // stop timing
2498 }
2499 
2500 
2501 
2502 /// store basis
2504 {
2505  assert(!_storedBasis);
2506 
2507  if(_hasBasis)
2508  {
2509  _storedBasis = true;
2512  }
2513  else
2514  _storedBasis = false;
2515 }
2516 
2517 
2518 
2519 /// restore basis
2521 {
2522  if(_storedBasis)
2523  {
2524  _hasBasis = true;
2527  _storedBasis = false;
2528  }
2529 }
2530 
2531 
2532 
2533 /// transforms LP to feasibility problem by removing the objective function, shifting variables, and homogenizing the
2534 /// right-hand side
2536 {
2537  MSG_INFO1(spxout, spxout << "Setting up LP to test for feasibility.\n");
2538 
2539  // start timing
2541 
2542  // print LP if in debug mode
2543  MSG_DEBUG(_realLP->writeFile("beforeTransFeas.lp", 0, 0, 0));
2544 
2545  // store objective function
2547 
2548  for(int c = numColsRational() - 1; c >= 0; c--)
2549  _feasObj[c] = _rationalLP->maxObj(c);
2550 
2551  // store bounds
2554 
2555  for(int c = numColsRational() - 1; c >= 0; c--)
2556  {
2557  if(_lowerFinite(_colTypes[c]))
2558  _feasLower[c] = lowerRational(c);
2559 
2560  if(_upperFinite(_colTypes[c]))
2561  _feasUpper[c] = upperRational(c);
2562  }
2563 
2564  // store sides
2567 
2568  for(int r = numRowsRational() - 1; r >= 0; r--)
2569  {
2570  if(_lowerFinite(_rowTypes[r]))
2571  _feasLhs[r] = lhsRational(r);
2572 
2573  if(_upperFinite(_rowTypes[r]))
2574  _feasRhs[r] = rhsRational(r);
2575  }
2576 
2577  // set objective coefficients to zero; shift primal space such as to guarantee that the zero solution is within
2578  // the bounds
2579  Rational shiftValue;
2580  Rational shiftValue2;
2581 
2582  for(int c = numColsRational() - 1; c >= 0; c--)
2583  {
2584  _rationalLP->changeMaxObj(c, 0);
2585  _realLP->changeMaxObj(c, 0.0);
2586 
2587  if(lowerRational(c) > 0)
2588  {
2589  const SVectorRational& colVector = colVectorRational(c);
2590 
2591  for(int i = 0; i < colVector.size(); i++)
2592  {
2593  shiftValue = colVector.value(i);
2594  shiftValue *= lowerRational(c);
2595  int r = colVector.index(i);
2596 
2597  assert((lhsRational(r) > _rationalNegInfty) == _lowerFinite(_rowTypes[r]));
2598  assert((rhsRational(r) < _rationalPosInfty) == _upperFinite(_rowTypes[r]));
2599 
2601  {
2602  shiftValue2 = lhsRational(r);
2603  shiftValue2 -= shiftValue;
2604  _rationalLP->changeLhs(r, shiftValue2);
2605  _realLP->changeLhs(r, Real(shiftValue2));
2606 
2607  shiftValue -= rhsRational(r);
2608  shiftValue *= -1;
2609  _rationalLP->changeRhs(r, shiftValue);
2610  _realLP->changeRhs(r, Real(shiftValue));
2611  }
2612  else if(_lowerFinite(_rowTypes[r]))
2613  {
2614  shiftValue -= lhsRational(r);
2615  shiftValue *= -1;
2616  _rationalLP->changeLhs(r, shiftValue);
2617  _realLP->changeLhs(r, Real(shiftValue));
2618  }
2619  else if(_upperFinite(_rowTypes[r]))
2620  {
2621  shiftValue -= rhsRational(r);
2622  shiftValue *= -1;
2623  _rationalLP->changeRhs(r, shiftValue);
2624  _realLP->changeRhs(r, Real(shiftValue));
2625  }
2626  }
2627 
2628  assert((upperRational(c) < _rationalPosInfty) == _upperFinite(_colTypes[c]));
2629 
2630  if(_upperFinite(_colTypes[c]))
2631  {
2633  _realLP->changeBounds(c, 0.0, Real(upperRational(c)));
2634  }
2635  else if(_realLP->upper(c) < realParam(SoPlex::INFTY))
2636  {
2637  _rationalLP->changeLower(c, 0);
2639  }
2640  else
2641  {
2642  _rationalLP->changeLower(c, 0);
2643  _realLP->changeLower(c, 0.0);
2644  }
2645  }
2646  else if(upperRational(c) < 0)
2647  {
2648  const SVectorRational& colVector = colVectorRational(c);
2649 
2650  for(int i = 0; i < colVector.size(); i++)
2651  {
2652  shiftValue = colVector.value(i);
2653  shiftValue *= upperRational(c);
2654  int r = colVector.index(i);
2655 
2656  assert((lhsRational(r) > _rationalNegInfty) == _lowerFinite(_rowTypes[r]));
2657  assert((rhsRational(r) < _rationalPosInfty) == _upperFinite(_rowTypes[r]));
2658 
2660  {
2661  shiftValue2 = lhsRational(r);
2662  shiftValue2 -= shiftValue;
2663  _rationalLP->changeLhs(r, shiftValue2);
2664  _realLP->changeLhs(r, Real(shiftValue2));
2665 
2666  shiftValue -= rhsRational(r);
2667  shiftValue *= -1;
2668  _rationalLP->changeRhs(r, shiftValue);
2669  _realLP->changeRhs(r, Real(shiftValue));
2670  }
2671  else if(_lowerFinite(_rowTypes[r]))
2672  {
2673  shiftValue -= lhsRational(r);
2674  shiftValue *= -1;
2675  _rationalLP->changeLhs(r, shiftValue);
2676  _realLP->changeLhs(r, Real(shiftValue));
2677  }
2678  else if(_upperFinite(_rowTypes[r]))
2679  {
2680  shiftValue -= rhsRational(r);
2681  shiftValue *= -1;
2682  _rationalLP->changeRhs(r, shiftValue);
2683  _realLP->changeRhs(r, Real(shiftValue));
2684  }
2685  }
2686 
2687  assert((lowerRational(c) > _rationalNegInfty) == _lowerFinite(_colTypes[c]));
2688 
2689  if(_lowerFinite(_colTypes[c]))
2690  {
2692  _realLP->changeBounds(c, Real(lowerRational(c)), 0.0);
2693  }
2694  else if(_realLP->lower(c) > -realParam(SoPlex::INFTY))
2695  {
2696  _rationalLP->changeUpper(c, 0);
2698  }
2699  else
2700  {
2701  _rationalLP->changeUpper(c, 0);
2702  _realLP->changeUpper(c, 0.0);
2703  }
2704  }
2705  else
2706  {
2707  if(_lowerFinite(_colTypes[c]))
2709  else if(_realLP->lower(c) > -realParam(SoPlex::INFTY))
2711 
2712  if(_upperFinite(_colTypes[c]))
2714  else if(_realLP->upper(c) < realParam(SoPlex::INFTY))
2716  }
2717 
2718  assert(lowerReal(c) <= upperReal(c));
2719  }
2720 
2721  // homogenize sides
2722  _tauColVector.clear();
2723 
2724  for(int r = numRowsRational() - 1; r >= 0; r--)
2725  {
2726  if(lhsRational(r) > 0)
2727  {
2728  _tauColVector.add(r, lhsRational(r));
2729  assert((rhsRational(r) < _rationalPosInfty) == _upperFinite(_rowTypes[r]));
2730 
2731  if(_upperFinite(_rowTypes[r]))
2732  {
2734  _realLP->changeRange(r, 0.0, Real(rhsRational(r)));
2735  }
2736  else
2737  {
2738  _rationalLP->changeLhs(r, 0);
2739  _realLP->changeLhs(r, 0.0);
2740 
2741  if(_realLP->rhs(r) < realParam(SoPlex::INFTY))
2743  }
2744  }
2745  else if(rhsRational(r) < 0)
2746  {
2747  _tauColVector.add(r, rhsRational(r));
2748  assert((lhsRational(r) > _rationalNegInfty) == _lowerFinite(_rowTypes[r]));
2749 
2750  if(_lowerFinite(_rowTypes[r]))
2751  {
2753  _realLP->changeRange(r, Real(lhsRational(r)), 0.0);
2754  }
2755  else
2756  {
2757  _rationalLP->changeRhs(r, 0);
2758  _realLP->changeRhs(r, 0.0);
2759 
2760  if(_realLP->lhs(r) > -realParam(SoPlex::INFTY))
2762  }
2763  }
2764  else
2765  {
2766  if(_lowerFinite(_rowTypes[r]))
2767  _realLP->changeLhs(r, Real(lhsRational(r)));
2768  else if(_realLP->lhs(r) > -realParam(SoPlex::INFTY))
2770 
2771  if(_upperFinite(_rowTypes[r]))
2772  _realLP->changeRhs(r, Real(rhsRational(r)));
2773  else if(_realLP->rhs(r) < realParam(SoPlex::INFTY))
2775  }
2776 
2777  assert(rhsReal(r) <= rhsReal(r));
2778  }
2779 
2780  ///@todo exploit this case by returning without LP solving
2781  if(_tauColVector.size() == 0)
2782  {
2783  MSG_INFO3(spxout, spxout << "LP is trivially feasible.\n");
2784  }
2785 
2786  // add artificial column
2787  SPxColId id;
2788  _tauColVector *= -1;
2789  _rationalLP->addCol(id,
2791  _rationalNegone),
2792  _tauColVector, 1, 0));
2793  _realLP->addCol(id,
2795  DSVectorReal(_tauColVector), 1.0, 0.0));
2797 
2798  // adjust basis
2799  if(_hasBasis)
2800  {
2802  }
2803 
2804  // invalidate rational basis factorization
2806 
2807  // print LP if in debug mode
2808  MSG_DEBUG(_realLP->writeFile("afterTransFeas.lp", 0, 0, 0));
2809 
2810  // stop timing
2812 }
2813 
2814 
2815 
2816 /// undoes transformation to feasibility problem
2818 {
2819  // start timing
2821 
2822  // print LP if in debug mode
2823  MSG_DEBUG(_realLP->writeFile("beforeUntransFeas.lp", 0, 0, 0));
2824 
2825  int numOrigCols = numColsRational() - 1;
2826 
2827  // adjust solution and basis
2828  if(infeasible)
2829  {
2830  assert(sol._isDualFeasible);
2831  assert(sol._primal[numOrigCols] < 1);
2832 
2833  sol._isPrimalFeasible = false;
2834  sol._hasPrimalRay = false;
2835  sol._isDualFeasible = false;
2836  sol._hasDualFarkas = true;
2837 
2838  sol._dualFarkas = sol._dual;
2839 
2840  _hasBasis = false;
2841  _basisStatusCols.reSize(numOrigCols);
2842  }
2843  else if(sol._isPrimalFeasible)
2844  {
2845  assert(sol._primal[numOrigCols] >= 1);
2846 
2847  sol._hasPrimalRay = false;
2848  sol._isDualFeasible = false;
2849  sol._hasDualFarkas = false;
2850 
2851  if(sol._primal[numOrigCols] != 1)
2852  {
2853  sol._slacks /= sol._primal[numOrigCols];
2854 
2855  for(int i = 0; i < numOrigCols; i++)
2856  sol._primal[i] /= sol._primal[numOrigCols];
2857 
2858  sol._primal[numOrigCols] = 1;
2859  }
2860 
2861  sol._primal.reDim(numOrigCols);
2862  sol._slacks -= _rationalLP->colVector(numOrigCols);
2863 
2864  _hasBasis = (_basisStatusCols[numOrigCols] != SPxSolver::BASIC);
2865  _basisStatusCols.reSize(numOrigCols);
2866  }
2867  else
2868  {
2869  _hasBasis = false;
2870  _basisStatusCols.reSize(numOrigCols);
2871  }
2872 
2873  // restore right-hand side
2874  for(int r = numRowsRational() - 1; r >= 0; r--)
2875  {
2877  || _feasLhs[r] - lhsRational(r) == _feasRhs[r] - rhsRational(r));
2878 
2879  if(_lowerFinite(_rowTypes[r]))
2880  {
2881  _rationalLP->changeLhs(r, _feasLhs[r]);
2882  _realLP->changeLhs(r, Real(_feasLhs[r]));
2883  }
2884  else if(_realLP->lhs(r) > -realParam(SoPlex::INFTY))
2886 
2887  assert(_lowerFinite(_rowTypes[r]) == (lhsRational(r) > _rationalNegInfty));
2888  assert(_lowerFinite(_rowTypes[r]) == (lhsReal(r) > -realParam(SoPlex::INFTY)));
2889 
2890  if(_upperFinite(_rowTypes[r]))
2891  {
2892  _rationalLP->changeRhs(r, _feasRhs[r]);
2893  _realLP->changeRhs(r, Real(_feasRhs[r]));
2894  }
2895  else if(_realLP->rhs(r) < realParam(SoPlex::INFTY))
2897 
2898  assert(_upperFinite(_rowTypes[r]) == (rhsRational(r) < _rationalPosInfty));
2899  assert(_upperFinite(_rowTypes[r]) == (rhsReal(r) < realParam(SoPlex::INFTY)));
2900 
2901  assert(lhsReal(r) <= rhsReal(r));
2902  }
2903 
2904  // unshift primal space and restore objective coefficients
2905  Rational shiftValue;
2906 
2907  for(int c = numOrigCols - 1; c >= 0; c--)
2908  {
2909  bool shifted = (_lowerFinite(_colTypes[c]) && _feasLower[c] > 0) || (_upperFinite(_colTypes[c])
2910  && _feasUpper[c] < 0);
2911  assert(shifted || !_lowerFinite(_colTypes[c]) || _feasLower[c] == lowerRational(c));
2912  assert(shifted || !_upperFinite(_colTypes[c]) || _feasUpper[c] == upperRational(c));
2913 #ifdef SOPLEX_WITH_GMP
2915  || _feasLower[c] - lowerRational(c) == _feasUpper[c] - upperRational(c));
2916 #endif
2917 
2918  if(shifted)
2919  {
2920  if(_lowerFinite(_colTypes[c]))
2921  {
2922  shiftValue = _feasLower[c];
2923  shiftValue -= lowerRational(c);
2924  }
2925  else if(_upperFinite(_colTypes[c]))
2926  {
2927  shiftValue = _feasUpper[c];
2928  shiftValue -= upperRational(c);
2929  }
2930 
2931  if(sol._isPrimalFeasible)
2932  {
2933  sol._primal[c] += shiftValue;
2934  sol._slacks.multAdd(shiftValue, _rationalLP->colVector(c));
2935  }
2936  }
2937 
2938  if(_lowerFinite(_colTypes[c]))
2939  {
2940  if(shifted)
2942 
2944  }
2945  else if(_realLP->lower(c) > -realParam(SoPlex::INFTY))
2947 
2948  assert(_lowerFinite(_colTypes[c]) == (lowerRational(c) > -_rationalPosInfty));
2949  assert(_lowerFinite(_colTypes[c]) == (lowerReal(c) > -realParam(SoPlex::INFTY)));
2950 
2951  if(_upperFinite(_colTypes[c]))
2952  {
2953  if(shifted)
2955 
2957  }
2958  else if(_realLP->upper(c) < realParam(SoPlex::INFTY))
2960 
2961  assert(_upperFinite(_colTypes[c]) == (upperRational(c) < _rationalPosInfty));
2962  assert(_upperFinite(_colTypes[c]) == (upperReal(c) < realParam(SoPlex::INFTY)));
2963 
2965  _realLP->changeMaxObj(c, Real(_feasObj[c]));
2966 
2967  assert(lowerReal(c) <= upperReal(c));
2968  }
2969 
2970  // remove last column
2971  _rationalLP->removeCol(numOrigCols);
2972  _realLP->removeCol(numOrigCols);
2973  _colTypes.reSize(numOrigCols);
2974 
2975  // invalidate rational basis factorization
2977 
2978  // print LP if in debug mode
2979  MSG_DEBUG(_realLP->writeFile("afterUntransFeas.lp", 0, 0, 0));
2980 
2981  // stop timing
2983 
2984 #ifndef NDEBUG
2985 #ifdef SOPLEX_WITH_GMP
2986 
2987  if(sol._isPrimalFeasible)
2988  {
2989  DVectorRational activity(numRowsRational());
2990  _rationalLP->computePrimalActivity(sol._primal, activity);
2991  assert(sol._slacks == activity);
2992  }
2993 
2994 #endif
2995 #endif
2996 }
2997 
2998 /** computes radius of infeasibility box implied by an approximate Farkas' proof
2999 
3000  Given constraints of the form \f$ lhs <= Ax <= rhs \f$, a farkas proof y should satisfy \f$ y^T A = 0 \f$ and
3001  \f$ y_+^T lhs - y_-^T rhs > 0 \f$, where \f$ y_+, y_- \f$ denote the positive and negative parts of \f$ y \f$.
3002  If \f$ y \f$ is approximate, it may not satisfy \f$ y^T A = 0 \f$ exactly, but the proof is still valid as long
3003  as the following holds for all potentially feasible \f$ x \f$:
3004 
3005  \f[
3006  y^T Ax < (y_+^T lhs - y_-^T rhs) (*)
3007  \f]
3008 
3009  we may therefore calculate \f$ y^T A \f$ and \f$ y_+^T lhs - y_-^T rhs \f$ exactly and check if the upper and lower
3010  bounds on \f$ x \f$ imply that all feasible \f$ x \f$ satisfy (*), and if not then compute bounds on \f$ x \f$ to
3011  guarantee (*). The simplest way to do this is to compute
3012 
3013  \f[
3014  B = (y_+^T lhs - y_-^T rhs) / \sum_i(|(y^T A)_i|)
3015  \f]
3016 
3017  noting that if every component of \f$ x \f$ has \f$ |x_i| < B \f$, then (*) holds.
3018 
3019  \f$ B \f$ can be increased by iteratively including variable bounds smaller than \f$ B \f$. The speed of this
3020  method can be further improved by using interval arithmetic for all computations. For related information see
3021  Sec. 4 of Neumaier and Shcherbina, Mathematical Programming A, 2004.
3022 
3023  Set transformed to true if this method is called after _transformFeasibility().
3024 */
3025 void SoPlex::_computeInfeasBox(SolRational& sol, bool transformed)
3026 {
3027  assert(sol.hasDualFarkas());
3028 
3029  const VectorRational& lower = transformed ? _feasLower : lowerRational();
3030  const VectorRational& upper = transformed ? _feasUpper : upperRational();
3031  const VectorRational& lhs = transformed ? _feasLhs : lhsRational();
3032  const VectorRational& rhs = transformed ? _feasRhs : rhsRational();
3033  const VectorRational& y = sol._dualFarkas;
3034 
3035  const int numRows = numRowsRational();
3036  const int numCols = transformed ? numColsRational() - 1 : numColsRational();
3037 
3038  SSVectorRational ytransA(numColsRational());
3039  Rational ytransb;
3040  Rational temp;
3041 
3042  // prepare ytransA and ytransb; since we want exact arithmetic, we set the zero threshold of the semi-sparse
3043  // vector to zero
3044  ytransA.setEpsilon(0);
3045  ytransA.clear();
3046  ytransb = 0;
3047 
3048  ///@todo this currently works only if all constraints are equations aggregate rows and sides using the multipliers of the Farkas ray
3049  for(int r = 0; r < numRows; r++)
3050  {
3051  ytransA += y[r] * _rationalLP->rowVector(r);
3052  ytransb += y[r] * (y[r] > 0 ? lhs[r] : rhs[r]);
3053  }
3054 
3055  // if we work on the feasibility problem, we ignore the last column
3056  if(transformed)
3057  ytransA.reDim(numCols);
3058 
3059  MSG_DEBUG(std::cout << "ytransb = " << rationalToString(ytransb) << "\n");
3060 
3061  // if we choose minus ytransb as vector of multipliers for the bound constraints on the variables, we obtain an
3062  // exactly feasible dual solution for the LP with zero objective function; we aggregate the bounds of the
3063  // variables accordingly and store its negation in temp
3064  temp = 0;
3065  bool isTempFinite = true;
3066 
3067  for(int c = 0; c < numCols && isTempFinite; c++)
3068  {
3069  const Rational& minusRedCost = ytransA[c];
3070 
3071  if(minusRedCost > 0)
3072  {
3073  assert((upper[c] < _rationalPosInfty) == _upperFinite(_colTypes[c]));
3074 
3075  if(_upperFinite(_colTypes[c]))
3076  temp.addProduct(minusRedCost, upper[c]);
3077  else
3078  isTempFinite = false;
3079  }
3080  else if(minusRedCost < 0)
3081  {
3082  assert((lower[c] > _rationalNegInfty) == _lowerFinite(_colTypes[c]));
3083 
3084  if(_lowerFinite(_colTypes[c]))
3085  temp.addProduct(minusRedCost, lower[c]);
3086  else
3087  isTempFinite = false;
3088  }
3089  }
3090 
3091  MSG_DEBUG(std::cout << "max ytransA*[x_l,x_u] = " << (isTempFinite ? rationalToString(
3092  temp) : "infinite") << "\n");
3093 
3094  // ytransb - temp is the increase in the dual objective along the Farkas ray; if this is positive, the dual is
3095  // unbounded and certifies primal infeasibility
3096  if(isTempFinite && temp < ytransb)
3097  {
3098  MSG_INFO1(spxout, spxout << "Farkas infeasibility proof verified exactly. (1)\n");
3099  return;
3100  }
3101 
3102  // ensure that array of nonzero elements in ytransA is available
3103  assert(ytransA.isSetup());
3104  ytransA.setup();
3105 
3106  // if ytransb is negative, try to make it zero by including a positive lower bound or a negative upper bound
3107  if(ytransb < 0)
3108  {
3109  for(int c = 0; c < numCols; c++)
3110  {
3111  if(lower[c] > 0)
3112  {
3113  ytransA.setValue(c, ytransA[c] - ytransb / lower[c]);
3114  ytransb = 0;
3115  break;
3116  }
3117  else if(upper[c] < 0)
3118  {
3119  ytransA.setValue(c, ytransA[c] - ytransb / upper[c]);
3120  ytransb = 0;
3121  break;
3122  }
3123  }
3124  }
3125 
3126  // if ytransb is still zero then the zero solution is inside the bounds and cannot be cut off by the Farkas
3127  // constraint; in this case, we cannot compute a Farkas box
3128  if(ytransb < 0)
3129  {
3130  MSG_INFO1(spxout, spxout <<
3131  "Approximate Farkas proof to weak. Could not compute Farkas box. (1)\n");
3132  return;
3133  }
3134 
3135  // compute the one norm of ytransA
3136  temp = 0;
3137  const int size = ytransA.size();
3138 
3139  for(int n = 0; n < size; n++)
3140  temp += spxAbs(ytransA.value(n));
3141 
3142  // if the one norm is zero then ytransA is zero the Farkas proof should have been verified above
3143  assert(temp != 0);
3144 
3145  // initialize variables in loop: size of Farkas box B, flag whether B has been increased, and number of current
3146  // nonzero in ytransA
3147  Rational B = ytransb / temp;
3148  bool success = false;
3149  int n = 0;
3150 
3151  // loop through nonzeros of ytransA
3152  MSG_DEBUG(std::cout << "B = " << rationalToString(B) << "\n");
3153  assert(ytransb >= 0);
3154 
3155  while(true)
3156  {
3157  // if all nonzeros have been inspected once without increasing B, we abort; otherwise, we start another round
3158  if(n >= ytransA.size())
3159  {
3160  if(!success)
3161  break;
3162 
3163  success = false;
3164  n = 0;
3165  }
3166 
3167  // get Farkas multiplier of the bound constraint as minus the value in ytransA
3168  const Rational& minusRedCost = ytransA.value(n);
3169  int colIdx = ytransA.index(n);
3170 
3171  // if the multiplier is positive we inspect the lower bound: if it is finite and within the Farkas box, we can
3172  // increase B by including it in the Farkas proof
3173  assert((upper[colIdx] < _rationalPosInfty) == _upperFinite(_colTypes[colIdx]));
3174  assert((lower[colIdx] > _rationalNegInfty) == _lowerFinite(_colTypes[colIdx]));
3175 
3176  if(minusRedCost < 0 && lower[colIdx] > -B && _lowerFinite(_colTypes[colIdx]))
3177  {
3178  ytransA.clearNum(n);
3179  ytransb.subProduct(minusRedCost, lower[colIdx]);
3180  temp += minusRedCost;
3181 
3182  assert(ytransb >= 0);
3183  assert(temp >= 0);
3184  assert(temp == 0 || ytransb / temp > B);
3185 
3186  // if ytransA and ytransb are zero, we have 0^T x >= 0 and cannot compute a Farkas box
3187  if(temp == 0 && ytransb == 0)
3188  {
3189  MSG_INFO1(spxout, spxout <<
3190  "Approximate Farkas proof to weak. Could not compute Farkas box. (2)\n");
3191  return;
3192  }
3193  // if ytransb is positive and ytransA is zero, we have 0^T x > 0, proving infeasibility
3194  else if(temp == 0)
3195  {
3196  assert(ytransb > 0);
3197  MSG_INFO1(spxout, spxout << "Farkas infeasibility proof verified exactly. (2)\n");
3198  return;
3199  }
3200  else
3201  {
3202  B = ytransb / temp;
3203  MSG_DEBUG(std::cout << "B = " << rationalToString(B) << "\n");
3204  }
3205 
3206  success = true;
3207  }
3208  // if the multiplier is negative we inspect the upper bound: if it is finite and within the Farkas box, we can
3209  // increase B by including it in the Farkas proof
3210  else if(minusRedCost > 0 && upper[colIdx] < B && _upperFinite(_colTypes[colIdx]))
3211  {
3212  ytransA.clearNum(n);
3213  ytransb.subProduct(minusRedCost, upper[colIdx]);
3214  temp -= minusRedCost;
3215 
3216  assert(ytransb >= 0);
3217  assert(temp >= 0);
3218  assert(temp == 0 || ytransb / temp > B);
3219 
3220  // if ytransA and ytransb are zero, we have 0^T x >= 0 and cannot compute a Farkas box
3221  if(temp == 0 && ytransb == 0)
3222  {
3223  MSG_INFO1(spxout, spxout <<
3224  "Approximate Farkas proof to weak. Could not compute Farkas box. (2)\n");
3225  return;
3226  }
3227  // if ytransb is positive and ytransA is zero, we have 0^T x > 0, proving infeasibility
3228  else if(temp == 0)
3229  {
3230  assert(ytransb > 0);
3231  MSG_INFO1(spxout, spxout << "Farkas infeasibility proof verified exactly. (2)\n");
3232  return;
3233  }
3234  else
3235  {
3236  B = ytransb / temp;
3237  MSG_DEBUG(std::cout << "B = " << rationalToString(B) << "\n");
3238  }
3239 
3240  success = true;
3241  }
3242  // the multiplier is zero, we can ignore the bound constraints on this variable
3243  else if(minusRedCost == 0)
3244  ytransA.clearNum(n);
3245  // currently this bound cannot be used to increase B; we will check it again in the next round, because B might
3246  // have increased by then
3247  else
3248  n++;
3249  }
3250 
3251  if(B > 0)
3252  {
3253  MSG_INFO1(spxout, spxout <<
3254  "Computed Farkas box: provably no feasible solutions with components less than "
3255  << rationalToString(B) << " in absolute value.\n");
3256  }
3257 }
3258 
3259 
3260 
3261 /// solves real LP during iterative refinement
3263  VectorReal& dual, DataArray< SPxSolver::VarStatus >& basisStatusRows,
3264  DataArray< SPxSolver::VarStatus >& basisStatusCols, bool& returnedBasis)
3265 {
3266  assert(_isConsistent());
3267 
3268  assert(_solver.nRows() == numRowsRational());
3269  assert(_solver.nCols() == numColsRational());
3270  assert(primal.dim() == numColsRational());
3271  assert(dual.dim() == numRowsRational());
3272 
3274 
3275 #ifndef SOPLEX_MANUAL_ALT
3276 
3277  if(fromscratch || !_hasBasis)
3279  else
3281 
3282 #else
3284 #endif
3285 
3286  // start timing
3288 
3289  // if preprocessing is applied, we need to restore the original LP at the end
3290  SPxLPRational* rationalLP = 0;
3291 
3292  if(_simplifier != 0 || _scaler != 0)
3293  {
3294  spx_alloc(rationalLP);
3295  rationalLP = new(rationalLP) SPxLPRational(_solver);
3296  }
3297 
3298  // if preprocessing is applied, the basis may change, hence invalidate the rational basis factorization; if no
3299  if(_simplifier != 0 || _scaler != 0)
3301 
3302  // stop timing
3304 
3305  returnedBasis = false;
3306 
3307  try
3308  {
3309  // apply problem simplification
3310  SPxSimplifier::Result simplificationStatus = SPxSimplifier::OKAY;
3311 
3312  if(_simplifier != 0)
3313  {
3314  // do not remove bounds of boxed variables or sides of ranged rows if bound flipping is used
3316  simplificationStatus = _simplifier->simplify(_solver, realParam(SoPlex::EPSILON_ZERO),
3318  }
3319 
3320  // apply scaling after the simplification
3321  if(_scaler != 0 && simplificationStatus == SPxSimplifier::OKAY)
3322  _scaler->scale(_solver, false);
3323 
3324  // run the simplex method if problem has not been solved by the simplifier
3325  if(simplificationStatus == SPxSimplifier::OKAY)
3326  {
3327  MSG_INFO1(spxout, spxout << std::endl);
3328 
3330 
3331  MSG_INFO1(spxout, spxout << std::endl);
3332  }
3333 
3334  ///@todo move to private helper methods
3335  // evaluate status flag
3336  if(simplificationStatus == SPxSimplifier::INFEASIBLE)
3337  result = SPxSolver::INFEASIBLE;
3338  else if(simplificationStatus == SPxSimplifier::DUAL_INFEASIBLE)
3339  result = SPxSolver::INForUNBD;
3340  else if(simplificationStatus == SPxSimplifier::UNBOUNDED)
3341  result = SPxSolver::UNBOUNDED;
3342  else if(simplificationStatus == SPxSimplifier::VANISHED
3343  || simplificationStatus == SPxSimplifier::OKAY)
3344  {
3345  result = simplificationStatus == SPxSimplifier::VANISHED ? SPxSolver::OPTIMAL : _solver.status();
3346 
3347  ///@todo move to private helper methods
3348  // process result
3349  switch(result)
3350  {
3351  case SPxSolver::OPTIMAL:
3352 
3353  // unsimplify if simplifier is active and LP is solved to optimality; this must be done here and not at solution
3354  // query, because we want to have the basis for the original problem
3355  if(_simplifier != 0)
3356  {
3357  assert(!_simplifier->isUnsimplified());
3358  assert(simplificationStatus == SPxSimplifier::VANISHED
3359  || simplificationStatus == SPxSimplifier::OKAY);
3360 
3361  bool vanished = simplificationStatus == SPxSimplifier::VANISHED;
3362 
3363  // get solution vectors for transformed problem
3364  DVectorReal tmpPrimal(vanished ? 0 : _solver.nCols());
3365  DVectorReal tmpSlacks(vanished ? 0 : _solver.nRows());
3366  DVectorReal tmpDual(vanished ? 0 : _solver.nRows());
3367  DVectorReal tmpRedCost(vanished ? 0 : _solver.nCols());
3368 
3369  if(!vanished)
3370  {
3371  assert(_solver.status() == SPxSolver::OPTIMAL);
3372 
3373  _solver.getPrimal(tmpPrimal);
3374  _solver.getSlacks(tmpSlacks);
3375  _solver.getDual(tmpDual);
3376  _solver.getRedCost(tmpRedCost);
3377 
3378  // unscale vectors
3379  if(_scaler != 0)
3380  {
3381  _scaler->unscalePrimal(_solver, tmpPrimal);
3382  _scaler->unscaleSlacks(_solver, tmpSlacks);
3383  _scaler->unscaleDual(_solver, tmpDual);
3384  _scaler->unscaleRedCost(_solver, tmpRedCost);
3385  }
3386 
3387  // get basis of transformed problem
3388  basisStatusRows.reSize(_solver.nRows());
3389  basisStatusCols.reSize(_solver.nCols());
3390  _solver.getBasis(basisStatusRows.get_ptr(), basisStatusCols.get_ptr(), basisStatusRows.size(),
3391  basisStatusCols.size());
3392  }
3393 
3394  ///@todo catch exception
3395  _simplifier->unsimplify(tmpPrimal, tmpDual, tmpSlacks, tmpRedCost, basisStatusRows.get_ptr(),
3396  basisStatusCols.get_ptr());
3397 
3398  // store basis for original problem
3399  basisStatusRows.reSize(numRowsRational());
3400  basisStatusCols.reSize(numColsRational());
3401  _simplifier->getBasis(basisStatusRows.get_ptr(), basisStatusCols.get_ptr(), basisStatusRows.size(),
3402  basisStatusCols.size());
3403  returnedBasis = true;
3404 
3405  primal = _simplifier->unsimplifiedPrimal();
3406  dual = _simplifier->unsimplifiedDual();
3407  }
3408  // if the original problem is not in the solver because of scaling, we also need to store the basis
3409  else
3410  {
3411  _solver.getPrimal(primal);
3412  _solver.getDual(dual);
3413 
3414  // unscale vectors
3415  if(_scaler != 0)
3416  {
3417  _scaler->unscalePrimal(_solver, primal);
3418  _scaler->unscaleDual(_solver, dual);
3419  }
3420 
3421  // get basis of transformed problem
3422  basisStatusRows.reSize(_solver.nRows());
3423  basisStatusCols.reSize(_solver.nCols());
3424  _solver.getBasis(basisStatusRows.get_ptr(), basisStatusCols.get_ptr(), basisStatusRows.size(),
3425  basisStatusCols.size());
3426  returnedBasis = true;
3427  }
3428 
3429  break;
3430 
3433  {
3434  _solver.getPrimal(primal);
3435  _solver.getDual(dual);
3436 
3437  // unscale vectors
3438  if(_scaler != 0)
3439  {
3440  _scaler->unscalePrimal(_solver, primal);
3441  _scaler->unscaleDual(_solver, dual);
3442  }
3443 
3444  // get basis of transformed problem
3445  basisStatusRows.reSize(_solver.nRows());
3446  basisStatusCols.reSize(_solver.nCols());
3447  _solver.getBasis(basisStatusRows.get_ptr(), basisStatusCols.get_ptr(), basisStatusRows.size(),
3448  basisStatusCols.size());
3449  returnedBasis = true;
3450  result = SPxSolver::OPTIMAL;
3451  }
3452 
3453  break;
3454 
3455  case SPxSolver::ABORT_TIME:
3456  case SPxSolver::ABORT_ITER:
3458  case SPxSolver::REGULAR:
3459  case SPxSolver::RUNNING:
3460  case SPxSolver::UNBOUNDED:
3461  break;
3462 
3463  case SPxSolver::INFEASIBLE:
3464 
3465  // if simplifier is active we cannot return a Farkas ray currently
3466  if(_simplifier != 0)
3467  break;
3468 
3469  // return Farkas ray as dual solution
3470  _solver.getDualfarkas(dual);
3471 
3472  // unscale vectors
3473  if(_scaler != 0)
3474  _scaler->unscaleDual(_solver, dual);
3475 
3476  // if the original problem is not in the solver because of scaling, we also need to store the basis
3477  basisStatusRows.reSize(_solver.nRows());
3478  basisStatusCols.reSize(_solver.nCols());
3479  _solver.getBasis(basisStatusRows.get_ptr(), basisStatusCols.get_ptr(), basisStatusRows.size(),
3480  basisStatusCols.size());
3481  returnedBasis = true;
3482  break;
3483 
3484  case SPxSolver::INForUNBD:
3485  case SPxSolver::SINGULAR:
3486  default:
3487  break;
3488  }
3489  }
3490  }
3491  catch(...)
3492  {
3493  MSG_INFO1(spxout, spxout << "Exception thrown during floating-point solve.\n");
3494  result = SPxSolver::ERROR;
3495  }
3496 
3497  // restore original LP if necessary
3498  if(_simplifier != 0 || _scaler != 0)
3499  {
3500  assert(rationalLP != 0);
3501  _solver.loadLP((SPxLPReal)(*rationalLP));
3502  rationalLP->~SPxLPRational();
3503  spx_free(rationalLP);
3504 
3505  if(_hasBasis)
3506  _solver.setBasis(basisStatusRows.get_ptr(), basisStatusCols.get_ptr());
3507  }
3508 
3509  return result;
3510 }
3511 
3512 
3513 
3514 /// solves real LP with recovery mechanism
3515 SPxSolver::Status SoPlex::_solveRealStable(bool acceptUnbounded, bool acceptInfeasible,
3516  VectorReal& primal, VectorReal& dual, DataArray< SPxSolver::VarStatus >& basisStatusRows,
3517  DataArray< SPxSolver::VarStatus >& basisStatusCols, bool& returnedBasis,
3518  const bool forceNoSimplifier)
3519 {
3521 
3522  bool fromScratch = false;
3523  bool solved = false;
3524  bool solvedFromScratch = false;
3525  bool initialSolve = true;
3526  bool increasedMarkowitz = false;
3527  bool relaxedTolerances = false;
3528  bool tightenedTolerances = false;
3529  bool switchedScaler = false;
3530  bool switchedSimplifier = false;
3531  bool switchedRatiotester = false;
3532  bool switchedPricer = false;
3533  bool turnedoffPre = false;
3534 
3535  Real markowitz = _slufactor.markowitz();
3536  int ratiotester = intParam(SoPlex::RATIOTESTER);
3537  int pricer = intParam(SoPlex::PRICER);
3538  int simplifier = intParam(SoPlex::SIMPLIFIER);
3539  int scaler = intParam(SoPlex::SCALER);
3540  int type = intParam(SoPlex::ALGORITHM);
3541 
3542  if(forceNoSimplifier)
3544 
3545  while(true)
3546  {
3547  assert(!increasedMarkowitz || GE(_slufactor.markowitz(), 0.9));
3548 
3549  result = _solveRealForRational(fromScratch, primal, dual, basisStatusRows, basisStatusCols,
3550  returnedBasis);
3551 
3552  solved = (result == SPxSolver::OPTIMAL)
3553  || (result == SPxSolver::INFEASIBLE && acceptInfeasible)
3554  || (result == SPxSolver::UNBOUNDED && acceptUnbounded);
3555 
3556  if(solved)
3557  break;
3558 
3559  // if( _isSolveStopped() )
3560  // break;
3561 
3562  if(initialSolve)
3563  {
3564  MSG_INFO1(spxout, spxout << "Numerical troubles during floating-point solve." << std::endl);
3565  initialSolve = false;
3566  }
3567 
3568  if(!turnedoffPre
3571  {
3572  MSG_INFO1(spxout, spxout << "Turning off preprocessing." << std::endl);
3573 
3574  turnedoffPre = true;
3575 
3578 
3579  fromScratch = true;
3580  _solver.reLoad();
3581  solvedFromScratch = true;
3582  continue;
3583  }
3584 
3585  setIntParam(SoPlex::SCALER, scaler);
3586  setIntParam(SoPlex::SIMPLIFIER, simplifier);
3587 
3588  if(!increasedMarkowitz)
3589  {
3590  MSG_INFO1(spxout, spxout << "Increasing Markowitz threshold." << std::endl);
3591 
3592  _slufactor.setMarkowitz(0.9);
3593  increasedMarkowitz = true;
3594 
3595  try
3596  {
3597  _solver.factorize();
3598  continue;
3599  }
3600  catch(...)
3601  {
3602  MSG_DEBUG(std::cout << std::endl << "Factorization failed." << std::endl);
3603  }
3604  }
3605 
3606  if(!solvedFromScratch)
3607  {
3608  MSG_INFO1(spxout, spxout << "Solving from scratch." << std::endl);
3609 
3610  fromScratch = true;
3611  _solver.reLoad();
3612 
3613  solvedFromScratch = true;
3614  continue;
3615  }
3616 
3617  setIntParam(SoPlex::RATIOTESTER, ratiotester);
3618  setIntParam(SoPlex::PRICER, pricer);
3619 
3620  if(!switchedScaler)
3621  {
3622  MSG_INFO1(spxout, spxout << "Switching scaling." << std::endl);
3623 
3624  if(scaler == int(SoPlex::SCALER_OFF))
3626  else
3628 
3629  fromScratch = true;
3630  _solver.reLoad();
3631 
3632  solvedFromScratch = true;
3633  switchedScaler = true;
3634  continue;
3635  }
3636 
3637  if(!switchedSimplifier && !forceNoSimplifier)
3638  {
3639  MSG_INFO1(spxout, spxout << "Switching simplification." << std::endl);
3640 
3641  if(simplifier == int(SoPlex::SIMPLIFIER_OFF))
3643  else
3645 
3646  fromScratch = true;
3647  _solver.reLoad();
3648 
3649  solvedFromScratch = true;
3650  switchedSimplifier = true;
3651  continue;
3652  }
3653 
3655 
3656  if(!relaxedTolerances)
3657  {
3658  MSG_INFO1(spxout, spxout << "Relaxing tolerances." << std::endl);
3659 
3661  _solver.setDelta((_solver.feastol() * 1e3 > 1e-3) ? 1e-3 : (_solver.feastol() * 1e3));
3662  relaxedTolerances = _solver.feastol() >= 1e-3;
3663  solvedFromScratch = false;
3664  continue;
3665  }
3666 
3667  if(!tightenedTolerances && result != SPxSolver::INFEASIBLE)
3668  {
3669  MSG_INFO1(spxout, spxout << "Tightening tolerances." << std::endl);
3670 
3672  _solver.setDelta(_solver.feastol() * 1e-3 < 1e-9 ? 1e-9 : _solver.feastol() * 1e-3);
3673  tightenedTolerances = _solver.feastol() <= 1e-9;
3674  solvedFromScratch = false;
3675  continue;
3676  }
3677 
3679 
3680  if(!switchedRatiotester)
3681  {
3682  MSG_INFO1(spxout, spxout << "Switching ratio test." << std::endl);
3683 
3685 
3688  else
3690 
3691  switchedRatiotester = true;
3692  solvedFromScratch = false;
3693  continue;
3694  }
3695 
3696  if(!switchedPricer)
3697  {
3698  MSG_INFO1(spxout, spxout << "Switching pricer." << std::endl);
3699 
3701 
3702  if(_solver.pricer() != (SPxPricer*)&_pricerDevex)
3704  else
3706 
3707  switchedPricer = true;
3708  solvedFromScratch = false;
3709  continue;
3710  }
3711 
3712  MSG_INFO1(spxout, spxout << "Giving up." << std::endl);
3713 
3714  break;
3715  }
3716 
3719  _slufactor.setMarkowitz(markowitz);
3720 
3721  setIntParam(SoPlex::RATIOTESTER, ratiotester);
3722  setIntParam(SoPlex::PRICER, pricer);
3723  setIntParam(SoPlex::SIMPLIFIER, simplifier);
3724  setIntParam(SoPlex::SCALER, scaler);
3726 
3727  return result;
3728 }
3729 
3730 
3731 
3732 /// computes rational inverse of basis matrix as defined by _rationalLUSolverBind
3734 {
3737 
3738  const int matrixdim = numRowsRational();
3739  assert(_rationalLUSolverBind.size() == matrixdim);
3740 
3741  DataArray< const SVectorRational* > matrix(matrixdim);
3742  _rationalLUSolverBind.reSize(matrixdim);
3743 
3744  for(int i = 0; i < matrixdim; i++)
3745  {
3746  if(_rationalLUSolverBind[i] >= 0)
3747  {
3748  assert(_rationalLUSolverBind[i] < numColsRational());
3749  matrix[i] = &colVectorRational(_rationalLUSolverBind[i]);
3750  }
3751  else
3752  {
3753  assert(-1 - _rationalLUSolverBind[i] >= 0);
3754  assert(-1 - _rationalLUSolverBind[i] < numRowsRational());
3755  matrix[i] = _unitVectorRational(-1 - _rationalLUSolverBind[i]);
3756  }
3757  }
3758 
3759  // load and factorize rational basis matrix
3762  else
3764 
3765  _rationalLUSolver.load(matrix.get_ptr(), matrixdim);
3766 
3767  // record statistics
3771 
3773  {
3774  MSG_INFO2(spxout, spxout << "Rational factorization hit time limit.\n");
3775  }
3777  {
3778  MSG_INFO1(spxout, spxout << "Error performing rational LU factorization.\n");
3779  }
3780 
3781  return;
3782 }
3783 
3784 
3785 
3786 /// factorizes rational basis matrix in column representation
3788  DataArray< SPxSolver::VarStatus >& basisStatusRows,
3789  DataArray< SPxSolver::VarStatus >& basisStatusCols, bool& stoppedTime, bool& stoppedIter,
3790  bool& error, bool& optimal)
3791 {
3792  // start rational solving time
3794 
3795  stoppedTime = false;
3796  stoppedIter = false;
3797  error = false;
3798  optimal = false;
3799 
3800  const bool maximizing = (intParam(SoPlex::OBJSENSE) == SoPlex::OBJSENSE_MAXIMIZE);
3801  const int matrixdim = numRowsRational();
3802  bool loadMatrix = (_rationalLUSolver.status() == SLinSolverRational::UNLOADED
3804  int numBasicRows;
3805 
3806  assert(loadMatrix || matrixdim == _rationalLUSolver.dim());
3807  assert(loadMatrix || matrixdim == _rationalLUSolverBind.size());
3808 
3809  if(!loadMatrix && (matrixdim != _rationalLUSolver.dim()
3810  || matrixdim != _rationalLUSolverBind.size()))
3811  {
3813  "Warning: dimensioning error in rational matrix factorization (recovered).\n");
3814  loadMatrix = true;
3815  }
3816 
3817  _workSol._primal.reDim(matrixdim);
3818  _workSol._slacks.reDim(matrixdim);
3819  _workSol._dual.reDim(matrixdim);
3820  _workSol._redCost.reDim(numColsRational() > matrixdim ? numColsRational() : matrixdim);
3821 
3822  if(loadMatrix)
3823  _rationalLUSolverBind.reSize(matrixdim);
3824 
3825  DVectorRational& basicPrimalRhs = _workSol._slacks;
3826  DVectorRational& basicDualRhs = _workSol._redCost;
3827  DVectorRational& basicPrimal = _workSol._primal;
3828  DVectorRational& basicDual = _workSol._dual;
3829 
3830  Rational violation;
3831  Rational primalViolation;
3832  Rational dualViolation;
3833  bool primalFeasible = false;
3834  bool dualFeasible = false;
3835 
3836  assert(basisStatusCols.size() == numColsRational());
3837  assert(basisStatusRows.size() == numRowsRational());
3838 
3839  int j = 0;
3840 
3841  for(int i = 0; i < basisStatusRows.size(); i++)
3842  {
3843  if(basisStatusRows[i] == SPxSolver::BASIC && j < matrixdim)
3844  {
3845  basicPrimalRhs[i] = 0;
3846  basicDualRhs[j] = 0;
3847 
3848  if(loadMatrix)
3849  _rationalLUSolverBind[j] = -1 - i;
3850 
3851  j++;
3852  }
3853  else if(basisStatusRows[i] == SPxSolver::ON_LOWER)
3854  basicPrimalRhs[i] = lhsRational(i);
3855  else if(basisStatusRows[i] == SPxSolver::ON_UPPER)
3856  basicPrimalRhs[i] = rhsRational(i);
3857  else if(basisStatusRows[i] == SPxSolver::ZERO)
3858  basicPrimalRhs[i] = 0;
3859  else if(basisStatusRows[i] == SPxSolver::FIXED)
3860  {
3861  assert(lhsRational(i) == rhsRational(i));
3862  basicPrimalRhs[i] = lhsRational(i);
3863  }
3864  else if(basisStatusRows[i] == SPxSolver::UNDEFINED)
3865  {
3866  MSG_INFO1(spxout, spxout << "Undefined basis status of row in rational factorization.\n");
3867  error = true;
3868  goto TERMINATE;
3869  }
3870  else
3871  {
3872  assert(basisStatusRows[i] == SPxSolver::BASIC);
3873  MSG_INFO1(spxout, spxout << "Too many basic rows in rational factorization.\n");
3874  error = true;
3875  goto TERMINATE;
3876  }
3877  }
3878 
3879  numBasicRows = j;
3880 
3881  for(int i = 0; i < basisStatusCols.size(); i++)
3882  {
3883  if(basisStatusCols[i] == SPxSolver::BASIC && j < matrixdim)
3884  {
3885  basicDualRhs[j] = objRational(i);
3886 
3887  if(loadMatrix)
3888  _rationalLUSolverBind[j] = i;
3889 
3890  j++;
3891  }
3892  else if(basisStatusCols[i] == SPxSolver::ON_LOWER)
3893  basicPrimalRhs.multAdd(-lowerRational(i), colVectorRational(i));
3894  else if(basisStatusCols[i] == SPxSolver::ON_UPPER)
3895  basicPrimalRhs.multAdd(-upperRational(i), colVectorRational(i));
3896  else if(basisStatusCols[i] == SPxSolver::ZERO)
3897  {}
3898  else if(basisStatusCols[i] == SPxSolver::FIXED)
3899  {
3900  assert(lowerRational(i) == upperRational(i));
3901  basicPrimalRhs.multAdd(-lowerRational(i), colVectorRational(i));
3902  }
3903  else if(basisStatusCols[i] == SPxSolver::UNDEFINED)
3904  {
3905  MSG_INFO1(spxout, spxout << "Undefined basis status of column in rational factorization.\n");
3906  error = true;
3907  goto TERMINATE;
3908  }
3909  else
3910  {
3911  assert(basisStatusCols[i] == SPxSolver::BASIC);
3912  MSG_INFO1(spxout, spxout << "Too many basic columns in rational factorization.\n");
3913  error = true;
3914  goto TERMINATE;
3915  }
3916  }
3917 
3918  if(j != matrixdim)
3919  {
3920  MSG_INFO1(spxout, spxout << "Too few basic entries in rational factorization.\n");
3921  error = true;
3922  goto TERMINATE;
3923  }
3924 
3925  // load and factorize rational basis matrix
3926  if(loadMatrix)
3928 
3930  {
3931  stoppedTime = true;
3932  return;
3933  }
3935  {
3936  error = true;
3937  return;
3938  }
3939 
3941 
3942  // solve for primal solution
3945  else
3947 
3948  _rationalLUSolver.solveRight(basicPrimal, basicPrimalRhs);
3949 
3950  // record statistics
3953 
3954  if(_isSolveStopped(stoppedTime, stoppedIter))
3955  {
3956  MSG_INFO2(spxout, spxout << "Rational factorization hit time limit while solving for primal.\n");
3957  return;
3958  }
3959 
3960  // check bound violation on basic rows and columns
3961  j = 0;
3962  primalViolation = 0;
3963  primalFeasible = true;
3964 
3965  for(int i = 0; i < basisStatusRows.size(); i++)
3966  {
3967  if(basisStatusRows[i] == SPxSolver::BASIC)
3968  {
3969  assert(j < matrixdim);
3970  assert(_rationalLUSolverBind[j] == -1 - i);
3971  violation = lhsRational(i);
3972  violation += basicPrimal[j];
3973 
3974  if(violation > primalViolation)
3975  {
3976  primalFeasible = false;
3977  primalViolation = violation;
3978  }
3979 
3980  violation = rhsRational(i);
3981  violation += basicPrimal[j];
3982  violation *= -1;
3983 
3984  if(violation > primalViolation)
3985  {
3986  primalFeasible = false;
3987  primalViolation = violation;
3988  }
3989 
3990  j++;
3991  }
3992  }
3993 
3994  for(int i = 0; i < basisStatusCols.size(); i++)
3995  {
3996  if(basisStatusCols[i] == SPxSolver::BASIC)
3997  {
3998  assert(j < matrixdim);
3999  assert(_rationalLUSolverBind[j] == i);
4000 
4001  if(basicPrimal[j] < lowerRational(i))
4002  {
4003  violation = lowerRational(i);
4004  violation -= basicPrimal[j];
4005 
4006  if(violation > primalViolation)
4007  {
4008  primalFeasible = false;
4009  primalViolation = violation;
4010  }
4011  }
4012 
4013  if(basicPrimal[j] > upperRational(i))
4014  {
4015  violation = basicPrimal[j];
4016  violation -= upperRational(i);
4017 
4018  if(violation > primalViolation)
4019  {
4020  primalFeasible = false;
4021  primalViolation = violation;
4022  }
4023  }
4024 
4025  j++;
4026  }
4027  }
4028 
4029  if(!primalFeasible)
4030  {
4031  MSG_INFO1(spxout, spxout << "Rational solution primal infeasible.\n");
4032  }
4033 
4034  // solve for dual solution
4037  else
4039 
4040  _rationalLUSolver.solveLeft(basicDual, basicDualRhs);
4041 
4042  // record statistics
4045 
4046  if(_isSolveStopped(stoppedTime, stoppedIter))
4047  {
4048  MSG_INFO2(spxout, spxout << "Rational factorization hit time limit while solving for dual.\n");
4049  return;
4050  }
4051 
4052  // check dual violation on nonbasic rows
4053  dualViolation = 0;
4054  dualFeasible = true;
4055 
4056  for(int i = 0; i < basisStatusRows.size(); i++)
4057  {
4058  if(_rowTypes[i] == RANGETYPE_FIXED
4059  && (basisStatusRows[i] == SPxSolver::ON_LOWER || basisStatusRows[i] == SPxSolver::ON_UPPER))
4060  {
4061  assert(lhsRational(i) == rhsRational(i));
4062  basisStatusRows[i] = SPxSolver::FIXED;
4063  }
4064 
4065  assert(basisStatusRows[i] != SPxSolver::BASIC || basicDual[i] == 0);
4066 
4067  if(basisStatusRows[i] == SPxSolver::BASIC || basisStatusRows[i] == SPxSolver::FIXED)
4068  continue;
4069  else if(basicDual[i] < 0)
4070  {
4071  if(((maximizing && basisStatusRows[i] != SPxSolver::ON_LOWER) || (!maximizing
4072  && basisStatusRows[i] != SPxSolver::ON_UPPER))
4073  && (basisStatusRows[i] != SPxSolver::ZERO || rhsRational(i) != 0))
4074  {
4075  dualFeasible = false;
4076  violation = -basicDual[i];
4077 
4078  if(violation > dualViolation)
4079  dualViolation = violation;
4080 
4081  MSG_DEBUG(spxout << "negative dual multliplier for row " << i
4082  << " with dual " << rationalToString(basicDual[i])
4083  << " and status " << basisStatusRows[i]
4084  << " and [lhs,rhs] = [" << rationalToString(lhsRational(i)) << "," << rationalToString(rhsRational(
4085  i)) << "]"
4086  << "\n");
4087  }
4088  }
4089  else if(basicDual[i] > 0)
4090  {
4091  if(((maximizing && basisStatusRows[i] != SPxSolver::ON_UPPER) || (!maximizing
4092  && basisStatusRows[i] != SPxSolver::ON_LOWER))
4093  && (basisStatusRows[i] != SPxSolver::ZERO || lhsRational(i) == 0))
4094  {
4095  dualFeasible = false;
4096 
4097  if(basicDual[i] > dualViolation)
4098  dualViolation = basicDual[i];
4099 
4100  MSG_DEBUG(spxout << "positive dual multliplier for row " << i
4101  << " with dual " << rationalToString(basicDual[i])
4102  << " and status " << basisStatusRows[i]
4103  << " and [lhs,rhs] = [" << rationalToString(lhsRational(i)) << "," << rationalToString(rhsRational(
4104  i)) << "]"
4105  << "\n");
4106  }
4107  }
4108  }
4109 
4110  // check reduced cost violation on nonbasic columns
4111  for(int i = 0; i < basisStatusCols.size(); i++)
4112  {
4113  if(_colTypes[i] == RANGETYPE_FIXED
4114  && (basisStatusCols[i] == SPxSolver::ON_LOWER || basisStatusCols[i] == SPxSolver::ON_UPPER))
4115  {
4116  assert(lowerRational(i) == upperRational(i));
4117  basisStatusCols[i] = SPxSolver::FIXED;
4118  }
4119 
4120 #ifdef SOPLEX_WITH_GMP
4121  assert(basisStatusCols[i] != SPxSolver::BASIC
4122  || basicDual * colVectorRational(i) == objRational(i));
4123 #endif
4124 
4125  if(basisStatusCols[i] == SPxSolver::BASIC || basisStatusCols[i] == SPxSolver::FIXED)
4126  continue;
4127  else
4128  {
4129  _workSol._redCost[i] = basicDual * colVectorRational(i);
4130  _workSol._redCost[i] -= objRational(i);
4131 
4132  if(_workSol._redCost[i] > 0)
4133  {
4134  if(((maximizing && basisStatusCols[i] != SPxSolver::ON_LOWER) || (!maximizing
4135  && basisStatusCols[i] != SPxSolver::ON_UPPER))
4136  && (basisStatusCols[i] != SPxSolver::ZERO || upperRational(i) != 0))
4137  {
4138  dualFeasible = false;
4139 
4140  if(_workSol._redCost[i] > dualViolation)
4141  dualViolation = _workSol._redCost[i];
4142  }
4143 
4144  _workSol._redCost[i] *= -1;
4145  }
4146  else if(_workSol._redCost[i] < 0)
4147  {
4148  _workSol._redCost[i] *= -1;
4149 
4150  if(((maximizing && basisStatusCols[i] != SPxSolver::ON_UPPER) || (!maximizing
4151  && basisStatusCols[i] != SPxSolver::ON_LOWER))
4152  && (basisStatusCols[i] != SPxSolver::ZERO || lowerRational(i) != 0))
4153  {
4154  dualFeasible = false;
4155 
4156  if(_workSol._redCost[i] > dualViolation)
4157  dualViolation = _workSol._redCost[i];
4158  }
4159  }
4160  else
4161  _workSol._redCost[i] *= -1;
4162  }
4163  }
4164 
4165  if(!dualFeasible)
4166  {
4167  MSG_INFO1(spxout, spxout << "Rational solution dual infeasible.\n");
4168  }
4169 
4170  // store solution
4171  optimal = primalFeasible && dualFeasible;
4172 
4173  if(optimal || boolParam(SoPlex::RATFACJUMP))
4174  {
4175  _hasBasis = true;
4176 
4177  if(&basisStatusRows != &_basisStatusRows)
4178  _basisStatusRows = basisStatusRows;
4179 
4180  if(&basisStatusCols != &_basisStatusCols)
4181  _basisStatusCols = basisStatusCols;
4182 
4183  sol._primal.reDim(numColsRational());
4184  j = numBasicRows;
4185 
4186  for(int i = 0; i < basisStatusCols.size(); i++)
4187  {
4188  if(basisStatusCols[i] == SPxSolver::BASIC)
4189  {
4190  assert(j < matrixdim);
4191  assert(_rationalLUSolverBind[j] == i);
4192  sol._primal[i] = basicPrimal[j];
4193  j++;
4194  }
4195  else if(basisStatusCols[i] == SPxSolver::ON_LOWER)
4196  sol._primal[i] = lowerRational(i);
4197  else if(basisStatusCols[i] == SPxSolver::ON_UPPER)
4198  sol._primal[i] = upperRational(i);
4199  else if(basisStatusCols[i] == SPxSolver::ZERO)
4200  sol._primal[i] = 0;
4201  else if(basisStatusCols[i] == SPxSolver::FIXED)
4202  {
4203  assert(lowerRational(i) == upperRational(i));
4204  sol._primal[i] = lowerRational(i);
4205  }
4206  else
4207  {
4208  assert(basisStatusCols[i] == SPxSolver::UNDEFINED);
4209  MSG_INFO1(spxout, spxout << "Undefined basis status of column in rational factorization.\n");
4210  error = true;
4211  goto TERMINATE;
4212  }
4213  }
4214 
4215  sol._slacks.reDim(numRowsRational());
4217  sol._isPrimalFeasible = true;
4218 
4219  sol._dual = basicDual;
4220 
4221  for(int i = 0; i < numColsRational(); i++)
4222  {
4223  if(basisStatusCols[i] == SPxSolver::BASIC)
4224  sol._redCost[i] = 0;
4225  else if(basisStatusCols[i] == SPxSolver::FIXED)
4226  {
4227  sol._redCost[i] = basicDual * colVectorRational(i);
4228  sol._redCost[i] -= objRational(i);
4229  sol._redCost[i] *= -1;
4230  }
4231  else
4232  sol._redCost[i] = _workSol._redCost[i];
4233  }
4234 
4235  sol._isDualFeasible = true;
4236  }
4237 
4238 TERMINATE:
4239  // stop rational solving time
4241  return;
4242 }
4243 
4244 /// attempts rational reconstruction of primal-dual solution
4246  DataArray< SPxSolver::VarStatus >& basisStatusRows,
4247  DataArray< SPxSolver::VarStatus >& basisStatusCols, const Rational& denomBoundSquared)
4248 {
4249  bool success;
4250  bool isSolBasic;
4251  DIdxSet basicIndices(numColsRational());
4252 
4253  success = false;
4254  isSolBasic = true;
4255 
4256  if(!sol.isPrimalFeasible() || !sol.isDualFeasible())
4257  return success;
4258 
4259  // start timing and increment statistics counter
4262 
4263  // reconstruct primal vector
4264  _workSol._primal = sol._primal;
4265 
4266  for(int j = 0; j < numColsRational(); ++j)
4267  {
4268  if(basisStatusCols[j] == SPxSolver::BASIC)
4269  basicIndices.addIdx(j);
4270  }
4271 
4272  success = reconstructVector(_workSol._primal, denomBoundSquared, &basicIndices);
4273 
4274  if(!success)
4275  {
4276  MSG_INFO1(spxout, spxout << "Rational reconstruction of primal solution failed.\n");
4278  return success;
4279  }
4280 
4281  MSG_DEBUG(spxout << "Rational reconstruction of primal solution successful.\n");
4282 
4283  // check violation of bounds
4284  for(int c = numColsRational() - 1; c >= 0; c--)
4285  {
4286  // we want to notify the user whether the reconstructed solution is basic; otherwise, this would be redundant
4287  SPxSolver::VarStatus& basisStatusCol = _basisStatusCols[c];
4288 
4289  if((basisStatusCol == SPxSolver::FIXED && _workSol._primal[c] != lowerRational(c))
4290  || (basisStatusCol == SPxSolver::ON_LOWER && _workSol._primal[c] != lowerRational(c))
4291  || (basisStatusCol == SPxSolver::ON_UPPER && _workSol._primal[c] != upperRational(c))
4292  || (basisStatusCol == SPxSolver::ZERO && _workSol._primal[c] != 0)
4293  || (basisStatusCol == SPxSolver::UNDEFINED))
4294  {
4295  isSolBasic = false;
4296  }
4297 
4299  {
4300  MSG_DEBUG(std::cout << "Lower bound of variable " << c << " violated by " << rationalToString(
4301  lowerRational(c) - _workSol._primal[c]) << "\n");
4302  MSG_INFO1(spxout, spxout << "Reconstructed solution primal infeasible (1).\n");
4304  return false;
4305  }
4306 
4308  {
4309  MSG_DEBUG(std::cout << "Upper bound of variable " << c << " violated by " << rationalToString(
4310  _workSol._primal[c] - upperRational(c)) << "\n");
4311  MSG_INFO1(spxout, spxout << "Reconstructed solution primal infeasible (2).\n");
4313  return false;
4314  }
4315  }
4316 
4317  // compute slacks
4318  ///@todo we should compute them one by one so we can abort when encountering an infeasibility
4321 
4322  // check violation of sides
4323  for(int r = numRowsRational() - 1; r >= 0; r--)
4324  {
4325  // we want to notify the user whether the reconstructed solution is basic; otherwise, this would be redundant
4326  SPxSolver::VarStatus& basisStatusRow = _basisStatusRows[r];
4327 
4328  if((basisStatusRow == SPxSolver::FIXED && _workSol._slacks[r] != lhsRational(r))
4329  || (basisStatusRow == SPxSolver::ON_LOWER && _workSol._slacks[r] != lhsRational(r))
4330  || (basisStatusRow == SPxSolver::ON_UPPER && _workSol._slacks[r] != rhsRational(r))
4331  || (basisStatusRow == SPxSolver::ZERO && _workSol._slacks[r] != 0)
4332  || (basisStatusRow == SPxSolver::UNDEFINED))
4333  {
4334  isSolBasic = false;
4335  }
4336 
4338  {
4339  MSG_DEBUG(std::cout << "Lhs of row " << r << " violated by " << rationalToString(lhsRational(
4340  r) - _workSol._slacks[r]) << "\n");
4341  MSG_INFO1(spxout, spxout << "Reconstructed solution primal infeasible (3).\n");
4343  return false;
4344  }
4345 
4347  {
4348  MSG_DEBUG(std::cout << "Rhs of row " << r << " violated by " << rationalToString(
4349  _workSol._slacks[r] - rhsRational(r)) << "\n");
4350  MSG_INFO1(spxout, spxout << "Reconstructed solution primal infeasible (4).\n");
4352  return false;
4353  }
4354  }
4355 
4356  // reconstruct dual vector
4357  _workSol._dual = sol._dual;
4358 
4359  success = reconstructVector(_workSol._dual, denomBoundSquared);
4360 
4361  if(!success)
4362  {
4363  MSG_INFO1(spxout, spxout << "Rational reconstruction of dual solution failed.\n");
4365  return success;
4366  }
4367 
4368  MSG_DEBUG(spxout << "Rational reconstruction of dual vector successful.\n");
4369 
4370  // check dual multipliers before reduced costs because this check is faster since it does not require the
4371  // computation of reduced costs
4372  const bool maximizing = (intParam(SoPlex::OBJSENSE) == SoPlex::OBJSENSE_MAXIMIZE);
4373 
4374  for(int r = numRowsRational() - 1; r >= 0; r--)
4375  {
4376  int sig = sign(_workSol._dual[r]);
4377 
4378  if((!maximizing && sig > 0) || (maximizing && sig < 0))
4379  {
4380  if(!_lowerFinite(_rowTypes[r]) || _workSol._slacks[r] > lhsRational(r))
4381  {
4382  MSG_DEBUG(std::cout << "complementary slackness violated by row " << r
4383  << " with dual " << rationalToString(_workSol._dual[r])
4384  << " and slack " << rationalToString(_workSol._slacks[r])
4385  << " not at lhs " << rationalToString(lhsRational(r))
4386  << "\n");
4387  MSG_INFO1(spxout, spxout << "Reconstructed solution dual infeasible (1).\n");
4389  return false;
4390  }
4391 
4393  {
4395  isSolBasic = false;
4396  else
4398  }
4399  }
4400  else if((!maximizing && sig < 0) || (maximizing && sig > 0))
4401  {
4402  if(!_upperFinite(_rowTypes[r]) || _workSol._slacks[r] < rhsRational(r))
4403  {
4404  MSG_DEBUG(std::cout << "complementary slackness violated by row " << r
4405  << " with dual " << rationalToString(_workSol._dual[r])
4406  << " and slack " << rationalToString(_workSol._slacks[r])
4407  << " not at rhs " << rationalToString(rhsRational(r))
4408  << "\n");
4409  MSG_INFO1(spxout, spxout << "Reconstructed solution dual infeasible (2).\n");
4411  return false;
4412  }
4413 
4415  {
4417  isSolBasic = false;
4418  else
4420  }
4421  }
4422  }
4423 
4424  // compute reduced cost vector; we assume that the objective function vector has less nonzeros than the reduced
4425  // cost vector, and so multiplying with -1 first and subtracting the dual activity should be faster than adding
4426  // the dual activity and negating afterwards
4427  ///@todo we should compute them one by one so we can abort when encountering an infeasibility
4431 
4432  // check reduced cost violation
4433  for(int c = numColsRational() - 1; c >= 0; c--)
4434  {
4435  int sig = sign(_workSol._redCost[c]);
4436 
4437  if((!maximizing && sig > 0) || (maximizing && sig < 0))
4438  {
4440  {
4441  MSG_DEBUG(std::cout << "complementary slackness violated by column " << c
4442  << " with reduced cost " << rationalToString(_workSol._redCost[c])
4443  << " and value " << rationalToString(_workSol._primal[c])
4444  << " not at lower bound " << rationalToString(lowerRational(c))
4445  << "\n");
4446  MSG_INFO1(spxout, spxout << "Reconstructed solution dual infeasible (3).\n");
4448  return false;
4449  }
4450 
4452  {
4454  isSolBasic = false;
4455  else
4457  }
4458  }
4459  else if((!maximizing && sig < 0) || (maximizing && sig > 0))
4460  {
4462  {
4463  MSG_DEBUG(std::cout << "complementary slackness violated by column " << c
4464  << " with reduced cost " << rationalToString(_workSol._redCost[c])
4465  << " and value " << rationalToString(_workSol._primal[c])
4466  << " not at upper bound " << rationalToString(upperRational(c))
4467  << "\n");
4468  MSG_INFO1(spxout, spxout << "Reconstructed solution dual infeasible (4).\n");
4470  return false;
4471  }
4472 
4474  {
4476  isSolBasic = false;
4477  else
4479  }
4480  }
4481  }
4482 
4483  // update solution
4484  sol._primal = _workSol._primal;
4485  sol._slacks = _workSol._slacks;
4486  sol._dual = _workSol._dual;
4487  sol._redCost = _workSol._redCost;
4488 
4489  if(!isSolBasic)
4490  {
4491  MSG_WARNING(spxout, spxout << "Warning: Reconstructed solution not basic.\n");
4492  _hasBasis = false;
4493  }
4494 
4495  // stop timing
4497 
4498  return success;
4499 }
4500 } // namespace soplex
const VectorBase< R > & rhs() const
Returns right hand side vector.
Definition: spxlpbase.h:221
Rational spxAbs(const Rational &r)
Absolute.
Definition: rational.cpp:3018
int _lastSolveMode
Definition: soplex.h:1867
const VectorRational & rhsRational() const
returns right-hand side vector
Definition: soplex.cpp:1214
DVectorBase< R > _slacks
Definition: solbase.h:219
void _computeBasisInverseRational()
computes rational inverse of basis matrix as defined by _rationalLUSolverBind
int unbdRefinements
number of refinement steps during undboundedness test
Definition: statistics.h:113
virtual void removeRow(int i)
Removes i &#39;th row.
Definition: spxlpbase.h:933
Rational _rationalMaxscaleincr
Definition: soplex.h:1603
free variable fixed to zero.
Definition: spxsolver.h:194
DVectorRational _unboundedRhs
Definition: soplex.h:1667
bool isSetup() const
Returns setup status.
Definition: ssvectorbase.h:121
bool GE(Real a, Real b, Real eps=Param::epsilon())
returns true iff a >= b + eps
Definition: spxdefines.h:406
SolRational _workSol
Definition: soplex.h:1874
void reDim(int newdim, const bool setZero=true)
Resets DVectorBase&#39;s dimension to newdim.
Definition: dvectorbase.h:253
Rational & addProduct(const Rational &r, const Rational &s)
add product of two rationals
Definition: rational.cpp:1637
void _transformEquality()
introduces slack variables to transform inequality constraints into equations for both rational and r...
DVectorBase< R > _dualFarkas
Definition: solbase.h:223
Timer * syncTime
time for synchronization between real and rational LP (included in solving time)
Definition: statistics.h:91
Basis is not known to be dual nor primal feasible.
Definition: spxbasis.h:94
int feasRefinements
number of refinement steps during infeasibility test
Definition: statistics.h:112
No matrix has yet been loaded.
virtual void unscalePrimal(const SPxLPBase< Real > &lp, Vector &x) const
unscale dense primal solution vector given in x.
Definition: spxscaler.cpp:614
int numRowsReal() const
returns number of rows
Definition: soplex.cpp:850
virtual void changeLower(const Vector &newLower, bool scale=false)
The time limit has been hit.
const VectorBase< R > & upper() const
Returns upper bound vector.
Definition: spxlpbase.h:461
virtual Status getPrimal(Vector &vector) const
get solution vector for primal variables.
Definition: spxsolve.cpp:1842
upper limit on objective value
Definition: soplex.h:1338
steepest edge pricer with exact initialization of norms
Definition: soplex.h:1200
THREADLOCAL const Real infinity
Definition: spxdefines.cpp:26
void _transformUnbounded()
transforms LP to unboundedness problem by moving the objective function to the constraints, changing right-hand side and bounds to zero, and adding an auxiliary variable for the decrease in the objective function
general zero tolerance
Definition: soplex.h:1317
LPRowBase< Rational > LPRowRational
Definition: lprow.h:29
Result
Result of the simplification.
Definition: spxsimplifier.h:81
const SPxRatioTester * ratiotester() const
return loaded SPxRatioTester.
Definition: spxsolver.h:1781
type of ratio test
Definition: soplex.h:1017
the problem was so much simplified that it vanished
Definition: spxsimplifier.h:87
continue iterative refinement with exact basic solution if not optimal?
Definition: soplex.h:953
void setBasis(const VarStatus rows[], const VarStatus cols[])
set the lp solver&#39;s basis.
Definition: spxsolver.cpp:1975
virtual Result simplify(SPxLP &lp, Real eps, Real delta)=0
simplify SPxLP lp with identical primal and dual feasibility tolerance.
DVectorRational _feasLhs
Definition: soplex.h:1670
type of computational form, i.e., column or row representation
Definition: soplex.h:978
int stallRefinements
number of refinement steps without pivots
Definition: statistics.h:110
T * get_ptr()
get a C pointer to the data.
Definition: dataarray.h:110
virtual void removeRowRange(int start, int end, int perm[]=0)
Removes rows from start to end (including both).
Definition: spxlpbase.h:1003
int size() const
Number of used indices.
Definition: svectorbase.h:153
int numRowsRational() const
returns number of rows
Definition: soplex.cpp:1142
SPxLPRational * _rationalLP
Definition: soplex.h:1659
Status getBasis(VarStatus rows[], VarStatus cols[], const int rowsSize=-1, const int colsSize=-1) const
get current basis, and return solver status.
Definition: spxsolver.cpp:1900
SPxSolver::Status _solveRealStable(bool acceptUnbounded, bool acceptInfeasible, VectorReal &primal, VectorReal &dual, DataArray< SPxSolver::VarStatus > &basisStatusRows, DataArray< SPxSolver::VarStatus > &basisStatusCols, bool &returnedBasis, const bool forceNoSimplifier=false)
solves real LP with recovery mechanism
Basis is optimal, i.e. dual and primal feasible.
Definition: spxbasis.h:97
Real feastol() const
allowed primal feasibility tolerance.
Definition: spxsolver.h:803
time limit in seconds (INFTY if unlimited)
Definition: soplex.h:1332
Rational _rationalFeastol
Definition: soplex.h:1601
DVectorBase< R > _primalRay
Definition: solbase.h:220
DVectorBase< R > _redCost
Definition: solbase.h:222
int getFactorCount() const
number of factorizations performed
virtual void clearRowObjs()
Definition: spxsolver.h:977
primal feasibility tolerance
Definition: soplex.h:1311
void getObj(VectorBase< R > &pobj) const
Gets objective vector.
Definition: spxlpbase.h:398
void setType(Type tp)
set LEAVE or ENTER algorithm.
Definition: spxsolver.cpp:180
DVectorRational _feasRhs
Definition: soplex.h:1671
DVectorRational _feasLower
Definition: soplex.h:1672
solve() aborted due to iteration limit.
Definition: spxsolver.h:213
SPxScaler * _scaler
Definition: soplex.h:1638
virtual void changeUpper(const Vector &newUpper, bool scale=false)
mode for synchronizing real and rational LP
Definition: soplex.h:1020
bool hasDualFarkas() const
is a dual farkas ray available?
Definition: solbase.h:110
void _optimizeRational()
solves rational LP
void setValue(int i, R x)
Sets i &#39;th element to x.
Definition: ssvectorbase.h:219
virtual void unscaleRedCost(const SPxLPBase< Real > &lp, Vector &r) const
unscale dense reduced cost vector given in r.
Definition: spxscaler.cpp:650
void _transformFeasibility()
transforms LP to feasibility problem by removing the objective function, shifting variables...
Abstract ratio test base class.Class SPxRatioTester is the virtual base class for computing the ratio...
virtual void unscaleDual(const SPxLPBase< Real > &lp, Vector &pi) const
unscale dense dual solution vector given in pi.
Definition: spxscaler.cpp:638
should cycling solutions be accepted during iterative refinement?
Definition: soplex.h:944
void _disableSimplifierAndScaler()
disables simplifier and scaler
Definition: soplex.cpp:8501
DataArray< SPxSolver::VarStatus > _storedBasisStatusCols
Definition: soplex.h:1681
void add(const LPColBase< R > &pcol)
Definition: lpcolsetbase.h:255
Real lowerReal(int i) const
returns lower bound of column i
Definition: soplex.cpp:1052
unsigned int _hasPrimalRay
Definition: solbase.h:228
Implementation of Sparse Linear Solver with Rational precision.
void _performFeasIRStable(SolRational &sol, bool &withDualFarkas, bool &stopped, bool &stoppedIter, bool &error)
performs iterative refinement on the auxiliary problem for testing feasibility
void _storeBasis()
store basis
Rational & subProduct(const Rational &r, const Rational &s)
subtract product of two rationals
Definition: rational.cpp:1688
Real upperReal(int i) const
returns upper bound of column i
Definition: soplex.cpp:1025
Rational & invert()
inversion
Definition: rational.cpp:1815
int refinements
number of refinement steps
Definition: statistics.h:109
variable fixed to identical bounds.
Definition: spxsolver.h:193
DVectorReal _manualObj
Definition: soplex.h:1650
objective sense
Definition: soplex.h:975
virtual void removeCol(int i)
Removes i &#39;th column.
Definition: spxlpbase.h:1033
LP has been proven to be primal infeasible.
Definition: spxsolver.h:222
R & value(int n)
Reference to value of n &#39;th nonzero.
Definition: svectorbase.h:253
SPxSolver::Status _solveRealForRational(bool fromscratch, VectorReal &primal, VectorReal &dual, DataArray< SPxSolver::VarStatus > &basisStatusRows, DataArray< SPxSolver::VarStatus > &basisStatusCols, bool &returnedBasis)
solves real LP during iterative refinement
void _untransformUnbounded(SolRational &sol, bool unbounded)
undoes transformation to unboundedness problem
void dump() const
Definition: spxdesc.cpp:114
Ids for LP columns.Class SPxColId provides DataKeys for the column indices of an SPxLP.
Definition: spxid.h:36
int intParam(const IntParam param) const
returns integer parameter value
Definition: soplex.cpp:5773
void setOpttol(Real d)
set parameter opttol.
Definition: spxsolver.cpp:992
minimum number of stalling refinements since last pivot to trigger rational factorization ...
Definition: soplex.h:1038
int sign(const Rational &r)
Sign function; returns 1 if r > 0, 0 if r = 0, and -1 if r < 0.
Definition: rational.cpp:3028
Wrapper for GMP type mpq_class.We wrap mpq_class so that we can replace it by a double type if GMP is...
Definition: rational.h:44
Real rhsReal(int i) const
returns right-hand side of row i
Definition: soplex.cpp:953
should a rational factorization be performed after iterative refinement?
Definition: soplex.h:928
const SPxPricer * pricer() const
return loaded SPxPricer.
Definition: spxsolver.h:1771
LPColBase< Real > LPColReal
Definition: lpcol.h:30
Rational _rationalPosInfty
Definition: soplex.h:1599
Rational _rationalOpttol
Definition: soplex.h:1602
const VectorRational & lhsRational() const
returns left-hand side vector
Definition: soplex.cpp:1232
int nRows() const
Returns number of rows in LP.
Definition: spxlpbase.h:152
Rational objRational(int i) const
returns objective value of column i
Definition: soplex.cpp:1342
void add(const SVectorBase< S > &vec)
Append nonzeros of sv.
Definition: dsvectorbase.h:218
DVectorRational _modLhs
Definition: soplex.h:1676
DVectorReal _manualLower
Definition: soplex.h:1646
virtual void changeRhs(const Vector &newRhs, bool scale=false)
virtual void start()=0
start timer, resume accounting user, system and real time.
Entering Simplex.
Definition: spxsolver.h:134
virtual Real stop()=0
stop timer, return accounted user time.
void spx_alloc(T &p, int n=1)
Allocate memory.
Definition: spxalloc.h:48
simplification could be done
Definition: spxsimplifier.h:83
const UnitVectorRational * _unitVectorRational(const int i)
returns pointer to a constant unit vector available until destruction of the SoPlex class ...
Definition: soplex.cpp:8872
virtual Status getDualfarkas(Vector &vector) const
get dual farkas proof of infeasibility.
Definition: spxsolve.cpp:2030
LP is primal infeasible or unbounded.
Definition: spxsolver.h:223
Rational reconstruction of solution vector.
Leaving Simplex.
Definition: spxsolver.h:143
void _ensureDSVectorRationalMemory(DSVectorRational &vec, const int newmax) const
extends sparse vector to hold newmax entries if and only if it holds no more free entries ...
Definition: soplex.cpp:7653
column representation Ax - s = 0, lower <= x <= upper, lhs <= s <= rhs
Definition: soplex.h:1082
DataArray< SPxSolver::VarStatus > _basisStatusCols
Definition: soplex.h:1870
DVectorRational _unboundedLower
Definition: soplex.h:1664
bool reconstructVector(VectorRational &input, const Rational &denomBoundSquared, const DIdxSet *indexSet)
Definition: ratrecon.cpp:230
nothing known about basis status (possibly due to a singular basis in transformed problem) ...
Definition: spxsolver.h:196
virtual void changeRowObj(const Vector &newObj, bool scale=false)
virtual void writeFile(const char *filename, const NameSet *rowNames=0, const NameSet *colNames=0, const DIdxSet *p_intvars=0) const
Write loaded LP to filename.
Definition: spxlpbase.h:1216
SPxStatus status() const
Definition: spxbasis.h:425
DVectorReal _manualRhs
Definition: soplex.h:1649
DataArray< RangeType > _colTypes
Definition: soplex.h:1706
type of scaler
Definition: soplex.h:1008
Real getSolveTime() const
time spent in solves
double Real
Definition: spxdefines.h:218
Rational _rationalPosone
Definition: soplex.h:1888
bool _isRealLPLoaded
Definition: soplex.h:1641
SLUFactorRational _rationalLUSolver
Definition: soplex.h:1660
void _solveRealLPAndRecordStatistics()
call floating-point solver and update statistics on iterations etc.
Definition: soplex.cpp:8555
DVectorBase< R > _primal
Definition: solbase.h:218
user sync of real and rational LP
Definition: soplex.h:1229
#define MSG_DEBUG(x)
Definition: spxdefines.h:132
Status status() const
Status of solution process.
Definition: spxsolve.cpp:2213
void setMarkowitz(Real m)
sets minimum Markowitz threshold.
Definition: slufactor.h:129
lower threshold in lifting (nonzero matrix coefficients with smaller absolute value will be reformula...
Definition: soplex.h:1350
int & index(int n)
Reference to index of n &#39;th nonzero.
Definition: svectorbase.h:235
virtual void changeMaxObj(const VectorBase< R > &newObj, bool scale=false)
Changes objective vector to newObj. scale determines whether the new data should be scaled...
Definition: spxlpbase.h:1371
Timer * rationalTime
time for rational LP solving (included in solving time)
Definition: statistics.h:93
int _beforeLiftCols
Definition: soplex.h:1685
bool _isConsistent() const
checks consistency
Definition: soplex.cpp:7697
void _performOptIRStable(SolRational &sol, bool acceptUnbounded, bool acceptInfeasible, int minRounds, bool &primalFeasible, bool &dualFeasible, bool &infeasible, bool &unbounded, bool &stopped, bool &stoppedIter, bool &error)
solves current problem with iterative refinement and recovery mechanism
LP has been solved to optimality.
Definition: spxsolver.h:220
void setTimeLimit(const Real limit)
set time limit on factorization
#define MSG_INFO2(spxout, x)
Prints out message x if the verbosity level is at least SPxOut::INFO2.
Definition: spxdefines.h:120
bool _upperFinite(const RangeType &rangeType) const
checks whether RangeType corresponds to finite upper bound
Definition: soplex.cpp:7813
bool _hasBasis
Definition: soplex.h:1876
unsigned int _hasDualFarkas
Definition: solbase.h:230
void append(const T &t)
append element t.
Definition: dataarray.h:121
LPRowBase< Real > LPRowReal
Definition: lprow.h:28
void _restoreLPReal()
restores objective, bounds, and sides of real LP
DVectorBase< Rational > DVectorRational
Definition: dvector.h:30
void _project(SolRational &sol)
undoes lifting
Class for collecting statistical information.
void clearNum(int n)
Sets n &#39;th nonzero element to 0 (index n must exist).
Definition: ssvectorbase.h:270
solve() aborted due to time limit.
Definition: spxsolver.h:212
void _performUnboundedIRStable(SolRational &sol, bool &hasUnboundedRay, bool &stopped, bool &stoppedIter, bool &error)
performs iterative refinement on the auxiliary problem for testing unboundedness
Rational _rationalNegone
Definition: soplex.h:1889
DVectorRational _feasObj
Definition: soplex.h:1669
an error occured.
Definition: spxsolver.h:204
void addIdx(int i)
adds index i to the index set
Definition: didxset.h:79
round scaling factors for iterative refinement to powers of two?
Definition: soplex.h:950
const T * get_const_ptr() const
get a const C pointer to the data.
Definition: dataarray.h:115
virtual void changeLhs(const Vector &newLhs, bool scale=false)
void _computeInfeasBox(SolRational &sol, bool transformed)
virtual void changeLower(const VectorBase< R > &newLower, bool scale=false)
Changes vector of lower bounds to newLower. scale determines whether the new data should be scaled...
Definition: spxlpbase.h:1409
Statistics * _statistics
statistics since last call to solveReal() or solveRational()
Definition: soplex.h:1586
virtual void changeRhs(const VectorBase< R > &newRhs, bool scale=false)
Changes right hand side vector for constraints to newRhs. scale determines whether the new data shoul...
Definition: spxlpbase.h:1555
LPColSetRational _slackCols
Definition: soplex.h:1663
type of simplifier
Definition: soplex.h:1005
bool isPrimalFeasible() const
is the stored solution primal feasible?
Definition: solbase.h:51
R obj(int i) const
Returns objective value of column i.
Definition: spxlpbase.h:407
void solveRight(VectorRational &x, const VectorRational &b)
Solves .
DVectorRational _feasUpper
Definition: soplex.h:1673
const VectorBase< R > & lhs() const
Returns left hand side vector.
Definition: spxlpbase.h:255
void clear()
Clears vector.
Definition: ssvectorbase.h:603
virtual void addPrimalActivity(const SVectorBase< R > &primal, VectorBase< R > &activity) const
Updates activity of the rows for a given primal vector; activity does not need to be zero...
Definition: spxlpbase.h:1856
int numColsRational() const
returns number of columns
Definition: soplex.cpp:1151
Abstract pricer base class.Class SPxPricer is a pure virtual class defining the interface for pricer ...
Definition: spxpricer.h:46
bool _reconstructSolutionRational(SolRational &sol, DataArray< SPxSolver::VarStatus > &basisStatusRows, DataArray< SPxSolver::VarStatus > &basisStatusCols, const Rational &denomBoundSquared)
attempts rational reconstruction of primal-dual solution
virtual void getBasis(SPxSolver::VarStatus[], SPxSolver::VarStatus[], const int rowsSize=-1, const int colsSize=-1) const =0
get optimal basis.
RangeType _switchRangeType(const RangeType &rangeType) const
switches RANGETYPE_LOWER to RANGETYPE_UPPER and vice versa
Definition: soplex.cpp:7791
SLUFactor _slufactor
Definition: soplex.h:1612
variable set to its upper bound.
Definition: spxsolver.h:191
void setEpsilon(R eps)
Changes the non-zero epsilon, invalidating the setup. */.
Definition: ssvectorbase.h:111
Dynamic index set.Class DIdxSet provides dynamic IdxSet in the sense, that no restrictions are posed ...
Definition: didxset.h:42
virtual void changeBounds(const VectorBase< R > &newLower, const VectorBase< R > &newUpper, bool scale=false)
Changes variable bounds to newLower and newUpper. scale determines whether the new data should be sca...
Definition: spxlpbase.h:1485
Real realParam(const RealParam param) const
returns real parameter value
Definition: soplex.cpp:5783
Real luSolveTimeRational
time for solving linear systems in rational precision
Definition: statistics.h:99
primal infeasibility was detected
Definition: spxsimplifier.h:84
virtual Real time() const =0
DVectorRational _modUpper
Definition: soplex.h:1675
SPxLPBase< Rational > SPxLPRational
Definition: spxlp.h:37
SPxOut spxout
Definition: soplex.h:1485
infinity threshold
Definition: soplex.h:1329
algorithm is running
Definition: spxsolver.h:218
const SVectorRational & colVectorRational(int i) const
returns vector of column i
Definition: soplex.cpp:1277
const VectorBase< R > & maxRowObj() const
Definition: spxlpbase.h:300
int index(int n) const
Returns index of the n &#39;th nonzero element.
Definition: ssvectorbase.h:175
SPxDefaultRT _ratiotesterTextbook
Definition: soplex.h:1629
Status load(const SVectorRational *vec[], int dim)
virtual const Vector & unsimplifiedPrimal()=0
returns a reference to the unsimplified primal solution.
virtual void loadLP(const SPxLP &LP, bool initSlackBasis=true)
copy LP.
Definition: spxsolver.cpp:71
variable set to its lower bound.
Definition: spxsolver.h:192
LPColBase< Rational > LPColRational
Definition: lpcol.h:31
Real lhsReal(int i) const
returns left-hand side of row i
Definition: soplex.cpp:980
Preconfigured SoPlex LP solver.
#define MSG_INFO3(spxout, x)
Prints out message x if the verbosity level is at least SPxOut::INFO3.
Definition: spxdefines.h:122
void add(int i, const R &v)
Append one nonzero (i,v).
Definition: svectorbase.h:271
Real markowitz()
returns Markowitz threshold.
Definition: slufactor.h:142
virtual void changeUpper(const VectorBase< R > &newUpper, bool scale=false)
Changes vector of upper bounds to newUpper. scale determines whether the new data should be scaled...
Definition: spxlpbase.h:1447
void reDim(int newdim)
Resets dimension to newdim.
Definition: ssvectorbase.h:569
dual simplex algorithm, i.e., leaving for column and entering for row representation ...
Definition: soplex.h:1095
int _beforeLiftRows
Definition: soplex.h:1684
force iterative refinement
Definition: soplex.h:1252
lower and upper bound finite, but different
Definition: soplex.h:1700
int luFactorizationsRational
number of basis matrix factorizations in rational precision
Definition: statistics.h:107
bool isDualFeasible() const
is a dual solution available?
Definition: solbase.h:88
DVectorReal _manualLhs
Definition: soplex.h:1648
Timer * preprocessingTime
preprocessing time
Definition: statistics.h:89
bool _storedBasis
Definition: soplex.h:1683
virtual void changeObj(const VectorBase< R > &newObj, bool scale=false)
Changes objective vector to newObj. scale determines whether the new data should be scaled...
Definition: spxlpbase.h:1335
void _storeLPReal()
stores objective, bounds, and sides of real LP
Real getFactorTime() const
time spent in factorizations
Rational _rationalNegInfty
Definition: soplex.h:1600
virtual void addDualActivity(const SVectorBase< R > &dual, VectorBase< R > &activity) const
Updates "dual" activity of the columns for a given dual vector, i.e., y^T A; activity does not need t...
Definition: spxlpbase.h:1880
VectorBase< R > & multAdd(const S &x, const VectorBase< T > &vec)
Addition of scaled vector.
Definition: vectorbase.h:412
lower bound equals upper bound
Definition: soplex.h:1703
virtual void addCol(const LPColBase< R > &col, bool scale=false)
Definition: spxlpbase.h:757
virtual void scale(SPxLPBase< Real > &lp, bool persistent=true)=0
scale SPxLP.
Timer * reconstructionTime
time for rational reconstructions
Definition: statistics.h:94
int dim() const
Dimension of vector.
Definition: vectorbase.h:217
int size() const
Returns the number of nonzeros.
Definition: ssvectorbase.h:200
Everything should be within this namespace.
DVectorReal _manualUpper
Definition: soplex.h:1647
working tolerance for feasibility in floating-point solver during iterative refinement ...
Definition: soplex.h:1341
SPxLPReal * _realLP
Definition: soplex.h:1635
bool _lowerFinite(const RangeType &rangeType) const
checks whether RangeType corresponds to finite lower bound
Definition: soplex.cpp:7804
virtual void changeRange(const VectorBase< R > &newLhs, const VectorBase< R > &newRhs, bool scale=false)
Changes left and right hand side vectors. scale determines whether the new data should be scaled...
Definition: spxlpbase.h:1585
textbook ratio test without stabilization
Definition: soplex.h:1207
SPxDevexPR _pricerDevex
Definition: soplex.h:1626
void clear()
Remove all indices.
Definition: svectorbase.h:431
DataArray< RangeType > _rowTypes
Definition: soplex.h:1707
DVectorRational _modObj
Definition: soplex.h:1678
apply rational reconstruction after each iterative refinement?
Definition: soplex.h:947
solve() aborted due to detection of cycling.
Definition: spxsolver.h:211
type of pricer
Definition: soplex.h:1014
bound flipping ratio test for long steps in the dual simplex
Definition: soplex.h:1216
Saving LPs in a form suitable for SoPlex.Class SPxLPBase provides the data structures required for sa...
Definition: spxlpbase.h:80
DSVectorBase< Real > DSVectorReal
Definition: dsvector.h:29
equilibrium scaling on rows and columns
Definition: soplex.h:1150
primal unboundedness was detected
Definition: spxsimplifier.h:86
working tolerance for optimality in floating-point solver during iterative refinement ...
Definition: soplex.h:1344
#define MSG_WARNING(spxout, x)
Prints out message x if the verbosity level is at least SPxOut::WARNING.
Definition: spxdefines.h:116
virtual void unsimplify(const Vector &, const Vector &, const Vector &, const Vector &, const SPxSolver::VarStatus[], const SPxSolver::VarStatus[], bool isOptimal=true)=0
reconstructs an optimal solution for the unsimplified LP.
Real spxNextafter(Real x, Real y)
Definition: spxdefines.h:338
int iterations
number of iterations/pivots
Definition: statistics.h:100
const VectorBase< R > & maxObj() const
Returns objective vector for maximization problem.
Definition: spxlpbase.h:434
DVectorRational _unboundedLhs
Definition: soplex.h:1666
DSVectorRational _primalDualDiff
Definition: soplex.h:1679
void setup()
Initializes nonzero indices for elements with absolute values above epsilon and sets all other elemen...
Definition: ssvectorbase.h:133
DVectorRational _unboundedUpper
Definition: soplex.h:1665
const VectorRational & upperRational() const
returns upper bound vector
Definition: soplex.cpp:1286
SPxSolver _solver
Definition: soplex.h:1611
nothing known on loaded problem.
Definition: spxsolver.h:219
variable is basic.
Definition: spxsolver.h:195
type of algorithm, i.e., primal or dual
Definition: soplex.h:981
const SVectorBase< R > & rowVector(int i) const
Gets row vector of row i.
Definition: spxlpbase.h:206
primal simplex algorithm, i.e., entering for column and leaving for row representation ...
Definition: soplex.h:1092
virtual void addRow(const LPRowBase< R > &row, bool scale=false)
Definition: spxlpbase.h:585
virtual bool isUnsimplified() const
specifies whether an optimal solution has already been unsimplified.
DataArray< SPxSolver::VarStatus > _basisStatusRows
Definition: soplex.h:1869
modified Harris ratio test
Definition: soplex.h:1213
virtual const Vector & unsimplifiedDual()=0
returns a reference to the unsimplified dual solution.
should dual infeasibility be tested in order to try to return a dual solution even if primal infeasib...
Definition: soplex.h:925
void _factorizeColumnRational(SolRational &sol, DataArray< SPxSolver::VarStatus > &basisStatusRows, DataArray< SPxSolver::VarStatus > &basisStatusCols, bool &stoppedTime, bool &stoppedIter, bool &error, bool &optimal)
factorizes rational basis matrix in column representation
Timer * solvingTime
solving time
Definition: statistics.h:88
int size() const
return nr. of elements.
Definition: dataarray.h:214
Type type() const
return current Type.
Definition: spxsolver.h:512
bool boolParam(const BoolParam param) const
returns boolean parameter value
Definition: soplex.cpp:5763
should lifting be used to reduce range of nonzero matrix coefficients?
Definition: soplex.h:919
virtual Status getRedCost(Vector &vector) const
get vector of reduced costs.
Definition: spxsolve.cpp:1951
DataArray< int > _rationalLUSolverBind
Definition: soplex.h:1661
#define MSG_INFO1(spxout, x)
Prints out message x if the verbosity level is at least SPxOut::INFO1.
Definition: spxdefines.h:118
virtual void removeColRange(int start, int end, int perm[]=0)
Removes columns from start to end (including both).
Definition: spxlpbase.h:1103
const SVectorBase< R > & colVector(int i) const
Returns column vector of column i.
Definition: spxlpbase.h:377
int nCols() const
Returns number of columns in LP.
Definition: spxlpbase.h:158
unsigned int _isPrimalFeasible
Definition: solbase.h:227
virtual void changeElement(int i, int j, const R &val, bool scale=false)
Changes LP element (i, j) to val. scale determines whether the new data should be scaled...
Definition: spxlpbase.h:1750
lower limit on objective value
Definition: soplex.h:1335
DSVectorRational _tauColVector
Definition: soplex.h:1668
DVectorRational _modLower
Definition: soplex.h:1674
bool _isSolveStopped(bool &stoppedTime, bool &stoppedIter) const
should solving process be stopped?
Definition: soplex.cpp:7725
virtual void changeLhs(const VectorBase< R > &newLhs, bool scale=false)
Changes left hand side vector for constraints to newLhs. scale determines whether the new data should...
Definition: spxlpbase.h:1517
void setFeastol(Real d)
set parameter feastol.
Definition: spxsolver.cpp:980
Timer * transformTime
time for transforming LPs (included in solving time)
Definition: statistics.h:92
void invalidate()
invalidate solution
Definition: solbase.h:209
void _restoreBasis()
restore basis
bool hasPrimalRay() const
is a primal unbounded ray available?
Definition: solbase.h:73
bool setIntParam(const IntParam param, const int value, const bool init=true)
sets integer parameter value; returns true on success
Definition: soplex.cpp:5885
SolRational _solRational
Definition: soplex.h:1873
std::string rationalToString(const Rational &r, const int precision)
convert rational number to string
Definition: rational.cpp:2108
geometric frequency at which to apply rational reconstruction
Definition: soplex.h:1362
Real opttol() const
allowed optimality, i.e., dual feasibility tolerance.
Definition: spxsolver.h:811
bool _hasSolRational
Definition: soplex.h:1878
void _enableSimplifierAndScaler()
enables simplifier and scaler according to current parameters
Definition: soplex.cpp:8443
DVectorRational _modRhs
Definition: soplex.h:1677
unsigned int _isDualFeasible
Definition: solbase.h:229
virtual void unscaleSlacks(const SPxLPBase< Real > &lp, Vector &s) const
unscale dense slack vector given in s.
Definition: spxscaler.cpp:626
bool setBoolParam(const BoolParam param, const bool value, const bool init=true)
sets boolean parameter value; returns true on success
Definition: soplex.cpp:5813
should LP be transformed to equality form before a rational solve?
Definition: soplex.h:922
const SVectorBase< R > & colVector(int i) const
Returns colVector of i &#39;th LPColBase in LPColSetBase.
Definition: lpcolsetbase.h:208
DVectorBase< R > _dual
Definition: solbase.h:221
virtual void setTerminationValue(Real value=infinity)
set objective limit.
Definition: spxsolver.cpp:1697
void clear()
Removes all LPColBases from the set.
Definition: lpcolsetbase.h:505
void solveLeft(VectorRational &x, const VectorRational &b)
Solves .
const SPxBasis & basis() const
Return current basis.
Definition: spxsolver.h:1761
virtual void changeObj(const Vector &newObj, bool scale=false)
scale determines whether the new data needs to be scaled according to the existing LP (persistent sca...
virtual void reLoad()
reload LP.
Definition: spxsolver.cpp:56
upper threshold in lifting (nonzero matrix coefficients with larger absolute value will be reformulat...
Definition: soplex.h:1353
DataArray< SPxSolver::VarStatus > _storedBasisStatusRows
Definition: soplex.h:1680
SPxLPReal _manualRealLP
Definition: soplex.h:1651
int numColsReal() const
returns number of columns
Definition: soplex.cpp:859
LP has been proven to be primal unbounded.
Definition: spxbasis.h:98
void resetCounters()
reset timers and counters
void reSize(int newsize)
reset size to newsize.
Definition: dataarray.h:226
Real luFactorizationTimeRational
time for factorizing bases matrices in rational precision
Definition: statistics.h:98
void _lift()
reduces matrix coefficient in absolute value by the lifting procedure of Thiele et al...
const VectorBase< R > & lower() const
Returns (internal and possibly scaled) lower bound vector.
Definition: spxlpbase.h:488
SPxSolver::Status _status
Definition: soplex.h:1866
int num() const
Returns the number of LPColBases currently in LPColSetBase.
Definition: lpcolsetbase.h:82
virtual void computePrimalActivity(const VectorBase< R > &primal, VectorBase< R > &activity, const bool unscaled=true) const
Computes activity of the rows for a given primal vector; activity does not need to be zero...
Rational _rationalZero
Definition: soplex.h:1890
const Desc & desc() const
Definition: spxbasis.h:464
int rationalReconstructions
number of rational reconstructions performed
Definition: statistics.h:108
solve() aborted due to objective limit.
Definition: spxsolver.h:214
void spx_free(T &p)
Release memory.
Definition: spxalloc.h:110
SPxSimplifier * _simplifier
Definition: soplex.h:1637
virtual void addCols(const LPColSetBase< R > &pset, bool scale=false)
Definition: spxlpbase.h:813
void _untransformEquality(SolRational &sol)
undoes transformation to equality form
int pivotRefinements
number of refinement steps until final basis is reached
Definition: statistics.h:111
virtual Status getDual(Vector &vector) const
get current solution vector for dual variables.
Definition: spxsolve.cpp:1899
Basis is singular, numerical troubles?
Definition: spxsolver.h:215
R value(int n) const
Returns value of the n &#39;th nonzero element.
Definition: ssvectorbase.h:183
virtual void factorize()
Factorize basis matrix.
Definition: spxsolver.cpp:557
upper bound is finite, lower bound is infinite
Definition: soplex.h:1697
LP has a usable Basis (maybe LP is changed).
Definition: spxsolver.h:217
dual infeasibility was detected
Definition: spxsimplifier.h:85
virtual Status getSlacks(Vector &vector) const
get vector of slack variables.
Definition: spxsolve.cpp:2048
void setBasisStatus(SPxBasis::SPxStatus stat)
set the lp solver&#39;s basis status.
Definition: spxsolver.h:2051
void _untransformFeasibility(SolRational &sol, bool infeasible)
undoes transformation to feasibility problem
LP has been proven to be primal unbounded.
Definition: spxsolver.h:221
LP has been proven to be primal infeasible.
Definition: spxbasis.h:99
virtual void subDualActivity(const VectorBase< R > &dual, VectorBase< R > &activity) const
Updates "dual" activity of the columns for a given dual vector, i.e., y^T A; activity does not need t...
Definition: spxlpbase.h:1898
No Problem has been loaded to the basis.
Definition: spxbasis.h:92
void setDelta(Real d)
set parameter delta, i.e., set feastol and opttol to same value.
Definition: spxsolver.cpp:1004
const VectorRational & lowerRational() const
returns lower bound vector
Definition: soplex.cpp:1304
Rational & powRound()
round up to next power of two
Definition: rational.cpp:1824