Scippy

SoPlex

Sequential object-oriented simPlex

solvedbds.cpp
Go to the documentation of this file.
1 /* */
2 /* This file is part of the class library */
3 /* SoPlex --- the Sequential object-oriented simPlex. */
4 /* */
5 /* Copyright (C) 1996-2018 Konrad-Zuse-Zentrum */
6 /* fuer Informationstechnik Berlin */
7 /* */
8 /* SoPlex is distributed under the terms of the ZIB Academic Licence. */
9 /* */
10 /* You should have received a copy of the ZIB Academic License */
11 /* along with SoPlex; see the file COPYING. If not email to soplex@zib.de. */
12 /* */
13 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
14 
15 #include <iostream>
16 #include <assert.h>
17 
18 #include "soplex.h"
19 #include "soplex/statistics.h"
20 #include "soplex/sorter.h"
21 
22 //#define NO_TOL
23 #define USE_FEASTOL
24 //#define NO_TRANSFORM
25 //#define PERFORM_COMPPROB_CHECK
26 
27 #define MAX_DEGENCHECK 20 /**< the maximum number of degen checks that are performed before the DECOMP is abandoned */
28 #define DEGENCHECK_OFFSET 50 /**< the number of iteration before the degeneracy check is reperformed */
29 #define SLACKCOEFF 1.0 /**< the coefficient of the slack variable in the incompatible rows. */
30 #define TIMELIMIT_FRAC 0.5 /**< the fraction of the total time limit given to the setup of the reduced problem */
31 
32 /* This file contains the private functions for the Decomposition Based Dual Simplex (DBDS)
33  *
34  * An important note about the implementation of the DBDS is the reliance on the row representation of the basis matrix.
35  * The forming of the reduced and complementary problems is involves identifying rows in the row-form of the basis
36  * matrix that have zero dual multipliers.
37  *
38  * Ideally, this work will be extended such that the DBDS can be executed using the column-form of the basis matrix. */
39 
40 namespace soplex
41 {
42 
43 
44 
45 
46  /// solves LP using the decomposition dual simplex
48  {
49  assert(_solver.rep() == SPxSolver::ROW);
50  assert(_solver.type() == SPxSolver::LEAVE);
51 
52  // flag to indicate that the algorithm must terminate
53  bool stop = false;
54 
55  // setting the initial status of the reduced problem
57 
58  // start timing
60 
61  // remember that last solve was in floating-point
63 
64  // setting the current solving mode.
66 
67  // setting the sense to maximise. This is to make all matrix operations more consistent.
68  // @todo if the objective sense is changed, the output of the current objective value is the negative of the
69  // actual value. This needs to be corrected in future versions.
71  {
73 
76  }
77 
78  // it is necessary to solve the initial problem to find a starting basis
80 
81  // setting the decomposition iteration limit to the parameter setting
83 
84  // variables used in the initialisation phase of the decomposition solve.
85  int numDegenCheck = 0;
86  Real degeneracyLevel = 0;
88  bool initSolveFromScratch = true;
89 
90 
91  /************************/
92  /* Initialisation phase */
93  /************************/
94 
95  // arrays to store the basis status for the rows and columns at the interruption of the original problem solve.
96  DataArray< SPxSolver::VarStatus > basisStatusRows;
97  DataArray< SPxSolver::VarStatus > basisStatusCols;
98  // since the original LP may have been shifted, the dual multiplier will not be correct for the original LP. This
99  // loop will recheck the degeneracy level and compute the proper dual multipliers.
100  do
101  {
102  // solving the instance.
103  _decompSimplifyAndSolve(_solver, _slufactor, initSolveFromScratch, initSolveFromScratch);
104  initSolveFromScratch = false;
105 
106  // checking whether the initialisation must terminate and the original problem is solved using the dual simplex.
108  || _solver.status() == SPxSolver::ABORT_EXDECOMP || numDegenCheck > MAX_DEGENCHECK )
109  {
110  // decomposition is deemed not useful. Solving the original problem using regular SoPlex.
111 
112  // returning the sense to minimise
114  {
116 
119  }
120 
121  // switching off the starting basis check. This is only required to initialise the decomposition simplex.
123 
124  // the basis is not computed correctly is the problem was unfeasible or unbounded.
126  _hasBasis = false;
127 
128 
129  // resolving the problem to update the real lp and solve with the correct objective.
130  // TODO: With some infeasible problem (e.g. refinery) the dual is violated. Setting fromScratch to true
131  // avoids this issue. Need to check what the problem is.
132  // @TODO: Should this be _preprocessAndSolveReal similar to the resolve at the end of the algorithm?
134 
135  // retreiving the original problem statistics prior to destroying it.
137 
138  // storing the solution from the reduced problem
140 
141  // stop timing
143  return;
144  }
147  {
148  // This cleans up the problem is an abort is reached.
149 
150  // at this point, the _decompSimplifyAndSolve does not store the realLP. It stores the _decompLP. As such, it is
151  // important to reinstall the _realLP to the _solver.
152  if( !_isRealLPLoaded )
153  {
156  _decompLP = &_solver;
157  _isRealLPLoaded = true;
158  }
159 
160  // returning the sense to minimise
162  {
164 
167  }
168 
169  // resolving the problem to set up all of the solution vectors. This is required because data from the
170  // initialisation solve may remain at termination causing an infeasible solution to be reported.
172 
173  // storing the solution from the reduced problem
175 
176  // stop timing
178  return;
179  }
180 
181  // checking the degeneracy level
183  degeneracyLevel = _solver.getDegeneracyLevel(_decompFeasVector);
184 
186 
187  numDegenCheck++;
188  } while( (degeneracyLevel > 0.9 || degeneracyLevel < 0.1) || !checkBasisDualFeasibility(_decompFeasVector) );
189 
190  // decomposition simplex will commence, so the start basis does not need to be found
192 
193  // if the original problem has a basis, this will be stored
194  if( _hasBasis )
195  {
196  basisStatusRows.reSize(numRowsReal());
197  basisStatusCols.reSize(numColsReal());
198  _solver.getBasis(basisStatusRows.get_ptr(), basisStatusCols.get_ptr(), basisStatusRows.size(),
199  basisStatusCols.size());
200  }
201 
202  // updating the algorithm iterations statistic
204 
205  // setting the statistic information
206  numDecompIter = 0;
208  numCompProbIter = 0;
209 
210  // setting the display information
211  _decompDisplayLine = 0;
212 
213  /************************/
214  /* Decomposition phase */
215  /************************/
216 
217  MSG_INFO1( spxout,
218  spxout << "======== Degeneracy Detected ========" << std::endl
219  << std::endl
220  << "======== Commencing decomposition solve ========" << std::endl
221  );
222 
223  //spxout.setVerbosity( SPxOut::DEBUG );
224  MSG_INFO2(spxout, spxout << "Creating the Reduced and Complementary problems." << std::endl );
225 
226  // setting the verbosity level
227  const SPxOut::Verbosity orig_verbosity = spxout.getVerbosity();
229  if( decomp_verbosity < orig_verbosity )
230  spxout.setVerbosity( decomp_verbosity );
231 
232  // creating copies of the original problem that will be manipulated to form the reduced and complementary
233  // problems.
235 
236  // creating the initial reduced problem from the basis information
238 
239  // setting flags for the decomposition solve
240  _hasBasis = false;
241  bool hasRedBasis = false;
242  bool redProbError = false;
243  bool noRedprobIter = false;
244  bool explicitviol = boolParam(SoPlex::EXPLICITVIOL);
245  int algIterCount = 0;
246 
247 
248  // a stop will be triggered if the reduced problem exceeded a specified fraction of the time limit
249  if( stop )
250  {
251  MSG_INFO1( spxout, spxout << "==== Error constructing the reduced problem ====" << std::endl );
252  redProbError = true;
254  }
255 
256  // the main solving loop of the decomposition simplex.
257  // This loop solves the Reduced problem, and if the problem is feasible, the complementary problem is solved.
258  while( !stop )
259  {
260  int previter = _statistics->iterations;
261 
262  // setting the current solving mode.
264 
265  // solve the reduced problem
266 
268  spxout << std::endl
269  << "=========================" << std::endl
270  << "Solving: Reduced Problem." << std::endl
271  << "=========================" << std::endl
272  << std::endl );
273 
274  _hasBasis = hasRedBasis;
275  // solving the reduced problem
276  _decompSimplifyAndSolve(_solver, _slufactor, !algIterCount, !algIterCount);
277 
278  stop = decompTerminate(realParam(SoPlex::TIMELIMIT)); // checking whether the algorithm should terminate
279 
280  // updating the algorithm iterations statistics
283 
284  assert(_isRealLPLoaded);
285  hasRedBasis = _hasBasis;
286  _hasBasis = false;
287 
288  // checking the status of the reduced problem
289  // It is expected that infeasibility and unboundedness will be found in the initialisation solve. If this is
290  // not the case and the reduced problem is infeasible or unbounded the decomposition simplex will terminate.
291  // If the decomposition simplex terminates, then the original problem will be solved using the stored basis.
293  {
295  MSG_INFO2(spxout, spxout << "Unbounded reduced problem." << std::endl );
297  MSG_INFO2(spxout, spxout << "Infeasible reduced problem." << std::endl );
298 
299  MSG_INFO2(spxout, spxout << "Reduced problem status: " << _solver.status() << std::endl );
300 
301  redProbError = true;
302  break;
303  }
304 
305  // as a final check, if no iterations were performed with the reduced problem, then the algorithm terminates
306  if( _statistics->iterations == previter )
307  {
309  spxout << "WIMDSM02: reduced problem performed zero iterations. Terminating." << std::endl; );
310 
311  noRedprobIter = true;
312  stop = true;
313  break;
314  }
315 
316  // printing display line
317  printDecompDisplayLine(_solver, orig_verbosity, !algIterCount, !algIterCount);
318 
319  // get the dual solutions from the reduced problem
320  DVector reducedLPDualVector(_solver.nRows());
321  DVector reducedLPRedcostVector(_solver.nCols());
322  _solver.getDual(reducedLPDualVector);
323  _solver.getRedCost(reducedLPRedcostVector);
324 
325 
326  // Using the solution to the reduced problem:
327  // In the first iteration of the algorithm create the complementary problem.
328  // In the subsequent iterations of the algorithm update the complementary problem.
329  if( algIterCount == 0 )
331  else
332  {
335  else
337  }
338 
339  // setting the current solving mode.
341 
342  // solve the complementary problem
344  spxout << std::endl
345  << "=========================" << std::endl
346  << "Solving: Complementary Problem." << std::endl
347  << "=========================" << std::endl
348  << std::endl );
349 
350  if( !explicitviol )
351  {
352  //_compSolver.writeFile("comp.lp");
353 
355 
356  MSG_INFO2(spxout, spxout << "Iteration " << algIterCount
357  << "Objective Value: " << std::setprecision(10) << _compSolver.objValue()
358  << std::endl );
359  }
360 
361 
362  assert(_isRealLPLoaded);
363 
364 
365  // Check whether the complementary problem is solved with a non-negative objective function, is infeasible or
366  // unbounded. If true, then stop the algorithm.
367  if( !explicitviol && (GE(_compSolver.objValue(), 0.0, 1e-20)
370  {
374  MSG_INFO2(spxout, spxout << "Unbounded complementary problem." << std::endl );
376  MSG_INFO2(spxout, spxout << "Infeasible complementary problem." << std::endl );
377 
379  explicitviol = true;
380 
381  stop = true;
382  }
383 
384  if( !stop && !explicitviol )
385  {
386  // get the primal solutions from the complementary problem
387  DVector compLPPrimalVector(_compSolver.nCols());
388  _compSolver.getPrimal(compLPPrimalVector);
389 
390  // get the dual solutions from the complementary problem
391  DVector compLPDualVector(_compSolver.nRows());
392  _compSolver.getDual(compLPDualVector);
393 
394  // updating the reduced problem
395  _updateDecompReducedProblem(_compSolver.objValue(), reducedLPDualVector, reducedLPRedcostVector,
396  compLPPrimalVector, compLPDualVector);
397  }
398  // if the complementary problem is infeasible or unbounded, it is possible that the algorithm can continue.
399  // a check of the original problem is required to determine whether there are any violations.
402  || explicitviol )
403  {
404  // getting the primal vector from the reduced problem
405  DVector reducedLPPrimalVector(_solver.nCols());
406  _solver.getPrimal(reducedLPPrimalVector);
407 
408  // checking the optimality of the reduced problem solution with the original problem
409  _checkOriginalProblemOptimality(reducedLPPrimalVector, true);
410 
411  // if there are any violated rows or bounds then stop is reset and the algorithm continues.
412  if( _nDecompViolBounds > 0 || _nDecompViolRows > 0 )
413  stop = false;
414  if( _nDecompViolBounds == 0 && _nDecompViolRows == 0 )
415  stop = true;
416 
417  // updating the reduced problem with the original problem violated rows
418  if( !stop )
420  }
421 
422 
423  // =============================================================================
424  // Code check completed up to here
425  // =============================================================================
426 
427  numDecompIter++;
428  algIterCount++;
429  }
430 
431  // if there is an error in solving the reduced problem, i.e. infeasible or unbounded, then we leave the
432  // decomposition solve and resolve the original. Infeasibility should be dealt with in the original problem.
433  if( !redProbError )
434  {
435 #ifndef NDEBUG
436  // computing the solution for the original variables
437  DVector reducedLPPrimalVector(_solver.nCols());
438  _solver.getPrimal(reducedLPPrimalVector);
439 
440  // checking the optimality of the reduced problem solution with the original problem
441  _checkOriginalProblemOptimality(reducedLPPrimalVector, true);
442 
443  // resetting the verbosity level
444  spxout.setVerbosity( orig_verbosity );
445 #endif
446 
447  // This is an additional check to ensure that the complementary problem is solving correctly.
448  // This is only used for debugging
449 #ifdef PERFORM_COMPPROB_CHECK
450  // solving the complementary problem with the original objective function
453  else
455 
456  // for clean up
457  // the real lp has to be set to not loaded.
458  //_isRealLPLoaded = false;
459  // the basis has to be set to false
460  _hasBasis = false;
461 
463  {
464  SPxLPReal compDualLP;
465  _compSolver.buildDualProblem(compDualLP, _decompPrimalRowIDs.get_ptr(), _decompPrimalColIDs.get_ptr(),
467 
468  _compSolver.loadLP(compDualLP);
469  }
470 
472 
473  _solReal._hasPrimal = true;
474  _hasSolReal = true;
475  // get the primal solutions from the reduced problem
476  DVector testPrimalVector(_compSolver.nCols());
477  _compSolver.getPrimal(testPrimalVector);
479  _solReal._primal = testPrimalVector;
480 
481  Real maxviol = 0;
482  Real sumviol = 0;
483 
484  // Since the original objective value has now been installed in the complementary problem, the solution will be
485  // a solution to the original problem.
486  // checking the bound violation of the solution from complementary problem
487  if( getDecompBoundViolation(maxviol, sumviol) )
488  MSG_INFO1(spxout, spxout << "Bound violation - "
489  << "Max: "<< std::setprecision(20) << maxviol << " "
490  << "Sum: "<< sumviol << std::endl );
491 
492  // checking the row violation of the solution from the complementary problem
493  if( getDecompRowViolation(maxviol, sumviol) )
494  MSG_INFO1(spxout, spxout << "Row violation - "
495  << "Max: "<< std::setprecision(21) << maxviol << " "
496  << "Sum: "<< sumviol << std::endl );
497 
498  MSG_INFO1(spxout, spxout << "Objective Value: " << _compSolver.objValue() << std::endl );
499 #endif
500  }
501 
502  // resetting the verbosity level
503  spxout.setVerbosity( orig_verbosity );
504 
505  MSG_INFO1( spxout,
506  spxout << "======== Decomposition solve completed ========" << std::endl
507  << std::endl
508  << "======== Resolving original problem ========" << std::endl
509  );
510 
511  // if there is a reduced problem error in the first iteration the complementary problme has not been
512  // set up. In this case no memory has been allocated for _decompCompProbColIDsIdx and _fixedOrigVars.
513  if( (!redProbError && !noRedprobIter) || algIterCount > 0 )
514  {
517  }
522 
523  // retreiving the original problem statistics prior to destroying it.
525 
526  // setting the reduced problem statistics
529 
530 
531  // printing display line for resolve of problem
532  _solver.printDisplayLine(false, true);
533 
534  // if there is an error solving the reduced problem the LP must be solved from scratch
535  if (redProbError)
536  {
537  MSG_INFO1( spxout, spxout << "=== Reduced problem error - Solving original ===" << std::endl );
538 
539  // the solver is loaded with the realLP to solve the problem from scratch
541  spx_free(_realLP);
542  _realLP = &_solver;
543  _isRealLPLoaded = true;
544 
545  // returning the sense to minimise
547  {
549 
552 
553  // Need to add commands to multiply the objective solution values by -1
554  }
555 
556  //_solver.setBasis(basisStatusRows.get_const_ptr(), basisStatusCols.get_const_ptr());
558  }
559  else
560  {
561  // resolving the problem to update the real lp and solve with the correct objective.
562  // the realLP is updated with the current solver. This is to resolve the problem to get the correct solution
563  // values
564  _realLP->~SPxLPReal();
565  spx_free(_realLP);
566  _realLP = &_solver;
567  _isRealLPLoaded = true;
568 
569  // returning the sense to minimise
571  {
573 
576 
577  // Need to add commands to multiply the objective solution values by -1
578  }
579 
581  }
582 
583  // stop timing
585  }
586 
587 
588 
589  /// creating copies of the original problem that will be manipulated to form the reduced and complementary problems
591  {
592  // the reduced problem is formed from the current problem
593  // So, we copy the _solver to the _realLP and work on the _solver
594  // NOTE: there is no need to preprocess because we always have a starting basis.
595  _realLP = 0;
597  _realLP = new (_realLP) SPxLPReal(_solver);
598 
599  // allocating memory for the reduced problem rows and cols flag array
604 
605  // the complementary problem is formulated with all incompatible rows and those from the reduced problem that have
606  // a positive reduced cost.
610 
611  // allocating memory for the violated bounds and rows arrays
616  _nDecompViolBounds = 0;
617  _nDecompViolRows = 0;
618  }
619 
620 
621 
622  /// forms the reduced problem
624  {
625  MSG_INFO2( spxout, spxout << "Forming the Reduced problem" << std::endl );
626  int* nonposind = 0;
627  int* compatind = 0;
628  int* rowsforremoval = 0;
629  int* colsforremoval = 0;
630  int nnonposind = 0;
631  int ncompatind = 0;
632 
633  assert(_solver.nCols() == numColsReal());
634  assert(_solver.nRows() == numRowsReal());
635 
636  // capturing the basis used for the transformation
638 
639  // setting row counter to zero
640  numIncludedRows = 0;
641 
642  // the _decompLP is used as a helper LP object. This is used so that _realLP can still hold the original problem.
643  _decompLP = 0;
646 
647  // retreiving the basis information
651 
652  // get the indices of the rows with positive dual multipliers and columns with positive reduced costs.
653  spx_alloc(nonposind, numColsReal());
654  spx_alloc(colsforremoval, numColsReal());
655  if( !stop )
656  _getZeroDualMultiplierIndices(_decompFeasVector, nonposind, colsforremoval, &nnonposind, stop);
657 
658  // get the compatible columns from the constraint matrix w.r.t the current basis matrix
659  MSG_INFO2(spxout, spxout << "Computing the compatible columns" << std::endl
660  << "Solving time: " << solveTime() << std::endl );
661 
662  spx_alloc(compatind, _solver.nRows());
663  spx_alloc(rowsforremoval, _solver.nRows());
664  if( !stop )
665  _getCompatibleColumns(_decompFeasVector, nonposind, compatind, rowsforremoval, colsforremoval, nnonposind,
666  &ncompatind, true, stop);
667 
668  int* compatboundcons = 0;
669  int ncompatboundcons = 0;
670  spx_alloc(compatboundcons, numColsReal());
671 
672  LPRowSet boundcons;
673 
674  // identifying the compatible bound constraints
675  if( !stop )
676  _getCompatibleBoundCons(boundcons, compatboundcons, nonposind, &ncompatboundcons, nnonposind, stop);
677 
678  // delete rows and columns from the LP to form the reduced problem
679  MSG_INFO2(spxout, spxout << "Deleting rows and columns to form the reduced problem" << std::endl
680  << "Solving time: " << solveTime() << std::endl );
681 
682  // allocating memory to add bound constraints
683  SPxRowId* addedrowids = 0;
684  spx_alloc(addedrowids, ncompatboundcons);
685 
686  // computing the reduced problem obj coefficient vector and updating the problem
687  if( !stop )
688  {
690 
692 
693  // the colsforremoval are the columns with a zero reduced cost.
694  // the rowsforremoval are the rows identified as incompatible.
695  _solver.removeRows(rowsforremoval);
696  // adding the rows for the compatible bound constraints
697  _solver.addRows(addedrowids, boundcons);
698 
699  for( int i = 0; i < ncompatboundcons; i++ )
700  _decompReducedProbColRowIDs[compatboundcons[i]] = addedrowids[i];
701  }
702 
703 
704  // freeing allocated memory
705  spx_free(addedrowids);
706  spx_free(compatboundcons);
707  spx_free(rowsforremoval);
708  spx_free(compatind);
709  spx_free(colsforremoval);
710  spx_free(nonposind);
711 
712  _decompLP->~SPxLPReal();
714  }
715 
716 
717 
718  /// forms the complementary problem
720  {
721  // delete rows and columns from the LP to form the reduced problem
722  _nElimPrimalRows = 0;
723  _decompElimPrimalRowIDs.reSize(_realLP->nRows()); // the number of eliminated rows is less than the number of rows
724  // in the reduced problem
727 
728  _fixedOrigVars = 0;
729  spx_alloc(_fixedOrigVars, _realLP->nCols());
730  for (int i = 0; i < _realLP->nCols(); i++)
731  {
732  _decompCompProbColIDsIdx[i] = -1;
733  _fixedOrigVars[i] = -2; // this must be set to a value differet from -1, 0, 1 to ensure the
734  // _updateComplementaryFixedPrimalVars function updates all variables in the problem.
735  }
736 
737  int naddedrows = 0;
738  DataArray< SPxRowId > rangedRowIds(numRowsReal());
739  _deleteAndUpdateRowsComplementaryProblem(rangedRowIds.get_ptr(), naddedrows);
740 
741  if( boolParam(SoPlex::USECOMPDUAL) ) // if we use the dual formulation of the complementary problem, we must
742  // perform the transformation
743  {
744  // initialising the arrays to store the row id's from the primal and the col id's from the dual
747  _decompDualRowIDs.reSize(3*_compSolver.nCols());
748  _decompDualColIDs.reSize(3*_compSolver.nRows());
749  _nPrimalRows = 0;
750  _nPrimalCols = 0;
751  _nDualRows = 0;
752  _nDualCols = 0;
753 
754  // convert complementary problem to dual problem
755  SPxLPReal compDualLP;
756  _compSolver.buildDualProblem(compDualLP, _decompPrimalRowIDs.get_ptr(), _decompPrimalColIDs.get_ptr(),
758  compDualLP.setOutstream(spxout);
759 
760  // setting the id index array for the complementary problem
761  for( int i = 0; i < _nPrimalRows; i++ )
762  {
763  // a primal row may result in two dual columns. So the index array points to the first of the indicies for the
764  // primal row.
765  if( i + 1 < _nPrimalRows &&
767  i++;
768  }
769 
770  for( int i = 0; i < _nPrimalCols; i++ )
771  {
772  if( _decompPrimalColIDs[i].getIdx() != _compSlackColId.getIdx() )
774  }
775 
776  // retrieving the dual row id for the complementary slack column
777  // there should be a one to one relationship between the number of primal columns and the number of dual rows.
778  // hence, it should be possible to equate the dual row id to the related primal column.
779  assert(_nPrimalCols == _nDualRows);
780  assert(_compSolver.nCols() == compDualLP.nRows());
782 
783  _compSolver.loadLP(compDualLP);
784 
785  _compSolver.init();
786 
788 
789  // initalising the array for the dual columns representing the fixed variables in the complementary problem.
791  _decompVarBoundDualIDs.reSize(2*_realLP->nCols());
792 
793 
794  // updating the constraints for the complementary problem
796  }
797  else // when using the primal of the complementary problem, no transformation of the problem is required.
798  {
799  // initialising the arrays to store the row and column id's from the original problem the col id's from the dual
800  // if a row or column is not included in the complementary problem, the ID is set to INVALID in the
801  // _decompPrimalRowIDs or _decompPrimalColIDs respectively.
806  _nPrimalRows = 0;
807  _nPrimalCols = 0;
808 
809  // at this point in time the complementary problem contains all rows and columns from the original problem
810  int addedrangedrows = 0;
811  _nCompPrimalRows = 0;
812  _nCompPrimalCols = 0;
813  for( int i = 0; i < _realLP->nRows(); i++ )
814  {
815  assert(_nCompPrimalRows < _compSolver.nRows());
818  _nPrimalRows++;
820 
822  {
823  assert(EQ(_compSolver.lhs(rangedRowIds[addedrangedrows]), _realLP->lhs(i)));
824  assert(LE(_compSolver.rhs(rangedRowIds[addedrangedrows]), infinity));
825  assert(LE(_compSolver.lhs(i), -infinity));
826  assert(LT(_compSolver.rhs(i), infinity));
827 
828  _decompPrimalRowIDs[_nPrimalRows] = _realLP->rId(i);
829  _decompCompPrimalRowIDs[_nCompPrimalRows] = rangedRowIds[addedrangedrows];
830  _nPrimalRows++;
832  addedrangedrows++;
833  }
834  }
835 
836  for( int i = 0; i < _compSolver.nCols(); i++ )
837  {
838 
840  {
843  _nPrimalCols++;
845 
847  }
848  }
849 
850  // updating the constraints for the complementary problem
852  }
853  }
854 
855 
856 
857  /// simplifies the problem and solves
858  void SoPlex::_decompSimplifyAndSolve(SPxSolver& solver, SLUFactor& sluFactor, bool fromScratch, bool applyPreprocessing)
859  {
862 
865 
867 
868  /* delete starting basis if solving from scratch */
869  if ( fromScratch )
870  {
871  try
872  {
873  solver.reLoad();
874  }
875  catch( const SPxException& E )
876  {
877  MSG_ERROR( spxout << "Caught exception <" << E.what() << "> during simplify and solve.\n" );
878  }
879  }
880  //assert(!fromScratch || solver.status() == SPxSolver::NO_PROBLEM);
881 
882  if( applyPreprocessing )
883  {
886  }
887  else
888  {
890  ///@todo implement for both objective senses
893  }
894 
895  /* store original lp */
896  applyPreprocessing = (_scaler != NULL || _simplifier != NULL);
897 
898  // @TODO The use of _isRealLPLoaded is not correct. An additional parameter would be useful for this algorithm.
899  // Maybe a parameter _isDecompLPLoaded?
900  if( _isRealLPLoaded )
901  {
902  //assert(_decompLP == &solver); // there should be an assert here, but I don't know what to use.
903 
904  // preprocessing is always applied to the LP in the solver; hence we have to create a copy of the original LP
905  // if preprocessing is turned on
906  if( applyPreprocessing )
907  {
908  _decompLP = 0;
910  _decompLP = new (_decompLP) SPxLPReal(solver);
911  _isRealLPLoaded = false;
912  }
913  else
914  _decompLP = &solver;
915  }
916  else
917  {
918  assert(_decompLP != &solver);
919 
920  // ensure that the solver has the original problem
921  solver.loadLP(*_decompLP);
922 
923  // load basis if available
924  if( _hasBasis )
925  {
926  assert(_basisStatusRows.size() == solver.nRows());
927  assert(_basisStatusCols.size() == solver.nCols());
928 
929  ///@todo this should not fail even if the basis is invalid (wrong dimension or wrong number of basic
930  /// entries); fix either in SPxSolver or in SPxBasis
932  }
933 
934  // if there is no preprocessing, then the original and the transformed problem are identical and it is more
935  // memory-efficient to keep only the problem in the solver
936  if( !applyPreprocessing )
937  {
938  _decompLP->~SPxLPReal();
940  _decompLP = &solver;
941  _isRealLPLoaded = true;
942  }
943  else
944  {
945  _decompLP = 0;
947  _decompLP = new (_decompLP) SPxLPReal(solver);
948  }
949  }
950 
951  // assert that we have two problems if and only if we apply preprocessing
952  assert(_decompLP == &solver || applyPreprocessing);
953  assert(_decompLP != &solver || !applyPreprocessing);
954 
955  // apply problem simplification
956  if( _simplifier != 0 )
957  {
961  }
962 
964 
965  // run the simplex method if problem has not been solved by the simplifier
966  if( result == SPxSimplifier::OKAY )
967  {
968  if( _scaler != 0 )
969  _scaler->scale(solver);
970 
971  bool _hadBasis = _hasBasis;
972 
974  try
975  {
976  solver.solve();
977  }
978  catch( const SPxException& E )
979  {
980  MSG_ERROR( std::cerr << "Caught exception <" << E.what() << "> while solving real LP.\n" );
982  }
983  catch( ... )
984  {
985  MSG_ERROR( std::cerr << "Caught unknown exception while solving real LP.\n" );
987  }
989 
990  // record statistics
991  // only record the main statistics for the original problem and reduced problem.
992  // the complementary problem is a pivoting rule, so these will be held in other statistics.
993  // statistics on the number of iterations for each problem is stored in individual variables.
995  {
996  _statistics->iterations += solver.iterations();
998  _statistics->iterationsFromBasis += _hadBasis ? solver.iterations() : 0;
999  _statistics->boundflips += solver.boundFlips();
1001  _statistics->luSolveTimeReal += sluFactor.getSolveTime();
1003  _statistics->luSolvesReal += sluFactor.getSolveCount();
1004  sluFactor.resetCounters();
1005 
1008 
1011 
1012  if( _currentProb == DECOMP_ORIG )
1013  _statistics->iterationsInit += solver.iterations();
1014  else
1016  }
1017 
1018  if( _currentProb == DECOMP_COMP )
1020 
1021  }
1022 
1023  // check the result and run again without preprocessing if necessary
1024  _evaluateSolutionDecomp(solver, sluFactor, result);
1025  }
1026 
1027 
1028 
1029  /// loads original problem into solver and solves again after it has been solved to optimality with preprocessing
1031  {
1032  assert(_simplifier != 0 || _scaler != 0);
1033  assert(result == SPxSimplifier::VANISHED
1034  || (result == SPxSimplifier::OKAY
1035  && (solver.status() == SPxSolver::OPTIMAL
1036  || solver.status() == SPxSolver::ABORT_DECOMP
1037  || solver.status() == SPxSolver::ABORT_EXDECOMP )));
1038 
1039  // if simplifier is active and LP is solved in presolving or to optimality, then we unsimplify to get the basis
1040  if( _simplifier != 0 )
1041  {
1042  assert(!_simplifier->isUnsimplified());
1043 
1044  bool vanished = result == SPxSimplifier::VANISHED;
1045 
1046  // get solution vectors for transformed problem
1047  DVectorReal primal(vanished ? 0 : solver.nCols());
1048  DVectorReal slacks(vanished ? 0 : solver.nRows());
1049  DVectorReal dual(vanished ? 0 : solver.nRows());
1050  DVectorReal redCost(vanished ? 0 : solver.nCols());
1051 
1052  assert(!_isRealLPLoaded);
1055  assert(vanished || _basisStatusRows.size() >= solver.nRows());
1056  assert(vanished || _basisStatusCols.size() >= solver.nCols());
1057 
1058  if( !vanished )
1059  {
1060  assert(solver.status() == SPxSolver::OPTIMAL || solver.status() == SPxSolver::ABORT_DECOMP || solver.status() == SPxSolver::ABORT_EXDECOMP);
1061 
1062  solver.getPrimal(primal);
1063  solver.getSlacks(slacks);
1064  solver.getDual(dual);
1065  solver.getRedCost(redCost);
1066 
1067  // unscale vectors
1068  if( _scaler && solver.isScaled() )
1069  {
1070  _scaler->unscalePrimal(solver, primal);
1071  _scaler->unscaleSlacks(solver, slacks);
1072  _scaler->unscaleDual(solver, dual);
1073  _scaler->unscaleRedCost(solver, redCost);
1074  }
1075 
1076  // get basis of transformed problem
1078  }
1079 
1080  try
1081  {
1082  _simplifier->unsimplify(primal, dual, slacks, redCost, _basisStatusRows.get_ptr(), _basisStatusCols.get_ptr(), solver.status() == SPxSolver::OPTIMAL);
1084  _hasBasis = true;
1085  }
1086  catch( const SPxException& E )
1087  {
1088  MSG_ERROR( spxout << "Caught exception <" << E.what() << "> during unsimplification. Resolving without simplifier and scaler.\n" );
1089  }
1090  catch( ... )
1091  {
1092  MSG_ERROR( spxout << "Caught unknown exception during unsimplification. Resolving without simplifier and scaler.\n" );
1094  }
1095  }
1096  // if the original problem is not in the solver because of scaling, we also need to store the basis
1097  else if( _scaler != 0 )
1098  {
1101  assert(_basisStatusRows.size() == solver.nRows());
1102  assert(_basisStatusCols.size() == solver.nCols());
1103 
1105  _hasBasis = true;
1106  }
1107 
1108  // resolve the original problem
1109  _decompSimplifyAndSolve(solver, sluFactor, false, false);
1110  return;
1111  }
1112 
1113 
1114  /// updates the reduced problem with additional rows using the solution to the complementary problem
1115  void SoPlex::_updateDecompReducedProblem(Real objValue, DVector dualVector, DVector redcostVector,
1116  DVector compPrimalVector, DVector compDualVector)
1117  {
1118  Real feastol = realParam(SoPlex::FEASTOL);
1119 
1120  Real maxDualRatio = infinity;
1121 
1122  bool usecompdual = boolParam(SoPlex::USECOMPDUAL);
1123 
1124  for( int i = 0; i < _nPrimalRows; i++ )
1125  {
1126  Real reducedProbDual = 0;
1127  Real compProbPrimal = 0;
1128  Real dualRatio = 0;
1129  int rownumber = _realLP->number(SPxRowId(_decompPrimalRowIDs[i]));
1130  if( _decompReducedProbRows[rownumber] && _solver.isBasic(_decompReducedProbRowIDs[rownumber]) )
1131  {
1132  int solverRowNum = _solver.number(_decompReducedProbRowIDs[rownumber]);
1133 
1134  // retreiving the reduced problem dual solutions and the complementary problem primal solutions
1135  reducedProbDual = dualVector[solverRowNum]; // this is y
1136  if( usecompdual )
1137  compProbPrimal = compPrimalVector[_compSolver.number(SPxColId(_decompDualColIDs[i]))]; // this is u
1138  else
1139  compProbPrimal = compDualVector[_compSolver.number(SPxRowId(_decompCompPrimalRowIDs[i]))];
1140 
1141  // the variable in the basis is degenerate.
1142  if( EQ(reducedProbDual, 0.0, feastol) )
1143  {
1145  spxout << "WIMDSM01: reduced problem dual value is very close to zero." << std::endl; );
1146  continue;
1147  }
1148 
1149  // the translation of the complementary primal problem to the dual some rows resulted in two columns.
1150  if( usecompdual && i < _nPrimalRows - 1 &&
1152  {
1153  i++;
1154  compProbPrimal += compPrimalVector[_compSolver.number(SPxColId(_decompDualColIDs[i]))]; // this is u
1155  }
1156 
1157 
1158 
1159  // updating the ratio
1160  SoPlex::DualSign varSign = getExpectedDualVariableSign(solverRowNum);
1161  if( varSign == SoPlex::IS_FREE || (varSign == SoPlex::IS_POS && LE(compProbPrimal, 0, feastol)) ||
1162  (varSign == SoPlex::IS_NEG && GE(compProbPrimal, 0, feastol)) )
1163  {
1164  dualRatio = infinity;
1165  }
1166  else
1167  {
1168  dualRatio = reducedProbDual/compProbPrimal;
1169  }
1170 
1171  if( LT(dualRatio, maxDualRatio, feastol) )
1172  maxDualRatio = dualRatio;
1173  }
1174  else
1175  {
1176  if( usecompdual )
1177  compProbPrimal = compPrimalVector[_compSolver.number(SPxColId(_decompDualColIDs[i]))]; // this is v
1178  else
1179  compProbPrimal = compDualVector[_compSolver.number(SPxRowId(_decompCompPrimalRowIDs[i]))];
1180  }
1181 
1182  }
1183 
1184  // setting the maxDualRatio to a maximum of 1
1185  if( maxDualRatio > 1.0 )
1186  maxDualRatio = 1.0;
1187 
1188  DVector compProbRedcost(_compSolver.nCols()); // the reduced costs of the complementary problem
1189 
1190  // Retrieving the reduced costs for each original problem row.
1191  _compSolver.getRedCost(compProbRedcost);
1192 
1193  LPRowSet updaterows;
1194 
1195 
1196  // Identifying the violated rows
1197  DataArray<RowViolation> violatedrows;
1198  int nviolatedrows = 0;
1199  int* newrowidx = 0;
1200  int nnewrowidx = 0;
1201  spx_alloc(newrowidx, _nPrimalRows);
1202 
1203  violatedrows.reSize(_nPrimalRows);
1204 
1205  bool ratioTest = true;
1206  //ratioTest = false;
1207  for( int i = 0; i < _nPrimalRows; i++ )
1208  {
1209  LPRowReal origlprow;
1210  DSVectorBase<Real> rowtoaddVec(_realLP->nCols());
1211  Real compProbPrimal = 0;
1212  Real compRowRedcost = 0;
1213  int rownumber = _realLP->number(SPxRowId(_decompPrimalRowIDs[i]));
1215  {
1216  int compRowNumber;
1217  if( usecompdual )
1218  {
1219  compRowNumber = _compSolver.number(_decompDualColIDs[i]);
1220  // retreiving the complementary problem primal solutions
1221  compProbPrimal = compPrimalVector[compRowNumber]; // this is v
1222  compRowRedcost = compProbRedcost[compRowNumber];
1223  }
1224  else
1225  {
1226  compRowNumber = _compSolver.number(_decompCompPrimalRowIDs[i]);
1227  // retreiving the complementary problem primal solutions
1228  compProbPrimal = compDualVector[compRowNumber]; // this is v
1229  }
1230 
1231  // the translation of the complementary primal problem to the dual some rows resulted in two columns.
1232  if( usecompdual && i < _nPrimalRows - 1 &&
1234  {
1235  i++;
1236  compRowNumber = _compSolver.number(SPxColId(_decompDualColIDs[i]));
1237  compProbPrimal += compPrimalVector[compRowNumber]; // this is v
1238  compRowRedcost += compProbRedcost[compRowNumber];
1239  }
1240 
1241  SoPlex::DualSign varSign = getOrigProbDualVariableSign(rownumber);
1242 
1243  // add row to the reduced problem if the computed dual is of the correct sign for a feasible dual solution
1244  if( ratioTest && ((varSign == SoPlex::IS_FREE && !isZero(compProbPrimal, feastol)) ||
1245  (varSign == SoPlex::IS_POS && GT(compProbPrimal*maxDualRatio, 0, feastol)) ||
1246  (varSign == SoPlex::IS_NEG && LT(compProbPrimal*maxDualRatio, 0, feastol))) )
1247  {
1248  //this set of statements are required to add rows to the reduced problem. This will add a row for every
1249  //violated constraint. I only want to add a row for the most violated constraint. That is why the row
1250  //adding functionality is put outside the for loop.
1251  if( !_decompReducedProbRows[rownumber] )
1252  {
1253  numIncludedRows++;
1254  assert(numIncludedRows <= _realLP->nRows());
1255  }
1256  violatedrows[nviolatedrows].idx = rownumber;
1257  violatedrows[nviolatedrows].violation = spxAbs(compProbPrimal*maxDualRatio);
1258  nviolatedrows++;
1259  }
1260  }
1261  }
1262 
1263 
1264  // sorting the violated rows by the absolute violation.
1265  // Only a predefined number of rows will be added to the reduced problem
1266  RowViolationCompare compare;
1267  compare.entry = violatedrows.get_const_ptr();
1268 
1269  // if no rows are identified by the pricing rule, we add rows based upon the constraint violations
1270  if( !ratioTest || nviolatedrows == 0 )
1271  {
1272  _findViolatedRows(objValue, violatedrows, nviolatedrows);
1273  }
1274 
1275  int sorted = 0;
1276  int sortsize = MINIMUM(intParam(SoPlex::DECOMP_MAXADDEDROWS), nviolatedrows);
1277 
1278  // only sorting if the sort size is less than the number of violated rows.
1279  if( sortsize > 0 && sortsize < nviolatedrows )
1280  sorted = SPxQuicksortPart(violatedrows.get_ptr(), compare, sorted + 1, nviolatedrows, sortsize);
1281 
1282  // adding the violated rows.
1283  for( int i = 0; i < sortsize; i++ )
1284  {
1285  updaterows.add(_transformedRows.lhs(violatedrows[i].idx), _transformedRows.rowVector(violatedrows[i].idx),
1286  _transformedRows.rhs(violatedrows[i].idx));
1287 
1288  _decompReducedProbRows[violatedrows[i].idx] = true;
1289  newrowidx[nnewrowidx] = violatedrows[i].idx;
1290  nnewrowidx++;
1291  }
1292 
1293  SPxRowId* addedrowids = 0;
1294  spx_alloc(addedrowids, nnewrowidx);
1295  _solver.addRows(addedrowids, updaterows);
1296 
1297  for( int i = 0; i < nnewrowidx; i++ )
1298  _decompReducedProbRowIDs[newrowidx[i]] = addedrowids[i];
1299 
1300  // freeing allocated memory
1301  spx_free(addedrowids);
1302  spx_free(newrowidx);
1303  }
1304 
1305 
1306 
1307  /// update the reduced problem with additional columns and rows based upon the violated original bounds and rows
1308  // TODO: Allow for the case that no rows are added. This should terminate the algorithm.
1309  // TODO: Check to make sure that only rows added to the problem do not currently exist in the reduced problem.
1311  {
1312 #ifdef NO_TOL
1313  Real feastol = 0.0;
1314 #else
1315 #ifdef USE_FEASTOL
1316  Real feastol = realParam(SoPlex::FEASTOL);
1317 #else
1318  Real feastol = realParam(SoPlex::EPSILON_ZERO);
1319 #endif
1320 #endif
1321  LPRowSet updaterows;
1322 
1323  int* newrowidx = 0;
1324  int nnewrowidx = 0;
1325  spx_alloc(newrowidx, _nPrimalRows);
1326 
1327  int rowNumber;
1328  int bestrow = -1;
1329  Real bestrownorm = infinity;
1330  Real percenttoadd = 1;
1331 
1333  if( allrows )
1334  nrowstoadd = _nDecompViolRows; // adding all violated rows
1335 
1336  SSVector y(_solver.nCols());
1337  y.unSetup();
1338 
1339  // identifying the rows not included in the reduced problem that are violated by the current solution.
1340  for( int i = 0; i < nrowstoadd; i++ )
1341  {
1342  rowNumber = _decompViolatedRows[i];
1343 
1344  if( !allrows )
1345  {
1346  Real norm = 0;
1347 
1348  // the rhs of this calculation are the rows of the constraint matrix
1349  // so we are solving y B = A_{i,.}
1350  try
1351  {
1352  _solver.basis().solve(y, _solver.vector(rowNumber));
1353  }
1354  catch( const SPxException& E )
1355  {
1356  MSG_ERROR( spxout << "Caught exception <" << E.what() << "> while computing compatability.\n" );
1357  }
1358 
1359 
1360  // comparing the constraints based upon the row norm
1361  if( y.isSetup() )
1362  {
1363  for( int j = 0; j < y.size(); j++ )
1364  {
1365  if( isZero(_solver.fVec()[i], feastol) )
1366  norm += spxAbs(y.value(j))*spxAbs(y.value(j));
1367  }
1368  }
1369  else
1370  {
1371  for( int j = 0; j < numColsReal(); j++ )
1372  {
1373  if( isZero(_solver.fVec()[i], feastol) )
1374  norm += spxAbs(y[j])*spxAbs(y[j]);
1375  }
1376  }
1377 
1378 
1379  // the best row is based upon the row norm
1380  // the best row is added if no violated row is found
1381  norm = spxSqrt(norm);
1382  if( LT(norm, bestrownorm) )
1383  {
1384  bestrow = rowNumber;
1385  bestrownorm = norm;
1386  }
1387 
1388 
1389  // adding the violated row
1390  if( isZero(norm, feastol) && LT(nnewrowidx/Real(numRowsReal()), percenttoadd) )
1391  {
1392  updaterows.add(_transformedRows.lhs(rowNumber), _transformedRows.rowVector(rowNumber),
1393  _transformedRows.rhs(rowNumber));
1394 
1395  _decompReducedProbRows[rowNumber] = true;
1396  newrowidx[nnewrowidx] = rowNumber;
1397  nnewrowidx++;
1398  }
1399 
1400  }
1401  else
1402  {
1403  // adding all violated rows
1404  updaterows.add(_transformedRows.lhs(rowNumber), _transformedRows.rowVector(rowNumber),
1405  _transformedRows.rhs(rowNumber));
1406 
1407  _decompReducedProbRows[rowNumber] = true;
1408  newrowidx[nnewrowidx] = rowNumber;
1409  nnewrowidx++;
1410  }
1411  }
1412 
1413  // if no violated row is found during the first pass of the available rows, then we add all violated rows.
1414  if( nnewrowidx == 0 )
1415  {
1416  for( int i = 0; i < nrowstoadd; i++ )
1417  {
1418  rowNumber = _decompViolatedRows[i];
1419 
1420  updaterows.add(_transformedRows.lhs(rowNumber), _transformedRows.rowVector(rowNumber),
1421  _transformedRows.rhs(rowNumber));
1422 
1423  _decompReducedProbRows[rowNumber] = true;
1424  newrowidx[nnewrowidx] = rowNumber;
1425  nnewrowidx++;
1426  }
1427  }
1428 
1429  // we will always add the row that is deemed best based upon the row norm.
1430  // TODO: check whether this should be skipped if a row has already been added.
1431  if( !allrows && bestrow >= 0 )
1432  {
1433  updaterows.add(_transformedRows.lhs(bestrow), _transformedRows.rowVector(bestrow),
1434  _transformedRows.rhs(bestrow));
1435 
1436  _decompReducedProbRows[bestrow] = true;
1437  newrowidx[nnewrowidx] = bestrow;
1438  nnewrowidx++;
1439  }
1440 
1441 
1442  SPxRowId* addedrowids = 0;
1443  spx_alloc(addedrowids, nnewrowidx);
1444  _solver.addRows(addedrowids, updaterows);
1445 
1446  for( int i = 0; i < nnewrowidx; i++ )
1447  _decompReducedProbRowIDs[newrowidx[i]] = addedrowids[i];
1448 
1449  // freeing allocated memory
1450  spx_free(addedrowids);
1451  spx_free(newrowidx);
1452  }
1453 
1454 
1455 
1456  /// builds the update rows with those violated in the complmentary problem
1457  // A row is violated in the constraint matrix Ax <= b, if b - A_{i}x < 0
1458  // To aid the computation, all violations are translated to <= constraints
1459  void SoPlex::_findViolatedRows(Real compObjValue, DataArray<RowViolation>& violatedrows, int& nviolatedrows)
1460  {
1461  Real feastol = realParam(SoPlex::FEASTOL);
1462  DVector compProbRedcost(_compSolver.nCols()); // the reduced costs of the complementary problem
1463  DVector compProbPrimal(_compSolver.nCols()); // the primal vector of the complementary problem
1464  DVector compProbActivity(_compSolver.nRows()); // the activity vector of the complementary problem
1465  Real compProbSlackVal = 0;
1466 
1468  {
1469  // Retrieving the slacks for each row.
1470  _compSolver.getRedCost(compProbRedcost);
1471  }
1472  else
1473  {
1474  // Retrieving the primal vector for the complementary problem
1475  _compSolver.getPrimal(compProbPrimal);
1476  _compSolver.computePrimalActivity(compProbPrimal, compProbActivity);
1477 
1478  compProbSlackVal = compProbPrimal[_compSolver.number(_compSlackColId)];
1479  }
1480 
1481  // scanning all rows of the complementary problem for violations.
1482  for( int i = 0; i < _nPrimalRows; i++ )
1483  {
1484  LPRowReal origlprow;
1485  DSVectorBase<Real> rowtoaddVec(_realLP->nCols());
1486  Real compProbViol = 0;
1487  Real compSlackCoeff = 0;
1488  int rownumber = _realLP->number(SPxRowId(_decompPrimalRowIDs[i]));
1489  int comprownum = _compSolver.number(SPxRowId(_decompPrimalRowIDs[i]));
1490 
1491  if( !_decompReducedProbRows[rownumber] )
1492  {
1493  // retreiving the violation of the complementary problem primal constraints
1495  {
1496  compSlackCoeff = getCompSlackVarCoeff(i);
1497  compProbViol = compProbRedcost[_compSolver.number(SPxColId(_decompDualColIDs[i]))]; // this is b - Ax
1498  // subtracting the slack variable value
1499  compProbViol += compObjValue*compSlackCoeff; // must add on the slack variable value.
1500  compProbViol *= compSlackCoeff; // translating the violation to a <= constraint
1501  }
1502  else
1503  {
1504  Real viol = _compSolver.rhs(comprownum) - (compProbActivity[comprownum] + compProbSlackVal);
1505  if( viol < 0.0 )
1506  compProbViol = viol;
1507 
1508  viol = (compProbActivity[comprownum] - compProbSlackVal) - _compSolver.lhs(comprownum);
1509  if( viol < 0.0 )
1510  compProbViol = viol;
1511 
1512  }
1513 
1514  // NOTE: if the row was originally a ranged constraint, we are only interest in one of the inequalities.
1515  // If one inequality of the range violates the bounds, then we will add the row.
1516 
1517  // the translation of the complementary primal problem to the dual some rows resulted in two columns.
1518  if( boolParam(SoPlex::USECOMPDUAL) && i < _nPrimalRows - 1 &&
1520  {
1521  i++;
1522  compSlackCoeff = getCompSlackVarCoeff(i);
1523  Real tempViol = compProbRedcost[_compSolver.number(SPxColId(_decompDualColIDs[i]))]; // this is b - Ax
1524  tempViol += compObjValue*compSlackCoeff;
1525  tempViol *= compSlackCoeff;
1526 
1527  // if the other side of the range constraint has a larger violation, then this is used for the
1528  // computation.
1529  if( tempViol < compProbViol )
1530  compProbViol = tempViol;
1531  }
1532 
1533 
1534  // checking the violation of the row.
1535  if( LT(compProbViol, 0, feastol) )
1536  {
1537  if( !_decompReducedProbRows[rownumber] )
1538  {
1539  numIncludedRows++;
1540  assert(numIncludedRows <= _realLP->nRows());
1541  }
1542  violatedrows[nviolatedrows].idx = rownumber;
1543  violatedrows[nviolatedrows].violation = spxAbs(compProbViol);
1544  nviolatedrows++;
1545  }
1546  }
1547  }
1548  }
1549 
1550 
1551 
1552  /// identifies the columns of the row-form basis that correspond to rows with zero dual multipliers.
1553  // This function assumes that the basis is in the row form.
1554  // @todo extend this to the case when the basis is in the column form.
1555  void SoPlex::_getZeroDualMultiplierIndices(Vector feasVector, int* nonposind, int* colsforremoval,
1556  int* nnonposind, bool& stop)
1557  {
1558  assert(_solver.rep() == SPxSolver::ROW);
1559 
1560 #ifdef NO_TOL
1561  Real feastol = 0.0;
1562 #else
1563 #ifdef USE_FEASTOL
1564  Real feastol = realParam(SoPlex::FEASTOL);
1565 #else
1566  Real feastol = realParam(SoPlex::EPSILON_ZERO);
1567 #endif
1568 #endif
1569 
1570  bool delCol;
1571 
1573  *nnonposind = 0;
1574 
1575  // iterating over all columns in the basis matrix
1576  // this identifies the basis indices and the indicies that are positive.
1577  for( int i = 0; i < _solver.nCols(); ++i )
1578  {
1579  _decompReducedProbCols[i] = true;
1580  _decompReducedProbColIDs[i].inValidate();
1581  colsforremoval[i] = i;
1582  delCol = false;
1583  if( _solver.basis().baseId(i).isSPxRowId() ) // find the row id's for rows in the basis
1584  {
1585  // record the row if the dual multiple is zero.
1586  if( isZero(feasVector[i], feastol) )
1587  {
1588  nonposind[*nnonposind] = i;
1589  (*nnonposind)++;
1590 
1591  // NOTE: commenting out the delCol flag at this point. The colsforremoval array should indicate the
1592  // columns that have a zero reduced cost. Hence, the delCol flag should only be set in the isSPxColId
1593  // branch of the if statement.
1594  //delCol = true;
1595  }
1596  }
1597  else if( _solver.basis().baseId(i).isSPxColId() ) // get the column id's for the columns in the basis
1598  {
1599  if( isZero(feasVector[i], feastol) )
1600  {
1601  nonposind[*nnonposind] = i;
1602  (*nnonposind)++;
1603 
1604  delCol = true;
1605  }
1606  }
1607 
1608  // setting an array to identify the columns to be removed from the LP to form the reduced problem
1609  if( delCol )
1610  {
1611  colsforremoval[i] = -1;
1612  _decompReducedProbCols[i] = false;
1613  }
1614  else if( _solver.basis().baseId(i).isSPxColId() )
1615  {
1616  if( _solver.basis().baseId(i).isSPxColId() )
1618  else
1620  }
1621  }
1622 
1624  }
1625 
1626 
1627 
1628  /// retrieves the compatible columns from the constraint matrix
1629  // This function also updates the constraint matrix of the reduced problem. It is efficient to perform this in the
1630  // following function because the required linear algebra has been performed.
1631  void SoPlex::_getCompatibleColumns(Vector feasVector, int* nonposind, int* compatind, int* rowsforremoval,
1632  int* colsforremoval, int nnonposind, int* ncompatind, bool formRedProb, bool& stop)
1633  {
1634 #ifdef NO_TOL
1635  Real feastol = 0.0;
1636 #else
1637 #ifdef USE_FEASTOL
1638  Real feastol = realParam(SoPlex::FEASTOL);
1639 #else
1640  Real feastol = realParam(SoPlex::EPSILON_ZERO);
1641 #endif
1642 #endif
1643 
1644  bool compatible;
1645  SSVector y(_solver.nCols());
1646  y.unSetup();
1647 
1648  *ncompatind = 0;
1649 
1650 #ifndef NDEBUG
1651  int bind = 0;
1652  bool* activerows = 0;
1653  spx_alloc(activerows, numRowsReal());
1654 
1655  for( int i = 0; i < numRowsReal(); ++i )
1656  activerows[i] = false;
1657 
1658  for( int i = 0; i < numColsReal(); ++i )
1659  {
1660  if( _solver.basis().baseId(i).isSPxRowId() ) // find the row id's for rows in the basis
1661  {
1662  if( !isZero(feasVector[i], feastol) )
1663  {
1664  bind = _realLP->number(SPxRowId(_solver.basis().baseId(i))); // getting the corresponding row
1665  // for the original LP.
1666  assert(bind >= 0 && bind < numRowsReal());
1667  activerows[bind] = true;
1668  }
1669  }
1670  }
1671 #endif
1672 
1673  // this function is called from other places where to identify the columns for removal. In these places the
1674  // reduced problem is not formed.
1675  if( formRedProb )
1676  {
1679  }
1680 
1681  for( int i = 0; i < numRowsReal(); ++i )
1682  {
1683  rowsforremoval[i] = i;
1684  if( formRedProb )
1685  _decompReducedProbRows[i] = true;
1686 
1687  numIncludedRows++;
1688 
1689  // the rhs of this calculation are the rows of the constraint matrix
1690  // so we are solving y B = A_{i,.}
1691  // @NOTE: This may not actually be necessary. The solve process is very time consuming and is a point where the
1692  // approach breaks down. It could be simplier if we use a faster solve. Maybe something like:
1693  // Omer, J.; Towhidi, M. & Soumis, F., "The positive edge pricing rule for the dual simplex",
1694  // Computers & Operations Research , 2015, 61, 135-142
1695  try
1696  {
1697  _solver.basis().solve(y, _solver.vector(i));
1698  }
1699  catch( const SPxException& E )
1700  {
1701  MSG_ERROR( spxout << "Caught exception <" << E.what() << "> while computing compatability.\n" );
1702  }
1703 
1704  compatible = true;
1705  // a compatible row is given by zeros in all columns related to the nonpositive indices
1706  for( int j = 0; j < nnonposind; ++j )
1707  {
1708  // @TODO: getting a tolerance issue with this check. Don't know how to fix it.
1709  if( !isZero(y[nonposind[j]], feastol) )
1710  {
1711  compatible = false;
1712  break;
1713  }
1714  }
1715 
1716  // checking that the active rows are compatible
1717  assert(!activerows[i] || compatible);
1718 
1719  // changing the matrix coefficients
1720  DSVector newRowVector;
1721  LPRowReal rowtoupdate;
1722 
1723  if( y.isSetup() )
1724  {
1725  for( int j = 0; j < y.size(); j++ )
1726  newRowVector.add(y.index(j), y.value(j));
1727  }
1728  else
1729  {
1730  for( int j = 0; j < numColsReal(); j++ )
1731  {
1732  if( !isZero(y[j], feastol) )
1733  newRowVector.add(j, y[j]);
1734  }
1735  }
1736 
1737  // transforming the original problem rows
1738  _solver.getRow(i, rowtoupdate);
1739 
1740 #ifndef NO_TRANSFORM
1741  rowtoupdate.setRowVector(newRowVector);
1742 #endif
1743 
1744  if( formRedProb )
1745  _transformedRows.add(rowtoupdate);
1746 
1747 
1748  // Making all equality constraints compatible, i.e. they are included in the reduced problem
1749  if( EQ(rowtoupdate.lhs(), rowtoupdate.rhs()) )
1750  compatible = true;
1751 
1752  if( compatible )
1753  {
1754  compatind[*ncompatind] = i;
1755  (*ncompatind)++;
1756 
1757  if( formRedProb )
1758  {
1760 
1761  // updating the compatible row
1762  _decompLP->changeRow(i, rowtoupdate);
1763  }
1764  }
1765  else
1766  {
1767  // setting an array to identify the rows to be removed from the LP to form the reduced problem
1768  rowsforremoval[i] = -1;
1769  numIncludedRows--;
1770 
1771  if( formRedProb )
1772  _decompReducedProbRows[i] = false;
1773  }
1774 
1775  // determine whether the reduced problem setup should be terminated
1777 
1778  if( stop )
1779  break;
1780  }
1781  assert(numIncludedRows <= _solver.nRows());
1782 
1783 #ifndef NDEBUG
1784  spx_free(activerows);
1785 #endif
1786  }
1787 
1788 
1789 
1790  /// computes the reduced problem objective coefficients
1792  {
1793 #ifdef NO_TOL
1794  Real feastol = 0.0;
1795 #else
1796 #ifdef USE_FEASTOL
1797  Real feastol = realParam(SoPlex::FEASTOL);
1798 #else
1799  Real feastol = realParam(SoPlex::EPSILON_ZERO);
1800 #endif
1801 #endif
1802 
1803  SSVector y(numColsReal());
1804  y.unSetup();
1805 
1806  // the rhs of this calculation is the original objective coefficient vector
1807  // so we are solving y B = c
1808  try
1809  {
1810  _solver.basis().solve(y, _solver.maxObj());
1811  }
1812  catch( const SPxException& E )
1813  {
1814  MSG_ERROR( spxout << "Caught exception <" << E.what() << "> while computing compatability.\n" );
1815  }
1816 
1818  if( y.isSetup() )
1819  {
1820  int ycount = 0;
1821  for( int i = 0; i < numColsReal(); i++ )
1822  {
1823  if( ycount < y.size() && i == y.index(ycount) )
1824  {
1825  _transformedObj[i] = y.value(ycount);
1826  ycount++;
1827  }
1828  else
1829  _transformedObj[i] = 0.0;
1830  }
1831  }
1832  else
1833  {
1834  for( int i = 0; i < numColsReal(); i++ )
1835  {
1836  if( isZero(y[i], feastol) )
1837  _transformedObj[i] = 0.0;
1838  else
1839  _transformedObj[i] = y[i];
1840  }
1841  }
1842 
1843  // setting the updated objective vector
1844 #ifndef NO_TRANSFORM
1846 #endif
1847 
1848  // determine whether the reduced problem setup should be terminated
1850  }
1851 
1852 
1853 
1854  /// computes the compatible bound constraints and adds them to the reduced problem
1855  // NOTE: No columns are getting removed from the reduced problem. Only the bound constraints are being removed.
1856  // So in the reduced problem, all variables are free unless the bound constraints are selected as compatible.
1857  void SoPlex::_getCompatibleBoundCons(LPRowSet& boundcons, int* compatboundcons, int* nonposind,
1858  int* ncompatboundcons, int nnonposind, bool& stop)
1859  {
1860 #ifdef NO_TOL
1861  Real feastol = 0.0;
1862 #else
1863 #ifdef USE_FEASTOL
1864  Real feastol = realParam(SoPlex::FEASTOL);
1865 #else
1866  Real feastol = realParam(SoPlex::EPSILON_ZERO);
1867 #endif
1868 #endif
1869 
1870  bool compatible;
1871  SSVector y(numColsReal());
1872  y.unSetup();
1873 
1875 
1876 
1877  // identifying the compatible bound constraints
1878  for( int i = 0; i < numColsReal(); i++ )
1879  {
1880  _decompReducedProbColRowIDs[i].inValidate();
1881 
1882  // setting all variables to free variables.
1883  // Bound constraints will only be added to the variables with compatible bound constraints.
1886 
1887  // the rhs of this calculation are the unit vectors of the bound constraints
1888  // so we are solving y B = I_{i,.}
1889  // this solve should not be required. We only need the column of the basis inverse.
1890  try
1891  {
1893  }
1894  catch( const SPxException& E )
1895  {
1896  MSG_ERROR( spxout << "Caught exception <" << E.what() << "> while computing compatability.\n" );
1897  }
1898 
1899  compatible = true;
1900  // a compatible row is given by zeros in all columns related to the nonpositive indices
1901  for( int j = 0; j < nnonposind; ++j )
1902  {
1903  // @todo really need to check this part of the code. Run through this with Ambros or Matthias.
1904  if( !isZero(y[nonposind[j]]) )
1905  {
1906  compatible = false;
1907  break;
1908  }
1909  }
1910 
1911  // changing the matrix coefficients
1912  DSVector newRowVector;
1913  LPRowReal rowtoupdate;
1914 
1915 #ifndef NO_TRANSFORM
1916  if( y.isSetup() )
1917  {
1918  for( int j = 0; j < y.size(); j++ )
1919  newRowVector.add(y.index(j), y.value(j));
1920  }
1921  else
1922  {
1923  for( int j = 0; j < numColsReal(); j++ )
1924  {
1925  if( !isZero(y[j], feastol) )
1926  {
1927  newRowVector.add(j, y[j]);
1928  }
1929  }
1930  }
1931 #else
1932  newRowVector.add(i, 1.0);
1933 #endif
1934 
1935  // will probably need to map this set of rows.
1936  _transformedRows.add(_solver.lower(i), newRowVector, _solver.upper(i));
1937 
1938  // variable bounds are compatible in the current implementation.
1939  // this is still function is still required to transform the bound constraints with respect to the basis matrix.
1940  compatible = true;
1941 
1942  // if the bound constraint is compatible, it remains in the reduced problem.
1943  // Otherwise the bound is removed and the variables are free.
1944  if( compatible )
1945  {
1946  Real lhs = -infinity;
1947  Real rhs = infinity;
1948  if( GT(_solver.lower(i), -infinity) )
1949  lhs = _solver.lower(i);
1950 
1951  if( LT(_solver.upper(i), infinity) )
1952  rhs = _solver.upper(i);
1953 
1954  if( GT(lhs, -infinity) || LT(rhs, infinity) )
1955  {
1956  compatboundcons[(*ncompatboundcons)] = i;
1957  (*ncompatboundcons)++;
1958 
1959  boundcons.add(lhs, newRowVector, rhs);
1960  }
1961 
1962 
1963  }
1964 
1965  // determine whether the reduced problem setup should be terminated
1967 
1968  if( stop )
1969  break;
1970  }
1971 
1972  }
1973 
1974 
1975 
1976  /// computes the rows to remove from the complementary problem
1977  void SoPlex::_getRowsForRemovalComplementaryProblem(int* nonposind, int* bind, int* rowsforremoval,
1978  int* nrowsforremoval, int nnonposind)
1979  {
1980  *nrowsforremoval = 0;
1981 
1982  for( int i = 0; i < nnonposind; i++ )
1983  {
1984  if( bind[nonposind[i]] < 0 )
1985  {
1986  rowsforremoval[*nrowsforremoval] = -1 - bind[nonposind[i]];
1987  (*nrowsforremoval)++;
1988  }
1989  }
1990  }
1991 
1992 
1993 
1994  /// removing rows from the complementary problem.
1995  // the rows that are removed from decompCompLP are the rows from the reduced problem that have a non-positive dual
1996  // multiplier in the optimal solution.
1997  void SoPlex::_deleteAndUpdateRowsComplementaryProblem(SPxRowId rangedRowIds[], int& naddedrows)
1998  {
1999  DSVector slackColCoeff;
2000 
2001  // setting the objective coefficients of the original variables to zero
2002  DVector newObjCoeff(numColsReal());
2003  for( int i = 0; i < numColsReal(); i++ )
2004  {
2006  newObjCoeff[i] = 0;
2007  }
2008 
2009  _compSolver.changeObj(newObjCoeff);
2010 
2011  // adding the slack column to the complementary problem
2012  SPxColId* addedcolid = 0;
2014  {
2015  spx_alloc(addedcolid, 1);
2016  LPColSetReal compSlackCol;
2017  compSlackCol.add(1.0, -infinity, slackColCoeff, infinity);
2018  _compSolver.addCols(addedcolid, compSlackCol);
2019  _compSlackColId = addedcolid[0];
2020  }
2021  else
2022  {
2023  LPRowSet addrangedrows; // the row set of ranged and equality rows that must be added to the complementary problem.
2024  naddedrows = 0;
2025  // finding all of the ranged and equality rows and creating two <= constraints.
2026  for( int i = 0; i < numRowsReal(); i++ )
2027  {
2029  {
2030  assert(GT(_compSolver.lhs(i), -infinity) && LT(_compSolver.rhs(i), infinity));
2032 
2034  addrangedrows.add(_realLP->lhs(i), _realLP->rowVector(i), infinity);
2035  naddedrows++;
2036  }
2037  }
2038 
2039  // adding the rows for the ranged rows to make <= conatraints
2040  SPxRowId* addedrowid = 0;
2041  spx_alloc(addedrowid, naddedrows);
2042  _compSolver.addRows(addedrowid, addrangedrows);
2043 
2044  // collecting the row ids
2045  for( int i = 0; i < naddedrows; i++ )
2046  rangedRowIds[i] = addedrowid[i];
2047 
2048  spx_free(addedrowid);
2049 
2050 
2051  // adding the slack column
2052  spx_alloc(addedcolid, 1);
2053  LPColSetReal compSlackCol;
2054  compSlackCol.add(-1.0, 0.0, slackColCoeff, infinity);
2055 
2056  _compSolver.addCols(addedcolid, compSlackCol);
2057  _compSlackColId = addedcolid[0];
2058  }
2059 
2060  // freeing allocated memory
2061  spx_free(addedcolid);
2062  }
2063 
2064 
2065 
2066  /// update the dual complementary problem with additional columns and rows
2067  // Given the solution to the updated reduced problem, the complementary problem will be updated with modifications to
2068  // the constraints and the removal of variables
2070  {
2071  Real feastol = realParam(SoPlex::FEASTOL);
2072 
2073  int prevNumCols = _compSolver.nCols(); // number of columns in the previous formulation of the complementary prob
2074  int prevNumRows = _compSolver.nRows();
2075  int prevPrimalRowIds = _nPrimalRows;
2076  int prevDualColIds = _nDualCols;
2077 
2078  LPColSetBase<Real> addElimCols(_nElimPrimalRows); // columns previously eliminated from the
2079  // complementary problem that must be added
2080  int numElimColsAdded = 0;
2081  int currnumrows = prevNumRows;
2082  // looping over all rows from the original LP that were eliminated during the formation of the complementary
2083  // problem. The eliminated rows will be added if they are basic in the reduced problem.
2084 
2085  for( int i = 0; i < _nElimPrimalRows; i++ )
2086  {
2087  int rowNumber = _realLP->number(_decompElimPrimalRowIDs[i]);
2088 
2089  int solverRowNum = _solver.number(_decompReducedProbRowIDs[rowNumber]);
2090  assert(solverRowNum >= 0 && solverRowNum < _solver.nRows());
2091 
2092  // checking for the basic rows in the reduced problem
2093  if( _solver.basis().desc().rowStatus(solverRowNum) == SPxBasis::Desc::P_ON_UPPER ||
2094  _solver.basis().desc().rowStatus(solverRowNum) == SPxBasis::Desc::P_ON_LOWER ||
2095  _solver.basis().desc().rowStatus(solverRowNum) == SPxBasis::Desc::P_FIXED ||
2096  _solver.basis().desc().rowStatus(solverRowNum) == SPxBasis::Desc::D_FREE ||
2097  (_solver.basis().desc().rowStatus(solverRowNum) == SPxBasis::Desc::D_ON_LOWER &&
2098  LE(_solver.rhs(solverRowNum) - _solver.pVec()[solverRowNum], 0.0, feastol)) ||
2099  (_solver.basis().desc().rowStatus(solverRowNum) == SPxBasis::Desc::D_ON_UPPER &&
2100  LE(_solver.pVec()[solverRowNum] - _solver.lhs(solverRowNum), 0.0, feastol)) )
2101  {
2102  LPRowReal origlprow;
2103  DSVectorBase<Real> coltoaddVec(_realLP->nCols());
2104 
2105  LPRowSet additionalrows;
2106  int nnewrows = 0;
2107 
2108  _realLP->getRow(rowNumber, origlprow);
2109  for( int j = 0; j < origlprow.rowVector().size(); j++ )
2110  {
2111  // the column of the new row may not exist in the current complementary problem.
2112  // if the column does not exist, then it is necessary to create the column.
2113  int colNumber = origlprow.rowVector().index(j);
2114  if( _decompCompProbColIDsIdx[colNumber] == -1 )
2115  {
2116  assert(!_decompReducedProbColIDs[colNumber].isValid());
2119  _fixedOrigVars[colNumber] = -2;
2120  _nPrimalCols++;
2121 
2122  // all columns for the complementary problem are converted to unrestricted.
2123  additionalrows.create(1, _realLP->maxObj(colNumber), _realLP->maxObj(colNumber));
2124  nnewrows++;
2125 
2126  coltoaddVec.add(currnumrows, origlprow.rowVector().value(j));
2127  currnumrows++;
2128  }
2129  else
2130  coltoaddVec.add(_compSolver.number(_decompDualRowIDs[_decompCompProbColIDsIdx[colNumber]]),
2131  origlprow.rowVector().value(j));
2132  }
2133 
2134  SPxRowId* addedrowids = 0;
2135  spx_alloc(addedrowids, nnewrows);
2136  _compSolver.addRows(addedrowids, additionalrows);
2137 
2138  for( int j = 0; j < nnewrows; j++ )
2139  {
2140  _decompDualRowIDs[_nDualRows] = addedrowids[j];
2141  _nDualRows++;
2142  }
2143 
2144  spx_free(addedrowids);
2145 
2146 
2147 
2148  if( _solver.basis().desc().rowStatus(solverRowNum) == SPxBasis::Desc::P_ON_UPPER ||
2149  _solver.basis().desc().rowStatus(solverRowNum) == SPxBasis::Desc::P_FIXED ||
2150  _solver.basis().desc().rowStatus(solverRowNum) == SPxBasis::Desc::D_FREE ||
2151  (_solver.basis().desc().rowStatus(solverRowNum) == SPxBasis::Desc::D_ON_LOWER &&
2152  LE(_solver.rhs(solverRowNum) - _solver.pVec()[solverRowNum], 0.0, feastol)) )
2153  {
2155  addElimCols.add(_realLP->rhs(_decompElimPrimalRowIDs[i]), -infinity, coltoaddVec, infinity);
2156 
2157  if( _nPrimalRows >= _decompPrimalRowIDs.size() )
2158  {
2160  _decompDualColIDs.reSize(_nPrimalRows*2);
2161  }
2162 
2164  _nPrimalRows++;
2165 
2166  _decompElimPrimalRowIDs.remove(i);
2167  _nElimPrimalRows--;
2168  i--;
2169 
2170  numElimColsAdded++;
2171  }
2172  else if( _solver.basis().desc().rowStatus(solverRowNum) == SPxBasis::Desc::P_ON_LOWER ||
2173  (_solver.basis().desc().rowStatus(solverRowNum) == SPxBasis::Desc::D_ON_UPPER &&
2174  LE(_solver.pVec()[solverRowNum] - _solver.lhs(solverRowNum), 0.0, feastol)) )
2175  {
2176  // this assert should stay, but there is an issue with the status and the dual vector
2177  //assert(LT(dualVector[_solver.number(_decompReducedProbRowIDs[rowNumber])], 0.0));
2178  assert(GT(_realLP->lhs(_decompElimPrimalRowIDs[i]), -infinity));
2179  addElimCols.add(_realLP->lhs(_decompElimPrimalRowIDs[i]), -infinity, coltoaddVec, infinity);
2180 
2182  _nPrimalRows++;
2183 
2184  _decompElimPrimalRowIDs.remove(i);
2185  _nElimPrimalRows--;
2186  i--;
2187 
2188  numElimColsAdded++;
2189  }
2190  }
2191  }
2192 
2193  MSG_INFO2(spxout, spxout << "Number of eliminated columns added to complementary problem: "
2194  << numElimColsAdded << std::endl );
2195 
2196  // updating the _decompDualColIDs with the additional columns from the eliminated rows.
2197  _compSolver.addCols(addElimCols);
2198  for( int i = prevNumCols; i < _compSolver.nCols(); i++ )
2199  {
2200  _decompDualColIDs[prevDualColIds + i - prevNumCols] = _compSolver.colId(i);
2201  _nDualCols++;
2202  }
2203 
2204  assert(_nDualCols == _nPrimalRows);
2205 
2206  // looping over all rows from the original problem that were originally contained in the complementary problem.
2207  // The basic rows will be set as free variables, the non-basic rows will be eliminated from the complementary
2208  // problem.
2209  DSVector slackRowCoeff(_compSolver.nCols());
2210 
2211  int* colsforremoval = 0;
2212  int ncolsforremoval = 0;
2213  spx_alloc(colsforremoval, prevPrimalRowIds);
2214  for( int i = 0; i < prevPrimalRowIds; i++ )
2215  {
2216  int rowNumber = _realLP->number(_decompPrimalRowIDs[i]);
2217  // this loop runs over all rows previously in the complementary problem. If rows are added to the reduced
2218  // problem, they will be transfered from the incompatible set to the compatible set in the following if
2219  // statement.
2220  if( _decompReducedProbRows[rowNumber] )
2221  {
2222  // rows added to the reduced problem may have been equality constriants. The equality constraints from the
2223  // original problem are converted into <= and >= constraints. Upon adding these constraints to the reduced
2224  // problem, only a single dual column is needed in the complementary problem. Hence, one of the dual columns
2225  // is removed.
2226  //
2227  // 22.06.2015 Testing keeping all constraints in the complementary problem.
2228  // This requires a dual column to be fixed to zero for the range and equality rows.
2229 #ifdef KEEP_ALL_ROWS_IN_COMP_PROB
2230  bool incrementI = false;
2231 #endif
2232  if( i + 1 < prevPrimalRowIds
2234  {
2235  assert(_decompPrimalRowIDs[i].idx == _decompPrimalRowIDs[i+1].idx);
2236 
2237 #ifdef KEEP_ALL_ROWS_IN_COMP_PROB // 22.06.2015
2239  {
2241  _compSolver.changeBounds(_decompDualColIDs[i + 1], 0.0, 0.0);
2242  }
2243  incrementI = true;
2244 #else
2245  colsforremoval[ncolsforremoval] = _compSolver.number(SPxColId(_decompDualColIDs[i + 1]));
2246  ncolsforremoval++;
2247 
2248  _decompPrimalRowIDs.remove(i + 1);
2249  _nPrimalRows--;
2250  _decompDualColIDs.remove(i + 1);
2251  _nDualCols--;
2252 
2253  prevPrimalRowIds--;
2254 #endif
2255  }
2256  //assert(i + 1 == prevPrimalRowIds || _decompPrimalRowIDs[i].idx != _decompPrimalRowIDs[i+1].idx);
2257 
2258  int solverRowNum = _solver.number(_decompReducedProbRowIDs[rowNumber]);
2259  assert(solverRowNum >= 0 && solverRowNum < _solver.nRows());
2260  if( _solver.basis().desc().rowStatus(solverRowNum) == SPxBasis::Desc::P_ON_UPPER ||
2261  _solver.basis().desc().rowStatus(solverRowNum) == SPxBasis::Desc::P_FIXED ||
2262  _solver.basis().desc().rowStatus(solverRowNum) == SPxBasis::Desc::D_FREE ||
2263  (_solver.basis().desc().rowStatus(solverRowNum) == SPxBasis::Desc::D_ON_LOWER &&
2264  LE(_solver.rhs(solverRowNum) - _solver.pVec()[solverRowNum], 0.0, feastol)) )
2265  {
2266  //assert(GT(dualVector[solverRowNum], 0.0));
2269  }
2270  else if( _solver.basis().desc().rowStatus(solverRowNum) == SPxBasis::Desc::P_ON_LOWER ||
2271  (_solver.basis().desc().rowStatus(solverRowNum) == SPxBasis::Desc::D_ON_UPPER &&
2272  LE(_solver.pVec()[solverRowNum] - _solver.lhs(solverRowNum), 0.0, feastol)) )
2273  {
2274  //assert(LT(dualVector[solverRowNum], 0.0));
2277  }
2278  else //if ( _solver.basis().desc().rowStatus(solverRowNum) != SPxBasis::Desc::D_FREE )
2279  {
2280  //assert(isZero(dualVector[solverRowNum], 0.0));
2281 
2282  // 22.06.2015 Testing keeping all rows in the complementary problem
2283 #ifdef KEEP_ALL_ROWS_IN_COMP_PROB
2284  switch( _realLP->rowType(_decompPrimalRowIDs[i]) )
2285  {
2287  assert(_realLP->number(SPxColId(_decompPrimalRowIDs[i])) ==
2291 
2296 
2297  i++;
2298  break;
2302  break;
2306  break;
2307  default:
2308  throw SPxInternalCodeException("XDECOMPSL01 This should never happen.");
2309  }
2310 
2311 #else // 22.06.2015 testing keeping all rows in the complementary problem
2312  colsforremoval[ncolsforremoval] = _compSolver.number(SPxColId(_decompDualColIDs[i]));
2313  ncolsforremoval++;
2314 
2315  if( _nElimPrimalRows >= _decompElimPrimalRowIDs.size() )
2317 
2319  _nElimPrimalRows++;
2320  _decompPrimalRowIDs.remove(i);
2321  _nPrimalRows--;
2322  _decompDualColIDs.remove(i);
2323  _nDualCols--;
2324 
2325  i--;
2326  prevPrimalRowIds--;
2327 #endif
2328  }
2329 #ifdef KEEP_ALL_ROWS_IN_COMP_PROB
2330  if( incrementI )
2331  i++;
2332 #endif
2333  }
2334  else
2335  {
2336  switch( _realLP->rowType(_decompPrimalRowIDs[i]) )
2337  {
2339  assert(_realLP->number(SPxColId(_decompPrimalRowIDs[i])) ==
2345  {
2346  slackRowCoeff.add(_compSolver.number(SPxColId(_decompDualColIDs[i])), -SLACKCOEFF);
2347  slackRowCoeff.add(_compSolver.number(SPxColId(_decompDualColIDs[i + 1])), SLACKCOEFF);
2348  }
2349  else
2350  {
2351  slackRowCoeff.add(_compSolver.number(SPxColId(_decompDualColIDs[i])), SLACKCOEFF);
2352  slackRowCoeff.add(_compSolver.number(SPxColId(_decompDualColIDs[i + 1])), -SLACKCOEFF);
2353  }
2354 
2355 
2356  i++;
2357  break;
2359  assert(_realLP->number(SPxColId(_decompPrimalRowIDs[i])) ==
2361 
2362  slackRowCoeff.add(_compSolver.number(SPxColId(_decompDualColIDs[i])), SLACKCOEFF);
2363  slackRowCoeff.add(_compSolver.number(SPxColId(_decompDualColIDs[i + 1])), SLACKCOEFF);
2364 
2365  i++;
2366  break;
2368  slackRowCoeff.add(_compSolver.number(SPxColId(_decompDualColIDs[i])), -SLACKCOEFF);
2369  break;
2371  slackRowCoeff.add(_compSolver.number(SPxColId(_decompDualColIDs[i])), SLACKCOEFF);
2372  break;
2373  default:
2374  throw SPxInternalCodeException("XDECOMPSL01 This should never happen.");
2375  }
2376 
2377  if( origObj )
2378  {
2379  int numRemove = 1;
2380  int removeCount = 0;
2383  numRemove++;
2384 
2385  do
2386  {
2387  colsforremoval[ncolsforremoval] = _compSolver.number(SPxColId(_decompDualColIDs[i]));
2388  ncolsforremoval++;
2389 
2390  if( _nElimPrimalRows >= _decompElimPrimalRowIDs.size() )
2392 
2394  _nElimPrimalRows++;
2395  _decompPrimalRowIDs.remove(i);
2396  _nPrimalRows--;
2397  _decompDualColIDs.remove(i);
2398  _nDualCols--;
2399 
2400  i--;
2401  prevPrimalRowIds--;
2402 
2403  removeCount++;
2404  } while( removeCount < numRemove );
2405  }
2406  }
2407  }
2408 
2409  // updating the slack column in the complementary problem
2410  Real lhs = 1.0;
2411  Real rhs = 1.0;
2412 
2413  // it is possible that all rows are included in the reduced problem. In this case, the slack row will be empty. To
2414  // avoid infeasibility, the lhs and rhs are set to 0.
2415  if( slackRowCoeff.size() == 0 )
2416  {
2417  lhs = 0.0;
2418  rhs = 0.0;
2419  }
2420  LPRowBase<Real> compSlackRow(lhs, slackRowCoeff, rhs);
2421  _compSolver.changeRow(_compSlackDualRowId, compSlackRow);
2422 
2423 
2424  // if the original objective is used, then all dual columns related to primal rows not in the reduced problem are
2425  // removed from the complementary problem.
2426  // As a result, the slack row becomes an empty row.
2427  int* perm = 0;
2428  spx_alloc(perm, _compSolver.nCols() + numElimColsAdded);
2429  _compSolver.removeCols(colsforremoval, ncolsforremoval, perm);
2430 
2431 
2432  // updating the dual columns to represent the fixed primal variables.
2433  int* currFixedVars = 0;
2434  spx_alloc(currFixedVars, _realLP->nCols());
2438 
2439 
2440  // freeing allocated memory
2441  spx_free(currFixedVars);
2442  spx_free(perm);
2443  spx_free(colsforremoval);
2444  }
2445 
2446 
2447 
2448  /// update the primal complementary problem with additional columns and rows
2449  // Given the solution to the updated reduced problem, the complementary problem will be updated with modifications to
2450  // the constraints and the removal of variables
2452  {
2453  Real feastol = realParam(SoPlex::FEASTOL);
2454 
2455  int prevNumRows = _compSolver.nRows();
2456  int prevPrimalRowIds = _nPrimalRows;
2457 
2458  assert(_nPrimalRows == _nCompPrimalRows);
2459 
2460  LPRowSetBase<Real> addElimRows(_nElimPrimalRows); // rows previously eliminated from the
2461  // complementary problem that must be added
2462  int numElimRowsAdded = 0;
2463  // looping over all rows from the original LP that were eliminated during the formation of the complementary
2464  // problem. The eliminated rows will be added if they are basic in the reduced problem.
2465 
2466  for( int i = 0; i < _nElimPrimalRows; i++ )
2467  {
2468  int rowNumber = _realLP->number(_decompElimPrimalRowIDs[i]);
2469 
2470  int solverRowNum = _solver.number(_decompReducedProbRowIDs[rowNumber]);
2471  assert(solverRowNum >= 0 && solverRowNum < _solver.nRows());
2472 
2473  // checking the rows that are basic in the reduced problem that should be added to the complementary problem
2474  if( _solver.basis().desc().rowStatus(solverRowNum) == SPxBasis::Desc::P_ON_UPPER
2475  || _solver.basis().desc().rowStatus(solverRowNum) == SPxBasis::Desc::P_ON_LOWER
2476  || _solver.basis().desc().rowStatus(solverRowNum) == SPxBasis::Desc::P_FIXED
2477  || _solver.basis().desc().rowStatus(solverRowNum) == SPxBasis::Desc::D_FREE
2478  || (_solver.basis().desc().rowStatus(solverRowNum) == SPxBasis::Desc::D_ON_LOWER &&
2479  EQ(_solver.rhs(solverRowNum) - _solver.pVec()[solverRowNum], 0.0, feastol))
2480  || (_solver.basis().desc().rowStatus(solverRowNum) == SPxBasis::Desc::D_ON_UPPER &&
2481  EQ(_solver.pVec()[solverRowNum] - _solver.lhs(solverRowNum), 0.0, feastol)) )
2482  {
2483  LPRowReal origlprow;
2484  _realLP->getRow(rowNumber, origlprow);
2485 
2486  // NOTE: 11.02.2016 I am assuming that all columns from the original problem are contained in the
2487  // complementary problem. Will need to check this. Since nothing is happenning in the
2488  // _deleteAndUpdateRowsComplementaryProblem function, I am feeling confident that all columns remain.
2489 
2490 
2491  if( _solver.basis().desc().rowStatus(solverRowNum) == SPxBasis::Desc::P_ON_UPPER
2492  || _solver.basis().desc().rowStatus(solverRowNum) == SPxBasis::Desc::P_FIXED
2493  || _solver.basis().desc().rowStatus(solverRowNum) == SPxBasis::Desc::D_FREE
2494  || (_solver.basis().desc().rowStatus(solverRowNum) == SPxBasis::Desc::D_ON_LOWER &&
2495  EQ(_solver.rhs(solverRowNum) - _solver.pVec()[solverRowNum], 0.0, feastol)) )
2496  {
2498 
2499  if( _nPrimalRows >= _decompPrimalRowIDs.size() )
2500  {
2503  }
2504 
2505  addElimRows.add(_realLP->rhs(_decompElimPrimalRowIDs[i]), origlprow.rowVector(),
2507 
2509  _nPrimalRows++;
2510 
2511  _decompElimPrimalRowIDs.remove(i);
2512  _nElimPrimalRows--;
2513  i--;
2514 
2515  numElimRowsAdded++;
2516  }
2517  else if( _solver.basis().desc().rowStatus(solverRowNum) == SPxBasis::Desc::P_ON_LOWER
2518  || (_solver.basis().desc().rowStatus(solverRowNum) == SPxBasis::Desc::D_ON_UPPER &&
2519  EQ(_solver.pVec()[solverRowNum] - _solver.lhs(solverRowNum), 0.0, feastol)) )
2520  {
2521  assert(GT(_realLP->lhs(_decompElimPrimalRowIDs[i]), -infinity));
2522 
2523  if( _nPrimalRows >= _decompPrimalRowIDs.size() )
2524  {
2527  }
2528 
2529  addElimRows.add(_realLP->lhs(_decompElimPrimalRowIDs[i]), origlprow.rowVector(),
2531 
2533  _nPrimalRows++;
2534 
2535  _decompElimPrimalRowIDs.remove(i);
2536  _nElimPrimalRows--;
2537  i--;
2538 
2539  numElimRowsAdded++;
2540  }
2541  }
2542  }
2543 
2544  MSG_INFO2(spxout, spxout << "Number of eliminated rows added to the complementary problem: "
2545  << numElimRowsAdded << std::endl );
2546 
2547  // adding the eliminated rows to the complementary problem.
2548  _compSolver.addRows(addElimRows);
2549  for( int i = prevNumRows; i < _compSolver.nRows(); i++ )
2550  {
2551  _decompCompPrimalRowIDs[prevPrimalRowIds + i - prevNumRows] = _compSolver.rowId(i);
2552  _nCompPrimalRows++;
2553  }
2554 
2555  assert(_nPrimalRows == _nCompPrimalRows);
2556 
2557 
2558  // looping over all rows from the original problem that were originally contained in the complementary problem.
2559  // The basic rows will be set as equalities, the non-basic rows will be eliminated from the complementary
2560  // problem.
2561  DSVector slackColCoeff(_compSolver.nRows());
2562 
2563  int* rowsforremoval = 0;
2564  int nrowsforremoval = 0;
2565  spx_alloc(rowsforremoval, prevPrimalRowIds);
2566  for( int i = 0; i < prevPrimalRowIds; i++ )
2567  {
2568  int rowNumber = _realLP->number(_decompPrimalRowIDs[i]);
2569  // this loop runs over all rows previously in the complementary problem. If rows are added to the reduced
2570  // problem, they will be transfered from the incompatible set to the compatible set in the following if
2571  // statement.
2572  if( _decompReducedProbRows[rowNumber] )
2573  {
2574  // rows added to the reduced problem may have been equality constriants. The equality constraints from the
2575  // original problem are converted into <= and >= constraints. Upon adding these constraints to the reduced
2576  // problem, only a single dual column is needed in the complementary problem. Hence, one of the dual columns
2577  // is removed.
2578  //
2579 
2580  int solverRowNum = _solver.number(_decompReducedProbRowIDs[rowNumber]);
2581  assert(solverRowNum >= 0 && solverRowNum < _solver.nRows());
2582  if( _solver.basis().desc().rowStatus(solverRowNum) == SPxBasis::Desc::P_ON_UPPER
2583  || _solver.basis().desc().rowStatus(solverRowNum) == SPxBasis::Desc::P_FIXED
2584  || _solver.basis().desc().rowStatus(solverRowNum) == SPxBasis::Desc::D_FREE
2585  || (_solver.basis().desc().rowStatus(solverRowNum) == SPxBasis::Desc::D_ON_LOWER &&
2586  EQ(_solver.rhs(solverRowNum) - _solver.pVec()[solverRowNum], 0.0, feastol)) )
2587  {
2589  // need to also update the RHS because a ranged row could have previously been fixed to LOWER
2591  }
2592  else if( _solver.basis().desc().rowStatus(solverRowNum) == SPxBasis::Desc::P_ON_LOWER
2593  || (_solver.basis().desc().rowStatus(solverRowNum) == SPxBasis::Desc::D_ON_UPPER &&
2594  EQ(_solver.pVec()[solverRowNum] - _solver.lhs(solverRowNum), 0.0, feastol)) )
2595  {
2597  // need to also update the LHS because a ranged row could have previously been fixed to UPPER
2599  }
2600  else //if ( _solver.basis().desc().rowStatus(solverRowNum) != SPxBasis::Desc::D_FREE )
2601  {
2602  rowsforremoval[nrowsforremoval] = _compSolver.number(SPxRowId(_decompCompPrimalRowIDs[i]));
2603  nrowsforremoval++;
2604 
2605  if( _nElimPrimalRows >= _decompElimPrimalRowIDs.size() )
2607 
2609  _nElimPrimalRows++;
2610  _decompPrimalRowIDs.remove(i);
2611  _nPrimalRows--;
2612  _decompCompPrimalRowIDs.remove(i);
2613  _nCompPrimalRows--;
2614 
2615  i--;
2616  prevPrimalRowIds--;
2617  }
2618  }
2619  else
2620  {
2622  {
2624  assert(false);
2625  break;
2627  assert(false);
2628  break;
2630  slackColCoeff.add(_compSolver.number(SPxRowId(_decompCompPrimalRowIDs[i])), -SLACKCOEFF);
2631  break;
2634  break;
2635  default:
2636  throw SPxInternalCodeException("XDECOMPSL01 This should never happen.");
2637  }
2638 
2639  // this is used as a check at the end of the algorithm. If the original objective function is used, then we
2640  // need to remove all unfixed variables.
2641  if( origObj )
2642  {
2643  rowsforremoval[nrowsforremoval] = _compSolver.number(SPxRowId(_decompCompPrimalRowIDs[i]));
2644  nrowsforremoval++;
2645 
2646  if( _nElimPrimalRows >= _decompElimPrimalRowIDs.size() )
2648 
2650  _nElimPrimalRows++;
2651  _decompPrimalRowIDs.remove(i);
2652  _nPrimalRows--;
2653  _decompCompPrimalRowIDs.remove(i);
2654  _nCompPrimalRows--;
2655 
2656  i--;
2657  prevPrimalRowIds--;
2658  }
2659  }
2660  }
2661 
2662  // updating the slack column in the complementary problem
2663  LPColBase<Real> compSlackCol(-1, slackColCoeff, infinity, 0.0);
2664  _compSolver.changeCol(_compSlackColId, compSlackCol);
2665 
2666 
2667  // if the original objective is used, then all complementary rows related to primal rows not in the reduced problem are
2668  // removed from the complementary problem.
2669  // As a result, the slack column becomes an empty column.
2670  int* perm = 0;
2671  spx_alloc(perm, _compSolver.nRows() + numElimRowsAdded);
2672  _compSolver.removeRows(rowsforremoval, nrowsforremoval, perm);
2673 
2674  // updating the dual columns to represent the fixed primal variables.
2675  int* currFixedVars = 0;
2676  spx_alloc(currFixedVars, _realLP->nCols());
2679 
2680 
2681  // freeing allocated memory
2682  spx_free(currFixedVars);
2683  spx_free(perm);
2684  spx_free(rowsforremoval);
2685  }
2686 
2687 
2688 
2689  /// checking the optimality of the original problem.
2690  // this function is called if the complementary problem is solved with a non-negative objective value. This implies
2691  // that the rows currently included in the reduced problem are sufficient to identify the optimal solution to the
2692  // original problem.
2693  void SoPlex::_checkOriginalProblemOptimality(Vector primalVector, bool printViol)
2694  {
2695  SSVector x(_solver.nCols());
2696  x.unSetup();
2697 
2698  // multiplying the solution vector of the reduced problem with the transformed basis to identify the original
2699  // solution vector.
2700  _decompTransBasis.coSolve(x, primalVector);
2701 
2702  if( printViol )
2703  {
2704  MSG_INFO1(spxout, spxout << std::endl
2705  << "Checking consistency between the reduced problem and the original problem." << std::endl );
2706  }
2707 
2708 
2709  // checking the objective function values of the reduced problem and the original problem.
2710  Real redObjVal = 0;
2711  Real objectiveVal = 0;
2712  for( int i = 0; i < _solver.nCols(); i++ )
2713  {
2714  redObjVal += _solver.maxObj(i)*primalVector[i];
2715  objectiveVal += _realLP->maxObj(i)*x[i];
2716  }
2717 
2718  if( printViol )
2719  {
2720  MSG_INFO1(spxout, spxout << "Reduced Problem Objective Value: " << redObjVal << std::endl
2721  << "Original Problem Objective Value: " << objectiveVal << std::endl );
2722  }
2723 
2724  _solReal._isPrimalFeasible = true;
2725  _hasSolReal = true;
2726  // get the primal solutions from the reduced problem
2728  _solReal._primal = x;
2729 
2730  Real maxviol = 0;
2731  Real sumviol = 0;
2732 
2733  // checking the bound violations
2734  if( getDecompBoundViolation(maxviol, sumviol) )
2735  {
2736  if( printViol )
2737  MSG_INFO1(spxout, spxout << "Bound violation - "
2738  << "Max violation: " << maxviol << " Sum violation: " << sumviol << std::endl );
2739  }
2740 
2741  _statistics->totalBoundViol = sumviol;
2742  _statistics->maxBoundViol = maxviol;
2743 
2744  // checking the row violations
2745  if( getDecompRowViolation(maxviol, sumviol) )
2746  {
2747  if( printViol )
2748  MSG_INFO1(spxout, spxout << "Row violation - "
2749  << "Max violation: " << maxviol << " Sum violation: " << sumviol << std::endl );
2750  }
2751 
2752  _statistics->totalRowViol = sumviol;
2753  _statistics->maxRowViol = maxviol;
2754 
2755  if( printViol )
2756  MSG_INFO1(spxout, spxout << std::endl );
2757  }
2758 
2759 
2760 
2761  /// updating the slack column coefficients to adjust for equality constraints
2763  {
2764  // the slack column for the equality constraints is not handled correctly in the dual conversion. Hence, it is
2765  // necessary to change the equality coefficients of the dual row related to the slack column.
2766  for( int i = 0; i < _nPrimalRows; i++ )
2767  {
2768  int rowNumber = _realLP->number(SPxRowId(_decompPrimalRowIDs[i]));
2769  if( !_decompReducedProbRows[rowNumber] )
2770  {
2772  {
2774  _compSolver.changeLower(_decompDualColIDs[i], 0.0); // setting the lower bound of the dual column to zero.
2775 
2776  LPColBase<Real> addEqualityCol(-_realLP->rhs(_decompPrimalRowIDs[i]),
2777  Real(-1.0)*_compSolver.colVector(_decompDualColIDs[i]), infinity, 0.0); // adding a new column to the dual
2778 
2779  SPxColId newDualCol;
2780  _compSolver.addCol(newDualCol, addEqualityCol);
2781 
2782  // inserting the row and col ids for the added column. This is to be next to the original column that has
2783  // been duplicated.
2784  _decompPrimalRowIDs.insert(i + 1, 1, _decompPrimalRowIDs[i]);
2785  _decompDualColIDs.insert(i + 1, 1, newDualCol);
2787 
2788  i++;
2789  _nPrimalRows++;
2790  _nDualCols++;
2791  }
2792  }
2793  }
2794  }
2795 
2796 
2797 
2798  /// identify the dual columns related to the fixed variables
2800  {
2801  Real feastol = realParam(SoPlex::FEASTOL);
2802 
2803  int numFixedVar = 0;
2804  for( int i = 0; i < _realLP->nCols(); i++ )
2805  {
2806  currFixedVars[i] = 0;
2807  if( !_decompReducedProbColRowIDs[i].isValid() )
2808  continue;
2809 
2810  int rowNumber = _solver.number(_decompReducedProbColRowIDs[i]);
2811  if( _decompReducedProbColRowIDs[i].isValid() )
2812  {
2813  if( _solver.basis().desc().rowStatus(rowNumber) == SPxBasis::Desc::P_ON_UPPER ||
2815  _solver.basis().desc().rowStatus(rowNumber) == SPxBasis::Desc::P_FIXED ||
2816  _solver.basis().desc().rowStatus(rowNumber) == SPxBasis::Desc::D_FREE )
2817  {
2818  // setting the value of the _fixedOrigVars array to indicate which variables are at their bounds.
2819  currFixedVars[i] = getOrigVarFixedDirection(i);
2820 
2821  numFixedVar++;
2822  }
2823  else
2824  {
2825  // the dual flags do not imply anything about the primal status of the rows.
2826  if( _solver.basis().desc().rowStatus(rowNumber) == SPxBasis::Desc::D_ON_LOWER &&
2827  EQ(_solver.rhs(rowNumber) - _solver.pVec()[rowNumber], 0.0, feastol) )
2828  currFixedVars[i] = 1;
2829  else if( _solver.basis().desc().rowStatus(rowNumber) == SPxBasis::Desc::D_ON_UPPER &&
2830  EQ(_solver.pVec()[rowNumber] - _solver.lhs(rowNumber), 0.0, feastol) )
2831  currFixedVars[i] = -1;
2832  }
2833  }
2834  }
2835 
2836  MSG_INFO3(spxout, spxout << "Number of fixed primal variables in the complementary (dual) problem: "
2837  << numFixedVar << std::endl );
2838  }
2839 
2840 
2841 
2842  /// removing the dual columns related to the fixed variables
2844  {
2845  SPxColId tempId;
2846  int ncolsforremoval = 0;
2847  int* colsforremoval = 0;
2848  spx_alloc(colsforremoval, _realLP->nCols()*2);
2849 
2850  tempId.inValidate();
2851  for( int i = 0; i < _realLP->nCols(); i++ )
2852  {
2853  assert(_decompCompProbColIDsIdx[i] != -1); // this should be true in the current implementation
2854  if( _decompCompProbColIDsIdx[i] != -1 && _fixedOrigVars[i] != -2 )//&& _fixedOrigVars[i] != currFixedVars[i] )
2855  {
2856  if( _fixedOrigVars[i] != 0 )
2857  {
2859  assert(_fixedOrigVars[i] == -1 || _fixedOrigVars[i] == 1);
2860  assert(_decompFixedVarDualIDs[i].isValid());
2861 
2862  colsforremoval[ncolsforremoval] = _compSolver.number(SPxColId(_decompFixedVarDualIDs[i]));
2863  ncolsforremoval++;
2864 
2865  _decompFixedVarDualIDs[i] = tempId;
2866  }
2867  else //if( false && !_decompReducedProbColRowIDs[i].isValid() ) // we want to remove all valid columns
2868  // in the current implementation, the only columns not included in the reduced problem are free columns.
2869  {
2870  assert((LE(_realLP->lower(i), -infinity) && GE(_realLP->upper(i), infinity)) ||
2872  int varcount = 0;
2873  if( GT(_realLP->lower(i), -infinity) )
2874  {
2875  colsforremoval[ncolsforremoval] = _compSolver.number(SPxColId(_decompVarBoundDualIDs[i*2 + varcount]));
2876  ncolsforremoval++;
2877 
2878  _decompVarBoundDualIDs[i*2 + varcount] = tempId;
2879  varcount++;
2880  }
2881 
2882  if( LT(_realLP->upper(i), infinity) )
2883  {
2884  colsforremoval[ncolsforremoval] = _compSolver.number(SPxColId(_decompVarBoundDualIDs[i*2 + varcount]));
2885  ncolsforremoval++;
2886 
2887  _decompVarBoundDualIDs[i*2 + varcount] = tempId;
2888  }
2889 
2890  }
2891  }
2892  }
2893 
2894  int* perm = 0;
2895  spx_alloc(perm, _compSolver.nCols());
2896  _compSolver.removeCols(colsforremoval, ncolsforremoval, perm);
2897 
2898  // freeing allocated memory
2899  spx_free(perm);
2900  spx_free(colsforremoval);
2901  }
2902 
2903 
2904 
2905  /// updating the dual columns related to the fixed primal variables.
2907  {
2908  DSVectorBase<Real> col(1);
2909  LPColSetBase<Real> boundConsCols;
2910  LPColSetBase<Real> fixedVarsDualCols(_nPrimalCols);
2911  int numFixedVars = 0;
2912  // the solution to the reduced problem results in a number of variables at their bounds. If such variables exist
2913  // it is necessary to include a dual column to the complementary problem related to a variable fixing. This is
2914  // equivalent to the tight constraints being converted to equality constraints.
2915  int numBoundConsCols = 0;
2916  int* boundConsColsAdded = 0;
2917  spx_alloc(boundConsColsAdded, _realLP->nCols());
2918  // NOTE: this loop only goes over the primal columns that are included in the complementary problem, i.e. the
2919  // columns from the original problem.
2920  // 29.04.15 in the current implementation, all bound constraints are included in the reduced problem. So, all
2921  // variables (columns) are included in the reduced problem.
2922  for( int i = 0; i < _realLP->nCols(); i++ )
2923  {
2924  boundConsColsAdded[i] = 0;
2925  assert(_decompCompProbColIDsIdx[i] != -1);
2926  if( _decompCompProbColIDsIdx[i] != -1 )
2927  {
2928  int idIndex = _decompCompProbColIDsIdx[i];
2929  assert(_compSolver.number(SPxRowId(_decompDualRowIDs[idIndex])) >= 0);
2930  col.add(_compSolver.number(SPxRowId(_decompDualRowIDs[idIndex])), 1.0);
2931  if( currFixedVars[i] != 0 )
2932  {
2933  assert(currFixedVars[i] == -1 || currFixedVars[i] == 1);
2934 
2937  Real colObjCoeff = 0;
2938  if( currFixedVars[i] == -1 )
2939  colObjCoeff = _solver.lhs(_decompReducedProbColRowIDs[i]);
2940  else
2941  colObjCoeff = _solver.rhs(_decompReducedProbColRowIDs[i]);
2942 
2943  fixedVarsDualCols.add(colObjCoeff, -infinity, col, infinity);
2944  numFixedVars++;
2945  }
2946  // 09.02.15 I think that the else should only be entered if the column does not exist in the reduced
2947  // prob. I have tested by just leaving this as an else (without the if), but I think that this is wrong.
2948  //else if( !_decompReducedProbColRowIDs[i].isValid() )
2949 
2950  // NOTE: in the current implementation all columns, except the free columns, are included int the reduced
2951  // problem. There in no need to include the variable bounds in the complementary problem.
2952  else //if( false && _fixedOrigVars[i] == -2 )
2953  {
2954  bool isRedProbCol = _decompReducedProbColRowIDs[i].isValid();
2955  // 29.04.15 in the current implementation only free variables are not included in the reduced problem
2956  if( GT(_realLP->lower(i), -infinity) )
2957  {
2958  if( !isRedProbCol )
2960  boundConsCols.add(_realLP->lower(i), Real(-infinity), col, 0.0);
2961 
2962  if( !isRedProbCol )
2963  col.remove(col.size() - 1);
2964 
2965  boundConsColsAdded[i]++;
2966  numBoundConsCols++;
2967  }
2968 
2969  if( LT(_realLP->upper(i), infinity) )
2970  {
2971  if( !isRedProbCol )
2973  boundConsCols.add(_realLP->upper(i), 0.0, col, Real(infinity));
2974 
2975  if( !isRedProbCol )
2976  col.remove(col.size() - 1);
2977 
2978  boundConsColsAdded[i]++;
2979  numBoundConsCols++;
2980  }
2981  }
2982  col.clear();
2983  _fixedOrigVars[i] = currFixedVars[i];
2984  }
2985  }
2986 
2987  // adding the fixed var dual columns to the complementary problem
2988  SPxColId* addedcolids = 0;
2989  spx_alloc(addedcolids, numFixedVars);
2990  _compSolver.addCols(addedcolids, fixedVarsDualCols);
2991 
2992  SPxColId tempId;
2993  int addedcolcount = 0;
2994 
2995  tempId.inValidate();
2996  for( int i = 0; i < _realLP->nCols(); i++ )
2997  {
2998  if( _fixedOrigVars[i] != 0 )
2999  {
3000  assert(_fixedOrigVars[i] == -1 || _fixedOrigVars[i] == 1);
3001  _decompFixedVarDualIDs[i] = addedcolids[addedcolcount];
3002  addedcolcount++;
3003  }
3004  else
3005  _decompFixedVarDualIDs[i] = tempId;
3006  }
3007 
3008  // adding the bound cons dual columns to the complementary problem
3009  SPxColId* addedbndcolids = 0;
3010  spx_alloc(addedbndcolids, numBoundConsCols);
3011  _compSolver.addCols(addedbndcolids, boundConsCols);
3012 
3013  addedcolcount = 0;
3014  for( int i = 0; i < _realLP->nCols(); i++ )
3015  {
3016  if( boundConsColsAdded[i] > 0 )
3017  {
3018  for( int j = 0; j < boundConsColsAdded[i]; j++ )
3019  {
3020  _decompVarBoundDualIDs[i*2 + j] = addedbndcolids[addedcolcount];
3021  addedcolcount++;
3022  }
3023  }
3024 
3025  switch( boundConsColsAdded[i] )
3026  {
3027  case 0:
3028  _decompVarBoundDualIDs[i*2] = tempId;
3029  // FALLTHROUGH
3030  case 1:
3031  _decompVarBoundDualIDs[i*2 + 1] = tempId;
3032  break;
3033  }
3034  }
3035 
3036  // freeing allocated memory
3037  spx_free(addedbndcolids);
3038  spx_free(addedcolids);
3039  spx_free(boundConsColsAdded);
3040  }
3041 
3042 
3043  /// identify the dual columns related to the fixed variables
3045  {
3046  int numFixedVar = 0;
3047  for( int i = 0; i < _realLP->nCols(); i++ )
3048  {
3049  currFixedVars[i] = 0;
3050  if( !_decompReducedProbColRowIDs[i].isValid() )
3051  continue;
3052 
3053  int rowNumber = _solver.number(_decompReducedProbColRowIDs[i]);
3054  if( _decompReducedProbColRowIDs[i].isValid() &&
3055  (_solver.basis().desc().rowStatus(rowNumber) == SPxBasis::Desc::P_ON_UPPER ||
3057  _solver.basis().desc().rowStatus(rowNumber) == SPxBasis::Desc::P_FIXED) )
3058  {
3059  // setting the value of the _fixedOrigVars array to indicate which variables are at their bounds.
3060  currFixedVars[i] = getOrigVarFixedDirection(i);
3061 
3062  numFixedVar++;
3063  }
3064  }
3065 
3066  MSG_INFO3(spxout, spxout << "Number of fixed primal variables in the complementary (primal) problem: "
3067  << numFixedVar << std::endl );
3068  }
3069 
3070 
3071 
3072  /// updating the dual columns related to the fixed primal variables.
3074  {
3075  int numFixedVars = 0;
3076  // NOTE: this loop only goes over the primal columns that are included in the complementary problem, i.e. the
3077  // columns from the original problem.
3078  // 29.04.15 in the current implementation, all bound constraints are included in the reduced problem. So, all
3079  // variables (columns) are included in the reduced problem.
3080  for( int i = 0; i < _nCompPrimalCols; i++ )
3081  {
3082  int colNumber = _compSolver.number(SPxColId(_decompCompPrimalColIDs[i]));
3083  if( _fixedOrigVars[colNumber] != currFixedVars[colNumber] )
3084  {
3085  if( currFixedVars[colNumber] != 0 )
3086  {
3087  assert(currFixedVars[colNumber] == -1 || currFixedVars[colNumber] == 1);
3088 
3089  if( currFixedVars[colNumber] == -1 )
3092  else
3095 
3096  numFixedVars++;
3097  }
3098  else
3099  {
3100  _compSolver.changeBounds(colNumber, -infinity, infinity);
3101  }
3102  }
3103 
3104  _fixedOrigVars[colNumber] = currFixedVars[colNumber];
3105  }
3106  }
3107 
3108 
3109 
3110  /// updating the complementary dual problem with the original objective function
3112  {
3113  for( int i = 0; i < _realLP->nCols(); i++ )
3114  {
3115  assert(_decompCompProbColIDsIdx[i] != -1); // this should be true in the current implementation
3116  int idIndex = _decompCompProbColIDsIdx[i];
3117  int compRowNumber = _compSolver.number(_decompDualRowIDs[idIndex]);
3118  if( _decompCompProbColIDsIdx[i] != -1 )
3119  {
3120  // In the dual conversion, when a variable has a non-standard bound it is converted to a free variable.
3121  if( LE(_realLP->lower(i), -infinity) && GE(_realLP->upper(i), infinity) )
3122  {
3123  // unrestricted variable
3124  _compSolver.changeLhs(compRowNumber, _realLP->obj(i));
3125  _compSolver.changeRhs(compRowNumber, _realLP->obj(i));
3126  assert(LE(_compSolver.lhs(compRowNumber), _compSolver.rhs(compRowNumber)));
3127  }
3128  else if( LE(_realLP->lower(i), -infinity) )
3129  {
3130  // variable with a finite upper bound
3131  _compSolver.changeRhs(compRowNumber, _realLP->obj(i));
3132  if( isZero(_realLP->upper(i)) )
3133  _compSolver.changeLhs(compRowNumber, -infinity);
3134  else
3135  _compSolver.changeLhs(compRowNumber, _realLP->obj(i));
3136  }
3137  else if( GE(_realLP->upper(i), infinity) )
3138  {
3139  // variable with a finite lower bound
3140  _compSolver.changeLhs(compRowNumber, _realLP->obj(i));
3141  if( isZero(_realLP->upper(i)) )
3142  _compSolver.changeRhs(compRowNumber, infinity);
3143  else
3144  _compSolver.changeRhs(compRowNumber, _realLP->obj(i));
3145  }
3146  else if( NE(_realLP->lower(i), _realLP->upper(i)) )
3147  {
3148  // variable with a finite upper and lower bound
3149  if( isZero(_realLP->upper(i)) )
3150  {
3151  _compSolver.changeLhs(compRowNumber, _realLP->obj(i));
3152  _compSolver.changeRhs(compRowNumber, infinity);
3153  }
3154  else if( isZero(_realLP->upper(i)) )
3155  {
3156  _compSolver.changeLhs(compRowNumber, -infinity);
3157  _compSolver.changeRhs(compRowNumber, _realLP->obj(i));
3158  }
3159  else
3160  {
3161  _compSolver.changeLhs(compRowNumber, _realLP->obj(i));
3162  _compSolver.changeRhs(compRowNumber, _realLP->obj(i));
3163  }
3164  }
3165  else
3166  {
3167  // fixed variable
3168  _compSolver.changeLhs(compRowNumber, _realLP->obj(i));
3169  _compSolver.changeRhs(compRowNumber, _realLP->obj(i));
3170  }
3171  }
3172  }
3173 
3174  // removing the complementary problem slack column dual row
3176  }
3177 
3178 
3179 
3180  /// updating the complementary primal problem with the original objective function
3182  {
3183  // the comp solver has not removed any columns. Only the slack variables have been added.
3184  assert(_realLP->nCols() == _compSolver.nCols() - 1);
3185  for( int i = 0; i < _realLP->nCols(); i++ )
3186  {
3187  int colNumber = _realLP->number(_decompPrimalColIDs[i]);
3188  int compColNumber = _compSolver.number(_decompCompPrimalColIDs[i]);
3189  _compSolver.changeObj(compColNumber, _realLP->maxObj(colNumber));
3190  }
3191 
3192  // removing the complementary problem slack column dual row
3194  }
3195 
3196 
3197 
3198  /// determining which bound the primal variables will be fixed to.
3200  {
3201  if( !_decompReducedProbColRowIDs[colNum].isValid() )
3202  return 0;
3203 
3204  int rowNumber = _solver.number(_decompReducedProbColRowIDs[colNum]);
3205  // setting the value of the _fixedOrigVars array to indicate which variables are at their bounds.
3206  if( _solver.basis().desc().rowStatus(rowNumber) == SPxBasis::Desc::P_ON_UPPER ||
3207  _solver.basis().desc().rowStatus(rowNumber) == SPxBasis::Desc::P_FIXED ||
3208  _solver.basis().desc().rowStatus(rowNumber) == SPxBasis::Desc::D_FREE )
3209  {
3210  assert(_solver.rhs(rowNumber) < infinity);
3211  return 1;
3212  }
3213  else if( _solver.basis().desc().rowStatus(rowNumber) == SPxBasis::Desc::P_ON_LOWER )
3214  {
3215  assert(_solver.lhs(rowNumber) > -infinity);
3216  return -1;
3217  }
3218 
3219  return 0;
3220  }
3221 
3222 
3223 
3224  // @todo update this function and related comments. It has only been hacked together.
3225  /// checks result of the solving process and solves again without preprocessing if necessary
3226  // @todo need to evaluate the solution to ensure that it is solved to optimality and then we are able to perform the
3227  // next steps in the algorithm.
3229  {
3231  if( result == SPxSimplifier::INFEASIBLE )
3232  solverStat = SPxSolver::INFEASIBLE;
3233  else if( result == SPxSimplifier::DUAL_INFEASIBLE )
3234  solverStat = SPxSolver::INForUNBD;
3235  else if( result == SPxSimplifier::UNBOUNDED )
3236  solverStat = SPxSolver::UNBOUNDED;
3237  else if( result == SPxSimplifier::VANISHED )
3238  solverStat = SPxSolver::OPTIMAL;
3239  else if( result == SPxSimplifier::OKAY )
3240  solverStat = solver.status();
3241 
3242  // updating the status of SoPlex if the problem solved is the reduced problem.
3244  _status = solverStat;
3245 
3246  // process result
3247  switch( solverStat )
3248  {
3249  case SPxSolver::OPTIMAL:
3250  if( !_isRealLPLoaded )
3251  {
3253  _decompResolveWithoutPreprocessing(solver, sluFactor, result);
3254  // Need to solve the complementary problem
3255  return;
3256  }
3257  else
3258  _hasBasis = true;
3259 
3260  break;
3261 
3262  case SPxSolver::UNBOUNDED:
3263  case SPxSolver::INFEASIBLE:
3264  case SPxSolver::INForUNBD:
3265  // in case of infeasibility or unboundedness, we currently can not unsimplify, but have to solve the original LP again
3266  if( !_isRealLPLoaded )
3267  {
3269  _decompSimplifyAndSolve(solver, sluFactor, false, false);
3270  return;
3271  }
3272  else
3273  _hasBasis = (solver.basis().status() > SPxBasis::NO_PROBLEM);
3274  break;
3275 
3278  // in the initialisation of the decomposition simplex, we want to keep the current basis.
3279  if( !_isRealLPLoaded )
3280  {
3282  _decompResolveWithoutPreprocessing(solver, sluFactor, result);
3283  //_decompSimplifyAndSolve(solver, sluFactor, false, false);
3284  return;
3285  }
3286  else
3287  _hasBasis = (solver.basis().status() > SPxBasis::NO_PROBLEM);
3288  break;
3289 
3290  case SPxSolver::SINGULAR:
3292  // in case of infeasibility or unboundedness, we currently can not unsimplify, but have to solve the original LP again
3293  if( !_isRealLPLoaded )
3294  {
3296  _decompSimplifyAndSolve(solver, sluFactor, false, false);
3297  return;
3298  }
3299  break;
3300 
3301 
3302  // else fallthrough
3303  case SPxSolver::ABORT_TIME:
3304  case SPxSolver::ABORT_ITER:
3306  case SPxSolver::REGULAR:
3307  case SPxSolver::RUNNING:
3308  // store regular basis if there is no simplifier and the original problem is not in the solver because of
3309  // scaling; non-optimal bases should currently not be unsimplified
3310  if( _simplifier == 0 && solver.basis().status() > SPxBasis::NO_PROBLEM )
3311  {
3314  assert(_basisStatusRows.size() == solver.nRows());
3315  assert(_basisStatusCols.size() == solver.nCols());
3316 
3318  _hasBasis = true;
3319  }
3320  else
3321  _hasBasis = false;
3322  break;
3323 
3324  default:
3325  _hasBasis = false;
3326  break;
3327  }
3328  }
3329 
3330 
3331 
3332 
3333  /// checks the dual feasibility of the current basis
3335  {
3336  assert(_solver.rep() == SPxSolver::ROW);
3338 
3339  Real feastol = realParam(SoPlex::FEASTOL);
3340  // iterating through all elements in the basis to determine whether the dual feasibility is satisfied.
3341  for( int i = 0; i < _solver.nCols(); i++ )
3342  {
3343  if( _solver.basis().baseId(i).isSPxRowId() ) // find the row id's for rows in the basis
3344  {
3345  int rownumber = _solver.number(_solver.basis().baseId(i));
3346  if( _solver.basis().desc().rowStatus(rownumber) != SPxBasis::Desc::P_ON_UPPER &&
3347  _solver.basis().desc().rowStatus(rownumber) != SPxBasis::Desc::P_FIXED )
3348  {
3349  if( GT(feasVec[i], 0, feastol) )
3350  return false;
3351  }
3352 
3353  if( _solver.basis().desc().rowStatus(rownumber) != SPxBasis::Desc::P_ON_LOWER &&
3354  _solver.basis().desc().rowStatus(rownumber) != SPxBasis::Desc::P_FIXED )
3355  {
3356  if( LT(feasVec[i], 0, feastol) )
3357  return false;
3358  }
3359 
3360  }
3361  else if( _solver.basis().baseId(i).isSPxColId() ) // get the column id's for the columns in the basis
3362  {
3363  int colnumber = _solver.number(_solver.basis().baseId(i));
3364  if( _solver.basis().desc().colStatus(colnumber) != SPxBasis::Desc::P_ON_UPPER &&
3365  _solver.basis().desc().colStatus(colnumber) != SPxBasis::Desc::P_FIXED )
3366  {
3367  if( GT(feasVec[i], 0, feastol) )
3368  return false;
3369  }
3370 
3371  if( _solver.basis().desc().colStatus(colnumber) != SPxBasis::Desc::P_ON_LOWER &&
3372  _solver.basis().desc().colStatus(colnumber) != SPxBasis::Desc::P_FIXED )
3373  {
3374  if( LT(feasVec[i], 0, feastol) )
3375  return false;
3376  }
3377  }
3378  }
3379 
3380  return true;
3381  }
3382 
3383 
3384 
3385  /// returns the expected sign of the dual variables for the reduced problem
3387  {
3388  if( _solver.isRowBasic(rowNumber) )
3389  {
3390  if( _solver.basis().desc().rowStatus(rowNumber) != SPxBasis::Desc::P_ON_UPPER &&
3391  _solver.basis().desc().rowStatus(rowNumber) != SPxBasis::Desc::P_FIXED )
3392  return SoPlex::IS_NEG;
3393 
3394  if( _solver.basis().desc().rowStatus(rowNumber) != SPxBasis::Desc::P_ON_LOWER &&
3395  _solver.basis().desc().rowStatus(rowNumber) != SPxBasis::Desc::P_FIXED )
3396  return SoPlex::IS_POS;
3397  }
3398 
3399  return SoPlex::IS_FREE;
3400  }
3401 
3402 
3403 
3404  /// returns the expected sign of the dual variables for the original problem
3406  {
3407  if( _realLP->rowType(rowNumber) == LPRowBase<Real>::LESS_EQUAL )
3408  return IS_POS;
3409 
3410  if( _realLP->rowType(rowNumber) == LPRowBase<Real>::GREATER_EQUAL )
3411  return IS_NEG;
3412 
3413  if( _realLP->rowType(rowNumber) == LPRowBase<Real>::EQUAL )
3414  return IS_FREE;
3415 
3416  // this final statement needs to be checked.
3417  if( _realLP->rowType(rowNumber) == LPRowBase<Real>::RANGE )
3418  return IS_FREE;
3419 
3420  return IS_FREE;
3421  }
3422 
3423 
3424  /// print display line of flying table
3425  void SoPlex::printDecompDisplayLine(SPxSolver& solver, const SPxOut::Verbosity origVerb, bool force, bool forceHead)
3426  {
3427  // setting the verbosity level
3428  const SPxOut::Verbosity currVerb = spxout.getVerbosity();
3429  spxout.setVerbosity( origVerb );
3430 
3431  int displayFreq = intParam(SoPlex::DECOMP_DISPLAYFREQ);
3432 
3433  MSG_INFO1( spxout,
3434  if( forceHead || (_decompDisplayLine % (displayFreq*30) == 0) )
3435  {
3436  spxout << "type | time | iters | red iter | alg iter | rows | cols | shift | value\n";
3437  }
3438  if( force || (_decompDisplayLine % displayFreq == 0) )
3439  {
3440  Real currentTime = _statistics->solvingTime->time();
3441  (solver.type() == SPxSolver::LEAVE) ? spxout << " L |" : spxout << " E |";
3442  spxout << std::fixed << std::setw(7) << std::setprecision(1) << currentTime << " |";
3443  spxout << std::scientific << std::setprecision(2);
3444  spxout << std::setw(8) << _statistics->iterations << " | ";
3445  spxout << std::scientific << std::setprecision(2);
3446  spxout << std::setw(8) << _statistics->iterationsRedProb << " | ";
3447  spxout << std::scientific << std::setprecision(2);
3448  spxout << std::setw(8) << _statistics->callsReducedProb << " | ";
3449  spxout << std::scientific << std::setprecision(2);
3450  spxout << std::setw(8) << numIncludedRows << " | ";
3451  spxout << std::scientific << std::setprecision(2);
3452  spxout << std::setw(8) << solver.nCols() << " | "
3453  << solver.shift() << " | "
3454  << std::setprecision(8) << solver.value() + solver.objOffset()
3455  << std::endl;
3456 
3457  }
3459  );
3460 
3461  spxout.setVerbosity( currVerb );
3462  }
3463 
3464 
3465 
3466  /// stores the problem statistics of the original problem
3468  {
3469  numProbRows = _realLP->nRows();
3470  numProbCols = _realLP->nCols();
3471  numNonzeros = _realLP->nNzos();
3474 
3475  origCountLower = 0;
3476  origCountUpper = 0;
3477  origCountBoxed = 0;
3478  origCountFreeCol = 0;
3479 
3480  origCountLhs = 0;
3481  origCountRhs = 0;
3482  origCountRanged = 0;
3483  origCountFreeRow = 0;
3484 
3485  for( int i = 0; i < _realLP->nCols(); i++ )
3486  {
3487  bool hasLower = false;
3488  bool hasUpper = false;
3489 
3490  if( _realLP->lower(i) > -infinity )
3491  {
3492  origCountLower++;
3493  hasLower = true;
3494  }
3495 
3496  if( _realLP->upper(i) < infinity )
3497  {
3498  origCountUpper++;
3499  hasUpper = true;
3500  }
3501 
3502  if( hasUpper && hasLower )
3503  {
3504  origCountBoxed++;
3505  origCountUpper--;
3506  origCountLower--;
3507  }
3508 
3509  if( !hasUpper && !hasLower )
3510  origCountFreeCol++;
3511  }
3512 
3513  for( int i = 0; i < _realLP->nRows(); i++)
3514  {
3515  bool hasRhs = false;
3516  bool hasLhs = false;
3517 
3518  if( _realLP->lhs(i) > -infinity )
3519  {
3520  origCountLhs++;
3521  hasLhs = true;
3522  }
3523 
3524  if( _realLP->rhs(i) < infinity )
3525  {
3526  origCountRhs++;
3527  hasRhs = true;
3528  }
3529 
3530  if( hasRhs && hasLhs )
3531  {
3532  if( EQ(_realLP->rhs(i), _realLP->lhs(i)) )
3533  origCountEqual++;
3534  else
3535  origCountRanged++;
3536  origCountLhs--;
3537  origCountRhs--;
3538  }
3539 
3540  if( !hasRhs && !hasLhs )
3541  origCountFreeRow++;
3542  }
3543  }
3544 
3545 
3547  {
3548  os << " Columns : " << numProbCols << "\n"
3549  << " boxed : " << origCountBoxed << "\n"
3550  << " lower bound : " << origCountLower << "\n"
3551  << " upper bound : " << origCountUpper << "\n"
3552  << " free : " << origCountFreeCol << "\n"
3553  << " Rows : " << numProbRows << "\n"
3554  << " equal : " << origCountEqual << "\n"
3555  << " ranged : " << origCountRanged << "\n"
3556  << " lhs : " << origCountLhs << "\n"
3557  << " rhs : " << origCountRhs << "\n"
3558  << " free : " << origCountFreeRow << "\n"
3559  << " Nonzeros : " << numNonzeros << "\n"
3560  << " per column : " << Real(numNonzeros) / Real(numProbCols) << "\n"
3561  << " per row : " << Real(numNonzeros) / Real(numProbRows) << "\n"
3562  << " sparsity : " << Real(numNonzeros) / Real(numProbCols) / Real(numProbRows) << "\n"
3563  << " min. abs. value : " << Real(minAbsNonzero) << "\n"
3564  << " max. abs. value : " << Real(maxAbsNonzero) << "\n";
3565  }
3566 
3567 
3568 
3569  /// gets the coefficient of the slack variable in the primal complementary problem
3571  {
3572  int indDir = 1;
3573  switch( _realLP->rowType(_decompPrimalRowIDs[primalRowNum]) )
3574  {
3575  // NOTE: check the sign of the slackCoeff for the Range constraints. This will depend on the method of
3576  // dual conversion.
3578  assert((primalRowNum < _nPrimalRows - 1 && _realLP->number(SPxColId(_decompPrimalRowIDs[primalRowNum])) ==
3579  _realLP->number(SPxColId(_decompPrimalRowIDs[primalRowNum+1]))) ||
3580  (primalRowNum > 0 && _realLP->number(SPxColId(_decompPrimalRowIDs[primalRowNum-1])) ==
3581  _realLP->number(SPxColId(_decompPrimalRowIDs[primalRowNum]))));
3582 
3583  // determine with primalRowNum and primalRowNum+1 or primalRowNum-1 and primalRowNum have the same row id.
3584  if( _realLP->number(SPxColId(_decompPrimalRowIDs[primalRowNum-1])) ==
3585  _realLP->number(SPxColId(_decompPrimalRowIDs[primalRowNum])) )
3586  indDir = -1;
3587 
3589  _compSolver.obj(_compSolver.number(SPxColId(_decompDualColIDs[primalRowNum + indDir]))))
3590  return -SLACKCOEFF;
3591  else
3592  return SLACKCOEFF;
3593 
3594  break;
3595 
3597  return -SLACKCOEFF;
3598  break;
3600  assert((primalRowNum < _nPrimalRows - 1 && _realLP->number(SPxColId(_decompPrimalRowIDs[primalRowNum])) ==
3601  _realLP->number(SPxColId(_decompPrimalRowIDs[primalRowNum+1]))) ||
3602  (primalRowNum > 0 && _realLP->number(SPxColId(_decompPrimalRowIDs[primalRowNum-1])) ==
3603  _realLP->number(SPxColId(_decompPrimalRowIDs[primalRowNum]))));
3604  // FALLTHROUGH
3606  return SLACKCOEFF;
3607  break;
3608  default:
3609  throw SPxInternalCodeException("XDECOMPSL01 This should never happen.");
3610  }
3611  }
3612 
3613 
3614 
3615  /// gets violation of bounds; returns true on success
3616  bool SoPlex::getDecompBoundViolation(Real& maxviol, Real& sumviol)
3617  {
3618  Real feastol = realParam(SoPlex::FEASTOL);
3619 
3620  VectorReal& primal = _solReal._primal;
3621  assert(primal.dim() == _realLP->nCols());
3622 
3623  _nDecompViolBounds = 0;
3624 
3625  maxviol = 0.0;
3626  sumviol = 0.0;
3627 
3628  bool isViol = false;
3629  bool isMaxViol = false;
3630 
3631  for( int i = _realLP->nCols() - 1; i >= 0; i-- )
3632  {
3633  Real currviol = 0.0;
3634 
3635  Real viol = _realLP->lower(i) - primal[i];
3636 
3637  isViol = false;
3638  isMaxViol = false;
3639 
3640  if( viol > 0.0 )
3641  {
3642  sumviol += viol;
3643  if( viol > maxviol )
3644  {
3645  maxviol = viol;
3646  isMaxViol = true;
3647  }
3648 
3649  if( currviol < viol )
3650  currviol = viol;
3651  }
3652 
3653  if( GT(viol, 0.0, feastol) )
3654  isViol = true;
3655 
3656  viol = primal[i] - _realLP->upper(i);
3657  if( viol > 0.0 )
3658  {
3659  sumviol += viol;
3660  if( viol > maxviol )
3661  {
3662  maxviol = viol;
3663  isMaxViol = true;
3664  }
3665 
3666  if( currviol < viol )
3667  currviol = viol;
3668  }
3669 
3670  if( GT(viol, 0.0, feastol) )
3671  isViol = true;
3672 
3673  if( isViol )
3674  {
3675  // updating the violated bounds list
3676  if( isMaxViol )
3677  {
3679  _decompViolatedBounds[0] = i;
3680  }
3681  else
3683 
3684  _nDecompViolBounds++;
3685  }
3686  }
3687 
3688  return true;
3689  }
3690 
3691 
3692 
3693  /// gets violation of constraints; returns true on success
3694  bool SoPlex::getDecompRowViolation(Real& maxviol, Real& sumviol)
3695  {
3696  Real feastol = realParam(SoPlex::FEASTOL);
3697 
3698  VectorReal& primal = _solReal._primal;
3699  assert(primal.dim() == _realLP->nCols());
3700 
3701  DVectorReal activity(_realLP->nRows());
3702  _realLP->computePrimalActivity(primal, activity);
3703 
3704  _nDecompViolRows = 0;
3705 
3706  maxviol = 0.0;
3707  sumviol = 0.0;
3708 
3709  bool isViol = false;
3710  bool isMaxViol = false;
3711 
3712  for( int i = _realLP->nRows() - 1; i >= 0; i-- )
3713  {
3714  Real currviol = 0.0;
3715 
3716  isViol = false;
3717  isMaxViol = false;
3718 
3719  Real viol = _realLP->lhs(i) - activity[i];
3720  if( viol > 0.0 )
3721  {
3722  sumviol += viol;
3723  if( viol > maxviol )
3724  {
3725  maxviol = viol;
3726  isMaxViol = true;
3727  }
3728 
3729  if( viol > currviol )
3730  currviol = viol;
3731  }
3732 
3733  if( GT(viol, 0.0, feastol) )
3734  isViol = true;
3735 
3736  viol = activity[i] - _realLP->rhs(i);
3737  if( viol > 0.0 )
3738  {
3739  sumviol += viol;
3740  if( viol > maxviol )
3741  {
3742  maxviol = viol;
3743  isMaxViol = true;
3744  }
3745 
3746  if( viol > currviol )
3747  currviol = viol;
3748  }
3749 
3750  if( GT(viol, 0.0, feastol) )
3751  isViol = true;
3752 
3753  if( isViol )
3754  {
3755  // updating the violated rows list
3756  if( isMaxViol )
3757  {
3759  _decompViolatedRows[0] = i;
3760  }
3761  else
3763 
3764  _nDecompViolRows++;
3765  }
3766  }
3767 
3768  return true;
3769  }
3770 
3771 
3772 
3773  /// function call to terminate the decomposition simplex
3775  {
3776  Real maxTime = timeLimit;
3777 
3778  // check if a time limit is actually set
3779  if( maxTime < 0 || maxTime >= infinity )
3780  return false;
3781 
3782  Real currentTime = _statistics->solvingTime->time();
3783  if ( currentTime >= maxTime )
3784  {
3785  MSG_INFO2( spxout, spxout << " --- timelimit (" << _solver.getMaxTime()
3786  << ") reached" << std::endl; )
3788  return true;
3789  }
3790 
3791  return false;
3792  }
3793 
3794 
3795 
3796  /// function to retrieve the original problem row basis status from the reduced and complementary problems
3798  DataArray< SPxSolver::VarStatus >& degenerateRowStatus, int& nDegenerateRows, int& nNonBasicRows)
3799  {
3800  Real feastol = realParam(SoPlex::FEASTOL);
3801  int basicRow = 0;
3802 
3803  // looping over all rows not contained in the complementary problem
3804  for( int i = 0; i < _nElimPrimalRows; i++ )
3805  {
3806  int rowNumber = _realLP->number(_decompElimPrimalRowIDs[i]);
3807 
3808  int solverRowNum = _solver.number(_decompReducedProbRowIDs[rowNumber]);
3809  assert(solverRowNum >= 0 && solverRowNum < _solver.nRows());
3810  if( _solver.basis().desc().rowStatus(solverRowNum) == SPxBasis::Desc::P_ON_UPPER ) /*||
3811  (_solver.basis().desc().rowStatus(solverRowNum) == SPxBasis::Desc::D_ON_LOWER &&
3812  EQ(_solver.rhs(solverRowNum) - _solver.pVec()[solverRowNum], 0.0, feastol)) )*/
3813  {
3815  }
3816  else if( _solver.basis().desc().rowStatus(solverRowNum) == SPxBasis::Desc::P_ON_LOWER ) /*||
3817  (_solver.basis().desc().rowStatus(solverRowNum) == SPxBasis::Desc::D_ON_UPPER &&
3818  EQ(_solver.pVec()[solverRowNum] - _solver.lhs(solverRowNum), 0.0, feastol)) )*/
3819  {
3821  }
3822  else if( _solver.basis().desc().rowStatus(solverRowNum) == SPxBasis::Desc::P_FIXED )
3823  {
3824  _basisStatusRows[rowNumber] = SPxSolver::FIXED;
3825  }
3826  else if( _solver.basis().desc().rowStatus(solverRowNum) == SPxBasis::Desc::P_FREE )
3827  {
3828  _basisStatusRows[rowNumber] = SPxSolver::ZERO;
3829  }
3830  else
3831  {
3832  _basisStatusRows[rowNumber] = SPxSolver::BASIC;
3833  basicRow++;
3834  }
3835  }
3836 
3837  for( int i = 0; i < _nPrimalRows; i++ )
3838  {
3839  int rowNumber = _realLP->number(_decompPrimalRowIDs[i]);
3840  // this loop runs over all rows previously in the complementary problem.
3841  if( _decompReducedProbRows[rowNumber] )
3842  {
3843  int solverRowNum = _solver.number(_decompReducedProbRowIDs[rowNumber]);
3844  assert(solverRowNum >= 0 && solverRowNum < _solver.nRows());
3845  if( _solver.basis().desc().rowStatus(solverRowNum) == SPxBasis::Desc::P_ON_UPPER )
3846  {
3848  }
3849  else if( _solver.basis().desc().rowStatus(solverRowNum) == SPxBasis::Desc::D_ON_LOWER &&
3850  EQ(_solver.rhs(solverRowNum) - _solver.pVec()[solverRowNum], 0.0, feastol) )
3851  {
3852  // if a row is non basic, but is at its bound then the row number and status is stored
3853  degenerateRowNums[nDegenerateRows] = rowNumber;
3854  degenerateRowStatus[nDegenerateRows] = SPxSolver::ON_UPPER;
3855  nDegenerateRows++;
3856  }
3857  else if( _solver.basis().desc().rowStatus(solverRowNum) == SPxBasis::Desc::P_ON_LOWER )
3858  {
3860  }
3861  else if( _solver.basis().desc().rowStatus(solverRowNum) == SPxBasis::Desc::D_ON_UPPER &&
3862  EQ(_solver.pVec()[solverRowNum] - _solver.lhs(solverRowNum), 0.0, feastol) )
3863  {
3864  // if a row is non basic, but is at its bound then the row number and status is stored
3865  degenerateRowNums[nDegenerateRows] = rowNumber;
3866  degenerateRowStatus[nDegenerateRows] = SPxSolver::ON_LOWER;
3867  nDegenerateRows++;
3868  }
3869  else if( _solver.basis().desc().rowStatus(solverRowNum) == SPxBasis::Desc::P_FIXED )
3870  {
3871  _basisStatusRows[rowNumber] = SPxSolver::FIXED;
3872  }
3873  else if( _solver.basis().desc().rowStatus(solverRowNum) == SPxBasis::Desc::P_FREE )
3874  {
3875  _basisStatusRows[rowNumber] = SPxSolver::ZERO;
3876  }
3877  else
3878  {
3879  _basisStatusRows[rowNumber] = SPxSolver::BASIC;
3880  basicRow++;
3881  }
3882  }
3883  else
3884  {
3885  _basisStatusRows[rowNumber] = SPxSolver::BASIC;
3886  basicRow++;
3887  switch( _realLP->rowType(_decompPrimalRowIDs[i]) )
3888  {
3890  //assert(_realLP->number(SPxColId(_decompPrimalRowIDs[i])) ==
3891  //_realLP->number(SPxColId(_decompPrimalRowIDs[i+1])));
3892  //assert(_compSolver.obj(_compSolver.number(SPxColId(_decompDualColIDs[i]))) !=
3893  //_compSolver.obj(_compSolver.number(SPxColId(_decompDualColIDs[i + 1]))));
3894 
3895  //// NOTE: This is not correct at present. Need to modify the inequalities. Look at the dual conversion
3896  //// function to get this correct.
3897  //if( _compSolver.obj(_compSolver.number(SPxColId(_decompDualColIDs[i]))) <
3898  //_compSolver.obj(_compSolver.number(SPxColId(_decompDualColIDs[i + 1]))))
3899  //{
3900  //if( _compSolver.basis().desc().rowStatus(_compSolver.number(SPxColId(_decompDualColIDs[i]))) ==
3901  //SPxBasis::Desc::D_ON_LOWER )
3902  //{
3903  //_basisStatusRows[rowNumber] = SPxSolver::ON_LOWER;
3904  //}
3905  //else if( _compSolver.basis().desc().rowStatus(_compSolver.number(SPxColId(_decompDualColIDs[i + 1]))) ==
3906  //SPxBasis::Desc::D_ON_UPPER )
3907  //{
3908  //_basisStatusRows[rowNumber] = SPxSolver::ON_UPPER;
3909  //}
3910  //else
3911  //{
3912  //_basisStatusRows[rowNumber] = SPxSolver::BASIC;
3913  //basicRow++;
3914  //}
3915  //}
3916  //else
3917  //{
3918  //if( _compSolver.basis().desc().rowStatus(_compSolver.number(SPxColId(_decompDualColIDs[i]))) ==
3919  //SPxBasis::Desc::D_ON_UPPER )
3920  //{
3921  //_basisStatusRows[rowNumber] = SPxSolver::ON_UPPER;
3922  //}
3923  //else if( _compSolver.basis().desc().rowStatus(_compSolver.number(SPxColId(_decompDualColIDs[i + 1]))) ==
3924  //SPxBasis::Desc::D_ON_LOWER )
3925  //{
3926  //_basisStatusRows[rowNumber] = SPxSolver::ON_LOWER;
3927  //}
3928  //else
3929  //{
3930  //_basisStatusRows[rowNumber] = SPxSolver::BASIC;
3931  //basicRow++;
3932  //}
3933  //}
3934 
3935  i++;
3936  break;
3938  //assert(_realLP->number(SPxColId(_decompPrimalRowIDs[i])) ==
3939  //_realLP->number(SPxColId(_decompPrimalRowIDs[i+1])));
3940 
3941  //_basisStatusRows[rowNumber] = SPxSolver::FIXED;
3942 
3943  i++;
3944  break;
3946  //if( _compSolver.basis().desc().rowStatus(_compSolver.number(SPxColId(_decompDualColIDs[i]))) ==
3947  //SPxBasis::Desc::D_ON_LOWER )
3948  //{
3949  //_basisStatusRows[rowNumber] = SPxSolver::ON_LOWER;
3950  //}
3951  //else
3952  //{
3953  //_basisStatusRows[rowNumber] = SPxSolver::BASIC;
3954  //basicRow++;
3955  //}
3956 
3957  break;
3959  //if( _compSolver.basis().desc().rowStatus(_compSolver.number(SPxColId(_decompDualColIDs[i]))) ==
3960  //SPxBasis::Desc::D_ON_UPPER )
3961  //{
3962  //_basisStatusRows[rowNumber] = SPxSolver::ON_UPPER;
3963  //}
3964  //else
3965  //{
3966  //_basisStatusRows[rowNumber] = SPxSolver::BASIC;
3967  //basicRow++;
3968  //}
3969 
3970  break;
3971  default:
3972  throw SPxInternalCodeException("XDECOMPSL01 This should never happen.");
3973  }
3974  }
3975  }
3976 
3977  nNonBasicRows = _realLP->nRows() - basicRow - nDegenerateRows;
3978  MSG_INFO2(spxout, spxout << "Number of non-basic rows: " << nNonBasicRows << " (from "
3979  << _realLP->nRows() << ")" << std::endl );
3980  }
3981 
3982 
3983  /// function to retrieve the column status for the original problem basis from the reduced and complementary problems
3984  // all columns are currently in the reduced problem, so it is only necessary to retrieve the status from there.
3985  // However, a transformation of the columns has been made, so it is only possible to retrieve the status from the
3986  // variable bound constraints.
3988  {
3989  Real feastol = realParam(SoPlex::FEASTOL);
3990  int basicCol = 0;
3991  int numZeroDual = 0;
3992 
3993  // looping over all variable bound constraints
3994  for( int i = 0; i < _realLP->nCols(); i++ )
3995  {
3996  if( !_decompReducedProbColRowIDs[i].isValid() )
3997  continue;
3998 
3999  int rowNumber = _solver.number(_decompReducedProbColRowIDs[i]);
4000  if( _decompReducedProbColRowIDs[i].isValid() )
4001  {
4002  if( _solver.basis().desc().rowStatus(rowNumber) == SPxBasis::Desc::P_ON_UPPER ) /*||
4003  (_solver.basis().desc().rowStatus(rowNumber) == SPxBasis::Desc::D_ON_LOWER &&
4004  EQ(_solver.rhs(rowNumber) - _solver.pVec()[rowNumber], 0.0, feastol)) )*/
4005  {
4007  }
4008  else if( _solver.basis().desc().rowStatus(rowNumber) == SPxBasis::Desc::P_ON_LOWER ) /*||
4009  (_solver.basis().desc().rowStatus(rowNumber) == SPxBasis::Desc::D_ON_UPPER &&
4010  EQ(_solver.pVec()[rowNumber] - _solver.lhs(rowNumber), 0.0, feastol)) )*/
4011  {
4013  }
4014  else if( _solver.basis().desc().rowStatus(rowNumber) == SPxBasis::Desc::P_FIXED )
4015  {
4017  }
4018  else if( _solver.basis().desc().rowStatus(rowNumber) == SPxBasis::Desc::P_FREE )
4019  {
4021  }
4022  else
4023  {
4025  basicCol++;
4026  }
4027  }
4028 
4029  if( EQ(_solver.fVec()[i], 0.0, feastol) )
4030  numZeroDual++;
4031  }
4032 
4033  nNonBasicCols = _realLP->nCols() - basicCol;
4034  MSG_INFO2(spxout, spxout << "Number of non-basic columns: "
4035  << nNonBasicCols << " (from " << _realLP->nCols() << ")" << std::endl
4036  << "Number of zero dual columns: " << numZeroDual << " (from " << _realLP->nCols() << ")" << std::endl );
4037  }
4038 
4039 
4040 
4041  /// function to build a basis for the original problem as given by the solution to the reduced problem
4042  void SoPlex::_writeOriginalProblemBasis(const char* filename, NameSet* rowNames, NameSet* colNames, bool cpxFormat)
4043  {
4044  int numrows = _realLP->nRows();
4045  int numcols = _realLP->nCols();
4046  int nNonBasicRows = 0;
4047  int nNonBasicCols = 0;
4048  int nDegenerateRows = 0;
4049  DataArray< int > degenerateRowNums; // array to store the orig prob row number of degenerate rows
4050  DataArray< SPxSolver::VarStatus > degenerateRowStatus; // possible status for the degenerate rows in the orig prob
4051 
4052  // setting the basis status rows and columns to size of the original problem
4053  _basisStatusRows.reSize(numrows);
4054  _basisStatusCols.reSize(numcols);
4055 
4056  degenerateRowNums.reSize(numrows);
4057  degenerateRowStatus.reSize(numrows);
4058 
4059  // setting the row and column status for the original problem
4060  getOriginalProblemBasisRowStatus(degenerateRowNums, degenerateRowStatus, nDegenerateRows, nNonBasicRows);
4061  getOriginalProblemBasisColStatus(nNonBasicCols);
4062 
4063  // checking the consistency of the non-basic rows and columns for printing out the basis.
4064  // it is necessary to have numcols of non-basic rows and columns.
4065  // if there are not enought non-basic rows and columns, then the degenerate rows are set as non-basic.
4066  // all degenerate rows that are not changed to non-basic must be set to basic.
4067  assert(nDegenerateRows + nNonBasicRows + nNonBasicCols >= numcols);
4068  int degenRowsSetNonBasic = 0;
4069  for( int i = 0; i < nDegenerateRows; i++ )
4070  {
4071  if( nNonBasicRows + nNonBasicCols + degenRowsSetNonBasic < numcols )
4072  {
4073  _basisStatusRows[degenerateRowNums[i]] = degenerateRowStatus[i];
4074  degenRowsSetNonBasic++;
4075  }
4076  else
4077  _basisStatusRows[degenerateRowNums[i]] = SPxSolver::BASIC;
4078  }
4079 
4080  // writing the basis file for the original problem
4081  bool wasRealLPLoaded = _isRealLPLoaded;
4082  _isRealLPLoaded = false;
4083  writeBasisFile(filename, rowNames, colNames, cpxFormat);
4084  _isRealLPLoaded = wasRealLPLoaded;
4085  }
4086 } // namespace soplex
const VectorBase< R > & rhs() const
Returns right hand side vector.
Definition: spxlpbase.h:219
virtual Real objValue()
get objective value of current solution.
Definition: spxsolver.h:1981
virtual void buildDualProblem(SPxLPBase< R > &dualLP, SPxRowId primalRowIds[]=0, SPxColId primalColIds[]=0, SPxRowId dualRowIds[]=0, SPxColId dualColIds[]=0, int *nprimalrows=0, int *nprimalcols=0, int *ndualrows=0, int *ndualcols=0)
Building the dual problem from a given LP.
Real getMaxTime()
the maximum runtime
Definition: spxsolver.h:2130
Rational spxAbs(const Rational &r)
Absolute.
Definition: rational.cpp:3908
int _lastSolveMode
Definition: soplex.h:1826
SPxLPBase< Real > SPxLPReal
Definition: spxlp.h:36
Starting basis has been found and the simplex can be executed as normal.
Definition: spxsolver.h:185
int getSolveCount() const
number of solves performed
Definition: slufactor.h:263
virtual void changeRow(int i, const LPRow &newRow, bool scale=false)
int _nCompPrimalCols
Definition: soplex.h:1786
Exception class for things that should NEVER happen.This class is derived from the SoPlex exception b...
Definition: exceptions.h:109
virtual void removeRow(int i)
Removes i &#39;th row.
Definition: spxlpbase.h:904
virtual Real shift() const
total current shift amount.
Definition: spxsolver.h:1606
int iterations() const
get number of iterations of current solution.
Definition: spxsolver.h:2095
void getRow(int i, LPRowBase< R > &row) const
Gets i &#39;th row.
Definition: spxlpbase.h:180
free variable fixed to zero.
Definition: spxsolver.h:193
SPxRowId rId(int n) const
Returns the row identifier for row n.
Definition: spxlpbase.h:562
not initialised error
Definition: spxsolver.h:207
bool isSetup() const
Returns setup status.
Definition: ssvectorbase.h:120
bool GE(Real a, Real b, Real eps=Param::epsilon())
returns true iff a >= b + eps
Definition: spxdefines.h:406
void reDim(int newdim, const bool setZero=true)
Resets DVectorBase&#39;s dimension to newdim.
Definition: dvectorbase.h:249
int callsReducedProb
number of times the reduced problem is solved. This includes the initial solve.
Definition: statistics.h:116
SPxColId _compSlackColId
Definition: soplex.h:1748
void coSolve(Vector &x, const Vector &rhs)
Cosolves linear system with basis matrix.
Definition: spxbasis.h:719
virtual void unscalePrimal(const SPxLPBase< Real > &lp, Vector &x) const
unscale dense primal solution vector given in x.
Definition: spxscaler.cpp:604
int numRowsReal() const
returns number of rows
Definition: soplex.cpp:800
primal variable is fixed to both bounds
Definition: spxbasis.h:190
virtual void changeLower(const Vector &newLower, bool scale=false)
const R & objOffset() const
Returns the objective function value offset.
Definition: spxlpbase.h:516
int _nDecompViolRows
Definition: soplex.h:1773
const VectorBase< R > & upper() const
Returns upper bound vector.
Definition: spxlpbase.h:456
const RowViolation * entry
Definition: soplex.h:1705
virtual Status getPrimal(Vector &vector) const
get solution vector for primal variables.
Definition: spxsolve.cpp:1729
upper limit on objective value
Definition: soplex.h:1314
void _updateDecompReducedProblem(Real objVal, DVector dualVector, DVector redcostVector, DVector compPrimalVector, DVector compDualVector)
update the reduced problem with additional columns and rows
Definition: solvedbds.cpp:1115
virtual R minAbsNzo(bool unscaled=true) const
Absolute smallest non-zero element in (possibly scaled) LP.
THREADLOCAL const Real infinity
Definition: spxdefines.cpp:26
general zero tolerance
Definition: soplex.h:1293
Result
Result of the simplification.
Definition: spxsimplifier.h:81
void setOutstream(SPxOut &newOutstream)
Definition: spxlpbase.h:125
#define MAX_DEGENCHECK
Definition: solvedbds.cpp:27
the problem was so much simplified that it vanished
Definition: spxsimplifier.h:87
int origCountLower
Definition: soplex.h:1806
void setBasis(const VarStatus rows[], const VarStatus cols[])
set the lp solver&#39;s basis.
Definition: spxsolver.cpp:1870
virtual Result simplify(SPxLP &lp, Real eps, Real delta)=0
simplify SPxLP lp with identical primal and dual feasibility tolerance.
int numRedProbIter
Definition: soplex.h:1796
void _findViolatedRows(Real compObjValue, DataArray< RowViolation > &violatedrows, int &nviolatedrows)
builds the update rows with those violated in the complmentary problem
Definition: solvedbds.cpp:1459
void resetCounters()
reset timers and counters
Definition: slufactor.h:268
DataArray< SPxRowId > _decompPrimalRowIDs
Definition: soplex.h:1758
DataArray< SPxRowId > _decompElimPrimalRowIDs
Definition: soplex.h:1760
int origCountRhs
Definition: soplex.h:1813
void _checkOriginalProblemOptimality(Vector primalVector, bool printViol)
checking the optimality of the original problem.
Definition: solvedbds.cpp:2693
void _removeComplementaryDualFixedPrimalVars(int *currFixedVars)
removing the dual columns related to the fixed variables
Definition: solvedbds.cpp:2843
void _setComplementaryPrimalOriginalObjective()
updating the complementary primal problem with the original objective function
Definition: solvedbds.cpp:3181
T * get_ptr()
get a C pointer to the data.
Definition: dataarray.h:110
#define TIMELIMIT_FRAC
Definition: solvedbds.cpp:30
const VectorBase< R > & lhs() const
Returns the vector of lhs values.
Definition: lprowsetbase.h:95
int origCountUpper
Definition: soplex.h:1807
int size() const
Number of used indices.
Definition: svectorbase.h:152
objective offset
Definition: soplex.h:1356
DataArray< SPxRowId > _decompReducedProbColRowIDs
Definition: soplex.h:1756
Status getBasis(VarStatus rows[], VarStatus cols[], const int rowsSize=-1, const int colsSize=-1) const
get current basis, and return solver status.
Definition: spxsolver.cpp:1797
virtual void setBasisSolver(SLinSolver *slu, const bool destroy=false)
setup linear solver to use. If destroy is true, slusolver will be freed in destructor.
Definition: spxsolver.cpp:83
LPRowSet _transformedRows
Definition: soplex.h:1747
int _nDecompViolBounds
Definition: soplex.h:1772
Real sumDualDegeneracy()
get the sum of dual degeneracy
Definition: spxsolver.h:2083
DVector _transformedObj
Definition: soplex.h:1745
time limit in seconds (INFTY if unlimited)
Definition: soplex.h:1308
Status & rowStatus(int i)
Definition: spxbasis.h:239
bool isScaled() const
Returns true if and only if the LP is scaled.
Definition: spxlpbase.h:139
virtual void removeCols(int perm[])
Removes multiple columns.
Definition: spxlpbase.h:1020
bool LE(Real a, Real b, Real eps=Param::epsilon())
returns true iff a <= b + eps
Definition: spxdefines.h:394
Real getFactorTime() const
time spent in factorizations
Definition: slufactor.h:238
primal feasibility tolerance
Definition: soplex.h:1287
bool LT(Real a, Real b, Real eps=Param::epsilon())
returns true iff a < b + eps
Definition: spxdefines.h:388
const SVectorBase< R > & rowVector() const
Constraint row vector.
Definition: lprowbase.h:239
bool writeBasisFile(const char *filename, const NameSet *rowNames=0, const NameSet *colNames=0, const bool cpxFormat=false) const
writes basis information to filename; if rowNames and colNames are NULL, default names are used; retu...
Definition: soplex.cpp:5392
int numRedProbCols
number of columns in the reduced problem
Definition: statistics.h:121
solve() aborted due to iteration limit.
Definition: spxsolver.h:212
R rhs() const
Right-hand side value.
Definition: lprowbase.h:215
SPxScaler * _scaler
Definition: soplex.h:1608
void unSetup()
Makes SSVectorBase not setup.
Definition: ssvectorbase.h:126
No Problem has been loaded.
Definition: spxsolver.h:215
void setSolverStatus(SPxSolver::Status stat)
setting the solver status external from the solve loop.
Definition: spxsolver.h:2037
bool NE(Real a, Real b, Real eps=Param::epsilon())
returns true iff |a-b| > eps
Definition: spxdefines.h:382
int iterationsInit
number of iterations in the initial LP
Definition: statistics.h:117
virtual void unscaleRedCost(const SPxLPBase< Real > &lp, Vector &r) const
unscale dense reduced cost vector given in r.
Definition: spxscaler.cpp:640
int number(const SPxRowId &id) const
Returns the row number of the row with identifier id.
Definition: spxlpbase.h:522
virtual void unscaleDual(const SPxLPBase< Real > &lp, Vector &pi) const
unscale dense dual solution vector given in pi.
Definition: spxscaler.cpp:628
void _disableSimplifierAndScaler()
disables simplifier and scaler
Definition: soplex.cpp:8010
void add(const LPColBase< R > &pcol)
Definition: lpcolsetbase.h:255
bool * _decompReducedProbCols
Definition: soplex.h:1751
int _nDualCols
Definition: soplex.h:1784
Timer * simplexTime
simplex time
Definition: statistics.h:90
int _nElimPrimalRows
Definition: soplex.h:1782
int luSolvesReal
number of (forward and backward) solves with basis matrix in real precision
Definition: statistics.h:106
void _computeReducedProbObjCoeff(bool &stop)
computes the reduced problem objective coefficients
Definition: solvedbds.cpp:1791
variable fixed to identical bounds.
Definition: spxsolver.h:192
int origCountBoxed
Definition: soplex.h:1808
int luFactorizationsReal
number of basis matrix factorizations in real precision
Definition: statistics.h:105
objective sense
Definition: soplex.h:951
int getFactorCount() const
number of factorizations performed
Definition: slufactor.h:248
virtual void removeCol(int i)
Removes i &#39;th column.
Definition: spxlpbase.h:1001
LP has been proven to be primal infeasible.
Definition: spxsolver.h:221
int getOrigVarFixedDirection(int colNum)
determining which bound the primal variables will be fixed to.
Definition: solvedbds.cpp:3199
Real finalCompObj
the final objective function of the complementary problem
Definition: statistics.h:135
Ids for LP columns.Class SPxColId provides DataKeys for the column indices of an SPxLP.
Definition: spxid.h:36
virtual void changeCol(int i, const LPCol &newCol, bool scale=false)
int intParam(const IntParam param) const
returns integer parameter value
Definition: soplex.cpp:5541
void remove(int n, int m)
Remove nonzeros n thru m.
Definition: svectorbase.h:387
void setDegenCompOffset(int iterOffset)
sets the offset for the number of iterations before the degeneracy is computed
Definition: spxsolver.h:2223
bool getDecompBoundViolation(Real &maxviol, Real &sumviol)
gets violation of bounds; returns true on success
Definition: solvedbds.cpp:3616
int origCountRanged
Definition: soplex.h:1814
virtual Real value()
current objective value.
Definition: spxsolver.cpp:876
rowwise representation.
Definition: spxsolver.h:106
void _getCompatibleBoundCons(LPRowSet &boundcons, int *compatboundcons, int *nonposind, int *ncompatboundcons, int nnonposind, bool &stop)
computes the compatible bound constraints and adds them to the reduced problem
Definition: solvedbds.cpp:1857
void add(const LPRowBase< R > &row)
Definition: lprowsetbase.h:321
SPxSolver _compSolver
Definition: soplex.h:1737
virtual void setTerminationTime(Real time=infinity)
set time limit.
Definition: spxsolver.cpp:1553
int numDecompIter
Definition: soplex.h:1795
DataArray< SPxColId > _decompCompPrimalColIDs
Definition: soplex.h:1770
virtual void changeObjOffset(const R &o)
Definition: spxlpbase.h:1773
SPxColId cId(int n) const
Returns the column identifier for column n.
Definition: spxlpbase.h:568
virtual void removeRows(int perm[])
Removes multiple rows.
Definition: spxlpbase.h:923
int origCountFreeRow
Definition: soplex.h:1815
DataArray< SPxColId > _decompReducedProbColIDs
Definition: soplex.h:1757
virtual const std::string what() const
returns exception message
Definition: exceptions.h:57
dual variable is left free, but unset
Definition: spxbasis.h:191
Real getDegeneracyLevel(Vector degenvec)
get level of dual degeneracy
Definition: spxsolver.cpp:1892
int nRows() const
Returns number of rows in LP.
Definition: spxlpbase.h:151
void add(const SVectorBase< S > &vec)
Append nonzeros of sv.
Definition: dsvectorbase.h:216
DataArray< SPxRowId > _decompReducedProbRowIDs
Definition: soplex.h:1755
void printOriginalProblemStatistics(std::ostream &os)
stores the problem statistics of the original problem
Definition: solvedbds.cpp:3546
virtual void changeRhs(const Vector &newRhs, bool scale=false)
virtual void start()=0
start timer, resume accounting user, system and real time.
virtual Real stop()=0
stop timer, return accounted user time.
int compProbStatus
status of the complementary problem
Definition: statistics.h:134
int dualDegeneratePivots()
get number of dual degenerate pivots
Definition: spxsolver.h:2071
void spx_alloc(T &p, int n=1)
Allocate memory.
Definition: spxalloc.h:48
simplification could be done
Definition: spxsimplifier.h:83
primal variable is set to its upper bound
Definition: spxbasis.h:188
SLUFactor _compSlufactor
Definition: soplex.h:1741
void _formDecompReducedProblem(bool &stop)
forms the reduced problem
Definition: solvedbds.cpp:623
virtual void changeBounds(const Vector &newLower, const Vector &newUpper, bool scale=false)
LP is primal infeasible or unbounded.
Definition: spxsolver.h:222
int nNzos() const
Returns number of nonzeros in LP.
Definition: spxlpbase.h:163
void inValidate()
makes the DataKey invalid and clears the info field.
Definition: datakey.h:111
Leaving Simplex.
Definition: spxsolver.h:142
DataArray< SPxRowId > _decompCompPrimalRowIDs
Definition: soplex.h:1769
Real luFactorizationTimeReal
time for factorizing bases matrices in real precision
Definition: statistics.h:96
void _updateComplementaryPrimalFixedPrimalVars(int *currFixedVars)
updating the dual columns related to the fixed primal variables.
Definition: solvedbds.cpp:3073
DataArray< SPxSolver::VarStatus > _basisStatusCols
Definition: soplex.h:1829
SPxStatus status() const
returns current SPxStatus.
Definition: spxbasis.h:425
decompStatus _currentProb
Definition: soplex.h:1817
double Real
Definition: spxdefines.h:218
bool _isRealLPLoaded
Definition: soplex.h:1611
void _getZeroDualMultiplierIndices(Vector feasVector, int *nonposind, int *colsforremoval, int *nnonposind, bool &stop)
identifies the columns of the row-form basis that correspond to rows with zero dual multipliers...
Definition: solvedbds.cpp:1555
void _evaluateSolutionDecomp(SPxSolver &solver, SLUFactor &sluFactor, SPxSimplifier::Result result)
evaluates the solution of the reduced problem for the DBDS
Definition: solvedbds.cpp:3228
DVectorBase< R > _primal
Definition: solbase.h:218
void _setComplementaryDualOriginalObjective()
updating the complementary dual problem with the original objective function
Definition: solvedbds.cpp:3111
Status status() const
Status of solution process.
Definition: spxsolve.cpp:2046
Real sumPrimalDegeneracy()
get the sum of primal degeneracy
Definition: spxsolver.h:2089
bool GT(Real a, Real b, Real eps=Param::epsilon())
returns true iff a > b + eps
Definition: spxdefines.h:400
SPxSense spxSense() const
Returns the optimization sense.
Definition: spxlpbase.h:510
void _decompSimplifyAndSolve(SPxSolver &solver, SLUFactor &sluFactor, bool fromScratch, bool applyPreprocessing)
simplifies the problem and solves
Definition: solvedbds.cpp:858
bool getDecompRowViolation(Real &maxviol, Real &sumviol)
gets violation of constraints; returns true on success
Definition: solvedbds.cpp:3694
const VectorBase< R > & rhs() const
Returns the vector of rhs values.
Definition: lprowsetbase.h:131
Real maxRowViol
the max row violations in the original problem using the red prob sol
Definition: statistics.h:132
SPxColId colId(int i) const
ColId of i &#39;th column.
Definition: spxsolver.h:2257
virtual Real getObjoffset() const
get objective offset.
R lhs() const
Left-hand side value.
Definition: lprowbase.h:203
the iteration frequency at which the decomposition solve output is displayed.
Definition: soplex.h:1029
void _getCompatibleColumns(Vector feasVector, int *nonposind, int *compatind, int *rowsforremoval, int *colsforremoval, int nnonposind, int *ncompatind, bool formRedProb, bool &stop)
retrieves the compatible columns from the constraint matrix
Definition: solvedbds.cpp:1631
LP has been solved to optimality.
Definition: spxsolver.h:219
int getIdx() const
gets the index number (idx) of the DataKey.
Definition: datakey.h:96
#define MSG_INFO2(spxout, x)
Prints out message x if the verbosity level is at least SPxOut::INFO2.
Definition: spxdefines.h:120
bool _hasBasis
Definition: soplex.h:1835
virtual void changeSense(SPxSense sns)
#define MSG_ERROR(x)
Prints out message x if the verbosity level is at least SPxOut::ERROR.
Definition: spxdefines.h:114
Real sumPrimalDegen
the sum of the rate of primal degeneracy at each iteration
Definition: statistics.h:127
UpdateVector & fVec() const
feasibility vector.
Definition: spxsolver.h:1302
virtual void addRows(const LPRowSetBase< R > &pset, bool scale=false)
Definition: spxlpbase.h:635
Class for collecting statistical information.
bool isSPxColId() const
is id a column id?
Definition: spxid.h:165
dual variable is set to its upper bound
Definition: spxbasis.h:192
solve() aborted due to commence decomposition simplex
Definition: spxsolver.h:209
solve() aborted due to time limit.
Definition: spxsolver.h:211
SPxRowId _compSlackDualRowId
Definition: soplex.h:1749
an error occured.
Definition: spxsolver.h:203
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)
bool isBasic(SPxBasis::Desc::Status stat) const
does stat describe a basic index ?
Definition: spxsolver.h:1242
primal variable is left free, but unset
Definition: spxbasis.h:189
virtual void changeLower(const VectorBase< R > &newLower, bool scale=false)
Changes vector of lower bounds to newLower. scale determines whether the new data should be scaled...
Definition: spxlpbase.h:1360
LPRowBase< R >::Type rowType(int i) const
Returns the inequality type of the i&#39;th LPRow.
Definition: spxlpbase.h:324
virtual void setVerbosity(const Verbosity &v)
Definition: spxout.h:111
Statistics * _statistics
statistics since last call to solveReal() or solveRational()
Definition: soplex.h:1557
R obj(int i) const
Returns objective value of column i.
Definition: spxlpbase.h:403
int origCountFreeCol
Definition: soplex.h:1809
int numNonzeros
Definition: soplex.h:1802
Real getCompSlackVarCoeff(int primalRowNum)
gets the coefficient of the slack variable in the primal complementary problem
Definition: solvedbds.cpp:3570
solve() aborted to exit decomposition simplex
Definition: spxsolver.h:208
const VectorBase< R > & lhs() const
Returns left hand side vector.
Definition: spxlpbase.h:253
Real spxSqrt(Real a)
returns square root
Definition: spxdefines.h:332
Verbosity getVerbosity() const
Definition: spxout.h:117
#define MINIMUM(x, y)
Definition: spxdefines.h:247
virtual void getBasis(SPxSolver::VarStatus[], SPxSolver::VarStatus[], const int rowsSize=-1, const int colsSize=-1) const =0
get optimal basis.
SLUFactor _slufactor
Definition: soplex.h:1583
variable set to its upper bound.
Definition: spxsolver.h:190
int primalDegeneratePivots()
get number of primal degenerate pivots
Definition: spxsolver.h:2077
Real maxBoundViol
the max bound violation in the original problem using the red prob sol
Definition: statistics.h:131
Real realParam(const RealParam param) const
returns real parameter value
Definition: soplex.cpp:5551
primal infeasibility was detected
Definition: spxsimplifier.h:84
DataArray< SPxColId > _decompPrimalColIDs
Definition: soplex.h:1759
virtual Real time() const =0
void _decompResolveWithoutPreprocessing(SPxSolver &solver, SLUFactor &sluFactor, SPxSimplifier::Result result)
loads original problem into solver and solves again after it has been solved to optimality with prepr...
Definition: solvedbds.cpp:1030
int _nPrimalCols
Definition: soplex.h:1781
int boundFlips() const
get number of bound flips.
Definition: spxsolver.h:2065
int degenPivotsDual
number of dual degenerate pivots
Definition: statistics.h:123
SPxOut spxout
Definition: soplex.h:1457
infinity threshold
Definition: soplex.h:1305
algorithm is running
Definition: spxsolver.h:217
int index(int n) const
Returns index of the n &#39;th nonzero element.
Definition: ssvectorbase.h:174
Status & colStatus(int i)
Definition: spxbasis.h:254
(In)equality for LPs.Class LPRowBase provides constraints for linear programs in the form where a is...
Definition: lprowbase.h:45
virtual void loadLP(const SPxLP &LP, bool initSlackBasis=true)
copy LP.
Definition: spxsolver.cpp:68
variable set to its lower bound.
Definition: spxsolver.h:191
SPxId & baseId(int i)
Definition: spxbasis.h:503
Generic QuickSort implementation.
Preconfigured SoPlex LP solver.
#define MSG_INFO3(spxout, x)
Prints out message x if the verbosity level is at least SPxOut::INFO3.
Definition: spxdefines.h:122
void getOriginalProblemBasisColStatus(int &nNonBasicCols)
function to retrieve the column status for the original problem basis from the reduced and complement...
Definition: solvedbds.cpp:3987
virtual void changeRow(int n, const LPRowBase< R > &newRow, bool scale=false)
Replaces i &#39;th row of LP with newRow. scale determines whether the new data should be scaled...
Definition: spxlpbase.h:1593
virtual void changeUpper(const VectorBase< R > &newUpper, bool scale=false)
Changes vector of upper bounds to newUpper. scale determines whether the new data should be scaled...
Definition: spxlpbase.h:1397
void _createDecompReducedAndComplementaryProblems()
creating copies of the original problem that will be manipulated to form the reduced and complementar...
Definition: solvedbds.cpp:590
apply standard floating-point algorithm
Definition: soplex.h:1222
Set of strings.Class NameSet implements a symbol or name table. It allows to store or remove names (i...
Definition: nameset.h:61
DataArray< SPxColId > _decompFixedVarDualIDs
Definition: soplex.h:1763
DualSign getOrigProbDualVariableSign(int rowNumber)
returns the expected sign of the dual variables for the original problem
Definition: solvedbds.cpp:3405
Sequential object-oriented SimPlex.SPxSolver is an LP solver class using the revised Simplex algorith...
Definition: spxsolver.h:84
bool EQ(Real a, Real b, Real eps=Param::epsilon())
returns true iff |a-b| <= eps
Definition: spxdefines.h:376
Timer * preprocessingTime
preprocessing time
Definition: statistics.h:89
UpdateVector & pVec() const
pricing vector.
Definition: spxsolver.h:1457
Real luSolveTimeReal
time for solving linear systems in real precision
Definition: statistics.h:97
virtual void changeObj(const VectorBase< R > &newObj, bool scale=false)
Changes objective vector to newObj. scale determines whether the new data should be scaled...
Definition: spxlpbase.h:1291
virtual void addCol(const LPColBase< R > &col, bool scale=false)
Definition: spxlpbase.h:741
virtual void scale(SPxLPBase< Real > &lp, bool persistent=true)=0
scale SPxLP.
int dim() const
Dimension of vector.
Definition: vectorbase.h:215
Implementation of Sparse Linear Solver.This class implements a SLinSolver interface by using the spar...
Definition: slufactor.h:41
Starting basis has not been found yet.
Definition: spxsolver.h:183
Exception base class.This class implements a base class for our SoPlex exceptions We provide a what()...
Definition: exceptions.h:32
int size() const
Returns the number of nonzeros.
Definition: ssvectorbase.h:199
int * _decompViolatedRows
Definition: soplex.h:1775
DataArray< SPxColId > _decompVarBoundDualIDs
Definition: soplex.h:1764
DataArray< SPxRowId > _decompDualRowIDs
Definition: soplex.h:1761
Everything should be within this namespace.
int numCompProbIter
Definition: soplex.h:1797
void _writeOriginalProblemBasis(const char *filename, NameSet *rowNames, NameSet *colNames, bool cpxFormat)
function to build a basis for the original problem as given by the solution to the reduced problem ...
Definition: solvedbds.cpp:4042
SPxLPReal * _realLP
Definition: soplex.h:1605
the maximum number of rows that are added in each iteration of the decomposition based simplex ...
Definition: soplex.h:1026
void _preprocessAndSolveReal(bool applyPreprocessing)
solves real LP with/without preprocessing
Definition: solvereal.cpp:203
void _deleteAndUpdateRowsComplementaryProblem(SPxRowId rangedRowIds[], int &naddedrows)
removing rows from the complementary problem.
Definition: solvedbds.cpp:1997
void clear()
Remove all indices.
Definition: svectorbase.h:422
Real minAbsNonzero
Definition: soplex.h:1803
DVector _decompFeasVector
Definition: soplex.h:1746
virtual void printDisplayLine(const bool force=false, const bool forceHead=false)
print display line of flying table
Definition: spxsolve.cpp:1500
solve() aborted due to detection of cycling.
Definition: spxsolver.h:210
void _formDecompComplementaryProblem()
forms the complementary problem
Definition: solvedbds.cpp:719
Saving LPs in a form suitable for SoPlex.Class SPxLPBase provides the data structures required for sa...
Definition: spxlpbase.h:80
int * _fixedOrigVars
Definition: soplex.h:1778
Set of LP columns.Class LPColSetBase implements a set of LPColBase%s. Unless for memory limitations...
Definition: lpcolsetbase.h:43
primal unboundedness was detected
Definition: spxsimplifier.h:86
const SVectorBase< R > & rowVector(int i) const
Returns the rowVector of the i &#39;th LPRowBase.
Definition: lprowsetbase.h:209
int _nCompPrimalRows
Definition: soplex.h:1785
should the dual of the complementary problem be used in the decomposition simplex?
Definition: soplex.h:914
#define MSG_WARNING(spxout, x)
Prints out message x if the verbosity level is at least SPxOut::WARNING.
Definition: spxdefines.h:116
virtual void unsimplify(const Vector &, const Vector &, const Vector &, const Vector &, const SPxSolver::VarStatus[], const SPxSolver::VarStatus[], bool isOptimal=true)=0
reconstructs an optimal solution for the unsimplified LP.
int iterations
number of iterations/pivots
Definition: statistics.h:100
primal variable is set to its lower bound
Definition: spxbasis.h:187
Real maxAbsNonzero
Definition: soplex.h:1804
const VectorBase< R > & maxObj() const
Returns objective vector for maximization problem.
Definition: spxlpbase.h:429
void getOriginalProblemBasisRowStatus(DataArray< int > &degenerateRowNums, DataArray< SPxSolver::VarStatus > &degenerateRowStatus, int &nDegenerateRows, int &nNonBasicRows)
function to retrieve the original problem row basis status from the reduced and complementary problem...
Definition: solvedbds.cpp:3797
int _decompDisplayLine
Definition: soplex.h:1788
void setRowVector(const DSVectorBase< R > &p_vec)
access constraint row vector.
Definition: lprowbase.h:245
#define DEGENCHECK_OFFSET
Definition: solvedbds.cpp:28
int boundflips
number of dual bound flips
Definition: statistics.h:104
SPxSolver _solver
Definition: soplex.h:1582
nothing known on loaded problem.
Definition: spxsolver.h:218
void printDecompDisplayLine(SPxSolver &solver, const SPxOut::Verbosity origVerb, bool force, bool forceHead)
prints a display line of the flying table for the DBDS
Definition: solvedbds.cpp:3425
int SPxQuicksortPart(T *keys, COMPARATOR &compare, int start, int end, int size, int start2=0, int end2=0, bool type=true)
Generic implementation of Partial QuickSort.
Definition: sorter.h:219
Verbosity
Verbosity level.
Definition: spxout.h:72
int iterationsRedProb
number of iterations of the reduced problem
Definition: statistics.h:118
void _identifyComplementaryPrimalFixedPrimalVars(int *currFixedVars)
removing the dual columns related to the fixed variables
Definition: solvedbds.cpp:3044
variable is basic.
Definition: spxsolver.h:194
const SVectorBase< R > & rowVector(int i) const
Gets row vector of row i.
Definition: spxlpbase.h:204
bool * _decompReducedProbRows
Definition: soplex.h:1750
void _getRowsForRemovalComplementaryProblem(int *nonposind, int *bind, int *rowsforremoval, int *nrowsforremoval, int nnonposind)
computes the rows to remove from the complementary problem
Definition: solvedbds.cpp:1977
virtual bool isUnsimplified() const
specifies whether an optimal solution has already been unsimplified.
bool isSPxRowId() const
is id a row id?
Definition: spxid.h:160
DataArray< SPxSolver::VarStatus > _basisStatusRows
Definition: soplex.h:1828
Real totalRowViol
the sum of the row violations in the original problem using the red prob sol
Definition: statistics.h:130
int iterationsFromBasis
number of iterations from Basis
Definition: statistics.h:102
int origCountLhs
Definition: soplex.h:1812
void _solveDecompositionDualSimplex()
solves LP using the decomposition based dual simplex
Definition: solvedbds.cpp:47
dual variable is set to its lower bound
Definition: spxbasis.h:193
Timer * solvingTime
solving time
Definition: statistics.h:88
int size() const
return nr. of elements.
Definition: dataarray.h:211
SPxBasis _decompTransBasis
Definition: soplex.h:1743
Type type() const
return current Type.
Definition: spxsolver.h:493
bool boolParam(const BoolParam param) const
returns boolean parameter value
Definition: soplex.cpp:5531
the verbosity of the decomposition based simplex
Definition: soplex.h:1032
Real getSolveTime() const
time spent in solves
Definition: slufactor.h:253
virtual Status getRedCost(Vector &vector) const
get vector of reduced costs.
Definition: spxsolve.cpp:1809
void _storeSolutionReal(bool verify=true)
stores solution of the real LP; before calling this, the real LP must be loaded in the solver and sol...
Definition: solvereal.cpp:428
#define MSG_INFO1(spxout, x)
Prints out message x if the verbosity level is at least SPxOut::INFO1.
Definition: spxdefines.h:118
Real solveTime() const
time spent in last call to solve
Definition: soplex.cpp:5047
const SVectorBase< R > & colVector(int i) const
Returns column vector of column i.
Definition: spxlpbase.h:373
int _nDualRows
Definition: soplex.h:1783
int nCols() const
Returns number of columns in LP.
Definition: spxlpbase.h:157
unsigned int _isPrimalFeasible
Definition: solbase.h:227
SolReal _solReal
Definition: soplex.h:1831
int iterationsPrimal
number of iterations with Primal
Definition: statistics.h:101
bool _hasSolReal
Definition: soplex.h:1836
int numProbRows
Definition: soplex.h:1800
int * _decompViolatedBounds
Definition: soplex.h:1774
void _updateComplementaryDualSlackColCoeff()
updating the slack column coefficients to adjust for equality constraints
Definition: solvedbds.cpp:2762
int iterationsCompProb
number of iterations of the complementary problem
Definition: statistics.h:119
virtual void init()
intialize data structures.
Definition: spxsolver.cpp:305
Ids for LP rows.Class SPxRowId provides DataKeys for the row indices of an SPxLP. ...
Definition: spxid.h:55
dual feasibility tolerance
Definition: soplex.h:1290
bool isZero(Real a, Real eps=Param::epsilon())
returns true iff |a| <= eps
Definition: spxdefines.h:412
void solve(Vector &x, const Vector &rhs)
Definition: spxbasis.h:631
const SVector & vector(int i) const
i &#39;th vector.
Definition: spxsolver.h:1136
void _identifyComplementaryDualFixedPrimalVars(int *currFixedVars)
removing the dual columns related to the fixed variables
Definition: solvedbds.cpp:2799
void _updateComplementaryDualFixedPrimalVars(int *currFixedVars)
updating the dual columns related to the fixed primal variables.
Definition: solvedbds.cpp:2906
DualSign getExpectedDualVariableSign(int rowNumber)
returns the expected sign of the dual variables for the reduced problem
Definition: solvedbds.cpp:3386
bool decompTerminate(Real timeLimit)
function call to terminate the decomposition simplex
Definition: solvedbds.cpp:3774
bool isRowBasic(int i) const
is the i &#39;th row vector basic ?
Definition: spxsolver.h:1269
void getOriginalProblemStatistics()
stores the problem statistics of the original problem
Definition: solvedbds.cpp:3467
int origCountEqual
Definition: soplex.h:1811
void _enableSimplifierAndScaler()
enables simplifier and scaler according to current parameters
Definition: soplex.cpp:7961
int _nPrimalRows
Definition: soplex.h:1780
int redProbStatus
status of the reduced problem
Definition: statistics.h:133
bool checkBasisDualFeasibility(Vector feasVec)
checks the dual feasibility of the current basis
Definition: solvedbds.cpp:3334
virtual void unscaleSlacks(const SPxLPBase< Real > &lp, Vector &s) const
unscale dense slack vector given in s.
Definition: spxscaler.cpp:616
void setOutstream(SPxOut &newOutstream)
Definition: spxsolver.h:450
Real sumDualDegen
the sum of the rate of dual degeneracy at each iteration
Definition: statistics.h:126
#define SLACKCOEFF
Definition: solvedbds.cpp:29
void setDecompIterationLimit(int iterationLimit)
sets the iteration limit for the decomposition simplex initialisation
Definition: spxsolver.h:2236
virtual void setTerminationValue(Real value=infinity)
set objective limit.
Definition: spxsolver.cpp:1617
const SPxBasis & basis() const
Return current basis.
Definition: spxsolver.h:1740
the number of iterations before the decomposition simplex initialisation is terminated.
Definition: soplex.h:1023
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...
int numIncludedRows
Definition: soplex.h:1794
virtual void reLoad()
reload LP.
Definition: spxsolver.cpp:55
void _updateDecompReducedProblemViol(bool allrows)
update the reduced problem with additional columns and rows based upon the violated original bounds a...
Definition: solvedbds.cpp:1310
int numColsReal() const
returns number of columns
Definition: soplex.cpp:809
virtual Status solve()
solve loaded LP.
Definition: spxsolve.cpp:130
void reSize(int newsize)
reset size to newsize.
Definition: dataarray.h:223
SPxLPReal * _decompLP
Definition: soplex.h:1606
const VectorBase< R > & lower() const
Returns (internal and possibly scaled) lower bound vector.
Definition: spxlpbase.h:483
SPxSolver::Status _status
Definition: soplex.h:1825
virtual R maxAbsNzo(bool unscaled=true) const
Absolute biggest non-zero element in (in rational case possibly scaled) LP.
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...
void setDecompStatus(DecompStatus decomp_stat)
turn on or off the improved dual simplex.
Definition: spxsolver.cpp:437
SPxRowId rowId(int i) const
RowId of i &#39;th inequality.
Definition: spxsolver.h:2252
LP column.Class LPColBase provides a datatype for storing the column of an LP a the form similar to ...
Definition: lpcolbase.h:45
const Desc & desc() const
Definition: spxbasis.h:463
Real totalBoundViol
the sum of the bound violations in the original problem using the red prob sol
Definition: statistics.h:129
Representation rep() const
return the current basis representation.
Definition: spxsolver.h:487
solve() aborted due to objective limit.
Definition: spxsolver.h:213
void spx_free(T &p)
Release memory.
Definition: spxalloc.h:109
SPxSimplifier * _simplifier
Definition: soplex.h:1607
void _updateDecompComplementaryPrimalProblem(bool origObj)
update the primal complementary problem with additional columns and rows
Definition: solvedbds.cpp:2451
int numProbCols
Definition: soplex.h:1801
DataArray< SPxColId > _decompDualColIDs
Definition: soplex.h:1762
virtual void addCols(const LPColSetBase< R > &pset, bool scale=false)
Definition: spxlpbase.h:793
virtual Status getDual(Vector &vector) const
get current solution vector for dual variables.
Definition: spxsolve.cpp:1778
Basis is singular, numerical troubles?
Definition: spxsolver.h:214
R value(int n) const
Returns value of the n &#39;th nonzero element.
Definition: ssvectorbase.h:182
const SVector & unitVector(int i) const
return i &#39;th unit vector.
Definition: spxsolver.h:1215
should row and bound violations be computed explicitly in the update of reduced problem in the decomp...
Definition: soplex.h:917
int numRedProbRows
number of rows in the reduced problem
Definition: statistics.h:120
int * _decompCompProbColIDsIdx
Definition: soplex.h:1754
LP has a usable Basis (maybe LP is changed).
Definition: spxsolver.h:216
int primalIterations()
return number of iterations done with primal algorithm
Definition: spxsolver.h:2101
dual infeasibility was detected
Definition: spxsimplifier.h:85
virtual Status getSlacks(Vector &vector) const
get vector of slack variables.
Definition: spxsolve.cpp:1888
LP has been proven to be primal unbounded.
Definition: spxsolver.h:220
int degenPivotsPrimal
number of primal degenerate pivots
Definition: statistics.h:122
No Problem has been loaded to the basis.
Definition: spxbasis.h:92
void _updateDecompComplementaryDualProblem(bool origObj)
update the dual complementary problem with additional columns and rows
Definition: solvedbds.cpp:2069