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