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