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  }
348 
349  // stop timing
351 }
352 
353 
354 
355 /// solves current problem with iterative refinement and recovery mechanism
357  SolRational& sol,
358  bool acceptUnbounded,
359  bool acceptInfeasible,
360  int minRounds,
361  bool& primalFeasible,
362  bool& dualFeasible,
363  bool& infeasible,
364  bool& unbounded,
365  bool& stoppedTime,
366  bool& stoppedIter,
367  bool& error)
368 {
369  // start rational solving timing
371 
372  primalFeasible = false;
373  dualFeasible = false;
374  infeasible = false;
375  unbounded = false;
376  stoppedTime = false;
377  stoppedIter = false;
378  error = false;
379 
380  // set working tolerances in floating-point solver
383 
384  // declare vectors and variables
386 
387  _modLower.reDim(numColsRational(), false);
388  _modUpper.reDim(numColsRational(), false);
389  _modLhs.reDim(numRowsRational(), false);
390  _modRhs.reDim(numRowsRational(), false);
391  _modObj.reDim(numColsRational(), false);
392 
393  DVectorReal primalReal(numColsRational());
394  DVectorReal dualReal(numRowsRational());
395 
396  Rational boundsViolation;
397  Rational sideViolation;
398  Rational redCostViolation;
399  Rational dualViolation;
400  Rational primalScale;
401  Rational dualScale;
402  Rational maxScale;
403 
404  // solve original LP
405  MSG_INFO1(spxout, spxout << "Initial floating-point solve . . .\n");
406 
407  if(_hasBasis)
408  {
409  assert(_basisStatusRows.size() == numRowsRational());
410  assert(_basisStatusCols.size() == numColsRational());
413  }
414 
415  for(int r = numRowsRational() - 1; r >= 0; r--)
416  {
417  assert(_solver.maxRowObj(r) == 0.0);
418  }
419 
421  result = _solveRealStable(acceptUnbounded, acceptInfeasible, primalReal, dualReal, _basisStatusRows,
423 
424  // evaluate result
425  switch(result)
426  {
427  case SPxSolver::OPTIMAL:
428  MSG_INFO1(spxout, spxout << "Floating-point optimal.\n");
429  break;
430 
432  MSG_INFO1(spxout, spxout << "Floating-point infeasible.\n");
433 
434  // the floating-point solve returns a Farkas ray if and only if the simplifier was not used, which is exactly
435  // the case when a basis could be returned
436  if(_hasBasis)
437  {
438  sol._dualFarkas = dualReal;
439  sol._hasDualFarkas = true;
440  }
441  else
442  sol._hasDualFarkas = false;
443 
444  infeasible = true;
445  return;
446 
448  MSG_INFO1(spxout, spxout << "Floating-point unbounded.\n");
449  unbounded = true;
450  return;
451 
453  stoppedTime = true;
454  return;
455 
457  stoppedIter = true;
458  return;
459 
460  default:
461  error = true;
462  return;
463  }
464 
466 
467  // store floating-point solution of original LP as current rational solution and ensure that solution vectors have
468  // right dimension; ensure that solution is aligned with basis
469  sol._primal.reDim(numColsRational(), false);
470  sol._slacks.reDim(numRowsRational(), false);
471  sol._dual.reDim(numRowsRational(), false);
472  sol._redCost.reDim(numColsRational(), false);
473  sol._isPrimalFeasible = true;
474  sol._isDualFeasible = true;
475 
476  for(int c = numColsRational() - 1; c >= 0; c--)
477  {
478  SPxSolver::VarStatus& basisStatusCol = _basisStatusCols[c];
479 
480  if(basisStatusCol == SPxSolver::ON_LOWER)
481  sol._primal[c] = lowerRational(c);
482  else if(basisStatusCol == SPxSolver::ON_UPPER)
483  sol._primal[c] = upperRational(c);
484  else if(basisStatusCol == SPxSolver::FIXED)
485  {
486  // it may happen that lower and upper are only equal in the real LP but different in the rational LP; we do
487  // not check this to avoid rational comparisons, but simply switch the basis status to the lower bound; this
488  // is necessary, because for fixed variables any reduced cost is feasible
489  sol._primal[c] = lowerRational(c);
490  basisStatusCol = SPxSolver::ON_LOWER;
491  }
492  else if(basisStatusCol == SPxSolver::ZERO)
493  sol._primal[c] = 0;
494  else
495  sol._primal[c] = primalReal[c];
496  }
497 
499 
500  int dualSize = 0;
501 
502  for(int r = numRowsRational() - 1; r >= 0; r--)
503  {
504  SPxSolver::VarStatus& basisStatusRow = _basisStatusRows[r];
505 
506  // it may happen that left-hand and right-hand side are different in the rational, but equal in the real LP,
507  // leading to a fixed basis status; this is critical because rows with fixed basis status are ignored in the
508  // computation of the dual violation; to avoid rational comparisons we do not check this but simply switch to
509  // the left-hand side status
510  if(basisStatusRow == SPxSolver::FIXED)
511  basisStatusRow = SPxSolver::ON_LOWER;
512 
513  {
514  sol._dual[r] = dualReal[r];
515 
516  if(dualReal[r] != 0.0)
517  dualSize++;
518  }
519  }
520 
521  // we assume that the objective function vector has less nonzeros than the reduced cost vector, and so multiplying
522  // with -1 first and subtracting the dual activity should be faster than adding the dual activity and negating
523  // afterwards
526 
527  // initial scaling factors are one
528  primalScale = _rationalPosone;
529  dualScale = _rationalPosone;
530 
531  // control progress
532  Rational maxViolation;
533  Rational bestViolation = _rationalPosInfty;
534  const Rational violationImprovementFactor = 0.9;
535  const Rational errorCorrectionFactor = 1.1;
536  Rational errorCorrection = 2;
537  int numFailedRefinements = 0;
538 
539  // store basis status in case solving modified problem failed
540  DataArray< SPxSolver::VarStatus > basisStatusRowsFirst;
541  DataArray< SPxSolver::VarStatus > basisStatusColsFirst;
542 
543  // refinement loop
544  const bool maximizing = (intParam(SoPlex::OBJSENSE) == SoPlex::OBJSENSE_MAXIMIZE);
545  const int maxDimRational = numColsRational() > numRowsRational() ? numColsRational() :
546  numRowsRational();
547  SolRational factorSol;
548  bool factorSolNewBasis = true;
549  int lastStallRefinements = 0;
550  int nextRatrecRefinement = 0;
551 
552  do
553  {
554  // decrement minRounds counter
555  minRounds--;
556 
557  MSG_DEBUG(std::cout << "Computing primal violations.\n");
558 
559  // compute violation of bounds
560  boundsViolation = 0;
561 
562  for(int c = numColsRational() - 1; c >= 0; c--)
563  {
564  // lower bound
566 
567  if(_lowerFinite(_colTypes[c]))
568  {
569  if(lowerRational(c) == 0)
570  {
571  _modLower[c] = sol._primal[c];
572  _modLower[c] *= -1;
573 
574  if(_modLower[c] > boundsViolation)
575  boundsViolation = _modLower[c];
576  }
577  else
578  {
579  _modLower[c] = lowerRational(c);
580  _modLower[c] -= sol._primal[c];
581 
582  if(_modLower[c] > boundsViolation)
583  boundsViolation = _modLower[c];
584  }
585  }
586 
587  // upper bound
589 
590  if(_upperFinite(_colTypes[c]))
591  {
592  if(upperRational(c) == 0)
593  {
594  _modUpper[c] = sol._primal[c];
595  _modUpper[c] *= -1;
596 
597  if(_modUpper[c] < -boundsViolation)
598  boundsViolation = -_modUpper[c];
599  }
600  else
601  {
602  _modUpper[c] = upperRational(c);
603  _modUpper[c] -= sol._primal[c];
604 
605  if(_modUpper[c] < -boundsViolation)
606  boundsViolation = -_modUpper[c];
607  }
608  }
609  }
610 
611  // compute violation of sides
612  sideViolation = 0;
613 
614  for(int r = numRowsRational() - 1; r >= 0; r--)
615  {
616  const SPxSolver::VarStatus& basisStatusRow = _basisStatusRows[r];
617 
618  // left-hand side
619  assert((lhsRational(r) > _rationalNegInfty) == _lowerFinite(_rowTypes[r]));
620 
621  if(_lowerFinite(_rowTypes[r]))
622  {
623  if(lhsRational(r) == 0)
624  {
625  _modLhs[r] = sol._slacks[r];
626  _modLhs[r] *= -1;
627  }
628  else
629  {
630  _modLhs[r] = lhsRational(r);
631  _modLhs[r] -= sol._slacks[r];
632  }
633 
634  if(_modLhs[r] > sideViolation)
635  sideViolation = _modLhs[r];
636  // if the activity is feasible, but too far from the bound, this violates complementary slackness; we
637  // count it as side violation here
638  else if(basisStatusRow == SPxSolver::ON_LOWER && _modLhs[r] < -sideViolation)
639  sideViolation = -_modLhs[r];
640  }
641 
642  // right-hand side
643  assert((rhsRational(r) < _rationalPosInfty) == _upperFinite(_rowTypes[r]));
644 
645  if(_upperFinite(_rowTypes[r]))
646  {
647  if(rhsRational(r) == 0)
648  {
649  _modRhs[r] = sol._slacks[r];
650  _modRhs[r] *= -1;
651  }
652  else
653  {
654  _modRhs[r] = rhsRational(r);
655  _modRhs[r] -= sol._slacks[r];
656  }
657 
658  if(_modRhs[r] < -sideViolation)
659  sideViolation = -_modRhs[r];
660  // if the activity is feasible, but too far from the bound, this violates complementary slackness; we
661  // count it as side violation here
662  else if(basisStatusRow == SPxSolver::ON_UPPER && _modRhs[r] > sideViolation)
663  sideViolation = _modRhs[r];
664  }
665  }
666 
667  MSG_DEBUG(std::cout << "Computing dual violations.\n");
668 
669  // compute reduced cost violation
670  redCostViolation = 0;
671 
672  for(int c = numColsRational() - 1; c >= 0; c--)
673  {
674  if(_colTypes[c] == RANGETYPE_FIXED)
675  continue;
676 
677  const SPxSolver::VarStatus& basisStatusCol = _basisStatusCols[c];
678  assert(basisStatusCol != SPxSolver::FIXED);
679 
680  if(((maximizing && basisStatusCol != SPxSolver::ON_LOWER) || (!maximizing
681  && basisStatusCol != SPxSolver::ON_UPPER))
682  && sol._redCost[c] < -redCostViolation)
683  {
684  MSG_DEBUG(std::cout << "basisStatusCol = " << basisStatusCol
685  << ", lower tight = " << bool(sol._primal[c] <= lowerRational(c))
686  << ", upper tight = " << bool(sol._primal[c] >= upperRational(c))
687  << ", sol._redCost[c] = " << rationalToString(sol._redCost[c])
688  << "\n");
689  redCostViolation = -sol._redCost[c];
690  }
691 
692  if(((maximizing && basisStatusCol != SPxSolver::ON_UPPER) || (!maximizing
693  && basisStatusCol != SPxSolver::ON_LOWER))
694  && sol._redCost[c] > redCostViolation)
695  {
696  MSG_DEBUG(std::cout << "basisStatusCol = " << basisStatusCol
697  << ", lower tight = " << bool(sol._primal[c] <= lowerRational(c))
698  << ", upper tight = " << bool(sol._primal[c] >= upperRational(c))
699  << ", sol._redCost[c] = " << rationalToString(sol._redCost[c])
700  << "\n");
701  redCostViolation = sol._redCost[c];
702  }
703  }
704 
705  // compute dual violation
706  dualViolation = 0;
707 
708  for(int r = numRowsRational() - 1; r >= 0; r--)
709  {
710  if(_rowTypes[r] == RANGETYPE_FIXED)
711  continue;
712 
713  const SPxSolver::VarStatus& basisStatusRow = _basisStatusRows[r];
714  assert(basisStatusRow != SPxSolver::FIXED);
715 
716  if(((maximizing && basisStatusRow != SPxSolver::ON_LOWER) || (!maximizing
717  && basisStatusRow != SPxSolver::ON_UPPER))
718  && sol._dual[r] < -dualViolation)
719  {
720  MSG_DEBUG(std::cout << "basisStatusRow = " << basisStatusRow
721  << ", lower tight = " << bool(sol._slacks[r] <= lhsRational(r))
722  << ", upper tight = " << bool(sol._slacks[r] >= rhsRational(r))
723  << ", sol._dual[r] = " << rationalToString(sol._dual[r])
724  << "\n");
725  dualViolation = -sol._dual[r];
726  }
727 
728  if(((maximizing && basisStatusRow != SPxSolver::ON_UPPER) || (!maximizing
729  && basisStatusRow != SPxSolver::ON_LOWER))
730  && sol._dual[r] > dualViolation)
731  {
732  MSG_DEBUG(std::cout << "basisStatusRow = " << basisStatusRow
733  << ", lower tight = " << bool(sol._slacks[r] <= lhsRational(r))
734  << ", upper tight = " << bool(sol._slacks[r] >= rhsRational(r))
735  << ", sol._dual[r] = " << rationalToString(sol._dual[r])
736  << "\n");
737  dualViolation = sol._dual[r];
738  }
739  }
740 
741  _modObj = sol._redCost;
742 
743  // output violations; the reduced cost violations for artificially introduced slack columns are actually violations of the dual multipliers
745  << "Max. bound violation = " << rationalToString(boundsViolation) << "\n"
746  << "Max. row violation = " << rationalToString(sideViolation) << "\n"
747  << "Max. reduced cost violation = " << rationalToString(redCostViolation) << "\n"
748  << "Max. dual violation = " << rationalToString(dualViolation) << "\n");
749 
751  << std::fixed << std::setprecision(2) << std::setw(10)
752  << "Progress table: "
753  << std::setw(10) << _statistics->refinements << " & "
754  << std::setw(10) << _statistics->iterations << " & "
755  << std::setw(10) << _statistics->solvingTime->time() << " & "
756  << std::setw(10) << _statistics->rationalTime->time() << " & "
757  << std::setw(10) << rationalToString(boundsViolation > sideViolation ? boundsViolation :
758  sideViolation, 2) << " & "
759  << std::setw(10) << rationalToString(redCostViolation > dualViolation ? redCostViolation :
760  dualViolation, 2) << "\n");
761 
762  // terminate if tolerances are satisfied
763  primalFeasible = (boundsViolation <= _rationalFeastol && sideViolation <= _rationalFeastol);
764  dualFeasible = (redCostViolation <= _rationalOpttol && dualViolation <= _rationalOpttol);
765 
766  if(primalFeasible && dualFeasible)
767  {
768  if(minRounds < 0)
769  {
770  MSG_INFO1(spxout, spxout << "Tolerances reached.\n");
771  break;
772  }
773  else
774  {
776  "Tolerances reached but minRounds forcing additional refinement rounds.\n");
777  }
778  }
779 
780  // terminate if some limit is reached
781  if(_isSolveStopped(stoppedTime, stoppedIter))
782  break;
783 
784  // check progress
785  maxViolation = boundsViolation;
786 
787  if(sideViolation > maxViolation)
788  maxViolation = sideViolation;
789 
790  if(redCostViolation > maxViolation)
791  maxViolation = redCostViolation;
792 
793  if(dualViolation > maxViolation)
794  maxViolation = dualViolation;
795 
796  bestViolation *= violationImprovementFactor;
797 
798  if(maxViolation > bestViolation)
799  {
800  MSG_INFO2(spxout, spxout << "Failed to reduce violation significantly.\n");
801  numFailedRefinements++;
802  }
803  else
804  bestViolation = maxViolation;
805 
806  // decide whether to perform rational reconstruction and/or factorization
807  bool performRatfac = boolParam(SoPlex::RATFAC)
808  && lastStallRefinements >= intParam(SoPlex::RATFAC_MINSTALLS) && _hasBasis && factorSolNewBasis;
809  bool performRatrec = boolParam(SoPlex::RATREC)
810  && (_statistics->refinements >= nextRatrecRefinement || performRatfac);
811 
812  // attempt rational reconstruction
813  errorCorrection *= errorCorrectionFactor;
814 
815  if(performRatrec && maxViolation > 0)
816  {
817  MSG_INFO1(spxout, spxout << "Performing rational reconstruction . . .\n");
818 
819  maxViolation *= errorCorrection; // only used for sign check later
820  maxViolation.invert();
821 
823  {
824  MSG_INFO1(spxout, spxout << "Tolerances reached.\n");
825  primalFeasible = true;
826  dualFeasible = true;
827  break;
828  }
829 
830  nextRatrecRefinement = int(_statistics->refinements * realParam(SoPlex::RATREC_FREQ)) + 1;
831  MSG_DEBUG(spxout << "Next rational reconstruction after refinement " << nextRatrecRefinement <<
832  ".\n");
833  }
834 
835  // solve basis systems exactly
836  if(performRatfac && maxViolation > 0)
837  {
838  MSG_INFO1(spxout, spxout << "Performing rational factorization . . .\n");
839 
840  bool optimal;
841  _factorizeColumnRational(sol, _basisStatusRows, _basisStatusCols, stoppedTime, stoppedIter, error,
842  optimal);
843  factorSolNewBasis = false;
844 
845  if(stoppedTime)
846  {
847  MSG_INFO1(spxout, spxout << "Stopped rational factorization.\n");
848  }
849  else if(error)
850  {
851  // message was already printed; reset error flag and continue without factorization
852  error = false;
853  }
854  else if(optimal)
855  {
856  MSG_INFO1(spxout, spxout << "Tolerances reached.\n");
857  primalFeasible = true;
858  dualFeasible = true;
859  break;
860  }
861  else if(boolParam(SoPlex::RATFACJUMP))
862  {
863  MSG_INFO1(spxout, spxout << "Jumping to exact basic solution.\n");
864  minRounds++;
865  continue;
866  }
867  }
868 
869  // start refinement
870 
871  // compute primal scaling factor; limit increase in scaling by tolerance used in floating point solve
872  maxScale = primalScale;
873  maxScale *= _rationalMaxscaleincr;
874 
875  primalScale = boundsViolation > sideViolation ? boundsViolation : sideViolation;
876 
877  if(primalScale < redCostViolation)
878  primalScale = redCostViolation;
879 
880  assert(primalScale >= 0);
881 
882  if(primalScale > 0)
883  {
884  primalScale.invert();
885 
886  if(primalScale > maxScale)
887  primalScale = maxScale;
888  }
889  else
890  primalScale = maxScale;
891 
893  primalScale.powRound();
894 
895  // apply scaled bounds
896  if(primalScale <= 1)
897  {
898  if(primalScale < 1)
899  primalScale = 1;
900 
901  for(int c = numColsRational() - 1; c >= 0; c--)
902  {
903  if(_lowerFinite(_colTypes[c]))
904  {
905  if(_modLower[c] <= _rationalNegInfty)
907  else
909  }
910 
911  if(_upperFinite(_colTypes[c]))
912  {
913  if(_modUpper[c] >= _rationalPosInfty)
915  else
917  }
918  }
919  }
920  else
921  {
922  MSG_INFO2(spxout, spxout << "Scaling primal by " << rationalToString(primalScale) << ".\n");
923 
924  for(int c = numColsRational() - 1; c >= 0; c--)
925  {
926  if(_lowerFinite(_colTypes[c]))
927  {
928  _modLower[c] *= primalScale;
929 
930  if(_modLower[c] <= _rationalNegInfty)
932  else
934  }
935 
936  if(_upperFinite(_colTypes[c]))
937  {
938  _modUpper[c] *= primalScale;
939 
940  if(_modUpper[c] >= _rationalPosInfty)
942  else
944  }
945  }
946  }
947 
948  // apply scaled sides
949  assert(primalScale >= 1);
950 
951  if(primalScale == 1)
952  {
953  for(int r = numRowsRational() - 1; r >= 0; r--)
954  {
955  if(_lowerFinite(_rowTypes[r]))
956  {
957  if(_modLhs[r] <= _rationalNegInfty)
959  else
960  _solver.changeLhs(r, Real(_modLhs[r]));
961  }
962 
963  if(_upperFinite(_rowTypes[r]))
964  {
965  if(_modRhs[r] >= _rationalPosInfty)
967  else
968  _solver.changeRhs(r, Real(_modRhs[r]));
969  }
970  }
971  }
972  else
973  {
974  for(int r = numRowsRational() - 1; r >= 0; r--)
975  {
976  if(_lowerFinite(_rowTypes[r]))
977  {
978  _modLhs[r] *= primalScale;
979 
980  if(_modLhs[r] <= _rationalNegInfty)
982  else
983  _solver.changeLhs(r, Real(_modLhs[r]));
984  }
985 
986  if(_upperFinite(_rowTypes[r]))
987  {
988  _modRhs[r] *= primalScale;
989 
990  if(_modRhs[r] >= _rationalPosInfty)
992  else
993  _solver.changeRhs(r, Real(_modRhs[r]));
994  }
995  }
996  }
997 
998  // compute dual scaling factor; limit increase in scaling by tolerance used in floating point solve
999  maxScale = dualScale;
1000  maxScale *= _rationalMaxscaleincr;
1001 
1002  dualScale = redCostViolation > dualViolation ? redCostViolation : dualViolation;
1003  assert(dualScale >= 0);
1004 
1005  if(dualScale > 0)
1006  {
1007  dualScale.invert();
1008 
1009  if(dualScale > maxScale)
1010  dualScale = maxScale;
1011  }
1012  else
1013  dualScale = maxScale;
1014 
1016  dualScale.powRound();
1017 
1018  if(dualScale > primalScale)
1019  dualScale = primalScale;
1020 
1021  if(dualScale < 1)
1022  dualScale = 1;
1023  else
1024  {
1025  MSG_INFO2(spxout, spxout << "Scaling dual by " << rationalToString(dualScale) << ".\n");
1026 
1027  // perform dual scaling
1028  ///@todo remove _modObj and use dualScale * sol._redCost directly
1029  _modObj *= dualScale;
1030  }
1031 
1032  // apply scaled objective function
1033  for(int c = numColsRational() - 1; c >= 0; c--)
1034  {
1035  if(_modObj[c] >= _rationalPosInfty)
1037  else if(_modObj[c] <= _rationalNegInfty)
1039  else
1040  _solver.changeObj(c, Real(_modObj[c]));
1041  }
1042 
1043  for(int r = numRowsRational() - 1; r >= 0; r--)
1044  {
1045  Rational newRowObj;
1046 
1047  if(_rowTypes[r] == RANGETYPE_FIXED)
1048  _solver.changeRowObj(r, 0.0);
1049  else
1050  {
1051  newRowObj = sol._dual[r];
1052  newRowObj *= dualScale;
1053 
1054  if(newRowObj >= _rationalPosInfty)
1056  else if(newRowObj <= _rationalNegInfty)
1058  else
1059  _solver.changeRowObj(r, -Real(newRowObj));
1060  }
1061  }
1062 
1063  MSG_INFO1(spxout, spxout << "Refined floating-point solve . . .\n");
1064 
1065  // ensure that artificial slack columns are basic and inequality constraints are nonbasic; otherwise we may end
1066  // up with dual violation on inequality constraints after removing the slack columns; do not change this in the
1067  // floating-point solver, though, because the solver may require its original basis to detect optimality
1068  if(_slackCols.num() > 0 && _hasBasis)
1069  {
1070  int numOrigCols = numColsRational() - _slackCols.num();
1071  assert(_slackCols.num() <= 0 || boolParam(SoPlex::EQTRANS));
1072 
1073  for(int i = 0; i < _slackCols.num(); i++)
1074  {
1075  int row = _slackCols.colVector(i).index(0);
1076  int col = numOrigCols + i;
1077 
1078  assert(row >= 0);
1079  assert(row < numRowsRational());
1080 
1082  {
1083  _basisStatusRows[row] = _basisStatusCols[col];
1086  }
1087  }
1088  }
1089 
1090  // load basis
1092  {
1093  MSG_DEBUG(spxout << "basis (status = " << _solver.basis().status() << ") desc before set:\n";
1094  _solver.basis().desc().dump());
1096  MSG_DEBUG(spxout << "basis (status = " << _solver.basis().status() << ") desc after set:\n";
1097  _solver.basis().desc().dump());
1098 
1100  MSG_DEBUG(spxout << "setting basis in solver " << (_hasBasis ? "successful" : "failed") <<
1101  " (3)\n");
1102  }
1103 
1104  // solve modified problem
1105  int prevIterations = _statistics->iterations;
1107  result = _solveRealStable(acceptUnbounded, acceptInfeasible, primalReal, dualReal, _basisStatusRows,
1108  _basisStatusCols, _hasBasis, primalScale > 1e20 || dualScale > 1e20);
1109 
1110  // count refinements and remember whether we moved to a new basis
1112 
1113  if(_statistics->iterations <= prevIterations)
1114  {
1115  lastStallRefinements++;
1117  }
1118  else
1119  {
1120  factorSolNewBasis = true;
1121  lastStallRefinements = 0;
1123  }
1124 
1125  // evaluate result; if modified problem was not solved to optimality, stop refinement
1126  switch(result)
1127  {
1128  case SPxSolver::OPTIMAL:
1129  MSG_INFO1(spxout, spxout << "Floating-point optimal.\n");
1130  break;
1131 
1132  case SPxSolver::INFEASIBLE:
1133  MSG_INFO1(spxout, spxout << "Floating-point infeasible.\n");
1134  sol._dualFarkas = dualReal;
1135  sol._hasDualFarkas = true;
1136  infeasible = true;
1138  return;
1139 
1140  case SPxSolver::UNBOUNDED:
1141  MSG_INFO1(spxout, spxout << "Floating-point unbounded.\n");
1142  unbounded = true;
1144  return;
1145 
1146  case SPxSolver::ABORT_TIME:
1147  stoppedTime = true;
1148  return;
1149 
1150  case SPxSolver::ABORT_ITER:
1151  stoppedIter = true;
1153  return;
1154 
1155  default:
1156  error = true;
1158  return;
1159  }
1160 
1162 
1163  // correct primal solution and align with basis
1164  MSG_DEBUG(std::cout << "Correcting primal solution.\n");
1165 
1166  int primalSize = 0;
1167  Rational primalScaleInverse = primalScale;
1168  primalScaleInverse.invert();
1170 
1171  for(int c = numColsRational() - 1; c >= 0; c--)
1172  {
1173  // force values of nonbasic variables to bounds
1174  SPxSolver::VarStatus& basisStatusCol = _basisStatusCols[c];
1175 
1176  if(basisStatusCol == SPxSolver::ON_LOWER)
1177  {
1178  if(sol._primal[c] != lowerRational(c))
1179  {
1180  int i = _primalDualDiff.size();
1182  _primalDualDiff.add(c);
1184  _primalDualDiff.value(i) -= sol._primal[c];
1185  sol._primal[c] = lowerRational(c);
1186  }
1187  }
1188  else if(basisStatusCol == SPxSolver::ON_UPPER)
1189  {
1190  if(sol._primal[c] != upperRational(c))
1191  {
1192  int i = _primalDualDiff.size();
1194  _primalDualDiff.add(c);
1196  _primalDualDiff.value(i) -= sol._primal[c];
1197  sol._primal[c] = upperRational(c);
1198  }
1199  }
1200  else if(basisStatusCol == SPxSolver::FIXED)
1201  {
1202  // it may happen that lower and upper are only equal in the real LP but different in the rational LP; we
1203  // do not check this to avoid rational comparisons, but simply switch the basis status to the lower
1204  // bound; this is necessary, because for fixed variables any reduced cost is feasible
1205  basisStatusCol = SPxSolver::ON_LOWER;
1206 
1207  if(sol._primal[c] != lowerRational(c))
1208  {
1209  int i = _primalDualDiff.size();
1211  _primalDualDiff.add(c);
1213  _primalDualDiff.value(i) -= sol._primal[c];
1214  sol._primal[c] = lowerRational(c);
1215  }
1216  }
1217  else if(basisStatusCol == SPxSolver::ZERO)
1218  {
1219  if(sol._primal[c] != 0)
1220  {
1221  int i = _primalDualDiff.size();
1223  _primalDualDiff.add(c);
1224  _primalDualDiff.value(i) = sol._primal[c];
1225  _primalDualDiff.value(i) *= -1;
1226  sol._primal[c] = 0;
1227  }
1228  }
1229  else
1230  {
1231  if(primalReal[c] == 1.0)
1232  {
1233  int i = _primalDualDiff.size();
1235  _primalDualDiff.add(c);
1236  _primalDualDiff.value(i) = primalScaleInverse;
1237  sol._primal[c] += _primalDualDiff.value(i);
1238  }
1239  else if(primalReal[c] == -1.0)
1240  {
1241  int i = _primalDualDiff.size();
1243  _primalDualDiff.add(c);
1244  _primalDualDiff.value(i) = primalScaleInverse;
1245  _primalDualDiff.value(i) *= -1;
1246  sol._primal[c] += _primalDualDiff.value(i);
1247  }
1248  else if(primalReal[c] != 0.0)
1249  {
1250  int i = _primalDualDiff.size();
1252  _primalDualDiff.add(c);
1253  _primalDualDiff.value(i) = primalReal[c];
1254  _primalDualDiff.value(i) *= primalScaleInverse;
1255  sol._primal[c] += _primalDualDiff.value(i);
1256  }
1257  }
1258 
1259  if(sol._primal[c] != 0)
1260  primalSize++;
1261  }
1262 
1263  // update or recompute slacks depending on which looks faster
1264  if(_primalDualDiff.size() < primalSize)
1265  {
1267 #ifndef NDEBUG
1268 #ifdef SOPLEX_WITH_GMP
1269  {
1270  DVectorRational activity(numRowsRational());
1271  _rationalLP->computePrimalActivity(sol._primal, activity);
1272  assert(sol._slacks == activity);
1273  }
1274 #endif
1275 #endif
1276  }
1277  else
1279 
1280  const int numCorrectedPrimals = _primalDualDiff.size();
1281 
1282  // correct dual solution and align with basis
1283  MSG_DEBUG(std::cout << "Correcting dual solution.\n");
1284 
1285 #ifndef NDEBUG
1286  {
1287  // compute reduced cost violation
1288  DVectorRational debugRedCost(numColsRational());
1289  debugRedCost = DVectorRational(_realLP->maxObj());
1290  debugRedCost *= -1;
1291  _rationalLP->subDualActivity(DVectorRational(dualReal), debugRedCost);
1292 
1293  Rational debugRedCostViolation = 0;
1294 
1295  for(int c = numColsRational() - 1; c >= 0; c--)
1296  {
1297  if(_colTypes[c] == RANGETYPE_FIXED)
1298  continue;
1299 
1300  const SPxSolver::VarStatus& basisStatusCol = _basisStatusCols[c];
1301  assert(basisStatusCol != SPxSolver::FIXED);
1302 
1303  if(((maximizing && basisStatusCol != SPxSolver::ON_LOWER) || (!maximizing
1304  && basisStatusCol != SPxSolver::ON_UPPER))
1305  && debugRedCost[c] < -debugRedCostViolation)
1306  {
1307  MSG_DEBUG(std::cout << "basisStatusCol = " << basisStatusCol
1308  << ", lower tight = " << bool(sol._primal[c] <= lowerRational(c))
1309  << ", upper tight = " << bool(sol._primal[c] >= upperRational(c))
1310  << ", obj[c] = " << _realLP->obj(c)
1311  << ", debugRedCost[c] = " << rationalToString(debugRedCost[c])
1312  << "\n");
1313  debugRedCostViolation = -debugRedCost[c];
1314  }
1315 
1316  if(((maximizing && basisStatusCol != SPxSolver::ON_UPPER) || (!maximizing
1317  && basisStatusCol != SPxSolver::ON_LOWER))
1318  && debugRedCost[c] > debugRedCostViolation)
1319  {
1320  MSG_DEBUG(std::cout << "basisStatusCol = " << basisStatusCol
1321  << ", lower tight = " << bool(sol._primal[c] <= lowerRational(c))
1322  << ", upper tight = " << bool(sol._primal[c] >= upperRational(c))
1323  << ", obj[c] = " << _realLP->obj(c)
1324  << ", debugRedCost[c] = " << rationalToString(debugRedCost[c])
1325  << "\n");
1326  debugRedCostViolation = debugRedCost[c];
1327  }
1328  }
1329 
1330  // compute dual violation
1331  Rational debugDualViolation = 0;
1332  Rational debugBasicDualViolation = 0;
1333 
1334  for(int r = numRowsRational() - 1; r >= 0; r--)
1335  {
1336  if(_rowTypes[r] == RANGETYPE_FIXED)
1337  continue;
1338 
1339  const SPxSolver::VarStatus& basisStatusRow = _basisStatusRows[r];
1340  assert(basisStatusRow != SPxSolver::FIXED);
1341 
1342  Rational val = (-dualScale * sol._dual[r]) - Rational(dualReal[r]);
1343 
1344  if(((maximizing && basisStatusRow != SPxSolver::ON_LOWER) || (!maximizing
1345  && basisStatusRow != SPxSolver::ON_UPPER))
1346  && val > debugDualViolation)
1347  {
1348  MSG_DEBUG(std::cout << "basisStatusRow = " << basisStatusRow
1349  << ", lower tight = " << bool(sol._slacks[r] <= lhsRational(r))
1350  << ", upper tight = " << bool(sol._slacks[r] >= rhsRational(r))
1351  << ", dualReal[r] = " << rationalToString(val)
1352  << ", dualReal[r] = " << dualReal[r]
1353  << "\n");
1354  debugDualViolation = val;
1355  }
1356 
1357  if(((maximizing && basisStatusRow != SPxSolver::ON_UPPER) || (!maximizing
1358  && basisStatusRow != SPxSolver::ON_LOWER))
1359  && val < -debugDualViolation)
1360  {
1361  MSG_DEBUG(std::cout << "basisStatusRow = " << basisStatusRow
1362  << ", lower tight = " << bool(sol._slacks[r] <= lhsRational(r))
1363  << ", upper tight = " << bool(sol._slacks[r] >= rhsRational(r))
1364  << ", dualReal[r] = " << rationalToString(val)
1365  << ", dualReal[r] = " << dualReal[r]
1366  << "\n");
1367  debugDualViolation = -val;
1368  }
1369 
1370  if(basisStatusRow == SPxSolver::BASIC && spxAbs(val) > debugBasicDualViolation)
1371  {
1372  MSG_DEBUG(std::cout << "basisStatusRow = " << basisStatusRow
1373  << ", lower tight = " << bool(sol._slacks[r] <= lhsRational(r))
1374  << ", upper tight = " << bool(sol._slacks[r] >= rhsRational(r))
1375  << ", dualReal[r] = " << rationalToString(val)
1376  << ", dualReal[r] = " << dualReal[r]
1377  << "\n");
1378  debugBasicDualViolation = spxAbs(val);
1379  }
1380  }
1381 
1382  if(debugRedCostViolation > _solver.opttol() || debugDualViolation > _solver.opttol()
1383  || debugBasicDualViolation > 1e-9)
1384  {
1385  MSG_WARNING(spxout, spxout << "Warning: floating-point dual solution with violation "
1386  << rationalToString(debugRedCostViolation) << " / "
1387  << rationalToString(debugDualViolation) << " / "
1388  << rationalToString(debugBasicDualViolation)
1389  << " (red. cost, dual, basic).\n");
1390  }
1391  }
1392 #endif
1393 
1394  Rational dualScaleInverseNeg = dualScale;
1395  dualScaleInverseNeg.invert();
1396  dualScaleInverseNeg *= -1;
1398  dualSize = 0;
1399 
1400  for(int r = numRowsRational() - 1; r >= 0; r--)
1401  {
1402  SPxSolver::VarStatus& basisStatusRow = _basisStatusRows[r];
1403 
1404  // it may happen that left-hand and right-hand side are different in the rational, but equal in the real LP,
1405  // leading to a fixed basis status; this is critical because rows with fixed basis status are ignored in the
1406  // computation of the dual violation; to avoid rational comparisons we do not check this but simply switch
1407  // to the left-hand side status
1408  if(basisStatusRow == SPxSolver::FIXED)
1409  basisStatusRow = SPxSolver::ON_LOWER;
1410 
1411  {
1412  if(dualReal[r] != 0)
1413  {
1414  int i = _primalDualDiff.size();
1416  _primalDualDiff.add(r);
1417  _primalDualDiff.value(i) = dualReal[r];
1418  _primalDualDiff.value(i) *= dualScaleInverseNeg;
1419  sol._dual[r] -= _primalDualDiff.value(i);
1420 
1421  dualSize++;
1422  }
1423  else
1424  {
1425  // we do not check whether the dual value is nonzero, because it probably is; this gives us an
1426  // overestimation of the number of nonzeros in the dual solution
1427  dualSize++;
1428  }
1429  }
1430  }
1431 
1432  // update or recompute reduced cost values depending on which looks faster; adding one to the length of the
1433  // dual vector accounts for the objective function vector
1434  if(_primalDualDiff.size() < dualSize + 1)
1435  {
1437 #ifndef NDEBUG
1438  {
1439  DVectorRational activity(_rationalLP->maxObj());
1440  activity *= -1;
1441  _rationalLP->subDualActivity(sol._dual, activity);
1442  }
1443 #endif
1444  }
1445  else
1446  {
1447  // we assume that the objective function vector has less nonzeros than the reduced cost vector, and so multiplying
1448  // with -1 first and subtracting the dual activity should be faster than adding the dual activity and negating
1449  // afterwards
1450  _rationalLP->getObj(sol._redCost);
1452  }
1453 
1454  const int numCorrectedDuals = _primalDualDiff.size();
1455 
1456  if(numCorrectedPrimals + numCorrectedDuals > 0)
1457  {
1458  MSG_INFO2(spxout, spxout << "Corrected " << numCorrectedPrimals << " primal variables and " <<
1459  numCorrectedDuals << " dual values.\n");
1460  }
1461  }
1462  while(true);
1463 
1464  // correct basis status for restricted inequalities
1465  if(_hasBasis)
1466  {
1467  for(int r = numRowsRational() - 1; r >= 0; r--)
1468  {
1469  assert((lhsRational(r) == rhsRational(r)) == (_rowTypes[r] == RANGETYPE_FIXED));
1470 
1472  _basisStatusRows[r] = (maximizing == (sol._dual[r] < 0))
1475  }
1476  }
1477 
1478  // compute objective function values
1479  assert(sol._isPrimalFeasible == sol._isDualFeasible);
1480 
1481  if(sol._isPrimalFeasible)
1482  {
1483  sol._objVal = sol._primal * _rationalLP->maxObj();
1484 
1486  sol._objVal *= -1;
1487  }
1488 
1489  // set objective coefficients for all rows to zero
1491 
1492  // stop rational solving time
1494 }
1495 
1496 
1497 
1498 /// performs iterative refinement on the auxiliary problem for testing unboundedness
1500  SolRational& sol,
1501  bool& hasUnboundedRay,
1502  bool& stopped,
1503  bool& stoppedIter,
1504  bool& error)
1505 {
1506  bool primalFeasible;
1507  bool dualFeasible;
1508  bool infeasible;
1509  bool unbounded;
1510 
1511  // move objective function to constraints and adjust sides and bounds
1513 
1514  // invalidate solution
1515  sol.invalidate();
1516 
1517  // remember current number of refinements
1518  int oldRefinements = _statistics->refinements;
1519 
1520  // perform iterative refinement
1521  _performOptIRStable(sol, false, false, 0, primalFeasible, dualFeasible, infeasible, unbounded,
1522  stopped, stoppedIter, error);
1523 
1524  // update unbounded refinement counter
1525  _statistics->unbdRefinements += _statistics->refinements - oldRefinements;
1526 
1527  // stopped due to some limit
1528  if(stopped)
1529  {
1530  sol.invalidate();
1531  hasUnboundedRay = false;
1532  error = false;
1533  }
1534  // the unbounded problem should always be solved to optimality
1535  else if(error || unbounded || infeasible || !primalFeasible || !dualFeasible)
1536  {
1537  sol.invalidate();
1538  hasUnboundedRay = false;
1539  stopped = false;
1540  error = true;
1541  }
1542  else
1543  {
1544  const Rational& tau = sol._primal[numColsRational() - 1];
1545 
1546  MSG_DEBUG(std::cout << "tau = " << tau << " (roughly " << rationalToString(tau) << ")\n");
1547 
1548  assert(tau <= 1.0 + 2.0 * realParam(SoPlex::FEASTOL));
1549  assert(tau >= -realParam(SoPlex::FEASTOL));
1550 
1551  // because the right-hand side and all bounds (but tau's upper bound) are zero, tau should be approximately
1552  // zero if basic; otherwise at its upper bound 1
1553  error = !(tau >= _rationalPosone || tau <= _rationalFeastol);
1554  assert(!error);
1555 
1556  hasUnboundedRay = (tau >= 1);
1557  }
1558 
1559  // restore problem
1560  _untransformUnbounded(sol, hasUnboundedRay);
1561 }
1562 
1563 
1564 
1565 /// performs iterative refinement on the auxiliary problem for testing feasibility
1567  SolRational& sol,
1568  bool& withDualFarkas,
1569  bool& stopped,
1570  bool& stoppedIter,
1571  bool& error)
1572 {
1573  bool primalFeasible;
1574  bool dualFeasible;
1575  bool infeasible;
1576  bool unbounded;
1577  bool success = false;
1578  error = false;
1579 
1580 #if 0
1581  // if the problem has been found to be infeasible and an approximate Farkas proof is available, we compute a
1582  // scaled unit box around the origin that provably contains no feasible solution; this currently only works for
1583  // equality form
1584  ///@todo check whether approximate Farkas proof can be used
1586  ///@todo if approx Farkas proof is good enough then exit without doing any transformation
1587 #endif
1588 
1589  // remove objective function, shift, homogenize
1591 
1592  // invalidate solution
1593  sol.invalidate();
1594 
1595  do
1596  {
1597  // remember current number of refinements
1598  int oldRefinements = _statistics->refinements;
1599 
1600  // perform iterative refinement
1601  _performOptIRStable(sol, false, false, 0, primalFeasible, dualFeasible, infeasible, unbounded,
1602  stopped, stoppedIter, error);
1603 
1604  // update feasible refinement counter
1605  _statistics->feasRefinements += _statistics->refinements - oldRefinements;
1606 
1607  // stopped due to some limit
1608  if(stopped)
1609  {
1610  sol.invalidate();
1611  withDualFarkas = false;
1612  error = false;
1613  }
1614  // the feasibility problem should always be solved to optimality
1615  else if(error || unbounded || infeasible || !primalFeasible || !dualFeasible)
1616  {
1617  sol.invalidate();
1618  withDualFarkas = false;
1619  stopped = false;
1620  error = true;
1621  }
1622  // else we should have either a refined Farkas proof or an approximate feasible solution to the original
1623  else
1624  {
1625  const Rational& tau = sol._primal[numColsRational() - 1];
1626 
1627  MSG_DEBUG(std::cout << "tau = " << tau << " (roughly " << rationalToString(tau) << ")\n");
1628 
1629  assert(tau >= -realParam(SoPlex::FEASTOL));
1630  assert(tau <= 1.0 + realParam(SoPlex::FEASTOL));
1631 
1632  error = (tau < -_rationalFeastol || tau > _rationalPosone + _rationalFeastol);
1633  withDualFarkas = (tau < _rationalPosone);
1634 
1635  if(withDualFarkas)
1636  {
1639 
1640 #if 0
1641  // check if we can compute sufficiently large Farkas box
1643 #endif
1644 
1645  if(true) //@todo check if computeInfeasBox found a sufficient box
1646  {
1647 
1648  success = true;
1649  sol._isPrimalFeasible = false;
1650  }
1651  }
1652  else
1653  {
1654  sol._isDualFeasible = false;
1655  success = true; //successfully found approximate feasible solution
1656  }
1657  }
1658  }
1659  while(!error && !success && !stopped);
1660 
1661  // restore problem
1662  _untransformFeasibility(sol, withDualFarkas);
1663 }
1664 
1665 
1666 
1667 /// reduces matrix coefficient in absolute value by the lifting procedure of Thiele et al. 2013
1669 {
1670  MSG_DEBUG(std::cout << "Reducing matrix coefficients by lifting.\n");
1671 
1672  // start timing
1674 
1675  MSG_DEBUG(_realLP->writeFile("beforeLift.lp", 0, 0, 0));
1676 
1677  // remember unlifted state
1680 
1681  // allocate vector memory
1682  DSVectorRational colVector;
1683  SVectorRational::Element liftingRowMem[2];
1684  SVectorRational liftingRowVector(2, liftingRowMem);
1685 
1686  // search each column for large nonzeros entries
1687  const Rational maxValue = realParam(SoPlex::LIFTMAXVAL);
1688 
1689  for(int i = 0; i < numColsRational(); i++)
1690  {
1691  MSG_DEBUG(std::cout << "in lifting: examining column " << i << "\n");
1692 
1693  // get column vector
1694  colVector = colVectorRational(i);
1695 
1696  bool addedLiftingRow = false;
1697  int liftingColumnIndex = -1;
1698 
1699  // go through nonzero entries of the column
1700  for(int k = colVector.size() - 1; k >= 0; k--)
1701  {
1702  const Rational& value = colVector.value(k);
1703 
1704  if(spxAbs(value) > maxValue)
1705  {
1706  MSG_DEBUG(std::cout << " --> nonzero " << k << " has value " << rationalToString(
1707  value) << " in row " << colVector.index(k) << "\n");
1708 
1709  // add new column equal to maxValue times original column
1710  if(!addedLiftingRow)
1711  {
1712  MSG_DEBUG(std::cout << " --> adding lifting row\n");
1713 
1714  assert(liftingRowVector.size() == 0);
1715 
1716  liftingColumnIndex = numColsRational();
1717  liftingRowVector.add(i, maxValue);
1718  liftingRowVector.add(liftingColumnIndex, -1);
1719 
1720  _rationalLP->addRow(LPRowRational(0, liftingRowVector, 0));
1721  _realLP->addRow(LPRowReal(0.0, DSVectorReal(liftingRowVector), 0.0));
1722 
1723  assert(liftingColumnIndex == numColsRational() - 1);
1724  assert(liftingColumnIndex == numColsReal() - 1);
1725 
1728 
1729  liftingRowVector.clear();
1730  addedLiftingRow = true;
1731  }
1732 
1733  // get row index
1734  int rowIndex = colVector.index(k);
1735  assert(rowIndex >= 0);
1736  assert(rowIndex < _beforeLiftRows);
1737  assert(liftingColumnIndex == numColsRational() - 1);
1738 
1739  MSG_DEBUG(std::cout << " --> changing matrix\n");
1740 
1741  // remove nonzero from original column
1742  _rationalLP->changeElement(rowIndex, i, 0);
1743  _realLP->changeElement(rowIndex, i, 0.0);
1744 
1745  // add nonzero divided by maxValue to new column
1746  Rational newValue(value);
1747  newValue /= maxValue;
1748  _rationalLP->changeElement(rowIndex, liftingColumnIndex, newValue);
1749  _realLP->changeElement(rowIndex, liftingColumnIndex, Real(newValue));
1750  }
1751  }
1752  }
1753 
1754  // search each column for small nonzeros entries
1755  const Rational minValue = realParam(SoPlex::LIFTMINVAL);
1756 
1757  for(int i = 0; i < numColsRational(); i++)
1758  {
1759  MSG_DEBUG(std::cout << "in lifting: examining column " << i << "\n");
1760 
1761  // get column vector
1762  colVector = colVectorRational(i);
1763 
1764  bool addedLiftingRow = false;
1765  int liftingColumnIndex = -1;
1766 
1767  // go through nonzero entries of the column
1768  for(int k = colVector.size() - 1; k >= 0; k--)
1769  {
1770  const Rational& value = colVector.value(k);
1771 
1772  if(spxAbs(value) < minValue)
1773  {
1774  MSG_DEBUG(std::cout << " --> nonzero " << k << " has value " << rationalToString(
1775  value) << " in row " << colVector.index(k) << "\n");
1776 
1777  // add new column equal to maxValue times original column
1778  if(!addedLiftingRow)
1779  {
1780  MSG_DEBUG(std::cout << " --> adding lifting row\n");
1781 
1782  assert(liftingRowVector.size() == 0);
1783 
1784  liftingColumnIndex = numColsRational();
1785  liftingRowVector.add(i, minValue);
1786  liftingRowVector.add(liftingColumnIndex, -1);
1787 
1788  _rationalLP->addRow(LPRowRational(0, liftingRowVector, 0));
1789  _realLP->addRow(LPRowReal(0.0, DSVectorReal(liftingRowVector), 0.0));
1790 
1791  assert(liftingColumnIndex == numColsRational() - 1);
1792  assert(liftingColumnIndex == numColsReal() - 1);
1793 
1796 
1797  liftingRowVector.clear();
1798  addedLiftingRow = true;
1799  }
1800 
1801  // get row index
1802  int rowIndex = colVector.index(k);
1803  assert(rowIndex >= 0);
1804  assert(rowIndex < _beforeLiftRows);
1805  assert(liftingColumnIndex == numColsRational() - 1);
1806 
1807  MSG_DEBUG(std::cout << " --> changing matrix\n");
1808 
1809  // remove nonzero from original column
1810  _rationalLP->changeElement(rowIndex, i, 0);
1811  _realLP->changeElement(rowIndex, i, 0.0);
1812 
1813  // add nonzero divided by maxValue to new column
1814  Rational newValue(value);
1815  newValue /= minValue;
1816  _rationalLP->changeElement(rowIndex, liftingColumnIndex, newValue);
1817  _realLP->changeElement(rowIndex, liftingColumnIndex, Real(newValue));
1818  }
1819  }
1820  }
1821 
1822  // adjust basis
1823  if(_hasBasis)
1824  {
1825  assert(numColsRational() >= _beforeLiftCols);
1826  assert(numRowsRational() >= _beforeLiftRows);
1827 
1831  }
1832 
1833  MSG_DEBUG(_realLP->writeFile("afterLift.lp", 0, 0, 0));
1834 
1835  // stop timing
1837 
1838  if(numColsRational() > _beforeLiftCols || numRowsRational() > _beforeLiftRows)
1839  {
1840  MSG_INFO1(spxout, spxout << "Added " << numColsRational() - _beforeLiftCols << " columns and "
1841  << numRowsRational() - _beforeLiftRows << " rows to reduce large matrix coefficients\n.");
1842  }
1843 }
1844 
1845 
1846 
1847 /// undoes lifting
1849 {
1850  // start timing
1852 
1853  // print LP if in debug mode
1854  MSG_DEBUG(_realLP->writeFile("beforeProject.lp", 0, 0, 0));
1855 
1856  assert(numColsRational() >= _beforeLiftCols);
1857  assert(numRowsRational() >= _beforeLiftRows);
1858 
1859  // shrink rational LP to original size
1862 
1863  // shrink real LP to original size
1866 
1867  // adjust solution
1868  if(sol.isPrimalFeasible())
1869  {
1872  }
1873 
1874  if(sol.hasPrimalRay())
1875  {
1877  }
1878 
1879  ///@todo if we know the mapping between original and lifting columns, we simply need to add the reduced cost of
1880  /// the lifting column to the reduced cost of the original column; this is not implemented now, because for
1881  /// optimal solutions the reduced costs of the lifting columns are zero
1882  const Rational maxValue = realParam(SoPlex::LIFTMAXVAL);
1883 
1884  for(int i = _beforeLiftCols; i < numColsRational() && sol._isDualFeasible; i++)
1885  {
1886  if(spxAbs(maxValue * sol._redCost[i]) > _rationalOpttol)
1887  {
1888  MSG_INFO1(spxout, spxout << "Warning: lost dual solution during project phase.\n");
1889  sol._isDualFeasible = false;
1890  }
1891  }
1892 
1893  if(sol.isDualFeasible())
1894  {
1897  }
1898 
1899  if(sol.hasDualFarkas())
1900  {
1902  }
1903 
1904  // adjust basis
1905  for(int i = _beforeLiftCols; i < numColsRational() && _hasBasis; i++)
1906  {
1908  {
1909  MSG_INFO1(spxout, spxout <<
1910  "Warning: lost basis during project phase because of nonbasic lifting column.\n");
1911  _hasBasis = false;
1913  }
1914  }
1915 
1916  for(int i = _beforeLiftRows; i < numRowsRational() && _hasBasis; i++)
1917  {
1919  {
1920  MSG_INFO1(spxout, spxout <<
1921  "Warning: lost basis during project phase because of basic lifting row.\n");
1922  _hasBasis = false;
1924  }
1925  }
1926 
1927  if(_hasBasis)
1928  {
1932  }
1933 
1934  // print LP if in debug mode
1935  MSG_DEBUG(_realLP->writeFile("afterProject.lp", 0, 0, 0));
1936 
1937  // stop timing
1939 }
1940 
1941 
1942 
1943 /// stores objective, bounds, and sides of real LP
1945 {
1946 #ifndef SOPLEX_MANUAL_ALT
1947 
1949  {
1951  return;
1952  }
1953 
1954 #endif
1955 
1956  _manualLower = _realLP->lower();
1957  _manualUpper = _realLP->upper();
1958  _manualLhs = _realLP->lhs();
1959  _manualRhs = _realLP->rhs();
1962 }
1963 
1964 
1965 
1966 /// restores objective, bounds, and sides of real LP
1968 {
1970  {
1971 #ifndef SOPLEX_MANUAL_ALT
1973 #else
1979 #endif
1980 
1981  if(_hasBasis)
1982  {
1983  // in manual sync mode, if the right-hand side of an equality constraint is not floating-point
1984  // representable, the user might have constructed the constraint in the real LP by rounding down the
1985  // left-hand side and rounding up the right-hand side; if the basis status is fixed, we need to adjust it
1986  for(int i = 0; i < _solver.nRows(); i++)
1987  {
1988  if(_basisStatusRows[i] == SPxSolver::FIXED && _solver.lhs(i) != _solver.rhs(i))
1989  {
1990  assert(_solver.rhs(i) == spxNextafter(_solver.lhs(i), infinity));
1991 
1995  {
1997  }
1998  else
1999  {
2001  }
2002  }
2003  }
2004 
2007  }
2008  }
2009  else
2010  {
2016  }
2017 }
2018 
2019 
2020 
2021 /// introduces slack variables to transform inequality constraints into equations for both rational and real LP,
2022 /// which should be in sync
2024 {
2025  MSG_DEBUG(std::cout << "Transforming rows to equation form.\n");
2026 
2027  // start timing
2029 
2030  MSG_DEBUG(_realLP->writeFile("beforeTransEqu.lp", 0, 0, 0));
2031 
2032  // clear array of slack columns
2033  _slackCols.clear();
2034 
2035  // add artificial slack variables to convert inequality to equality constraints
2036  for(int i = 0; i < numRowsRational(); i++)
2037  {
2038  assert((lhsRational(i) == rhsRational(i)) == (_rowTypes[i] == RANGETYPE_FIXED));
2039 
2040  if(_rowTypes[i] != RANGETYPE_FIXED)
2041  {
2043 
2044  if(_rationalLP->lhs(i) != 0)
2046 
2047  if(_rationalLP->rhs(i) != 0)
2049 
2050  assert(_rationalLP->lhs(i) == 0);
2051  assert(_rationalLP->rhs(i) == 0);
2052  _realLP->changeRange(i, 0.0, 0.0);
2055  }
2056  }
2057 
2060 
2061  // adjust basis
2062  if(_hasBasis)
2063  {
2064  for(int i = 0; i < _slackCols.num(); i++)
2065  {
2066  int row = _slackCols.colVector(i).index(0);
2067 
2068  assert(row >= 0);
2069  assert(row < numRowsRational());
2070 
2071  switch(_basisStatusRows[row])
2072  {
2073  case SPxSolver::ON_LOWER:
2075  break;
2076 
2077  case SPxSolver::ON_UPPER:
2079  break;
2080 
2081  case SPxSolver::BASIC:
2082  case SPxSolver::FIXED:
2083  default:
2085  break;
2086  }
2087 
2089  }
2090 
2092  }
2093 
2094  MSG_DEBUG(_realLP->writeFile("afterTransEqu.lp", 0, 0, 0));
2095 
2096  // stop timing
2098 
2099  if(_slackCols.num() > 0)
2100  {
2101  MSG_INFO1(spxout, spxout << "Added " << _slackCols.num() <<
2102  " slack columns to transform rows to equality form.\n");
2103  }
2104 }
2105 
2106 
2107 
2108 /// restores original problem
2110 {
2111  // start timing
2113 
2114  // print LP if in debug mode
2115  MSG_DEBUG(_realLP->writeFile("beforeUntransEqu.lp", 0, 0, 0));
2116 
2117  int numCols = numColsRational();
2118  int numOrigCols = numColsRational() - _slackCols.num();
2119 
2120  // adjust solution
2121  if(sol.isPrimalFeasible())
2122  {
2123  for(int i = 0; i < _slackCols.num(); i++)
2124  {
2125  int col = numOrigCols + i;
2126  int row = _slackCols.colVector(i).index(0);
2127 
2128  assert(row >= 0);
2129  assert(row < numRowsRational());
2130 
2131  sol._slacks[row] -= sol._primal[col];
2132  }
2133 
2134  sol._primal.reDim(numOrigCols);
2135  }
2136 
2137  if(sol.hasPrimalRay())
2138  {
2139  sol._primalRay.reDim(numOrigCols);
2140  }
2141 
2142  // adjust basis
2143  if(_hasBasis)
2144  {
2145  for(int i = 0; i < _slackCols.num(); i++)
2146  {
2147  int col = numOrigCols + i;
2148  int row = _slackCols.colVector(i).index(0);
2149 
2150  assert(row >= 0);
2151  assert(row < numRowsRational());
2152  assert(_basisStatusRows[row] != SPxSolver::UNDEFINED);
2153  assert(_basisStatusRows[row] != SPxSolver::ZERO || lhsRational(row) == 0);
2154  assert(_basisStatusRows[row] != SPxSolver::ZERO || rhsRational(row) == 0);
2156 
2157  MSG_DEBUG(std::cout << "slack column " << col << " for row " << row
2158  << ": col status=" << _basisStatusCols[col]
2159  << ", row status=" << _basisStatusRows[row]
2160  << ", redcost=" << rationalToString(sol._redCost[col])
2161  << ", dual=" << rationalToString(sol._dual[row]) << "\n");
2162 
2164  {
2165  switch(_basisStatusCols[col])
2166  {
2167  case SPxSolver::ON_LOWER:
2169  break;
2170 
2171  case SPxSolver::ON_UPPER:
2173  break;
2174 
2175  case SPxSolver::BASIC:
2176  case SPxSolver::FIXED:
2177  default:
2178  _basisStatusRows[row] = _basisStatusCols[col];
2179  break;
2180  }
2181  }
2182  }
2183 
2184  _basisStatusCols.reSize(numOrigCols);
2185 
2186  if(_slackCols.num() > 0)
2188  }
2189 
2190  // not earlier because of debug message
2191  if(sol.isDualFeasible())
2192  {
2193  sol._redCost.reDim(numOrigCols);
2194  }
2195 
2196  // restore sides and remove slack columns
2197  for(int i = 0; i < _slackCols.num(); i++)
2198  {
2199  int col = numOrigCols + i;
2200  int row = _slackCols.colVector(i).index(0);
2201 
2202  if(upperRational(col) != 0)
2203  _rationalLP->changeLhs(row, -upperRational(col));
2204 
2205  if(lowerRational(col) != 0)
2206  _rationalLP->changeRhs(row, -lowerRational(col));
2207 
2208  assert(_rationalLP->lhs(row) == -upperRational(col));
2209  assert(_rationalLP->rhs(row) == -lowerRational(col));
2210  _rowTypes[row] = _switchRangeType(_colTypes[col]);
2211  }
2212 
2213  _rationalLP->removeColRange(numOrigCols, numCols - 1);
2214  _realLP->removeColRange(numOrigCols, numCols - 1);
2215  _colTypes.reSize(numOrigCols);
2216 
2217  // objective, bounds, and sides of real LP are restored only after _solveRational()
2218 
2219  // print LP if in debug mode
2220  MSG_DEBUG(_realLP->writeFile("afterUntransEqu.lp", 0, 0, 0));
2221 
2222  // stop timing
2224 }
2225 
2226 
2227 
2228 /// transforms LP to unboundedness problem by moving the objective function to the constraints, changing right-hand
2229 /// side and bounds to zero, and adding an auxiliary variable for the decrease in the objective function
2231 {
2232  MSG_INFO1(spxout, spxout << "Setting up LP to compute primal unbounded ray.\n");
2233 
2234  // start timing
2236 
2237  // print LP if in debug mode
2238  MSG_DEBUG(_realLP->writeFile("beforeTransUnbounded.lp", 0, 0, 0));
2239 
2240  // store bounds
2243 
2244  for(int c = numColsRational() - 1; c >= 0; c--)
2245  {
2246  if(_lowerFinite(_colTypes[c]))
2248 
2249  if(_upperFinite(_colTypes[c]))
2251  }
2252 
2253  // store sides
2256 
2257  for(int r = numRowsRational() - 1; r >= 0; r--)
2258  {
2259  if(_lowerFinite(_rowTypes[r]))
2260  _unboundedLhs[r] = lhsRational(r);
2261 
2262  if(_upperFinite(_rowTypes[r]))
2263  _unboundedRhs[r] = rhsRational(r);
2264  }
2265 
2266  // make right-hand side zero
2267  for(int r = numRowsRational() - 1; r >= 0; r--)
2268  {
2269  assert((lhsRational(r) > _rationalNegInfty) == _lowerFinite(_rowTypes[r]));
2270 
2271  if(_lowerFinite(_rowTypes[r]))
2272  {
2273  _rationalLP->changeLhs(r, 0);
2274  _realLP->changeLhs(r, 0.0);
2275  }
2276  else if(_realLP->lhs(r) > -realParam(SoPlex::INFTY))
2278 
2279  assert((rhsRational(r) < _rationalPosInfty) == _upperFinite(_rowTypes[r]));
2280 
2281  if(_upperFinite(_rowTypes[r]))
2282  {
2283  _rationalLP->changeRhs(r, 0);
2284  _realLP->changeRhs(r, 0.0);
2285  }
2286  else if(_realLP->rhs(r) < realParam(SoPlex::INFTY))
2288  }
2289 
2290  // transform objective function to constraint and add auxiliary variable
2291  int numOrigCols = numColsRational();
2292  DSVectorRational obj(numOrigCols + 1);
2293  ///@todo implement this without copying the objective function
2294  obj = _rationalLP->maxObj();
2295  obj.add(numOrigCols, -1);
2296  _rationalLP->addRow(LPRowRational(0, obj, 0));
2297  _realLP->addRow(LPRowReal(0, DSVectorReal(obj), 0));
2299 
2300  assert(numColsRational() == numOrigCols + 1);
2301 
2302  // set objective coefficient and bounds for auxiliary variable
2303  _rationalLP->changeMaxObj(numOrigCols, 1);
2304  _realLP->changeMaxObj(numOrigCols, 1.0);
2305 
2306  _rationalLP->changeBounds(numOrigCols, _rationalNegInfty, 1);
2307  _realLP->changeBounds(numOrigCols, -realParam(SoPlex::INFTY), 1.0);
2309 
2310  // set objective coefficients to zero and adjust bounds for problem variables
2311  for(int c = numColsRational() - 2; c >= 0; c--)
2312  {
2313  _rationalLP->changeObj(c, 0);
2314  _realLP->changeObj(c, 0.0);
2315 
2316  assert((lowerRational(c) > _rationalNegInfty) == _lowerFinite(_colTypes[c]));
2317 
2318  if(_lowerFinite(_colTypes[c]))
2319  {
2320  _rationalLP->changeLower(c, 0);
2321  _realLP->changeLower(c, 0.0);
2322  }
2323  else if(_realLP->lower(c) > -realParam(SoPlex::INFTY))
2325 
2326  assert((upperRational(c) < _rationalPosInfty) == _upperFinite(_colTypes[c]));
2327 
2328  if(_upperFinite(_colTypes[c]))
2329  {
2330  _rationalLP->changeUpper(c, 0);
2331  _realLP->changeUpper(c, 0.0);
2332  }
2333  else if(_realLP->upper(c) < realParam(SoPlex::INFTY))
2335  }
2336 
2337  // adjust basis
2338  if(_hasBasis)
2339  {
2343  }
2344 
2345  // print LP if in debug mode
2346  MSG_DEBUG(_realLP->writeFile("afterTransUnbounded.lp", 0, 0, 0));
2347 
2348  // stop timing
2350 }
2351 
2352 
2353 
2354 /// undoes transformation to unboundedness problem
2355 void SoPlex::_untransformUnbounded(SolRational& sol, bool unbounded)
2356 {
2357  // start timing
2359 
2360  // print LP if in debug mode
2361  MSG_DEBUG(_realLP->writeFile("beforeUntransUnbounded.lp", 0, 0, 0));
2362 
2363  int numOrigCols = numColsRational() - 1;
2364  int numOrigRows = numRowsRational() - 1;
2365  const Rational& tau = sol._primal[numOrigCols];
2366 
2367  // adjust solution and basis
2368  if(unbounded)
2369  {
2370  assert(tau >= _rationalPosone);
2371 
2372  sol._isPrimalFeasible = false;
2373  sol._hasPrimalRay = true;
2374  sol._isDualFeasible = false;
2375  sol._hasDualFarkas = false;
2376 
2377  if(tau != 1)
2378  sol._primal /= tau;
2379 
2380  sol._primalRay = sol._primal;
2381  sol._primalRay.reDim(numOrigCols);
2382 
2383  _hasBasis = (_basisStatusCols[numOrigCols] != SPxSolver::BASIC
2384  && _basisStatusRows[numOrigRows] == SPxSolver::BASIC);
2385  _basisStatusCols.reSize(numOrigCols);
2386  _basisStatusRows.reSize(numOrigRows);
2387  }
2389  {
2390  const Rational& alpha = sol._dual[numOrigRows];
2391 
2392  assert(sol._isDualFeasible);
2393  assert(alpha <= _rationalFeastol - _rationalPosone);
2394 
2395  sol._isPrimalFeasible = false;
2396  sol._hasPrimalRay = false;
2397  sol._hasDualFarkas = false;
2398 
2399  if(alpha != -1)
2400  {
2401  sol._dual /= -alpha;
2402  sol._redCost /= -alpha;
2403  }
2404 
2405  sol._dual.reDim(numOrigRows);
2406  sol._redCost.reDim(numOrigCols);
2407  }
2408  else
2409  {
2410  sol.invalidate();
2411  _hasBasis = false;
2412  _basisStatusCols.reSize(numOrigCols);
2413  _basisStatusCols.reSize(numOrigRows);
2414  }
2415 
2416  // recover objective function
2417  const SVectorRational& objRowVector = _rationalLP->rowVector(numOrigRows);
2418 
2419  for(int i = objRowVector.size() - 1; i >= 0; i--)
2420  {
2421  _rationalLP->changeMaxObj(objRowVector.index(i), objRowVector.value(i));
2422  _realLP->changeMaxObj(objRowVector.index(i), Real(objRowVector.value(i)));
2423  }
2424 
2425  // remove objective function constraint and auxiliary variable
2426  _rationalLP->removeRow(numOrigRows);
2427  _realLP->removeRow(numOrigRows);
2428  _rowTypes.reSize(numOrigRows);
2429 
2430  _rationalLP->removeCol(numOrigCols);
2431  _realLP->removeCol(numOrigCols);
2432  _colTypes.reSize(numOrigCols);
2433 
2434  // restore objective, sides and bounds
2435  for(int r = numRowsRational() - 1; r >= 0; r--)
2436  {
2437  if(_lowerFinite(_rowTypes[r]))
2438  {
2441  }
2442 
2443  if(_upperFinite(_rowTypes[r]))
2444  {
2447  }
2448 
2449  assert((lhsRational(r) > _rationalNegInfty) == _lowerFinite(_rowTypes[r]));
2450  assert((rhsRational(r) < _rationalPosInfty) == _upperFinite(_rowTypes[r]));
2451  assert((lhsReal(r) > -realParam(SoPlex::INFTY)) == _lowerFinite(_rowTypes[r]));
2452  assert((rhsReal(r) < realParam(SoPlex::INFTY)) == _upperFinite(_rowTypes[r]));
2453  }
2454 
2455  for(int c = numColsRational() - 1; c >= 0; c--)
2456  {
2457  if(_lowerFinite(_colTypes[c]))
2458  {
2461  }
2462 
2463  if(_upperFinite(_colTypes[c]))
2464  {
2467  }
2468 
2469  assert((lowerRational(c) > _rationalNegInfty) == _lowerFinite(_colTypes[c]));
2470  assert((upperRational(c) < _rationalPosInfty) == _upperFinite(_colTypes[c]));
2471  assert((lowerReal(c) > -realParam(SoPlex::INFTY)) == _lowerFinite(_colTypes[c]));
2472  assert((upperReal(c) < realParam(SoPlex::INFTY)) == _upperFinite(_colTypes[c]));
2473  }
2474 
2475  // invalidate rational basis factorization
2477 
2478  // print LP if in debug mode
2479  MSG_DEBUG(_realLP->writeFile("afterUntransUnbounded.lp", 0, 0, 0));
2480 
2481  // stop timing
2483 }
2484 
2485 
2486 
2487 /// store basis
2489 {
2490  assert(!_storedBasis);
2491 
2492  if(_hasBasis)
2493  {
2494  _storedBasis = true;
2497  }
2498  else
2499  _storedBasis = false;
2500 }
2501 
2502 
2503 
2504 /// restore basis
2506 {
2507  if(_storedBasis)
2508  {
2509  _hasBasis = true;
2512  _storedBasis = false;
2513  }
2514 }
2515 
2516 
2517 
2518 /// transforms LP to feasibility problem by removing the objective function, shifting variables, and homogenizing the
2519 /// right-hand side
2521 {
2522  MSG_INFO1(spxout, spxout << "Setting up LP to test for feasibility.\n");
2523 
2524  // start timing
2526 
2527  // print LP if in debug mode
2528  MSG_DEBUG(_realLP->writeFile("beforeTransFeas.lp", 0, 0, 0));
2529 
2530  // store objective function
2532 
2533  for(int c = numColsRational() - 1; c >= 0; c--)
2534  _feasObj[c] = _rationalLP->maxObj(c);
2535 
2536  // store bounds
2539 
2540  for(int c = numColsRational() - 1; c >= 0; c--)
2541  {
2542  if(_lowerFinite(_colTypes[c]))
2543  _feasLower[c] = lowerRational(c);
2544 
2545  if(_upperFinite(_colTypes[c]))
2546  _feasUpper[c] = upperRational(c);
2547  }
2548 
2549  // store sides
2552 
2553  for(int r = numRowsRational() - 1; r >= 0; r--)
2554  {
2555  if(_lowerFinite(_rowTypes[r]))
2556  _feasLhs[r] = lhsRational(r);
2557 
2558  if(_upperFinite(_rowTypes[r]))
2559  _feasRhs[r] = rhsRational(r);
2560  }
2561 
2562  // set objective coefficients to zero; shift primal space such as to guarantee that the zero solution is within
2563  // the bounds
2564  Rational shiftValue;
2565  Rational shiftValue2;
2566 
2567  for(int c = numColsRational() - 1; c >= 0; c--)
2568  {
2569  _rationalLP->changeMaxObj(c, 0);
2570  _realLP->changeMaxObj(c, 0.0);
2571 
2572  if(lowerRational(c) > 0)
2573  {
2574  const SVectorRational& colVector = colVectorRational(c);
2575 
2576  for(int i = 0; i < colVector.size(); i++)
2577  {
2578  shiftValue = colVector.value(i);
2579  shiftValue *= lowerRational(c);
2580  int r = colVector.index(i);
2581 
2582  assert((lhsRational(r) > _rationalNegInfty) == _lowerFinite(_rowTypes[r]));
2583  assert((rhsRational(r) < _rationalPosInfty) == _upperFinite(_rowTypes[r]));
2584 
2586  {
2587  shiftValue2 = lhsRational(r);
2588  shiftValue2 -= shiftValue;
2589  _rationalLP->changeLhs(r, shiftValue2);
2590  _realLP->changeLhs(r, Real(shiftValue2));
2591 
2592  shiftValue -= rhsRational(r);
2593  shiftValue *= -1;
2594  _rationalLP->changeRhs(r, shiftValue);
2595  _realLP->changeRhs(r, Real(shiftValue));
2596  }
2597  else if(_lowerFinite(_rowTypes[r]))
2598  {
2599  shiftValue -= lhsRational(r);
2600  shiftValue *= -1;
2601  _rationalLP->changeLhs(r, shiftValue);
2602  _realLP->changeLhs(r, Real(shiftValue));
2603  }
2604  else if(_upperFinite(_rowTypes[r]))
2605  {
2606  shiftValue -= rhsRational(r);
2607  shiftValue *= -1;
2608  _rationalLP->changeRhs(r, shiftValue);
2609  _realLP->changeRhs(r, Real(shiftValue));
2610  }
2611  }
2612 
2613  assert((upperRational(c) < _rationalPosInfty) == _upperFinite(_colTypes[c]));
2614 
2615  if(_upperFinite(_colTypes[c]))
2616  {
2618  _realLP->changeBounds(c, 0.0, Real(upperRational(c)));
2619  }
2620  else if(_realLP->upper(c) < realParam(SoPlex::INFTY))
2621  {
2622  _rationalLP->changeLower(c, 0);
2624  }
2625  else
2626  {
2627  _rationalLP->changeLower(c, 0);
2628  _realLP->changeLower(c, 0.0);
2629  }
2630  }
2631  else if(upperRational(c) < 0)
2632  {
2633  const SVectorRational& colVector = colVectorRational(c);
2634 
2635  for(int i = 0; i < colVector.size(); i++)
2636  {
2637  shiftValue = colVector.value(i);
2638  shiftValue *= upperRational(c);
2639  int r = colVector.index(i);
2640 
2641  assert((lhsRational(r) > _rationalNegInfty) == _lowerFinite(_rowTypes[r]));
2642  assert((rhsRational(r) < _rationalPosInfty) == _upperFinite(_rowTypes[r]));
2643 
2645  {
2646  shiftValue2 = lhsRational(r);
2647  shiftValue2 -= shiftValue;
2648  _rationalLP->changeLhs(r, shiftValue2);
2649  _realLP->changeLhs(r, Real(shiftValue2));
2650 
2651  shiftValue -= rhsRational(r);
2652  shiftValue *= -1;
2653  _rationalLP->changeRhs(r, shiftValue);
2654  _realLP->changeRhs(r, Real(shiftValue));
2655  }
2656  else if(_lowerFinite(_rowTypes[r]))
2657  {
2658  shiftValue -= lhsRational(r);
2659  shiftValue *= -1;
2660  _rationalLP->changeLhs(r, shiftValue);
2661  _realLP->changeLhs(r, Real(shiftValue));
2662  }
2663  else if(_upperFinite(_rowTypes[r]))
2664  {
2665  shiftValue -= rhsRational(r);
2666  shiftValue *= -1;
2667  _rationalLP->changeRhs(r, shiftValue);
2668  _realLP->changeRhs(r, Real(shiftValue));
2669  }
2670  }
2671 
2672  assert((lowerRational(c) > _rationalNegInfty) == _lowerFinite(_colTypes[c]));
2673 
2674  if(_lowerFinite(_colTypes[c]))
2675  {
2677  _realLP->changeBounds(c, Real(lowerRational(c)), 0.0);
2678  }
2679  else if(_realLP->lower(c) > -realParam(SoPlex::INFTY))
2680  {
2681  _rationalLP->changeUpper(c, 0);
2683  }
2684  else
2685  {
2686  _rationalLP->changeUpper(c, 0);
2687  _realLP->changeUpper(c, 0.0);
2688  }
2689  }
2690  else
2691  {
2692  if(_lowerFinite(_colTypes[c]))
2694  else if(_realLP->lower(c) > -realParam(SoPlex::INFTY))
2696 
2697  if(_upperFinite(_colTypes[c]))
2699  else if(_realLP->upper(c) < realParam(SoPlex::INFTY))
2701  }
2702 
2703  assert(lowerReal(c) <= upperReal(c));
2704  }
2705 
2706  // homogenize sides
2707  _tauColVector.clear();
2708 
2709  for(int r = numRowsRational() - 1; r >= 0; r--)
2710  {
2711  if(lhsRational(r) > 0)
2712  {
2713  _tauColVector.add(r, lhsRational(r));
2714  assert((rhsRational(r) < _rationalPosInfty) == _upperFinite(_rowTypes[r]));
2715 
2716  if(_upperFinite(_rowTypes[r]))
2717  {
2719  _realLP->changeRange(r, 0.0, Real(rhsRational(r)));
2720  }
2721  else
2722  {
2723  _rationalLP->changeLhs(r, 0);
2724  _realLP->changeLhs(r, 0.0);
2725 
2726  if(_realLP->rhs(r) < realParam(SoPlex::INFTY))
2728  }
2729  }
2730  else if(rhsRational(r) < 0)
2731  {
2732  _tauColVector.add(r, rhsRational(r));
2733  assert((lhsRational(r) > _rationalNegInfty) == _lowerFinite(_rowTypes[r]));
2734 
2735  if(_lowerFinite(_rowTypes[r]))
2736  {
2738  _realLP->changeRange(r, Real(lhsRational(r)), 0.0);
2739  }
2740  else
2741  {
2742  _rationalLP->changeRhs(r, 0);
2743  _realLP->changeRhs(r, 0.0);
2744 
2745  if(_realLP->lhs(r) > -realParam(SoPlex::INFTY))
2747  }
2748  }
2749  else
2750  {
2751  if(_lowerFinite(_rowTypes[r]))
2752  _realLP->changeLhs(r, Real(lhsRational(r)));
2753  else if(_realLP->lhs(r) > -realParam(SoPlex::INFTY))
2755 
2756  if(_upperFinite(_rowTypes[r]))
2757  _realLP->changeRhs(r, Real(rhsRational(r)));
2758  else if(_realLP->rhs(r) < realParam(SoPlex::INFTY))
2760  }
2761 
2762  assert(rhsReal(r) <= rhsReal(r));
2763  }
2764 
2765  ///@todo exploit this case by returning without LP solving
2766  if(_tauColVector.size() == 0)
2767  {
2768  MSG_INFO3(spxout, spxout << "LP is trivially feasible.\n");
2769  }
2770 
2771  // add artificial column
2772  SPxColId id;
2773  _tauColVector *= -1;
2774  _rationalLP->addCol(id,
2776  _rationalNegone),
2777  _tauColVector, 1, 0));
2778  _realLP->addCol(id,
2780  DSVectorReal(_tauColVector), 1.0, 0.0));
2782 
2783  // adjust basis
2784  if(_hasBasis)
2785  {
2787  }
2788 
2789  // invalidate rational basis factorization
2791 
2792  // print LP if in debug mode
2793  MSG_DEBUG(_realLP->writeFile("afterTransFeas.lp", 0, 0, 0));
2794 
2795  // stop timing
2797 }
2798 
2799 
2800 
2801 /// undoes transformation to feasibility problem
2803 {
2804  // start timing
2806 
2807  // print LP if in debug mode
2808  MSG_DEBUG(_realLP->writeFile("beforeUntransFeas.lp", 0, 0, 0));
2809 
2810  int numOrigCols = numColsRational() - 1;
2811 
2812  // adjust solution and basis
2813  if(infeasible)
2814  {
2815  assert(sol._isDualFeasible);
2816  assert(sol._primal[numOrigCols] < 1);
2817 
2818  sol._isPrimalFeasible = false;
2819  sol._hasPrimalRay = false;
2820  sol._isDualFeasible = false;
2821  sol._hasDualFarkas = true;
2822 
2823  sol._dualFarkas = sol._dual;
2824 
2825  _hasBasis = false;
2826  _basisStatusCols.reSize(numOrigCols);
2827  }
2828  else if(sol._isPrimalFeasible)
2829  {
2830  assert(sol._primal[numOrigCols] >= 1);
2831 
2832  sol._hasPrimalRay = false;
2833  sol._isDualFeasible = false;
2834  sol._hasDualFarkas = false;
2835 
2836  if(sol._primal[numOrigCols] != 1)
2837  {
2838  sol._slacks /= sol._primal[numOrigCols];
2839 
2840  for(int i = 0; i < numOrigCols; i++)
2841  sol._primal[i] /= sol._primal[numOrigCols];
2842 
2843  sol._primal[numOrigCols] = 1;
2844  }
2845 
2846  sol._primal.reDim(numOrigCols);
2847  sol._slacks -= _rationalLP->colVector(numOrigCols);
2848 
2849  _hasBasis = (_basisStatusCols[numOrigCols] != SPxSolver::BASIC);
2850  _basisStatusCols.reSize(numOrigCols);
2851  }
2852  else
2853  {
2854  _hasBasis = false;
2855  _basisStatusCols.reSize(numOrigCols);
2856  }
2857 
2858  // restore right-hand side
2859  for(int r = numRowsRational() - 1; r >= 0; r--)
2860  {
2862  || _feasLhs[r] - lhsRational(r) == _feasRhs[r] - rhsRational(r));
2863 
2864  if(_lowerFinite(_rowTypes[r]))
2865  {
2866  _rationalLP->changeLhs(r, _feasLhs[r]);
2867  _realLP->changeLhs(r, Real(_feasLhs[r]));
2868  }
2869  else if(_realLP->lhs(r) > -realParam(SoPlex::INFTY))
2871 
2872  assert(_lowerFinite(_rowTypes[r]) == (lhsRational(r) > _rationalNegInfty));
2873  assert(_lowerFinite(_rowTypes[r]) == (lhsReal(r) > -realParam(SoPlex::INFTY)));
2874 
2875  if(_upperFinite(_rowTypes[r]))
2876  {
2877  _rationalLP->changeRhs(r, _feasRhs[r]);
2878  _realLP->changeRhs(r, Real(_feasRhs[r]));
2879  }
2880  else if(_realLP->rhs(r) < realParam(SoPlex::INFTY))
2882 
2883  assert(_upperFinite(_rowTypes[r]) == (rhsRational(r) < _rationalPosInfty));
2884  assert(_upperFinite(_rowTypes[r]) == (rhsReal(r) < realParam(SoPlex::INFTY)));
2885 
2886  assert(lhsReal(r) <= rhsReal(r));
2887  }
2888 
2889  // unshift primal space and restore objective coefficients
2890  Rational shiftValue;
2891 
2892  for(int c = numOrigCols - 1; c >= 0; c--)
2893  {
2894  bool shifted = (_lowerFinite(_colTypes[c]) && _feasLower[c] > 0) || (_upperFinite(_colTypes[c])
2895  && _feasUpper[c] < 0);
2896  assert(shifted || !_lowerFinite(_colTypes[c]) || _feasLower[c] == lowerRational(c));
2897  assert(shifted || !_upperFinite(_colTypes[c]) || _feasUpper[c] == upperRational(c));
2898 #ifdef SOPLEX_WITH_GMP
2900  || _feasLower[c] - lowerRational(c) == _feasUpper[c] - upperRational(c));
2901 #endif
2902 
2903  if(shifted)
2904  {
2905  if(_lowerFinite(_colTypes[c]))
2906  {
2907  shiftValue = _feasLower[c];
2908  shiftValue -= lowerRational(c);
2909  }
2910  else if(_upperFinite(_colTypes[c]))
2911  {
2912  shiftValue = _feasUpper[c];
2913  shiftValue -= upperRational(c);
2914  }
2915 
2916  if(sol._isPrimalFeasible)
2917  {
2918  sol._primal[c] += shiftValue;
2919  sol._slacks.multAdd(shiftValue, _rationalLP->colVector(c));
2920  }
2921  }
2922 
2923  if(_lowerFinite(_colTypes[c]))
2924  {
2925  if(shifted)
2927 
2929  }
2930  else if(_realLP->lower(c) > -realParam(SoPlex::INFTY))
2932 
2933  assert(_lowerFinite(_colTypes[c]) == (lowerRational(c) > -_rationalPosInfty));
2934  assert(_lowerFinite(_colTypes[c]) == (lowerReal(c) > -realParam(SoPlex::INFTY)));
2935 
2936  if(_upperFinite(_colTypes[c]))
2937  {
2938  if(shifted)
2940 
2942  }
2943  else if(_realLP->upper(c) < realParam(SoPlex::INFTY))
2945 
2946  assert(_upperFinite(_colTypes[c]) == (upperRational(c) < _rationalPosInfty));
2947  assert(_upperFinite(_colTypes[c]) == (upperReal(c) < realParam(SoPlex::INFTY)));
2948 
2950  _realLP->changeMaxObj(c, Real(_feasObj[c]));
2951 
2952  assert(lowerReal(c) <= upperReal(c));
2953  }
2954 
2955  // remove last column
2956  _rationalLP->removeCol(numOrigCols);
2957  _realLP->removeCol(numOrigCols);
2958  _colTypes.reSize(numOrigCols);
2959 
2960  // invalidate rational basis factorization
2962 
2963  // print LP if in debug mode
2964  MSG_DEBUG(_realLP->writeFile("afterUntransFeas.lp", 0, 0, 0));
2965 
2966  // stop timing
2968 
2969 #ifndef NDEBUG
2970 #ifdef SOPLEX_WITH_GMP
2971 
2972  if(sol._isPrimalFeasible)
2973  {
2974  DVectorRational activity(numRowsRational());
2975  _rationalLP->computePrimalActivity(sol._primal, activity);
2976  assert(sol._slacks == activity);
2977  }
2978 
2979 #endif
2980 #endif
2981 }
2982 
2983 /** computes radius of infeasibility box implied by an approximate Farkas' proof
2984 
2985  Given constraints of the form \f$ lhs <= Ax <= rhs \f$, a farkas proof y should satisfy \f$ y^T A = 0 \f$ and
2986  \f$ y_+^T lhs - y_-^T rhs > 0 \f$, where \f$ y_+, y_- \f$ denote the positive and negative parts of \f$ y \f$.
2987  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
2988  as the following holds for all potentially feasible \f$ x \f$:
2989 
2990  \f[
2991  y^T Ax < (y_+^T lhs - y_-^T rhs) (*)
2992  \f]
2993 
2994  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
2995  bounds on \f$ x \f$ imply that all feasible \f$ x \f$ satisfy (*), and if not then compute bounds on \f$ x \f$ to
2996  guarantee (*). The simplest way to do this is to compute
2997 
2998  \f[
2999  B = (y_+^T lhs - y_-^T rhs) / \sum_i(|(y^T A)_i|)
3000  \f]
3001 
3002  noting that if every component of \f$ x \f$ has \f$ |x_i| < B \f$, then (*) holds.
3003 
3004  \f$ B \f$ can be increased by iteratively including variable bounds smaller than \f$ B \f$. The speed of this
3005  method can be further improved by using interval arithmetic for all computations. For related information see
3006  Sec. 4 of Neumaier and Shcherbina, Mathematical Programming A, 2004.
3007 
3008  Set transformed to true if this method is called after _transformFeasibility().
3009 */
3010 void SoPlex::_computeInfeasBox(SolRational& sol, bool transformed)
3011 {
3012  assert(sol.hasDualFarkas());
3013 
3014  const VectorRational& lower = transformed ? _feasLower : lowerRational();
3015  const VectorRational& upper = transformed ? _feasUpper : upperRational();
3016  const VectorRational& lhs = transformed ? _feasLhs : lhsRational();
3017  const VectorRational& rhs = transformed ? _feasRhs : rhsRational();
3018  const VectorRational& y = sol._dualFarkas;
3019 
3020  const int numRows = numRowsRational();
3021  const int numCols = transformed ? numColsRational() - 1 : numColsRational();
3022 
3023  SSVectorRational ytransA(numColsRational());
3024  Rational ytransb;
3025  Rational temp;
3026 
3027  // prepare ytransA and ytransb; since we want exact arithmetic, we set the zero threshold of the semi-sparse
3028  // vector to zero
3029  ytransA.setEpsilon(0);
3030  ytransA.clear();
3031  ytransb = 0;
3032 
3033  ///@todo this currently works only if all constraints are equations aggregate rows and sides using the multipliers of the Farkas ray
3034  for(int r = 0; r < numRows; r++)
3035  {
3036  ytransA += y[r] * _rationalLP->rowVector(r);
3037  ytransb += y[r] * (y[r] > 0 ? lhs[r] : rhs[r]);
3038  }
3039 
3040  // if we work on the feasibility problem, we ignore the last column
3041  if(transformed)
3042  ytransA.reDim(numCols);
3043 
3044  MSG_DEBUG(std::cout << "ytransb = " << rationalToString(ytransb) << "\n");
3045 
3046  // if we choose minus ytransb as vector of multipliers for the bound constraints on the variables, we obtain an
3047  // exactly feasible dual solution for the LP with zero objective function; we aggregate the bounds of the
3048  // variables accordingly and store its negation in temp
3049  temp = 0;
3050  bool isTempFinite = true;
3051 
3052  for(int c = 0; c < numCols && isTempFinite; c++)
3053  {
3054  const Rational& minusRedCost = ytransA[c];
3055 
3056  if(minusRedCost > 0)
3057  {
3058  assert((upper[c] < _rationalPosInfty) == _upperFinite(_colTypes[c]));
3059 
3060  if(_upperFinite(_colTypes[c]))
3061  temp.addProduct(minusRedCost, upper[c]);
3062  else
3063  isTempFinite = false;
3064  }
3065  else if(minusRedCost < 0)
3066  {
3067  assert((lower[c] > _rationalNegInfty) == _lowerFinite(_colTypes[c]));
3068 
3069  if(_lowerFinite(_colTypes[c]))
3070  temp.addProduct(minusRedCost, lower[c]);
3071  else
3072  isTempFinite = false;
3073  }
3074  }
3075 
3076  MSG_DEBUG(std::cout << "max ytransA*[x_l,x_u] = " << (isTempFinite ? rationalToString(
3077  temp) : "infinite") << "\n");
3078 
3079  // ytransb - temp is the increase in the dual objective along the Farkas ray; if this is positive, the dual is
3080  // unbounded and certifies primal infeasibility
3081  if(isTempFinite && temp < ytransb)
3082  {
3083  MSG_INFO1(spxout, spxout << "Farkas infeasibility proof verified exactly. (1)\n");
3084  return;
3085  }
3086 
3087  // ensure that array of nonzero elements in ytransA is available
3088  assert(ytransA.isSetup());
3089  ytransA.setup();
3090 
3091  // if ytransb is negative, try to make it zero by including a positive lower bound or a negative upper bound
3092  if(ytransb < 0)
3093  {
3094  for(int c = 0; c < numCols; c++)
3095  {
3096  if(lower[c] > 0)
3097  {
3098  ytransA.setValue(c, ytransA[c] - ytransb / lower[c]);
3099  ytransb = 0;
3100  break;
3101  }
3102  else if(upper[c] < 0)
3103  {
3104  ytransA.setValue(c, ytransA[c] - ytransb / upper[c]);
3105  ytransb = 0;
3106  break;
3107  }
3108  }
3109  }
3110 
3111  // if ytransb is still zero then the zero solution is inside the bounds and cannot be cut off by the Farkas
3112  // constraint; in this case, we cannot compute a Farkas box
3113  if(ytransb < 0)
3114  {
3115  MSG_INFO1(spxout, spxout <<
3116  "Approximate Farkas proof to weak. Could not compute Farkas box. (1)\n");
3117  return;
3118  }
3119 
3120  // compute the one norm of ytransA
3121  temp = 0;
3122  const int size = ytransA.size();
3123 
3124  for(int n = 0; n < size; n++)
3125  temp += spxAbs(ytransA.value(n));
3126 
3127  // if the one norm is zero then ytransA is zero the Farkas proof should have been verified above
3128  assert(temp != 0);
3129 
3130  // initialize variables in loop: size of Farkas box B, flag whether B has been increased, and number of current
3131  // nonzero in ytransA
3132  Rational B = ytransb / temp;
3133  bool success = false;
3134  int n = 0;
3135 
3136  // loop through nonzeros of ytransA
3137  MSG_DEBUG(std::cout << "B = " << rationalToString(B) << "\n");
3138  assert(ytransb >= 0);
3139 
3140  while(true)
3141  {
3142  // if all nonzeros have been inspected once without increasing B, we abort; otherwise, we start another round
3143  if(n >= ytransA.size())
3144  {
3145  if(!success)
3146  break;
3147 
3148  success = false;
3149  n = 0;
3150  }
3151 
3152  // get Farkas multiplier of the bound constraint as minus the value in ytransA
3153  const Rational& minusRedCost = ytransA.value(n);
3154  int colIdx = ytransA.index(n);
3155 
3156  // if the multiplier is positive we inspect the lower bound: if it is finite and within the Farkas box, we can
3157  // increase B by including it in the Farkas proof
3158  assert((upper[colIdx] < _rationalPosInfty) == _upperFinite(_colTypes[colIdx]));
3159  assert((lower[colIdx] > _rationalNegInfty) == _lowerFinite(_colTypes[colIdx]));
3160 
3161  if(minusRedCost < 0 && lower[colIdx] > -B && _lowerFinite(_colTypes[colIdx]))
3162  {
3163  ytransA.clearNum(n);
3164  ytransb.subProduct(minusRedCost, lower[colIdx]);
3165  temp += minusRedCost;
3166 
3167  assert(ytransb >= 0);
3168  assert(temp >= 0);
3169  assert(temp == 0 || ytransb / temp > B);
3170 
3171  // if ytransA and ytransb are zero, we have 0^T x >= 0 and cannot compute a Farkas box
3172  if(temp == 0 && ytransb == 0)
3173  {
3174  MSG_INFO1(spxout, spxout <<
3175  "Approximate Farkas proof to weak. Could not compute Farkas box. (2)\n");
3176  return;
3177  }
3178  // if ytransb is positive and ytransA is zero, we have 0^T x > 0, proving infeasibility
3179  else if(temp == 0)
3180  {
3181  assert(ytransb > 0);
3182  MSG_INFO1(spxout, spxout << "Farkas infeasibility proof verified exactly. (2)\n");
3183  return;
3184  }
3185  else
3186  {
3187  B = ytransb / temp;
3188  MSG_DEBUG(std::cout << "B = " << rationalToString(B) << "\n");
3189  }
3190 
3191  success = true;
3192  }
3193  // if the multiplier is negative we inspect the upper bound: if it is finite and within the Farkas box, we can
3194  // increase B by including it in the Farkas proof
3195  else if(minusRedCost > 0 && upper[colIdx] < B && _upperFinite(_colTypes[colIdx]))
3196  {
3197  ytransA.clearNum(n);
3198  ytransb.subProduct(minusRedCost, upper[colIdx]);
3199  temp -= minusRedCost;
3200 
3201  assert(ytransb >= 0);
3202  assert(temp >= 0);
3203  assert(temp == 0 || ytransb / temp > B);
3204 
3205  // if ytransA and ytransb are zero, we have 0^T x >= 0 and cannot compute a Farkas box
3206  if(temp == 0 && ytransb == 0)
3207  {
3208  MSG_INFO1(spxout, spxout <<
3209  "Approximate Farkas proof to weak. Could not compute Farkas box. (2)\n");
3210  return;
3211  }
3212  // if ytransb is positive and ytransA is zero, we have 0^T x > 0, proving infeasibility
3213  else if(temp == 0)
3214  {
3215  assert(ytransb > 0);
3216  MSG_INFO1(spxout, spxout << "Farkas infeasibility proof verified exactly. (2)\n");
3217  return;
3218  }
3219  else
3220  {
3221  B = ytransb / temp;
3222  MSG_DEBUG(std::cout << "B = " << rationalToString(B) << "\n");
3223  }
3224 
3225  success = true;
3226  }
3227  // the multiplier is zero, we can ignore the bound constraints on this variable
3228  else if(minusRedCost == 0)
3229  ytransA.clearNum(n);
3230  // currently this bound cannot be used to increase B; we will check it again in the next round, because B might
3231  // have increased by then
3232  else
3233  n++;
3234  }
3235 
3236  if(B > 0)
3237  {
3238  MSG_INFO1(spxout, spxout <<
3239  "Computed Farkas box: provably no feasible solutions with components less than "
3240  << rationalToString(B) << " in absolute value.\n");
3241  }
3242 }
3243 
3244 
3245 
3246 /// solves real LP during iterative refinement
3248  VectorReal& dual, DataArray< SPxSolver::VarStatus >& basisStatusRows,
3249  DataArray< SPxSolver::VarStatus >& basisStatusCols, bool& returnedBasis)
3250 {
3251  assert(_isConsistent());
3252 
3253  assert(_solver.nRows() == numRowsRational());
3254  assert(_solver.nCols() == numColsRational());
3255  assert(primal.dim() == numColsRational());
3256  assert(dual.dim() == numRowsRational());
3257 
3259 
3260 #ifndef SOPLEX_MANUAL_ALT
3261 
3262  if(fromscratch || !_hasBasis)
3264  else
3266 
3267 #else
3269 #endif
3270 
3271  // start timing
3273 
3274  // if preprocessing is applied, we need to restore the original LP at the end
3275  SPxLPRational* rationalLP = 0;
3276 
3277  if(_simplifier != 0 || _scaler != 0)
3278  {
3279  spx_alloc(rationalLP);
3280  rationalLP = new(rationalLP) SPxLPRational(_solver);
3281  }
3282 
3283  // if preprocessing is applied, the basis may change, hence invalidate the rational basis factorization; if no
3284  if(_simplifier != 0 || _scaler != 0)
3286 
3287  // stop timing
3289 
3290  returnedBasis = false;
3291 
3292  try
3293  {
3294  // apply problem simplification
3295  SPxSimplifier::Result simplificationStatus = SPxSimplifier::OKAY;
3296 
3297  if(_simplifier != 0)
3298  {
3299  // do not remove bounds of boxed variables or sides of ranged rows if bound flipping is used
3301  simplificationStatus = _simplifier->simplify(_solver, realParam(SoPlex::EPSILON_ZERO),
3303  }
3304 
3305  // apply scaling after the simplification
3306  if(_scaler != 0 && simplificationStatus == SPxSimplifier::OKAY)
3307  _scaler->scale(_solver, false);
3308 
3309  // run the simplex method if problem has not been solved by the simplifier
3310  if(simplificationStatus == SPxSimplifier::OKAY)
3311  {
3312  MSG_INFO1(spxout, spxout << std::endl);
3313 
3315 
3316  MSG_INFO1(spxout, spxout << std::endl);
3317  }
3318 
3319  ///@todo move to private helper methods
3320  // evaluate status flag
3321  if(simplificationStatus == SPxSimplifier::INFEASIBLE)
3322  result = SPxSolver::INFEASIBLE;
3323  else if(simplificationStatus == SPxSimplifier::DUAL_INFEASIBLE)
3324  result = SPxSolver::INForUNBD;
3325  else if(simplificationStatus == SPxSimplifier::UNBOUNDED)
3326  result = SPxSolver::UNBOUNDED;
3327  else if(simplificationStatus == SPxSimplifier::VANISHED
3328  || simplificationStatus == SPxSimplifier::OKAY)
3329  {
3330  result = simplificationStatus == SPxSimplifier::VANISHED ? SPxSolver::OPTIMAL : _solver.status();
3331 
3332  ///@todo move to private helper methods
3333  // process result
3334  switch(result)
3335  {
3336  case SPxSolver::OPTIMAL:
3337 
3338  // unsimplify if simplifier is active and LP is solved to optimality; this must be done here and not at solution
3339  // query, because we want to have the basis for the original problem
3340  if(_simplifier != 0)
3341  {
3342  assert(!_simplifier->isUnsimplified());
3343  assert(simplificationStatus == SPxSimplifier::VANISHED
3344  || simplificationStatus == SPxSimplifier::OKAY);
3345 
3346  bool vanished = simplificationStatus == SPxSimplifier::VANISHED;
3347 
3348  // get solution vectors for transformed problem
3349  DVectorReal tmpPrimal(vanished ? 0 : _solver.nCols());
3350  DVectorReal tmpSlacks(vanished ? 0 : _solver.nRows());
3351  DVectorReal tmpDual(vanished ? 0 : _solver.nRows());
3352  DVectorReal tmpRedCost(vanished ? 0 : _solver.nCols());
3353 
3354  if(!vanished)
3355  {
3356  assert(_solver.status() == SPxSolver::OPTIMAL);
3357 
3358  _solver.getPrimal(tmpPrimal);
3359  _solver.getSlacks(tmpSlacks);
3360  _solver.getDual(tmpDual);
3361  _solver.getRedCost(tmpRedCost);
3362 
3363  // unscale vectors
3364  if(_scaler != 0)
3365  {
3366  _scaler->unscalePrimal(_solver, tmpPrimal);
3367  _scaler->unscaleSlacks(_solver, tmpSlacks);
3368  _scaler->unscaleDual(_solver, tmpDual);
3369  _scaler->unscaleRedCost(_solver, tmpRedCost);
3370  }
3371 
3372  // get basis of transformed problem
3373  basisStatusRows.reSize(_solver.nRows());
3374  basisStatusCols.reSize(_solver.nCols());
3375  _solver.getBasis(basisStatusRows.get_ptr(), basisStatusCols.get_ptr(), basisStatusRows.size(),
3376  basisStatusCols.size());
3377  }
3378 
3379  ///@todo catch exception
3380  _simplifier->unsimplify(tmpPrimal, tmpDual, tmpSlacks, tmpRedCost, basisStatusRows.get_ptr(),
3381  basisStatusCols.get_ptr());
3382 
3383  // store basis for original problem
3384  basisStatusRows.reSize(numRowsRational());
3385  basisStatusCols.reSize(numColsRational());
3386  _simplifier->getBasis(basisStatusRows.get_ptr(), basisStatusCols.get_ptr(), basisStatusRows.size(),
3387  basisStatusCols.size());
3388  returnedBasis = true;
3389 
3390  primal = _simplifier->unsimplifiedPrimal();
3391  dual = _simplifier->unsimplifiedDual();
3392  }
3393  // if the original problem is not in the solver because of scaling, we also need to store the basis
3394  else
3395  {
3396  _solver.getPrimal(primal);
3397  _solver.getDual(dual);
3398 
3399  // unscale vectors
3400  if(_scaler != 0)
3401  {
3402  _scaler->unscalePrimal(_solver, primal);
3403  _scaler->unscaleDual(_solver, dual);
3404  }
3405 
3406  // get basis of transformed problem
3407  basisStatusRows.reSize(_solver.nRows());
3408  basisStatusCols.reSize(_solver.nCols());
3409  _solver.getBasis(basisStatusRows.get_ptr(), basisStatusCols.get_ptr(), basisStatusRows.size(),
3410  basisStatusCols.size());
3411  returnedBasis = true;
3412  }
3413 
3414  break;
3415 
3418  {
3419  _solver.getPrimal(primal);
3420  _solver.getDual(dual);
3421 
3422  // unscale vectors
3423  if(_scaler != 0)
3424  {
3425  _scaler->unscalePrimal(_solver, primal);
3426  _scaler->unscaleDual(_solver, dual);
3427  }
3428 
3429  // get basis of transformed problem
3430  basisStatusRows.reSize(_solver.nRows());
3431  basisStatusCols.reSize(_solver.nCols());
3432  _solver.getBasis(basisStatusRows.get_ptr(), basisStatusCols.get_ptr(), basisStatusRows.size(),
3433  basisStatusCols.size());
3434  returnedBasis = true;
3435  result = SPxSolver::OPTIMAL;
3436  }
3437 
3438  break;
3439 
3440  case SPxSolver::ABORT_TIME:
3441  case SPxSolver::ABORT_ITER:
3443  case SPxSolver::REGULAR:
3444  case SPxSolver::RUNNING:
3445  case SPxSolver::UNBOUNDED:
3446  break;
3447 
3448  case SPxSolver::INFEASIBLE:
3449 
3450  // if simplifier is active we cannot return a Farkas ray currently
3451  if(_simplifier != 0)
3452  break;
3453 
3454  // return Farkas ray as dual solution
3455  _solver.getDualfarkas(dual);
3456 
3457  // unscale vectors
3458  if(_scaler != 0)
3459  _scaler->unscaleDual(_solver, dual);
3460 
3461  // if the original problem is not in the solver because of scaling, we also need to store the basis
3462  basisStatusRows.reSize(_solver.nRows());
3463  basisStatusCols.reSize(_solver.nCols());
3464  _solver.getBasis(basisStatusRows.get_ptr(), basisStatusCols.get_ptr(), basisStatusRows.size(),
3465  basisStatusCols.size());
3466  returnedBasis = true;
3467  break;
3468 
3469  case SPxSolver::INForUNBD:
3470  case SPxSolver::SINGULAR:
3471  default:
3472  break;
3473  }
3474  }
3475  }
3476  catch(...)
3477  {
3478  MSG_INFO1(spxout, spxout << "Exception thrown during floating-point solve.\n");
3479  result = SPxSolver::ERROR;
3480  }
3481 
3482  // restore original LP if necessary
3483  if(_simplifier != 0 || _scaler != 0)
3484  {
3485  assert(rationalLP != 0);
3486  _solver.loadLP((SPxLPReal)(*rationalLP));
3487  rationalLP->~SPxLPRational();
3488  spx_free(rationalLP);
3489 
3490  if(_hasBasis)
3491  _solver.setBasis(basisStatusRows.get_ptr(), basisStatusCols.get_ptr());
3492  }
3493 
3494  return result;
3495 }
3496 
3497 
3498 
3499 /// solves real LP with recovery mechanism
3500 SPxSolver::Status SoPlex::_solveRealStable(bool acceptUnbounded, bool acceptInfeasible,
3501  VectorReal& primal, VectorReal& dual, DataArray< SPxSolver::VarStatus >& basisStatusRows,
3502  DataArray< SPxSolver::VarStatus >& basisStatusCols, bool& returnedBasis,
3503  const bool forceNoSimplifier)
3504 {
3506 
3507  bool fromScratch = false;
3508  bool solved = false;
3509  bool solvedFromScratch = false;
3510  bool initialSolve = true;
3511  bool increasedMarkowitz = false;
3512  bool relaxedTolerances = false;
3513  bool tightenedTolerances = false;
3514  bool switchedScaler = false;
3515  bool switchedSimplifier = false;
3516  bool switchedRatiotester = false;
3517  bool switchedPricer = false;
3518  bool turnedoffPre = false;
3519 
3520  Real markowitz = _slufactor.markowitz();
3521  int ratiotester = intParam(SoPlex::RATIOTESTER);
3522  int pricer = intParam(SoPlex::PRICER);
3523  int simplifier = intParam(SoPlex::SIMPLIFIER);
3524  int scaler = intParam(SoPlex::SCALER);
3525  int type = intParam(SoPlex::ALGORITHM);
3526 
3527  if(forceNoSimplifier)
3529 
3530  while(true)
3531  {
3532  assert(!increasedMarkowitz || GE(_slufactor.markowitz(), 0.9));
3533 
3534  result = _solveRealForRational(fromScratch, primal, dual, basisStatusRows, basisStatusCols,
3535  returnedBasis);
3536 
3537  solved = (result == SPxSolver::OPTIMAL)
3538  || (result == SPxSolver::INFEASIBLE && acceptInfeasible)
3539  || (result == SPxSolver::UNBOUNDED && acceptUnbounded);
3540 
3541  if(solved)
3542  break;
3543 
3544  // if( _isSolveStopped() )
3545  // break;
3546 
3547  if(initialSolve)
3548  {
3549  MSG_INFO1(spxout, spxout << "Numerical troubles during floating-point solve." << std::endl);
3550  initialSolve = false;
3551  }
3552 
3553  if(!turnedoffPre
3556  {
3557  MSG_INFO1(spxout, spxout << "Turning off preprocessing." << std::endl);
3558 
3559  turnedoffPre = true;
3560 
3563 
3564  fromScratch = true;
3565  _solver.reLoad();
3566  solvedFromScratch = true;
3567  continue;
3568  }
3569 
3570  setIntParam(SoPlex::SCALER, scaler);
3571  setIntParam(SoPlex::SIMPLIFIER, simplifier);
3572 
3573  if(!increasedMarkowitz)
3574  {
3575  MSG_INFO1(spxout, spxout << "Increasing Markowitz threshold." << std::endl);
3576 
3577  _slufactor.setMarkowitz(0.9);
3578  increasedMarkowitz = true;
3579 
3580  try
3581  {
3582  _solver.factorize();
3583  continue;
3584  }
3585  catch(...)
3586  {
3587  MSG_DEBUG(std::cout << std::endl << "Factorization failed." << std::endl);
3588  }
3589  }
3590 
3591  if(!solvedFromScratch)
3592  {
3593  MSG_INFO1(spxout, spxout << "Solving from scratch." << std::endl);
3594 
3595  fromScratch = true;
3596  _solver.reLoad();
3597 
3598  solvedFromScratch = true;
3599  continue;
3600  }
3601 
3602  setIntParam(SoPlex::RATIOTESTER, ratiotester);
3603  setIntParam(SoPlex::PRICER, pricer);
3604 
3605  if(!switchedScaler)
3606  {
3607  MSG_INFO1(spxout, spxout << "Switching scaling." << std::endl);
3608 
3609  if(scaler == int(SoPlex::SCALER_OFF))
3611  else
3613 
3614  fromScratch = true;
3615  _solver.reLoad();
3616 
3617  solvedFromScratch = true;
3618  switchedScaler = true;
3619  continue;
3620  }
3621 
3622  if(!switchedSimplifier && !forceNoSimplifier)
3623  {
3624  MSG_INFO1(spxout, spxout << "Switching simplification." << std::endl);
3625 
3626  if(simplifier == int(SoPlex::SIMPLIFIER_OFF))
3628  else
3630 
3631  fromScratch = true;
3632  _solver.reLoad();
3633 
3634  solvedFromScratch = true;
3635  switchedSimplifier = true;
3636  continue;
3637  }
3638 
3640 
3641  if(!relaxedTolerances)
3642  {
3643  MSG_INFO1(spxout, spxout << "Relaxing tolerances." << std::endl);
3644 
3646  _solver.setDelta((_solver.feastol() * 1e3 > 1e-3) ? 1e-3 : (_solver.feastol() * 1e3));
3647  relaxedTolerances = _solver.feastol() >= 1e-3;
3648  solvedFromScratch = false;
3649  continue;
3650  }
3651 
3652  if(!tightenedTolerances && result != SPxSolver::INFEASIBLE)
3653  {
3654  MSG_INFO1(spxout, spxout << "Tightening tolerances." << std::endl);
3655 
3657  _solver.setDelta(_solver.feastol() * 1e-3 < 1e-9 ? 1e-9 : _solver.feastol() * 1e-3);
3658  tightenedTolerances = _solver.feastol() <= 1e-9;
3659  solvedFromScratch = false;
3660  continue;
3661  }
3662 
3664 
3665  if(!switchedRatiotester)
3666  {
3667  MSG_INFO1(spxout, spxout << "Switching ratio test." << std::endl);
3668 
3670 
3673  else
3675 
3676  switchedRatiotester = true;
3677  solvedFromScratch = false;
3678  continue;
3679  }
3680 
3681  if(!switchedPricer)
3682  {
3683  MSG_INFO1(spxout, spxout << "Switching pricer." << std::endl);
3684 
3686 
3687  if(_solver.pricer() != (SPxPricer*)&_pricerDevex)
3689  else
3691 
3692  switchedPricer = true;
3693  solvedFromScratch = false;
3694  continue;
3695  }
3696 
3697  MSG_INFO1(spxout, spxout << "Giving up." << std::endl);
3698 
3699  break;
3700  }
3701 
3704  _slufactor.setMarkowitz(markowitz);
3705 
3706  setIntParam(SoPlex::RATIOTESTER, ratiotester);
3707  setIntParam(SoPlex::PRICER, pricer);
3708  setIntParam(SoPlex::SIMPLIFIER, simplifier);
3709  setIntParam(SoPlex::SCALER, scaler);
3711 
3712  return result;
3713 }
3714 
3715 
3716 
3717 /// computes rational inverse of basis matrix as defined by _rationalLUSolverBind
3719 {
3722 
3723  const int matrixdim = numRowsRational();
3724  assert(_rationalLUSolverBind.size() == matrixdim);
3725 
3726  DataArray< const SVectorRational* > matrix(matrixdim);
3727  _rationalLUSolverBind.reSize(matrixdim);
3728 
3729  for(int i = 0; i < matrixdim; i++)
3730  {
3731  if(_rationalLUSolverBind[i] >= 0)
3732  {
3733  assert(_rationalLUSolverBind[i] < numColsRational());
3734  matrix[i] = &colVectorRational(_rationalLUSolverBind[i]);
3735  }
3736  else
3737  {
3738  assert(-1 - _rationalLUSolverBind[i] >= 0);
3739  assert(-1 - _rationalLUSolverBind[i] < numRowsRational());
3740  matrix[i] = _unitVectorRational(-1 - _rationalLUSolverBind[i]);
3741  }
3742  }
3743 
3744  // load and factorize rational basis matrix
3747  else
3749 
3750  _rationalLUSolver.load(matrix.get_ptr(), matrixdim);
3751 
3752  // record statistics
3756 
3758  {
3759  MSG_INFO2(spxout, spxout << "Rational factorization hit time limit.\n");
3760  }
3762  {
3763  MSG_INFO1(spxout, spxout << "Error performing rational LU factorization.\n");
3764  }
3765 
3766  return;
3767 }
3768 
3769 
3770 
3771 /// factorizes rational basis matrix in column representation
3773  DataArray< SPxSolver::VarStatus >& basisStatusRows,
3774  DataArray< SPxSolver::VarStatus >& basisStatusCols, bool& stoppedTime, bool& stoppedIter,
3775  bool& error, bool& optimal)
3776 {
3777  // start rational solving time
3779 
3780  stoppedTime = false;
3781  stoppedIter = false;
3782  error = false;
3783  optimal = false;
3784 
3785  const bool maximizing = (intParam(SoPlex::OBJSENSE) == SoPlex::OBJSENSE_MAXIMIZE);
3786  const int matrixdim = numRowsRational();
3787  bool loadMatrix = (_rationalLUSolver.status() == SLinSolverRational::UNLOADED
3789  int numBasicRows;
3790 
3791  assert(loadMatrix || matrixdim == _rationalLUSolver.dim());
3792  assert(loadMatrix || matrixdim == _rationalLUSolverBind.size());
3793 
3794  if(!loadMatrix && (matrixdim != _rationalLUSolver.dim()
3795  || matrixdim != _rationalLUSolverBind.size()))
3796  {
3798  "Warning: dimensioning error in rational matrix factorization (recovered).\n");
3799  loadMatrix = true;
3800  }
3801 
3802  _workSol._primal.reDim(matrixdim);
3803  _workSol._slacks.reDim(matrixdim);
3804  _workSol._dual.reDim(matrixdim);
3805  _workSol._redCost.reDim(numColsRational() > matrixdim ? numColsRational() : matrixdim);
3806 
3807  if(loadMatrix)
3808  _rationalLUSolverBind.reSize(matrixdim);
3809 
3810  DVectorRational& basicPrimalRhs = _workSol._slacks;
3811  DVectorRational& basicDualRhs = _workSol._redCost;
3812  DVectorRational& basicPrimal = _workSol._primal;
3813  DVectorRational& basicDual = _workSol._dual;
3814 
3815  Rational violation;
3816  Rational primalViolation;
3817  Rational dualViolation;
3818  bool primalFeasible = false;
3819  bool dualFeasible = false;
3820 
3821  assert(basisStatusCols.size() == numColsRational());
3822  assert(basisStatusRows.size() == numRowsRational());
3823 
3824  int j = 0;
3825 
3826  for(int i = 0; i < basisStatusRows.size(); i++)
3827  {
3828  if(basisStatusRows[i] == SPxSolver::BASIC && j < matrixdim)
3829  {
3830  basicPrimalRhs[i] = 0;
3831  basicDualRhs[j] = 0;
3832 
3833  if(loadMatrix)
3834  _rationalLUSolverBind[j] = -1 - i;
3835 
3836  j++;
3837  }
3838  else if(basisStatusRows[i] == SPxSolver::ON_LOWER)
3839  basicPrimalRhs[i] = lhsRational(i);
3840  else if(basisStatusRows[i] == SPxSolver::ON_UPPER)
3841  basicPrimalRhs[i] = rhsRational(i);
3842  else if(basisStatusRows[i] == SPxSolver::ZERO)
3843  basicPrimalRhs[i] = 0;
3844  else if(basisStatusRows[i] == SPxSolver::FIXED)
3845  {
3846  assert(lhsRational(i) == rhsRational(i));
3847  basicPrimalRhs[i] = lhsRational(i);
3848  }
3849  else if(basisStatusRows[i] == SPxSolver::UNDEFINED)
3850  {
3851  MSG_INFO1(spxout, spxout << "Undefined basis status of row in rational factorization.\n");
3852  error = true;
3853  goto TERMINATE;
3854  }
3855  else
3856  {
3857  assert(basisStatusRows[i] == SPxSolver::BASIC);
3858  MSG_INFO1(spxout, spxout << "Too many basic rows in rational factorization.\n");
3859  error = true;
3860  goto TERMINATE;
3861  }
3862  }
3863 
3864  numBasicRows = j;
3865 
3866  for(int i = 0; i < basisStatusCols.size(); i++)
3867  {
3868  if(basisStatusCols[i] == SPxSolver::BASIC && j < matrixdim)
3869  {
3870  basicDualRhs[j] = objRational(i);
3871 
3872  if(loadMatrix)
3873  _rationalLUSolverBind[j] = i;
3874 
3875  j++;
3876  }
3877  else if(basisStatusCols[i] == SPxSolver::ON_LOWER)
3878  basicPrimalRhs.multAdd(-lowerRational(i), colVectorRational(i));
3879  else if(basisStatusCols[i] == SPxSolver::ON_UPPER)
3880  basicPrimalRhs.multAdd(-upperRational(i), colVectorRational(i));
3881  else if(basisStatusCols[i] == SPxSolver::ZERO)
3882  {}
3883  else if(basisStatusCols[i] == SPxSolver::FIXED)
3884  {
3885  assert(lowerRational(i) == upperRational(i));
3886  basicPrimalRhs.multAdd(-lowerRational(i), colVectorRational(i));
3887  }
3888  else if(basisStatusCols[i] == SPxSolver::UNDEFINED)
3889  {
3890  MSG_INFO1(spxout, spxout << "Undefined basis status of column in rational factorization.\n");
3891  error = true;
3892  goto TERMINATE;
3893  }
3894  else
3895  {
3896  assert(basisStatusCols[i] == SPxSolver::BASIC);
3897  MSG_INFO1(spxout, spxout << "Too many basic columns in rational factorization.\n");
3898  error = true;
3899  goto TERMINATE;
3900  }
3901  }
3902 
3903  if(j != matrixdim)
3904  {
3905  MSG_INFO1(spxout, spxout << "Too few basic entries in rational factorization.\n");
3906  error = true;
3907  goto TERMINATE;
3908  }
3909 
3910  // load and factorize rational basis matrix
3911  if(loadMatrix)
3913 
3915  {
3916  stoppedTime = true;
3917  return;
3918  }
3920  {
3921  error = true;
3922  return;
3923  }
3924 
3926 
3927  // solve for primal solution
3930  else
3932 
3933  _rationalLUSolver.solveRight(basicPrimal, basicPrimalRhs);
3934 
3935  // record statistics
3938 
3939  if(_isSolveStopped(stoppedTime, stoppedIter))
3940  {
3941  MSG_INFO2(spxout, spxout << "Rational factorization hit time limit while solving for primal.\n");
3942  return;
3943  }
3944 
3945  // check bound violation on basic rows and columns
3946  j = 0;
3947  primalViolation = 0;
3948  primalFeasible = true;
3949 
3950  for(int i = 0; i < basisStatusRows.size(); i++)
3951  {
3952  if(basisStatusRows[i] == SPxSolver::BASIC)
3953  {
3954  assert(j < matrixdim);
3955  assert(_rationalLUSolverBind[j] == -1 - i);
3956  violation = lhsRational(i);
3957  violation += basicPrimal[j];
3958 
3959  if(violation > primalViolation)
3960  {
3961  primalFeasible = false;
3962  primalViolation = violation;
3963  }
3964 
3965  violation = rhsRational(i);
3966  violation += basicPrimal[j];
3967  violation *= -1;
3968 
3969  if(violation > primalViolation)
3970  {
3971  primalFeasible = false;
3972  primalViolation = violation;
3973  }
3974 
3975  j++;
3976  }
3977  }
3978 
3979  for(int i = 0; i < basisStatusCols.size(); i++)
3980  {
3981  if(basisStatusCols[i] == SPxSolver::BASIC)
3982  {
3983  assert(j < matrixdim);
3984  assert(_rationalLUSolverBind[j] == i);
3985 
3986  if(basicPrimal[j] < lowerRational(i))
3987  {
3988  violation = lowerRational(i);
3989  violation -= basicPrimal[j];
3990 
3991  if(violation > primalViolation)
3992  {
3993  primalFeasible = false;
3994  primalViolation = violation;
3995  }
3996  }
3997 
3998  if(basicPrimal[j] > upperRational(i))
3999  {
4000  violation = basicPrimal[j];
4001  violation -= upperRational(i);
4002 
4003  if(violation > primalViolation)
4004  {
4005  primalFeasible = false;
4006  primalViolation = violation;
4007  }
4008  }
4009 
4010  j++;
4011  }
4012  }
4013 
4014  if(!primalFeasible)
4015  {
4016  MSG_INFO1(spxout, spxout << "Rational solution primal infeasible.\n");
4017  }
4018 
4019  // solve for dual solution
4022  else
4024 
4025  _rationalLUSolver.solveLeft(basicDual, basicDualRhs);
4026 
4027  // record statistics
4030 
4031  if(_isSolveStopped(stoppedTime, stoppedIter))
4032  {
4033  MSG_INFO2(spxout, spxout << "Rational factorization hit time limit while solving for dual.\n");
4034  return;
4035  }
4036 
4037  // check dual violation on nonbasic rows
4038  dualViolation = 0;
4039  dualFeasible = true;
4040 
4041  for(int i = 0; i < basisStatusRows.size(); i++)
4042  {
4043  if(_rowTypes[i] == RANGETYPE_FIXED
4044  && (basisStatusRows[i] == SPxSolver::ON_LOWER || basisStatusRows[i] == SPxSolver::ON_UPPER))
4045  {
4046  assert(lhsRational(i) == rhsRational(i));
4047  basisStatusRows[i] = SPxSolver::FIXED;
4048  }
4049 
4050  assert(basisStatusRows[i] != SPxSolver::BASIC || basicDual[i] == 0);
4051 
4052  if(basisStatusRows[i] == SPxSolver::BASIC || basisStatusRows[i] == SPxSolver::FIXED)
4053  continue;
4054  else if(basicDual[i] < 0)
4055  {
4056  if(((maximizing && basisStatusRows[i] != SPxSolver::ON_LOWER) || (!maximizing
4057  && basisStatusRows[i] != SPxSolver::ON_UPPER))
4058  && (basisStatusRows[i] != SPxSolver::ZERO || rhsRational(i) != 0))
4059  {
4060  dualFeasible = false;
4061  violation = -basicDual[i];
4062 
4063  if(violation > dualViolation)
4064  dualViolation = violation;
4065 
4066  MSG_DEBUG(spxout << "negative dual multliplier for row " << i
4067  << " with dual " << rationalToString(basicDual[i])
4068  << " and status " << basisStatusRows[i]
4069  << " and [lhs,rhs] = [" << rationalToString(lhsRational(i)) << "," << rationalToString(rhsRational(
4070  i)) << "]"
4071  << "\n");
4072  }
4073  }
4074  else if(basicDual[i] > 0)
4075  {
4076  if(((maximizing && basisStatusRows[i] != SPxSolver::ON_UPPER) || (!maximizing
4077  && basisStatusRows[i] != SPxSolver::ON_LOWER))
4078  && (basisStatusRows[i] != SPxSolver::ZERO || lhsRational(i) == 0))
4079  {
4080  dualFeasible = false;
4081 
4082  if(basicDual[i] > dualViolation)
4083  dualViolation = basicDual[i];
4084 
4085  MSG_DEBUG(spxout << "positive dual multliplier for row " << i
4086  << " with dual " << rationalToString(basicDual[i])
4087  << " and status " << basisStatusRows[i]
4088  << " and [lhs,rhs] = [" << rationalToString(lhsRational(i)) << "," << rationalToString(rhsRational(
4089  i)) << "]"
4090  << "\n");
4091  }
4092  }
4093  }
4094 
4095  // check reduced cost violation on nonbasic columns
4096  for(int i = 0; i < basisStatusCols.size(); i++)
4097  {
4098  if(_colTypes[i] == RANGETYPE_FIXED
4099  && (basisStatusCols[i] == SPxSolver::ON_LOWER || basisStatusCols[i] == SPxSolver::ON_UPPER))
4100  {
4101  assert(lowerRational(i) == upperRational(i));
4102  basisStatusCols[i] = SPxSolver::FIXED;
4103  }
4104 
4105 #ifdef SOPLEX_WITH_GMP
4106  assert(basisStatusCols[i] != SPxSolver::BASIC
4107  || basicDual * colVectorRational(i) == objRational(i));
4108 #endif
4109 
4110  if(basisStatusCols[i] == SPxSolver::BASIC || basisStatusCols[i] == SPxSolver::FIXED)
4111  continue;
4112  else
4113  {
4114  _workSol._redCost[i] = basicDual * colVectorRational(i);
4115  _workSol._redCost[i] -= objRational(i);
4116 
4117  if(_workSol._redCost[i] > 0)
4118  {
4119  if(((maximizing && basisStatusCols[i] != SPxSolver::ON_LOWER) || (!maximizing
4120  && basisStatusCols[i] != SPxSolver::ON_UPPER))
4121  && (basisStatusCols[i] != SPxSolver::ZERO || upperRational(i) != 0))
4122  {
4123  dualFeasible = false;
4124 
4125  if(_workSol._redCost[i] > dualViolation)
4126  dualViolation = _workSol._redCost[i];
4127  }
4128 
4129  _workSol._redCost[i] *= -1;
4130  }
4131  else if(_workSol._redCost[i] < 0)
4132  {
4133  _workSol._redCost[i] *= -1;
4134 
4135  if(((maximizing && basisStatusCols[i] != SPxSolver::ON_UPPER) || (!maximizing
4136  && basisStatusCols[i] != SPxSolver::ON_LOWER))
4137  && (basisStatusCols[i] != SPxSolver::ZERO || lowerRational(i) != 0))
4138  {
4139  dualFeasible = false;
4140 
4141  if(_workSol._redCost[i] > dualViolation)
4142  dualViolation = _workSol._redCost[i];
4143  }
4144  }
4145  else
4146  _workSol._redCost[i] *= -1;
4147  }
4148  }
4149 
4150  if(!dualFeasible)
4151  {
4152  MSG_INFO1(spxout, spxout << "Rational solution dual infeasible.\n");
4153  }
4154 
4155  // store solution
4156  optimal = primalFeasible && dualFeasible;
4157 
4158  if(optimal || boolParam(SoPlex::RATFACJUMP))
4159  {
4160  _hasBasis = true;
4161 
4162  if(&basisStatusRows != &_basisStatusRows)
4163  _basisStatusRows = basisStatusRows;
4164 
4165  if(&basisStatusCols != &_basisStatusCols)
4166  _basisStatusCols = basisStatusCols;
4167 
4168  sol._primal.reDim(numColsRational());
4169  j = numBasicRows;
4170 
4171  for(int i = 0; i < basisStatusCols.size(); i++)
4172  {
4173  if(basisStatusCols[i] == SPxSolver::BASIC)
4174  {
4175  assert(j < matrixdim);
4176  assert(_rationalLUSolverBind[j] == i);
4177  sol._primal[i] = basicPrimal[j];
4178  j++;
4179  }
4180  else if(basisStatusCols[i] == SPxSolver::ON_LOWER)
4181  sol._primal[i] = lowerRational(i);
4182  else if(basisStatusCols[i] == SPxSolver::ON_UPPER)
4183  sol._primal[i] = upperRational(i);
4184  else if(basisStatusCols[i] == SPxSolver::ZERO)
4185  sol._primal[i] = 0;
4186  else if(basisStatusCols[i] == SPxSolver::FIXED)
4187  {
4188  assert(lowerRational(i) == upperRational(i));
4189  sol._primal[i] = lowerRational(i);
4190  }
4191  else
4192  {
4193  assert(basisStatusCols[i] == SPxSolver::UNDEFINED);
4194  MSG_INFO1(spxout, spxout << "Undefined basis status of column in rational factorization.\n");
4195  error = true;
4196  goto TERMINATE;
4197  }
4198  }
4199 
4200  sol._slacks.reDim(numRowsRational());
4202  sol._isPrimalFeasible = true;
4203 
4204  sol._dual = basicDual;
4205 
4206  for(int i = 0; i < numColsRational(); i++)
4207  {
4208  if(basisStatusCols[i] == SPxSolver::BASIC)
4209  sol._redCost[i] = 0;
4210  else if(basisStatusCols[i] == SPxSolver::FIXED)
4211  {
4212  sol._redCost[i] = basicDual * colVectorRational(i);
4213  sol._redCost[i] -= objRational(i);
4214  sol._redCost[i] *= -1;
4215  }
4216  else
4217  sol._redCost[i] = _workSol._redCost[i];
4218  }
4219 
4220  sol._isDualFeasible = true;
4221  }
4222 
4223 TERMINATE:
4224  // stop rational solving time
4226  return;
4227 }
4228 
4229 /// attempts rational reconstruction of primal-dual solution
4231  DataArray< SPxSolver::VarStatus >& basisStatusRows,
4232  DataArray< SPxSolver::VarStatus >& basisStatusCols, const Rational& denomBoundSquared)
4233 {
4234  bool success;
4235  bool isSolBasic;
4236  DIdxSet basicIndices(numColsRational());
4237 
4238  success = false;
4239  isSolBasic = true;
4240 
4241  if(!sol.isPrimalFeasible() || !sol.isDualFeasible())
4242  return success;
4243 
4244  // start timing and increment statistics counter
4247 
4248  // reconstruct primal vector
4249  _workSol._primal = sol._primal;
4250 
4251  for(int j = 0; j < numColsRational(); ++j)
4252  {
4253  if(basisStatusCols[j] == SPxSolver::BASIC)
4254  basicIndices.addIdx(j);
4255  }
4256 
4257  success = reconstructVector(_workSol._primal, denomBoundSquared, &basicIndices);
4258 
4259  if(!success)
4260  {
4261  MSG_INFO1(spxout, spxout << "Rational reconstruction of primal solution failed.\n");
4263  return success;
4264  }
4265 
4266  MSG_DEBUG(spxout << "Rational reconstruction of primal solution successful.\n");
4267 
4268  // check violation of bounds
4269  for(int c = numColsRational() - 1; c >= 0; c--)
4270  {
4271  // we want to notify the user whether the reconstructed solution is basic; otherwise, this would be redundant
4272  SPxSolver::VarStatus& basisStatusCol = _basisStatusCols[c];
4273 
4274  if((basisStatusCol == SPxSolver::FIXED && _workSol._primal[c] != lowerRational(c))
4275  || (basisStatusCol == SPxSolver::ON_LOWER && _workSol._primal[c] != lowerRational(c))
4276  || (basisStatusCol == SPxSolver::ON_UPPER && _workSol._primal[c] != upperRational(c))
4277  || (basisStatusCol == SPxSolver::ZERO && _workSol._primal[c] != 0)
4278  || (basisStatusCol == SPxSolver::UNDEFINED))
4279  {
4280  isSolBasic = false;
4281  }
4282 
4284  {
4285  MSG_DEBUG(std::cout << "Lower bound of variable " << c << " violated by " << rationalToString(
4286  lowerRational(c) - _workSol._primal[c]) << "\n");
4287  MSG_INFO1(spxout, spxout << "Reconstructed solution primal infeasible (1).\n");
4289  return false;
4290  }
4291 
4293  {
4294  MSG_DEBUG(std::cout << "Upper bound of variable " << c << " violated by " << rationalToString(
4295  _workSol._primal[c] - upperRational(c)) << "\n");
4296  MSG_INFO1(spxout, spxout << "Reconstructed solution primal infeasible (2).\n");
4298  return false;
4299  }
4300  }
4301 
4302  // compute slacks
4303  ///@todo we should compute them one by one so we can abort when encountering an infeasibility
4306 
4307  // check violation of sides
4308  for(int r = numRowsRational() - 1; r >= 0; r--)
4309  {
4310  // we want to notify the user whether the reconstructed solution is basic; otherwise, this would be redundant
4311  SPxSolver::VarStatus& basisStatusRow = _basisStatusRows[r];
4312 
4313  if((basisStatusRow == SPxSolver::FIXED && _workSol._slacks[r] != lhsRational(r))
4314  || (basisStatusRow == SPxSolver::ON_LOWER && _workSol._slacks[r] != lhsRational(r))
4315  || (basisStatusRow == SPxSolver::ON_UPPER && _workSol._slacks[r] != rhsRational(r))
4316  || (basisStatusRow == SPxSolver::ZERO && _workSol._slacks[r] != 0)
4317  || (basisStatusRow == SPxSolver::UNDEFINED))
4318  {
4319  isSolBasic = false;
4320  }
4321 
4323  {
4324  MSG_DEBUG(std::cout << "Lhs of row " << r << " violated by " << rationalToString(lhsRational(
4325  r) - _workSol._slacks[r]) << "\n");
4326  MSG_INFO1(spxout, spxout << "Reconstructed solution primal infeasible (3).\n");
4328  return false;
4329  }
4330 
4332  {
4333  MSG_DEBUG(std::cout << "Rhs of row " << r << " violated by " << rationalToString(
4334  _workSol._slacks[r] - rhsRational(r)) << "\n");
4335  MSG_INFO1(spxout, spxout << "Reconstructed solution primal infeasible (4).\n");
4337  return false;
4338  }
4339  }
4340 
4341  // reconstruct dual vector
4342  _workSol._dual = sol._dual;
4343 
4344  success = reconstructVector(_workSol._dual, denomBoundSquared);
4345 
4346  if(!success)
4347  {
4348  MSG_INFO1(spxout, spxout << "Rational reconstruction of dual solution failed.\n");
4350  return success;
4351  }
4352 
4353  MSG_DEBUG(spxout << "Rational reconstruction of dual vector successful.\n");
4354 
4355  // check dual multipliers before reduced costs because this check is faster since it does not require the
4356  // computation of reduced costs
4357  const bool maximizing = (intParam(SoPlex::OBJSENSE) == SoPlex::OBJSENSE_MAXIMIZE);
4358 
4359  for(int r = numRowsRational() - 1; r >= 0; r--)
4360  {
4361  int sig = sign(_workSol._dual[r]);
4362 
4363  if((!maximizing && sig > 0) || (maximizing && sig < 0))
4364  {
4365  if(!_lowerFinite(_rowTypes[r]) || _workSol._slacks[r] > lhsRational(r))
4366  {
4367  MSG_DEBUG(std::cout << "complementary slackness violated by row " << r
4368  << " with dual " << rationalToString(_workSol._dual[r])
4369  << " and slack " << rationalToString(_workSol._slacks[r])
4370  << " not at lhs " << rationalToString(lhsRational(r))
4371  << "\n");
4372  MSG_INFO1(spxout, spxout << "Reconstructed solution dual infeasible (1).\n");
4374  return false;
4375  }
4376 
4378  {
4380  isSolBasic = false;
4381  else
4383  }
4384  }
4385  else if((!maximizing && sig < 0) || (maximizing && sig > 0))
4386  {
4387  if(!_upperFinite(_rowTypes[r]) || _workSol._slacks[r] < rhsRational(r))
4388  {
4389  MSG_DEBUG(std::cout << "complementary slackness violated by row " << r
4390  << " with dual " << rationalToString(_workSol._dual[r])
4391  << " and slack " << rationalToString(_workSol._slacks[r])
4392  << " not at rhs " << rationalToString(rhsRational(r))
4393  << "\n");
4394  MSG_INFO1(spxout, spxout << "Reconstructed solution dual infeasible (2).\n");
4396  return false;
4397  }
4398 
4400  {
4402  isSolBasic = false;
4403  else
4405  }
4406  }
4407  }
4408 
4409  // compute reduced cost vector; we assume that the objective function vector has less nonzeros than the reduced
4410  // cost vector, and so multiplying with -1 first and subtracting the dual activity should be faster than adding
4411  // the dual activity and negating afterwards
4412  ///@todo we should compute them one by one so we can abort when encountering an infeasibility
4416 
4417  // check reduced cost violation
4418  for(int c = numColsRational() - 1; c >= 0; c--)
4419  {
4420  int sig = sign(_workSol._redCost[c]);
4421 
4422  if((!maximizing && sig > 0) || (maximizing && sig < 0))
4423  {
4425  {
4426  MSG_DEBUG(std::cout << "complementary slackness violated by column " << c
4427  << " with reduced cost " << rationalToString(_workSol._redCost[c])
4428  << " and value " << rationalToString(_workSol._primal[c])
4429  << " not at lower bound " << rationalToString(lowerRational(c))
4430  << "\n");
4431  MSG_INFO1(spxout, spxout << "Reconstructed solution dual infeasible (3).\n");
4433  return false;
4434  }
4435 
4437  {
4439  isSolBasic = false;
4440  else
4442  }
4443  }
4444  else if((!maximizing && sig < 0) || (maximizing && sig > 0))
4445  {
4447  {
4448  MSG_DEBUG(std::cout << "complementary slackness violated by column " << c
4449  << " with reduced cost " << rationalToString(_workSol._redCost[c])
4450  << " and value " << rationalToString(_workSol._primal[c])
4451  << " not at upper bound " << rationalToString(upperRational(c))
4452  << "\n");
4453  MSG_INFO1(spxout, spxout << "Reconstructed solution dual infeasible (4).\n");
4455  return false;
4456  }
4457 
4459  {
4461  isSolBasic = false;
4462  else
4464  }
4465  }
4466  }
4467 
4468  // update solution
4469  sol._primal = _workSol._primal;
4470  sol._slacks = _workSol._slacks;
4471  sol._dual = _workSol._dual;
4472  sol._redCost = _workSol._redCost;
4473 
4474  if(!isSolBasic)
4475  {
4476  MSG_WARNING(spxout, spxout << "Warning: Reconstructed solution not basic.\n");
4477  _hasBasis = false;
4478  }
4479 
4480  // stop timing
4482 
4483  return success;
4484 }
4485 } // 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:4102
int _lastSolveMode
Definition: soplex.h:1858
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
textbook ratio test without stabilization
Definition: soplex.h:1198
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:1594
free variable fixed to zero.
Definition: spxsolver.h:194
DVectorRational _unboundedRhs
Definition: soplex.h:1658
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:1865
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:3549
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:1329
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:1308
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:1008
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:944
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:1661
type of computational form, i.e., column or row representation
Definition: soplex.h:969
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
dual simplex algorithm, i.e., leaving for column and entering for row representation ...
Definition: soplex.h:1086
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:1650
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
primal simplex algorithm, i.e., entering for column and leaving for row representation ...
Definition: soplex.h:1083
Real feastol() const
allowed primal feasibility tolerance.
Definition: spxsolver.h:803
time limit in seconds (INFTY if unlimited)
Definition: soplex.h:1323
steepest edge pricer with exact initialization of norms
Definition: soplex.h:1191
Rational _rationalFeastol
Definition: soplex.h:1592
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:1302
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:1662
DVectorRational _feasLower
Definition: soplex.h:1663
solve() aborted due to iteration limit.
Definition: spxsolver.h:213
SPxScaler * _scaler
Definition: soplex.h:1629
virtual void changeUpper(const Vector &newUpper, bool scale=false)
mode for synchronizing real and rational LP
Definition: soplex.h:1011
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:935
void _disableSimplifierAndScaler()
disables simplifier and scaler
Definition: soplex.cpp:8503
DataArray< SPxSolver::VarStatus > _storedBasisStatusCols
Definition: soplex.h:1672
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:3558
Real upperReal(int i) const
returns upper bound of column i
Definition: soplex.cpp:1025
Rational & invert()
inversion
Definition: rational.cpp:3585
int refinements
number of refinement steps
Definition: statistics.h:109
variable fixed to identical bounds.
Definition: spxsolver.h:193
DVectorReal _manualObj
Definition: soplex.h:1641
objective sense
Definition: soplex.h:966
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
Prints out status.
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:5775
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:1029
int sign(const Rational &r)
Sign function; returns 1 if r > 0, 0 if r = 0, and -1 if r < 0.
Definition: rational.cpp:4115
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:919
const SPxPricer * pricer() const
return loaded SPxPricer.
Definition: spxsolver.h:1771
user sync of real and rational LP
Definition: soplex.h:1220
LPColBase< Real > LPColReal
Definition: lpcol.h:30
bound flipping ratio test for long steps in the dual simplex
Definition: soplex.h:1207
Rational _rationalPosInfty
Definition: soplex.h:1590
Rational _rationalOpttol
Definition: soplex.h:1593
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:1667
DVectorReal _manualLower
Definition: soplex.h:1637
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:8874
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:7655
DataArray< SPxSolver::VarStatus > _basisStatusCols
Definition: soplex.h:1861
DVectorRational _unboundedLower
Definition: soplex.h:1655
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
returns current SPxStatus.
Definition: spxbasis.h:425
DVectorReal _manualRhs
Definition: soplex.h:1640
DataArray< RangeType > _colTypes
Definition: soplex.h:1697
type of scaler
Definition: soplex.h:999
Real getSolveTime() const
time spent in solves
double Real
Definition: spxdefines.h:218
Rational _rationalPosone
Definition: soplex.h:1879
bool _isRealLPLoaded
Definition: soplex.h:1632
SLUFactorRational _rationalLUSolver
Definition: soplex.h:1651
void _solveRealLPAndRecordStatistics()
call floating-point solver and update statistics on iterations etc.
Definition: soplex.cpp:8557
DVectorBase< R > _primal
Definition: solbase.h:218
#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:1341
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:1676
bool _isConsistent() const
checks consistency
Definition: soplex.cpp:7699
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:7815
bool _hasBasis
Definition: soplex.h:1867
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:1880
DVectorRational _feasObj
Definition: soplex.h:1660
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:941
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:1577
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:1654
type of simplifier
Definition: soplex.h:996
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:1664
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
force iterative refinement
Definition: soplex.h:1243
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:7793
SLUFactor _slufactor
Definition: soplex.h:1603
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:5785
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:1666
SPxLPBase< Rational > SPxLPRational
Definition: spxlp.h:37
SPxOut spxout
Definition: soplex.h:1476
infinity threshold
Definition: soplex.h:1320
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:1620
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
int _beforeLiftRows
Definition: soplex.h:1675
lower and upper bound finite, but different
Definition: soplex.h:1691
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:1639
Timer * preprocessingTime
preprocessing time
Definition: statistics.h:89
bool _storedBasis
Definition: soplex.h:1674
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:1591
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:1694
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:1638
working tolerance for feasibility in floating-point solver during iterative refinement ...
Definition: soplex.h:1332
SPxLPReal * _realLP
Definition: soplex.h:1626
bool _lowerFinite(const RangeType &rangeType) const
checks whether RangeType corresponds to finite lower bound
Definition: soplex.cpp:7806
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
SPxDevexPR _pricerDevex
Definition: soplex.h:1617
void clear()
Remove all indices.
Definition: svectorbase.h:431
DataArray< RangeType > _rowTypes
Definition: soplex.h:1698
DVectorRational _modObj
Definition: soplex.h:1669
apply rational reconstruction after each iterative refinement?
Definition: soplex.h:938
solve() aborted due to detection of cycling.
Definition: spxsolver.h:211
type of pricer
Definition: soplex.h:1005
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
primal unboundedness was detected
Definition: spxsimplifier.h:86
working tolerance for optimality in floating-point solver during iterative refinement ...
Definition: soplex.h:1335
#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:1657
DSVectorRational _primalDualDiff
Definition: soplex.h:1670
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:1656
const VectorRational & upperRational() const
returns upper bound vector
Definition: soplex.cpp:1286
SPxSolver _solver
Definition: soplex.h:1602
column representation Ax - s = 0, lower <= x <= upper, lhs <= s <= rhs
Definition: soplex.h:1073
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:972
const SVectorBase< R > & rowVector(int i) const
Gets row vector of row i.
Definition: spxlpbase.h:206
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:1860
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:916
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:5765
should lifting be used to reduce range of nonzero matrix coefficients?
Definition: soplex.h:910
virtual Status getRedCost(Vector &vector) const
get vector of reduced costs.
Definition: spxsolve.cpp:1951
DataArray< int > _rationalLUSolverBind
Definition: soplex.h:1652
#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:1326
DSVectorRational _tauColVector
Definition: soplex.h:1659
DVectorRational _modLower
Definition: soplex.h:1665
bool _isSolveStopped(bool &stoppedTime, bool &stoppedIter) const
should solving process be stopped?
Definition: soplex.cpp:7727
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
equilibrium scaling on rows and columns
Definition: soplex.h:1141
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:5887
SolRational _solRational
Definition: soplex.h:1864
std::string rationalToString(const Rational &r, const int precision)
convert rational number to string
Definition: rational.cpp:3645
geometric frequency at which to apply rational reconstruction
Definition: soplex.h:1353
Real opttol() const
allowed optimality, i.e., dual feasibility tolerance.
Definition: spxsolver.h:811
bool _hasSolRational
Definition: soplex.h:1869
void _enableSimplifierAndScaler()
enables simplifier and scaler according to current parameters
Definition: soplex.cpp:8445
DVectorRational _modRhs
Definition: soplex.h:1668
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:5815
should LP be transformed to equality form before a rational solve?
Definition: soplex.h:913
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:1344
DataArray< SPxSolver::VarStatus > _storedBasisStatusRows
Definition: soplex.h:1671
SPxLPReal _manualRealLP
Definition: soplex.h:1642
int numColsReal() const
returns number of columns
Definition: soplex.cpp:859
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:1857
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:1881
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:1628
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:1688
LP has a usable Basis (maybe LP is changed).
Definition: spxsolver.h:217
modified Harris ratio test
Definition: soplex.h:1204
dual infeasibility was detected
Definition: spxsimplifier.h:85
virtual Status getSlacks(Vector &vector) const
get vector of slack variables.
Definition: spxsolve.cpp:2048
void _untransformFeasibility(SolRational &sol, bool infeasible)
undoes transformation to feasibility problem
LP has been proven to be primal unbounded.
Definition: spxsolver.h:221
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:3594