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