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 #ifdef KEEP_ALL_ROWS_IN_COMP_PROB
2231  bool incrementI = false;
2232 #endif
2233  if( i + 1 < prevPrimalRowIds
2235  {
2236  assert(_decompPrimalRowIDs[i].idx == _decompPrimalRowIDs[i+1].idx);
2237 
2238 #ifdef KEEP_ALL_ROWS_IN_COMP_PROB // 22.06.2015
2240  {
2242  _compSolver.changeBounds(_decompDualColIDs[i + 1], 0.0, 0.0);
2243  }
2244  incrementI = true;
2245 #else
2246  colsforremoval[ncolsforremoval] = _compSolver.number(SPxColId(_decompDualColIDs[i + 1]));
2247  ncolsforremoval++;
2248 
2249  _decompPrimalRowIDs.remove(i + 1);
2250  _nPrimalRows--;
2251  _decompDualColIDs.remove(i + 1);
2252  _nDualCols--;
2253 
2254  prevPrimalRowIds--;
2255 #endif
2256  }
2257  //assert(i + 1 == prevPrimalRowIds || _decompPrimalRowIDs[i].idx != _decompPrimalRowIDs[i+1].idx);
2258 
2259  int solverRowNum = _solver.number(_decompReducedProbRowIDs[rowNumber]);
2260  assert(solverRowNum >= 0 && solverRowNum < _solver.nRows());
2261  if( _solver.basis().desc().rowStatus(solverRowNum) == SPxBasis::Desc::P_ON_UPPER ||
2262  _solver.basis().desc().rowStatus(solverRowNum) == SPxBasis::Desc::P_FIXED ||
2263  _solver.basis().desc().rowStatus(solverRowNum) == SPxBasis::Desc::D_FREE ||
2264  (_solver.basis().desc().rowStatus(solverRowNum) == SPxBasis::Desc::D_ON_LOWER &&
2265  LE(_solver.rhs(solverRowNum) - _solver.pVec()[solverRowNum], 0.0, feastol)) )
2266  {
2267  //assert(GT(dualVector[solverRowNum], 0.0));
2270  }
2271  else if( _solver.basis().desc().rowStatus(solverRowNum) == SPxBasis::Desc::P_ON_LOWER ||
2272  (_solver.basis().desc().rowStatus(solverRowNum) == SPxBasis::Desc::D_ON_UPPER &&
2273  LE(_solver.pVec()[solverRowNum] - _solver.lhs(solverRowNum), 0.0, feastol)) )
2274  {
2275  //assert(LT(dualVector[solverRowNum], 0.0));
2278  }
2279  else //if ( _solver.basis().desc().rowStatus(solverRowNum) != SPxBasis::Desc::D_FREE )
2280  {
2281  //assert(isZero(dualVector[solverRowNum], 0.0));
2282 
2283  // 22.06.2015 Testing keeping all rows in the complementary problem
2284 #ifdef KEEP_ALL_ROWS_IN_COMP_PROB
2285  switch( _realLP->rowType(_decompPrimalRowIDs[i]) )
2286  {
2288  assert(_realLP->number(SPxColId(_decompPrimalRowIDs[i])) ==
2292 
2297 
2298  i++;
2299  break;
2303  break;
2307  break;
2308  default:
2309  throw SPxInternalCodeException("XDECOMPSL01 This should never happen.");
2310  }
2311 
2312 #else // 22.06.2015 testing keeping all rows in the complementary problem
2313  colsforremoval[ncolsforremoval] = _compSolver.number(SPxColId(_decompDualColIDs[i]));
2314  ncolsforremoval++;
2315 
2316  if( _nElimPrimalRows >= _decompElimPrimalRowIDs.size() )
2318 
2320  _nElimPrimalRows++;
2321  _decompPrimalRowIDs.remove(i);
2322  _nPrimalRows--;
2323  _decompDualColIDs.remove(i);
2324  _nDualCols--;
2325 
2326  i--;
2327  prevPrimalRowIds--;
2328 #endif
2329  }
2330 #ifdef KEEP_ALL_ROWS_IN_COMP_PROB
2331  if( incrementI )
2332  i++;
2333 #endif
2334  }
2335  else
2336  {
2337  switch( _realLP->rowType(_decompPrimalRowIDs[i]) )
2338  {
2340  assert(_realLP->number(SPxColId(_decompPrimalRowIDs[i])) ==
2346  {
2347  slackRowCoeff.add(_compSolver.number(SPxColId(_decompDualColIDs[i])), -SLACKCOEFF);
2348  slackRowCoeff.add(_compSolver.number(SPxColId(_decompDualColIDs[i + 1])), SLACKCOEFF);
2349  }
2350  else
2351  {
2352  slackRowCoeff.add(_compSolver.number(SPxColId(_decompDualColIDs[i])), SLACKCOEFF);
2353  slackRowCoeff.add(_compSolver.number(SPxColId(_decompDualColIDs[i + 1])), -SLACKCOEFF);
2354  }
2355 
2356 
2357  i++;
2358  break;
2360  assert(_realLP->number(SPxColId(_decompPrimalRowIDs[i])) ==
2362 
2363  slackRowCoeff.add(_compSolver.number(SPxColId(_decompDualColIDs[i])), SLACKCOEFF);
2364  slackRowCoeff.add(_compSolver.number(SPxColId(_decompDualColIDs[i + 1])), SLACKCOEFF);
2365 
2366  i++;
2367  break;
2369  slackRowCoeff.add(_compSolver.number(SPxColId(_decompDualColIDs[i])), -SLACKCOEFF);
2370  break;
2372  slackRowCoeff.add(_compSolver.number(SPxColId(_decompDualColIDs[i])), SLACKCOEFF);
2373  break;
2374  default:
2375  throw SPxInternalCodeException("XDECOMPSL01 This should never happen.");
2376  }
2377 
2378  if( origObj )
2379  {
2380  int numRemove = 1;
2381  int removeCount = 0;
2384  numRemove++;
2385 
2386  do
2387  {
2388  colsforremoval[ncolsforremoval] = _compSolver.number(SPxColId(_decompDualColIDs[i]));
2389  ncolsforremoval++;
2390 
2391  if( _nElimPrimalRows >= _decompElimPrimalRowIDs.size() )
2393 
2395  _nElimPrimalRows++;
2396  _decompPrimalRowIDs.remove(i);
2397  _nPrimalRows--;
2398  _decompDualColIDs.remove(i);
2399  _nDualCols--;
2400 
2401  i--;
2402  prevPrimalRowIds--;
2403 
2404  removeCount++;
2405  } while( removeCount < numRemove );
2406  }
2407  }
2408  }
2409 
2410  // updating the slack column in the complementary problem
2411  Real lhs = 1.0;
2412  Real rhs = 1.0;
2413 
2414  // it is possible that all rows are included in the reduced problem. In this case, the slack row will be empty. To
2415  // avoid infeasibility, the lhs and rhs are set to 0.
2416  if( slackRowCoeff.size() == 0 )
2417  {
2418  lhs = 0.0;
2419  rhs = 0.0;
2420  }
2421  LPRowBase<Real> compSlackRow(lhs, slackRowCoeff, rhs);
2422  _compSolver.changeRow(_compSlackDualRowId, compSlackRow);
2423 
2424 
2425  // if the original objective is used, then all dual columns related to primal rows not in the reduced problem are
2426  // removed from the complementary problem.
2427  // As a result, the slack row becomes an empty row.
2428  int* perm = 0;
2429  spx_alloc(perm, _compSolver.nCols() + numElimColsAdded);
2430  _compSolver.removeCols(colsforremoval, ncolsforremoval, perm);
2431 
2432 
2433  // updating the dual columns to represent the fixed primal variables.
2434  int* currFixedVars = 0;
2435  spx_alloc(currFixedVars, _realLP->nCols());
2439 
2440 
2441  // freeing allocated memory
2442  spx_free(currFixedVars);
2443  spx_free(perm);
2444  spx_free(colsforremoval);
2445  }
2446 
2447 
2448 
2449  /// update the primal complementary problem with additional columns and rows
2450  // Given the solution to the updated reduced problem, the complementary problem will be updated with modifications to
2451  // the constraints and the removal of variables
2453  {
2454  Real feastol = realParam(SoPlex::FEASTOL);
2455 
2456  int prevNumRows = _compSolver.nRows();
2457  int prevPrimalRowIds = _nPrimalRows;
2458 
2459  assert(_nPrimalRows == _nCompPrimalRows);
2460 
2461  LPRowSetBase<Real> addElimRows(_nElimPrimalRows); // rows previously eliminated from the
2462  // complementary problem that must be added
2463  int numElimRowsAdded = 0;
2464  // looping over all rows from the original LP that were eliminated during the formation of the complementary
2465  // problem. The eliminated rows will be added if they are basic in the reduced problem.
2466 
2467  for( int i = 0; i < _nElimPrimalRows; i++ )
2468  {
2469  int rowNumber = _realLP->number(_decompElimPrimalRowIDs[i]);
2470 
2471  int solverRowNum = _solver.number(_decompReducedProbRowIDs[rowNumber]);
2472  assert(solverRowNum >= 0 && solverRowNum < _solver.nRows());
2473 
2474  // checking the rows that are basic in the reduced problem that should be added to the complementary problem
2475  if( _solver.basis().desc().rowStatus(solverRowNum) == SPxBasis::Desc::P_ON_UPPER
2476  || _solver.basis().desc().rowStatus(solverRowNum) == SPxBasis::Desc::P_ON_LOWER
2477  || _solver.basis().desc().rowStatus(solverRowNum) == SPxBasis::Desc::P_FIXED
2478  || _solver.basis().desc().rowStatus(solverRowNum) == SPxBasis::Desc::D_FREE
2479  || (_solver.basis().desc().rowStatus(solverRowNum) == SPxBasis::Desc::D_ON_LOWER &&
2480  EQ(_solver.rhs(solverRowNum) - _solver.pVec()[solverRowNum], 0.0, feastol))
2481  || (_solver.basis().desc().rowStatus(solverRowNum) == SPxBasis::Desc::D_ON_UPPER &&
2482  EQ(_solver.pVec()[solverRowNum] - _solver.lhs(solverRowNum), 0.0, feastol)) )
2483  {
2484  LPRowReal origlprow;
2485  _realLP->getRow(rowNumber, origlprow);
2486 
2487  // NOTE: 11.02.2016 I am assuming that all columns from the original problem are contained in the
2488  // complementary problem. Will need to check this. Since nothing is happenning in the
2489  // _deleteAndUpdateRowsComplementaryProblem function, I am feeling confident that all columns remain.
2490 
2491 
2492  if( _solver.basis().desc().rowStatus(solverRowNum) == SPxBasis::Desc::P_ON_UPPER
2493  || _solver.basis().desc().rowStatus(solverRowNum) == SPxBasis::Desc::P_FIXED
2494  || _solver.basis().desc().rowStatus(solverRowNum) == SPxBasis::Desc::D_FREE
2495  || (_solver.basis().desc().rowStatus(solverRowNum) == SPxBasis::Desc::D_ON_LOWER &&
2496  EQ(_solver.rhs(solverRowNum) - _solver.pVec()[solverRowNum], 0.0, feastol)) )
2497  {
2499 
2500  if( _nPrimalRows >= _decompPrimalRowIDs.size() )
2501  {
2504  }
2505 
2506  addElimRows.add(_realLP->rhs(_decompElimPrimalRowIDs[i]), origlprow.rowVector(),
2508 
2510  _nPrimalRows++;
2511 
2512  _decompElimPrimalRowIDs.remove(i);
2513  _nElimPrimalRows--;
2514  i--;
2515 
2516  numElimRowsAdded++;
2517  }
2518  else if( _solver.basis().desc().rowStatus(solverRowNum) == SPxBasis::Desc::P_ON_LOWER
2519  || (_solver.basis().desc().rowStatus(solverRowNum) == SPxBasis::Desc::D_ON_UPPER &&
2520  EQ(_solver.pVec()[solverRowNum] - _solver.lhs(solverRowNum), 0.0, feastol)) )
2521  {
2522  assert(GT(_realLP->lhs(_decompElimPrimalRowIDs[i]), -infinity));
2523 
2524  if( _nPrimalRows >= _decompPrimalRowIDs.size() )
2525  {
2528  }
2529 
2530  addElimRows.add(_realLP->lhs(_decompElimPrimalRowIDs[i]), origlprow.rowVector(),
2532 
2534  _nPrimalRows++;
2535 
2536  _decompElimPrimalRowIDs.remove(i);
2537  _nElimPrimalRows--;
2538  i--;
2539 
2540  numElimRowsAdded++;
2541  }
2542  }
2543  }
2544 
2545  MSG_INFO2(spxout, spxout << "Number of eliminated rows added to the complementary problem: "
2546  << numElimRowsAdded << std::endl );
2547 
2548  // adding the eliminated rows to the complementary problem.
2549  _compSolver.addRows(addElimRows);
2550  for( int i = prevNumRows; i < _compSolver.nRows(); i++ )
2551  {
2552  _decompCompPrimalRowIDs[prevPrimalRowIds + i - prevNumRows] = _compSolver.rowId(i);
2553  _nCompPrimalRows++;
2554  }
2555 
2556  assert(_nPrimalRows == _nCompPrimalRows);
2557 
2558 
2559  // looping over all rows from the original problem that were originally contained in the complementary problem.
2560  // The basic rows will be set as equalities, the non-basic rows will be eliminated from the complementary
2561  // problem.
2562  DSVector slackColCoeff(_compSolver.nRows());
2563 
2564  int* rowsforremoval = 0;
2565  int nrowsforremoval = 0;
2566  spx_alloc(rowsforremoval, prevPrimalRowIds);
2567  for( int i = 0; i < prevPrimalRowIds; i++ )
2568  {
2569  int rowNumber = _realLP->number(_decompPrimalRowIDs[i]);
2570  // this loop runs over all rows previously in the complementary problem. If rows are added to the reduced
2571  // problem, they will be transfered from the incompatible set to the compatible set in the following if
2572  // statement.
2573  if( _decompReducedProbRows[rowNumber] )
2574  {
2575  // rows added to the reduced problem may have been equality constriants. The equality constraints from the
2576  // original problem are converted into <= and >= constraints. Upon adding these constraints to the reduced
2577  // problem, only a single dual column is needed in the complementary problem. Hence, one of the dual columns
2578  // is removed.
2579  //
2580 
2581  int solverRowNum = _solver.number(_decompReducedProbRowIDs[rowNumber]);
2582  assert(solverRowNum >= 0 && solverRowNum < _solver.nRows());
2583  if( _solver.basis().desc().rowStatus(solverRowNum) == SPxBasis::Desc::P_ON_UPPER
2584  || _solver.basis().desc().rowStatus(solverRowNum) == SPxBasis::Desc::P_FIXED
2585  || _solver.basis().desc().rowStatus(solverRowNum) == SPxBasis::Desc::D_FREE
2586  || (_solver.basis().desc().rowStatus(solverRowNum) == SPxBasis::Desc::D_ON_LOWER &&
2587  EQ(_solver.rhs(solverRowNum) - _solver.pVec()[solverRowNum], 0.0, feastol)) )
2588  {
2590  // need to also update the RHS because a ranged row could have previously been fixed to LOWER
2592  }
2593  else if( _solver.basis().desc().rowStatus(solverRowNum) == SPxBasis::Desc::P_ON_LOWER
2594  || (_solver.basis().desc().rowStatus(solverRowNum) == SPxBasis::Desc::D_ON_UPPER &&
2595  EQ(_solver.pVec()[solverRowNum] - _solver.lhs(solverRowNum), 0.0, feastol)) )
2596  {
2598  // need to also update the LHS because a ranged row could have previously been fixed to UPPER
2600  }
2601  else //if ( _solver.basis().desc().rowStatus(solverRowNum) != SPxBasis::Desc::D_FREE )
2602  {
2603  rowsforremoval[nrowsforremoval] = _compSolver.number(SPxRowId(_decompCompPrimalRowIDs[i]));
2604  nrowsforremoval++;
2605 
2606  if( _nElimPrimalRows >= _decompElimPrimalRowIDs.size() )
2608 
2610  _nElimPrimalRows++;
2611  _decompPrimalRowIDs.remove(i);
2612  _nPrimalRows--;
2613  _decompCompPrimalRowIDs.remove(i);
2614  _nCompPrimalRows--;
2615 
2616  i--;
2617  prevPrimalRowIds--;
2618  }
2619  }
2620  else
2621  {
2623  {
2625  assert(false);
2626  break;
2628  assert(false);
2629  break;
2631  slackColCoeff.add(_compSolver.number(SPxRowId(_decompCompPrimalRowIDs[i])), -SLACKCOEFF);
2632  break;
2635  break;
2636  default:
2637  throw SPxInternalCodeException("XDECOMPSL01 This should never happen.");
2638  }
2639 
2640  // this is used as a check at the end of the algorithm. If the original objective function is used, then we
2641  // need to remove all unfixed variables.
2642  if( origObj )
2643  {
2644  rowsforremoval[nrowsforremoval] = _compSolver.number(SPxRowId(_decompCompPrimalRowIDs[i]));
2645  nrowsforremoval++;
2646 
2647  if( _nElimPrimalRows >= _decompElimPrimalRowIDs.size() )
2649 
2651  _nElimPrimalRows++;
2652  _decompPrimalRowIDs.remove(i);
2653  _nPrimalRows--;
2654  _decompCompPrimalRowIDs.remove(i);
2655  _nCompPrimalRows--;
2656 
2657  i--;
2658  prevPrimalRowIds--;
2659  }
2660  }
2661  }
2662 
2663  // updating the slack column in the complementary problem
2664  LPColBase<Real> compSlackCol(-1, slackColCoeff, infinity, 0.0);
2665  _compSolver.changeCol(_compSlackColId, compSlackCol);
2666 
2667 
2668  // if the original objective is used, then all complementary rows related to primal rows not in the reduced problem are
2669  // removed from the complementary problem.
2670  // As a result, the slack column becomes an empty column.
2671  int* perm = 0;
2672  spx_alloc(perm, _compSolver.nRows() + numElimRowsAdded);
2673  _compSolver.removeRows(rowsforremoval, nrowsforremoval, perm);
2674 
2675  // updating the dual columns to represent the fixed primal variables.
2676  int* currFixedVars = 0;
2677  spx_alloc(currFixedVars, _realLP->nCols());
2680 
2681 
2682  // freeing allocated memory
2683  spx_free(currFixedVars);
2684  spx_free(perm);
2685  spx_free(rowsforremoval);
2686  }
2687 
2688 
2689 
2690  /// checking the optimality of the original problem.
2691  // this function is called if the complementary problem is solved with a non-negative objective value. This implies
2692  // that the rows currently included in the reduced problem are sufficient to identify the optimal solution to the
2693  // original problem.
2694  void SoPlex::_checkOriginalProblemOptimality(Vector primalVector, bool printViol)
2695  {
2696  SSVector x(_solver.nCols());
2697  x.unSetup();
2698 
2699  // multiplying the solution vector of the reduced problem with the transformed basis to identify the original
2700  // solution vector.
2701  _decompTransBasis.coSolve(x, primalVector);
2702 
2703  if( printViol )
2704  {
2705  MSG_INFO1(spxout, spxout << std::endl
2706  << "Checking consistency between the reduced problem and the original problem." << std::endl );
2707  }
2708 
2709 
2710  // checking the objective function values of the reduced problem and the original problem.
2711  Real redObjVal = 0;
2712  Real objectiveVal = 0;
2713  for( int i = 0; i < _solver.nCols(); i++ )
2714  {
2715  redObjVal += _solver.maxObj(i)*primalVector[i];
2716  objectiveVal += _realLP->maxObj(i)*x[i];
2717  }
2718 
2719  if( printViol )
2720  {
2721  MSG_INFO1(spxout, spxout << "Reduced Problem Objective Value: " << redObjVal << std::endl
2722  << "Original Problem Objective Value: " << objectiveVal << std::endl );
2723  }
2724 
2725  _solReal._isPrimalFeasible = true;
2726  _hasSolReal = true;
2727  // get the primal solutions from the reduced problem
2729  _solReal._primal = x;
2730 
2731  Real maxviol = 0;
2732  Real sumviol = 0;
2733 
2734  // checking the bound violations
2735  if( getDecompBoundViolation(maxviol, sumviol) )
2736  {
2737  if( printViol )
2738  MSG_INFO1(spxout, spxout << "Bound violation - "
2739  << "Max violation: " << maxviol << " Sum violation: " << sumviol << std::endl );
2740  }
2741 
2742  _statistics->totalBoundViol = sumviol;
2743  _statistics->maxBoundViol = maxviol;
2744 
2745  // checking the row violations
2746  if( getDecompRowViolation(maxviol, sumviol) )
2747  {
2748  if( printViol )
2749  MSG_INFO1(spxout, spxout << "Row violation - "
2750  << "Max violation: " << maxviol << " Sum violation: " << sumviol << std::endl );
2751  }
2752 
2753  _statistics->totalRowViol = sumviol;
2754  _statistics->maxRowViol = maxviol;
2755 
2756  if( printViol )
2757  MSG_INFO1(spxout, spxout << std::endl );
2758  }
2759 
2760 
2761 
2762  /// updating the slack column coefficients to adjust for equality constraints
2764  {
2765  // the slack column for the equality constraints is not handled correctly in the dual conversion. Hence, it is
2766  // necessary to change the equality coefficients of the dual row related to the slack column.
2767  for( int i = 0; i < _nPrimalRows; i++ )
2768  {
2769  int rowNumber = _realLP->number(SPxRowId(_decompPrimalRowIDs[i]));
2770  if( !_decompReducedProbRows[rowNumber] )
2771  {
2773  {
2775  _compSolver.changeLower(_decompDualColIDs[i], 0.0); // setting the lower bound of the dual column to zero.
2776 
2777  LPColBase<Real> addEqualityCol(-_realLP->rhs(_decompPrimalRowIDs[i]),
2778  Real(-1.0)*_compSolver.colVector(_decompDualColIDs[i]), infinity, 0.0); // adding a new column to the dual
2779 
2780  SPxColId newDualCol;
2781  _compSolver.addCol(newDualCol, addEqualityCol);
2782 
2783  // inserting the row and col ids for the added column. This is to be next to the original column that has
2784  // been duplicated.
2785  _decompPrimalRowIDs.insert(i + 1, 1, _decompPrimalRowIDs[i]);
2786  _decompDualColIDs.insert(i + 1, 1, newDualCol);
2788 
2789  i++;
2790  _nPrimalRows++;
2791  _nDualCols++;
2792  }
2793  }
2794  }
2795  }
2796 
2797 
2798 
2799  /// identify the dual columns related to the fixed variables
2801  {
2802  Real feastol = realParam(SoPlex::FEASTOL);
2803 
2804  int numFixedVar = 0;
2805  for( int i = 0; i < _realLP->nCols(); i++ )
2806  {
2807  currFixedVars[i] = 0;
2808  if( !_decompReducedProbColRowIDs[i].isValid() )
2809  continue;
2810 
2811  int rowNumber = _solver.number(_decompReducedProbColRowIDs[i]);
2812  if( _decompReducedProbColRowIDs[i].isValid() )
2813  {
2814  if( _solver.basis().desc().rowStatus(rowNumber) == SPxBasis::Desc::P_ON_UPPER ||
2816  _solver.basis().desc().rowStatus(rowNumber) == SPxBasis::Desc::P_FIXED ||
2817  _solver.basis().desc().rowStatus(rowNumber) == SPxBasis::Desc::D_FREE )
2818  {
2819  // setting the value of the _fixedOrigVars array to indicate which variables are at their bounds.
2820  currFixedVars[i] = getOrigVarFixedDirection(i);
2821 
2822  numFixedVar++;
2823  }
2824  else
2825  {
2826  // the dual flags do not imply anything about the primal status of the rows.
2827  if( _solver.basis().desc().rowStatus(rowNumber) == SPxBasis::Desc::D_ON_LOWER &&
2828  EQ(_solver.rhs(rowNumber) - _solver.pVec()[rowNumber], 0.0, feastol) )
2829  currFixedVars[i] = 1;
2830  else if( _solver.basis().desc().rowStatus(rowNumber) == SPxBasis::Desc::D_ON_UPPER &&
2831  EQ(_solver.pVec()[rowNumber] - _solver.lhs(rowNumber), 0.0, feastol) )
2832  currFixedVars[i] = -1;
2833  }
2834  }
2835  }
2836 
2837  MSG_INFO3(spxout, spxout << "Number of fixed primal variables in the complementary (dual) problem: "
2838  << numFixedVar << std::endl );
2839  }
2840 
2841 
2842 
2843  /// removing the dual columns related to the fixed variables
2845  {
2846  SPxColId tempId;
2847  int ncolsforremoval = 0;
2848  int* colsforremoval = 0;
2849  spx_alloc(colsforremoval, _realLP->nCols()*2);
2850 
2851  tempId.inValidate();
2852  for( int i = 0; i < _realLP->nCols(); i++ )
2853  {
2854  assert(_decompCompProbColIDsIdx[i] != -1); // this should be true in the current implementation
2855  if( _decompCompProbColIDsIdx[i] != -1 && _fixedOrigVars[i] != -2 )//&& _fixedOrigVars[i] != currFixedVars[i] )
2856  {
2857  if( _fixedOrigVars[i] != 0 )
2858  {
2860  assert(_fixedOrigVars[i] == -1 || _fixedOrigVars[i] == 1);
2861  assert(_decompFixedVarDualIDs[i].isValid());
2862 
2863  colsforremoval[ncolsforremoval] = _compSolver.number(SPxColId(_decompFixedVarDualIDs[i]));
2864  ncolsforremoval++;
2865 
2866  _decompFixedVarDualIDs[i] = tempId;
2867  }
2868  else //if( false && !_decompReducedProbColRowIDs[i].isValid() ) // we want to remove all valid columns
2869  // in the current implementation, the only columns not included in the reduced problem are free columns.
2870  {
2871  assert((LE(_realLP->lower(i), -infinity) && GE(_realLP->upper(i), infinity)) ||
2873  int varcount = 0;
2874  if( GT(_realLP->lower(i), -infinity) )
2875  {
2876  colsforremoval[ncolsforremoval] = _compSolver.number(SPxColId(_decompVarBoundDualIDs[i*2 + varcount]));
2877  ncolsforremoval++;
2878 
2879  _decompVarBoundDualIDs[i*2 + varcount] = tempId;
2880  varcount++;
2881  }
2882 
2883  if( LT(_realLP->upper(i), infinity) )
2884  {
2885  colsforremoval[ncolsforremoval] = _compSolver.number(SPxColId(_decompVarBoundDualIDs[i*2 + varcount]));
2886  ncolsforremoval++;
2887 
2888  _decompVarBoundDualIDs[i*2 + varcount] = tempId;
2889  }
2890 
2891  }
2892  }
2893  }
2894 
2895  int* perm = 0;
2896  spx_alloc(perm, _compSolver.nCols());
2897  _compSolver.removeCols(colsforremoval, ncolsforremoval, perm);
2898 
2899  // freeing allocated memory
2900  spx_free(perm);
2901  spx_free(colsforremoval);
2902  }
2903 
2904 
2905 
2906  /// updating the dual columns related to the fixed primal variables.
2908  {
2909  DSVectorBase<Real> col(1);
2910  LPColSetBase<Real> boundConsCols;
2911  LPColSetBase<Real> fixedVarsDualCols(_nPrimalCols);
2912  int numFixedVars = 0;
2913  // the solution to the reduced problem results in a number of variables at their bounds. If such variables exist
2914  // it is necessary to include a dual column to the complementary problem related to a variable fixing. This is
2915  // equivalent to the tight constraints being converted to equality constraints.
2916  int numBoundConsCols = 0;
2917  int* boundConsColsAdded = 0;
2918  spx_alloc(boundConsColsAdded, _realLP->nCols());
2919  // NOTE: this loop only goes over the primal columns that are included in the complementary problem, i.e. the
2920  // columns from the original problem.
2921  // 29.04.15 in the current implementation, all bound constraints are included in the reduced problem. So, all
2922  // variables (columns) are included in the reduced problem.
2923  for( int i = 0; i < _realLP->nCols(); i++ )
2924  {
2925  boundConsColsAdded[i] = 0;
2926  assert(_decompCompProbColIDsIdx[i] != -1);
2927  if( _decompCompProbColIDsIdx[i] != -1 )
2928  {
2929  int idIndex = _decompCompProbColIDsIdx[i];
2930  assert(_compSolver.number(SPxRowId(_decompDualRowIDs[idIndex])) >= 0);
2931  col.add(_compSolver.number(SPxRowId(_decompDualRowIDs[idIndex])), 1.0);
2932  if( currFixedVars[i] != 0 )
2933  {
2934  assert(currFixedVars[i] == -1 || currFixedVars[i] == 1);
2935 
2938  Real colObjCoeff = 0;
2939  if( currFixedVars[i] == -1 )
2940  colObjCoeff = _solver.lhs(_decompReducedProbColRowIDs[i]);
2941  else
2942  colObjCoeff = _solver.rhs(_decompReducedProbColRowIDs[i]);
2943 
2944  fixedVarsDualCols.add(colObjCoeff, -infinity, col, infinity);
2945  numFixedVars++;
2946  }
2947  // 09.02.15 I think that the else should only be entered if the column does not exist in the reduced
2948  // prob. I have tested by just leaving this as an else (without the if), but I think that this is wrong.
2949  //else if( !_decompReducedProbColRowIDs[i].isValid() )
2950 
2951  // NOTE: in the current implementation all columns, except the free columns, are included int the reduced
2952  // problem. There in no need to include the variable bounds in the complementary problem.
2953  else //if( false && _fixedOrigVars[i] == -2 )
2954  {
2955  bool isRedProbCol = _decompReducedProbColRowIDs[i].isValid();
2956  // 29.04.15 in the current implementation only free variables are not included in the reduced problem
2957  if( GT(_realLP->lower(i), -infinity) )
2958  {
2959  if( !isRedProbCol )
2961  boundConsCols.add(_realLP->lower(i), Real(-infinity), col, 0.0);
2962 
2963  if( !isRedProbCol )
2964  col.remove(col.size() - 1);
2965 
2966  boundConsColsAdded[i]++;
2967  numBoundConsCols++;
2968  }
2969 
2970  if( LT(_realLP->upper(i), infinity) )
2971  {
2972  if( !isRedProbCol )
2974  boundConsCols.add(_realLP->upper(i), 0.0, col, Real(infinity));
2975 
2976  if( !isRedProbCol )
2977  col.remove(col.size() - 1);
2978 
2979  boundConsColsAdded[i]++;
2980  numBoundConsCols++;
2981  }
2982  }
2983  col.clear();
2984  _fixedOrigVars[i] = currFixedVars[i];
2985  }
2986  }
2987 
2988  // adding the fixed var dual columns to the complementary problem
2989  SPxColId* addedcolids = 0;
2990  spx_alloc(addedcolids, numFixedVars);
2991  _compSolver.addCols(addedcolids, fixedVarsDualCols);
2992 
2993  SPxColId tempId;
2994  int addedcolcount = 0;
2995 
2996  tempId.inValidate();
2997  for( int i = 0; i < _realLP->nCols(); i++ )
2998  {
2999  if( _fixedOrigVars[i] != 0 )
3000  {
3001  assert(_fixedOrigVars[i] == -1 || _fixedOrigVars[i] == 1);
3002  _decompFixedVarDualIDs[i] = addedcolids[addedcolcount];
3003  addedcolcount++;
3004  }
3005  else
3006  _decompFixedVarDualIDs[i] = tempId;
3007  }
3008 
3009  // adding the bound cons dual columns to the complementary problem
3010  SPxColId* addedbndcolids = 0;
3011  spx_alloc(addedbndcolids, numBoundConsCols);
3012  _compSolver.addCols(addedbndcolids, boundConsCols);
3013 
3014  addedcolcount = 0;
3015  for( int i = 0; i < _realLP->nCols(); i++ )
3016  {
3017  if( boundConsColsAdded[i] > 0 )
3018  {
3019  for( int j = 0; j < boundConsColsAdded[i]; j++ )
3020  {
3021  _decompVarBoundDualIDs[i*2 + j] = addedbndcolids[addedcolcount];
3022  addedcolcount++;
3023  }
3024  }
3025 
3026  switch( boundConsColsAdded[i] )
3027  {
3028  case 0:
3029  _decompVarBoundDualIDs[i*2] = tempId;
3030  // FALLTHROUGH
3031  case 1:
3032  _decompVarBoundDualIDs[i*2 + 1] = tempId;
3033  break;
3034  }
3035  }
3036 
3037  // freeing allocated memory
3038  spx_free(addedbndcolids);
3039  spx_free(addedcolids);
3040  spx_free(boundConsColsAdded);
3041  }
3042 
3043 
3044  /// identify the dual columns related to the fixed variables
3046  {
3047  int numFixedVar = 0;
3048  for( int i = 0; i < _realLP->nCols(); i++ )
3049  {
3050  currFixedVars[i] = 0;
3051  if( !_decompReducedProbColRowIDs[i].isValid() )
3052  continue;
3053 
3054  int rowNumber = _solver.number(_decompReducedProbColRowIDs[i]);
3055  if( _decompReducedProbColRowIDs[i].isValid() &&
3056  (_solver.basis().desc().rowStatus(rowNumber) == SPxBasis::Desc::P_ON_UPPER ||
3058  _solver.basis().desc().rowStatus(rowNumber) == SPxBasis::Desc::P_FIXED) )
3059  {
3060  // setting the value of the _fixedOrigVars array to indicate which variables are at their bounds.
3061  currFixedVars[i] = getOrigVarFixedDirection(i);
3062 
3063  numFixedVar++;
3064  }
3065  }
3066 
3067  MSG_INFO3(spxout, spxout << "Number of fixed primal variables in the complementary (primal) problem: "
3068  << numFixedVar << std::endl );
3069  }
3070 
3071 
3072 
3073  /// updating the dual columns related to the fixed primal variables.
3075  {
3076  int numFixedVars = 0;
3077  // NOTE: this loop only goes over the primal columns that are included in the complementary problem, i.e. the
3078  // columns from the original problem.
3079  // 29.04.15 in the current implementation, all bound constraints are included in the reduced problem. So, all
3080  // variables (columns) are included in the reduced problem.
3081  for( int i = 0; i < _nCompPrimalCols; i++ )
3082  {
3083  int colNumber = _compSolver.number(SPxColId(_decompCompPrimalColIDs[i]));
3084  if( _fixedOrigVars[colNumber] != currFixedVars[colNumber] )
3085  {
3086  if( currFixedVars[colNumber] != 0 )
3087  {
3088  assert(currFixedVars[colNumber] == -1 || currFixedVars[colNumber] == 1);
3089 
3090  if( currFixedVars[colNumber] == -1 )
3093  else
3096 
3097  numFixedVars++;
3098  }
3099  else
3100  {
3101  _compSolver.changeBounds(colNumber, -infinity, infinity);
3102  }
3103  }
3104 
3105  _fixedOrigVars[colNumber] = currFixedVars[colNumber];
3106  }
3107  }
3108 
3109 
3110 
3111  /// updating the complementary dual problem with the original objective function
3113  {
3114  for( int i = 0; i < _realLP->nCols(); i++ )
3115  {
3116  assert(_decompCompProbColIDsIdx[i] != -1); // this should be true in the current implementation
3117  int idIndex = _decompCompProbColIDsIdx[i];
3118  int compRowNumber = _compSolver.number(_decompDualRowIDs[idIndex]);
3119  if( _decompCompProbColIDsIdx[i] != -1 )
3120  {
3121  // In the dual conversion, when a variable has a non-standard bound it is converted to a free variable.
3122  if( LE(_realLP->lower(i), -infinity) && GE(_realLP->upper(i), infinity) )
3123  {
3124  // unrestricted variable
3125  _compSolver.changeLhs(compRowNumber, _realLP->obj(i));
3126  _compSolver.changeRhs(compRowNumber, _realLP->obj(i));
3127  assert(LE(_compSolver.lhs(compRowNumber), _compSolver.rhs(compRowNumber)));
3128  }
3129  else if( LE(_realLP->lower(i), -infinity) )
3130  {
3131  // variable with a finite upper bound
3132  _compSolver.changeRhs(compRowNumber, _realLP->obj(i));
3133  if( isZero(_realLP->upper(i)) )
3134  _compSolver.changeLhs(compRowNumber, -infinity);
3135  else
3136  _compSolver.changeLhs(compRowNumber, _realLP->obj(i));
3137  }
3138  else if( GE(_realLP->upper(i), infinity) )
3139  {
3140  // variable with a finite lower bound
3141  _compSolver.changeLhs(compRowNumber, _realLP->obj(i));
3142  if( isZero(_realLP->upper(i)) )
3143  _compSolver.changeRhs(compRowNumber, infinity);
3144  else
3145  _compSolver.changeRhs(compRowNumber, _realLP->obj(i));
3146  }
3147  else if( NE(_realLP->lower(i), _realLP->upper(i)) )
3148  {
3149  // variable with a finite upper and lower bound
3150  if( isZero(_realLP->upper(i)) )
3151  {
3152  _compSolver.changeLhs(compRowNumber, _realLP->obj(i));
3153  _compSolver.changeRhs(compRowNumber, infinity);
3154  }
3155  else if( isZero(_realLP->upper(i)) )
3156  {
3157  _compSolver.changeLhs(compRowNumber, -infinity);
3158  _compSolver.changeRhs(compRowNumber, _realLP->obj(i));
3159  }
3160  else
3161  {
3162  _compSolver.changeLhs(compRowNumber, _realLP->obj(i));
3163  _compSolver.changeRhs(compRowNumber, _realLP->obj(i));
3164  }
3165  }
3166  else
3167  {
3168  // fixed variable
3169  _compSolver.changeLhs(compRowNumber, _realLP->obj(i));
3170  _compSolver.changeRhs(compRowNumber, _realLP->obj(i));
3171  }
3172  }
3173  }
3174 
3175  // removing the complementary problem slack column dual row
3177  }
3178 
3179 
3180 
3181  /// updating the complementary primal problem with the original objective function
3183  {
3184  // the comp solver has not removed any columns. Only the slack variables have been added.
3185  assert(_realLP->nCols() == _compSolver.nCols() - 1);
3186  for( int i = 0; i < _realLP->nCols(); i++ )
3187  {
3188  int colNumber = _realLP->number(_decompPrimalColIDs[i]);
3189  int compColNumber = _compSolver.number(_decompCompPrimalColIDs[i]);
3190  _compSolver.changeObj(compColNumber, _realLP->maxObj(colNumber));
3191  }
3192 
3193  // removing the complementary problem slack column dual row
3195  }
3196 
3197 
3198 
3199  /// determining which bound the primal variables will be fixed to.
3201  {
3202  if( !_decompReducedProbColRowIDs[colNum].isValid() )
3203  return 0;
3204 
3205  int rowNumber = _solver.number(_decompReducedProbColRowIDs[colNum]);
3206  // setting the value of the _fixedOrigVars array to indicate which variables are at their bounds.
3207  if( _solver.basis().desc().rowStatus(rowNumber) == SPxBasis::Desc::P_ON_UPPER ||
3208  _solver.basis().desc().rowStatus(rowNumber) == SPxBasis::Desc::P_FIXED ||
3209  _solver.basis().desc().rowStatus(rowNumber) == SPxBasis::Desc::D_FREE )
3210  {
3211  assert(_solver.rhs(rowNumber) < infinity);
3212  return 1;
3213  }
3214  else if( _solver.basis().desc().rowStatus(rowNumber) == SPxBasis::Desc::P_ON_LOWER )
3215  {
3216  assert(_solver.lhs(rowNumber) > -infinity);
3217  return -1;
3218  }
3219 
3220  return 0;
3221  }
3222 
3223 
3224 
3225  // @todo update this function and related comments. It has only been hacked together.
3226  /// checks result of the solving process and solves again without preprocessing if necessary
3227  // @todo need to evaluate the solution to ensure that it is solved to optimality and then we are able to perform the
3228  // next steps in the algorithm.
3230  {
3232  if( result == SPxSimplifier::INFEASIBLE )
3233  solverStat = SPxSolver::INFEASIBLE;
3234  else if( result == SPxSimplifier::DUAL_INFEASIBLE )
3235  solverStat = SPxSolver::INForUNBD;
3236  else if( result == SPxSimplifier::UNBOUNDED )
3237  solverStat = SPxSolver::UNBOUNDED;
3238  else if( result == SPxSimplifier::VANISHED )
3239  solverStat = SPxSolver::OPTIMAL;
3240  else if( result == SPxSimplifier::OKAY )
3241  solverStat = solver.status();
3242 
3243  // updating the status of SoPlex if the problem solved is the reduced problem.
3245  _status = solverStat;
3246 
3247  // process result
3248  switch( solverStat )
3249  {
3250  case SPxSolver::OPTIMAL:
3251  if( !_isRealLPLoaded )
3252  {
3254  _decompResolveWithoutPreprocessing(solver, sluFactor, result);
3255  // Need to solve the complementary problem
3256  return;
3257  }
3258  else
3259  _hasBasis = true;
3260 
3261  break;
3262 
3263  case SPxSolver::UNBOUNDED:
3264  case SPxSolver::INFEASIBLE:
3265  case SPxSolver::INForUNBD:
3266  // in case of infeasibility or unboundedness, we currently can not unsimplify, but have to solve the original LP again
3267  if( !_isRealLPLoaded )
3268  {
3270  _decompSimplifyAndSolve(solver, sluFactor, false, false);
3271  return;
3272  }
3273  else
3274  _hasBasis = (solver.basis().status() > SPxBasis::NO_PROBLEM);
3275  break;
3276 
3279  // in the initialisation of the decomposition simplex, we want to keep the current basis.
3280  if( !_isRealLPLoaded )
3281  {
3283  _decompResolveWithoutPreprocessing(solver, sluFactor, result);
3284  //_decompSimplifyAndSolve(solver, sluFactor, false, false);
3285  return;
3286  }
3287  else
3288  _hasBasis = (solver.basis().status() > SPxBasis::NO_PROBLEM);
3289  break;
3290 
3291  case SPxSolver::SINGULAR:
3293  // in case of infeasibility or unboundedness, we currently can not unsimplify, but have to solve the original LP again
3294  if( !_isRealLPLoaded )
3295  {
3297  _decompSimplifyAndSolve(solver, sluFactor, false, false);
3298  return;
3299  }
3300  break;
3301 
3302 
3303  // else fallthrough
3304  case SPxSolver::ABORT_TIME:
3305  case SPxSolver::ABORT_ITER:
3307  case SPxSolver::REGULAR:
3308  case SPxSolver::RUNNING:
3309  // store regular basis if there is no simplifier and the original problem is not in the solver because of
3310  // scaling; non-optimal bases should currently not be unsimplified
3311  if( _simplifier == 0 && solver.basis().status() > SPxBasis::NO_PROBLEM )
3312  {
3315  assert(_basisStatusRows.size() == solver.nRows());
3316  assert(_basisStatusCols.size() == solver.nCols());
3317 
3319  _hasBasis = true;
3320  }
3321  else
3322  _hasBasis = false;
3323  break;
3324 
3325  default:
3326  _hasBasis = false;
3327  break;
3328  }
3329  }
3330 
3331 
3332 
3333 
3334  /// checks the dual feasibility of the current basis
3336  {
3337  assert(_solver.rep() == SPxSolver::ROW);
3339 
3340  Real feastol = realParam(SoPlex::FEASTOL);
3341  // iterating through all elements in the basis to determine whether the dual feasibility is satisfied.
3342  for( int i = 0; i < _solver.nCols(); i++ )
3343  {
3344  if( _solver.basis().baseId(i).isSPxRowId() ) // find the row id's for rows in the basis
3345  {
3346  int rownumber = _solver.number(_solver.basis().baseId(i));
3347  if( _solver.basis().desc().rowStatus(rownumber) != SPxBasis::Desc::P_ON_UPPER &&
3348  _solver.basis().desc().rowStatus(rownumber) != SPxBasis::Desc::P_FIXED )
3349  {
3350  if( GT(feasVec[i], 0, feastol) )
3351  return false;
3352  }
3353 
3354  if( _solver.basis().desc().rowStatus(rownumber) != SPxBasis::Desc::P_ON_LOWER &&
3355  _solver.basis().desc().rowStatus(rownumber) != SPxBasis::Desc::P_FIXED )
3356  {
3357  if( LT(feasVec[i], 0, feastol) )
3358  return false;
3359  }
3360 
3361  }
3362  else if( _solver.basis().baseId(i).isSPxColId() ) // get the column id's for the columns in the basis
3363  {
3364  int colnumber = _solver.number(_solver.basis().baseId(i));
3365  if( _solver.basis().desc().colStatus(colnumber) != SPxBasis::Desc::P_ON_UPPER &&
3366  _solver.basis().desc().colStatus(colnumber) != SPxBasis::Desc::P_FIXED )
3367  {
3368  if( GT(feasVec[i], 0, feastol) )
3369  return false;
3370  }
3371 
3372  if( _solver.basis().desc().colStatus(colnumber) != SPxBasis::Desc::P_ON_LOWER &&
3373  _solver.basis().desc().colStatus(colnumber) != SPxBasis::Desc::P_FIXED )
3374  {
3375  if( LT(feasVec[i], 0, feastol) )
3376  return false;
3377  }
3378  }
3379  }
3380 
3381  return true;
3382  }
3383 
3384 
3385 
3386  /// returns the expected sign of the dual variables for the reduced problem
3388  {
3389  if( _solver.isRowBasic(rowNumber) )
3390  {
3391  if( _solver.basis().desc().rowStatus(rowNumber) != SPxBasis::Desc::P_ON_UPPER &&
3392  _solver.basis().desc().rowStatus(rowNumber) != SPxBasis::Desc::P_FIXED )
3393  return SoPlex::IS_NEG;
3394 
3395  if( _solver.basis().desc().rowStatus(rowNumber) != SPxBasis::Desc::P_ON_LOWER &&
3396  _solver.basis().desc().rowStatus(rowNumber) != SPxBasis::Desc::P_FIXED )
3397  return SoPlex::IS_POS;
3398  }
3399 
3400  return SoPlex::IS_FREE;
3401  }
3402 
3403 
3404 
3405  /// returns the expected sign of the dual variables for the original problem
3407  {
3408  if( _realLP->rowType(rowNumber) == LPRowBase<Real>::LESS_EQUAL )
3409  return IS_POS;
3410 
3411  if( _realLP->rowType(rowNumber) == LPRowBase<Real>::GREATER_EQUAL )
3412  return IS_NEG;
3413 
3414  if( _realLP->rowType(rowNumber) == LPRowBase<Real>::EQUAL )
3415  return IS_FREE;
3416 
3417  // this final statement needs to be checked.
3418  if( _realLP->rowType(rowNumber) == LPRowBase<Real>::RANGE )
3419  return IS_FREE;
3420 
3421  return IS_FREE;
3422  }
3423 
3424 
3425  /// print display line of flying table
3426  void SoPlex::printDecompDisplayLine(SPxSolver& solver, const SPxOut::Verbosity origVerb, bool force, bool forceHead)
3427  {
3428  // setting the verbosity level
3429  const SPxOut::Verbosity currVerb = spxout.getVerbosity();
3430  spxout.setVerbosity( origVerb );
3431 
3432  int displayFreq = intParam(SoPlex::DECOMP_DISPLAYFREQ);
3433 
3434  MSG_INFO1( spxout,
3435  if( forceHead || (_decompDisplayLine % (displayFreq*30) == 0) )
3436  {
3437  spxout << "type | time | iters | red iter | alg iter | rows | cols | shift | value\n";
3438  }
3439  if( force || (_decompDisplayLine % displayFreq == 0) )
3440  {
3441  Real currentTime = _statistics->solvingTime->time();
3442  (solver.type() == SPxSolver::LEAVE) ? spxout << " L |" : spxout << " E |";
3443  spxout << std::fixed << std::setw(7) << std::setprecision(1) << currentTime << " |";
3444  spxout << std::scientific << std::setprecision(2);
3445  spxout << std::setw(8) << _statistics->iterations << " | ";
3446  spxout << std::scientific << std::setprecision(2);
3447  spxout << std::setw(8) << _statistics->iterationsRedProb << " | ";
3448  spxout << std::scientific << std::setprecision(2);
3449  spxout << std::setw(8) << _statistics->callsReducedProb << " | ";
3450  spxout << std::scientific << std::setprecision(2);
3451  spxout << std::setw(8) << numIncludedRows << " | ";
3452  spxout << std::scientific << std::setprecision(2);
3453  spxout << std::setw(8) << solver.nCols() << " | "
3454  << solver.shift() << " | "
3455  << std::setprecision(8) << solver.value() + solver.objOffset()
3456  << std::endl;
3457 
3458  }
3460  );
3461 
3462  spxout.setVerbosity( currVerb );
3463  }
3464 
3465 
3466 
3467  /// stores the problem statistics of the original problem
3469  {
3470  numProbRows = _realLP->nRows();
3471  numProbCols = _realLP->nCols();
3472  numNonzeros = _realLP->nNzos();
3475 
3476  origCountLower = 0;
3477  origCountUpper = 0;
3478  origCountBoxed = 0;
3479  origCountFreeCol = 0;
3480 
3481  origCountLhs = 0;
3482  origCountRhs = 0;
3483  origCountRanged = 0;
3484  origCountFreeRow = 0;
3485 
3486  for( int i = 0; i < _realLP->nCols(); i++ )
3487  {
3488  bool hasLower = false;
3489  bool hasUpper = false;
3490 
3491  if( _realLP->lower(i) > -infinity )
3492  {
3493  origCountLower++;
3494  hasLower = true;
3495  }
3496 
3497  if( _realLP->upper(i) < infinity )
3498  {
3499  origCountUpper++;
3500  hasUpper = true;
3501  }
3502 
3503  if( hasUpper && hasLower )
3504  origCountBoxed++;
3505 
3506  if( !hasUpper && !hasLower )
3507  origCountFreeCol++;
3508  }
3509 
3510  for( int i = 0; i < _realLP->nRows(); i++)
3511  {
3512  bool hasRhs = false;
3513  bool hasLhs = false;
3514 
3515  if( _realLP->lhs(i) > -infinity )
3516  {
3517  origCountLhs++;
3518  hasLhs = true;
3519  }
3520 
3521  if( _realLP->rhs(i) < infinity )
3522  {
3523  origCountRhs++;
3524  hasRhs = true;
3525  }
3526 
3527  if( hasRhs && hasLhs )
3528  origCountRanged++;
3529 
3530  if( !hasRhs && !hasLhs )
3531  origCountFreeRow++;
3532  }
3533  }
3534 
3535 
3537  {
3538  os << " Columns : " << numProbCols << "\n"
3539  << " boxed : " << origCountBoxed << "\n"
3540  << " lower bound : " << origCountLower << "\n"
3541  << " upper bound : " << origCountUpper << "\n"
3542  << " free : " << origCountFreeCol << "\n"
3543  << " Rows : " << numProbRows << "\n"
3544  << " ranged : " << origCountRanged << "\n"
3545  << " lhs : " << origCountLhs << "\n"
3546  << " rhs : " << origCountRhs << "\n"
3547  << " free : " << origCountFreeRow << "\n"
3548  << " Nonzeros : " << numNonzeros << "\n"
3549  << " per column : " << Real(numNonzeros) / Real(numProbCols) << "\n"
3550  << " per row : " << Real(numNonzeros) / Real(numProbRows) << "\n"
3551  << " sparsity : " << Real(numNonzeros) / Real(numProbCols) / Real(numProbRows) << "\n"
3552  << " min. abs. value : " << Real(minAbsNonzero) << "\n"
3553  << " max. abs. value : " << Real(maxAbsNonzero) << "\n";
3554  }
3555 
3556 
3557 
3558  /// gets the coefficient of the slack variable in the primal complementary problem
3560  {
3561  int indDir = 1;
3562  switch( _realLP->rowType(_decompPrimalRowIDs[primalRowNum]) )
3563  {
3564  // NOTE: check the sign of the slackCoeff for the Range constraints. This will depend on the method of
3565  // dual conversion.
3567  assert((primalRowNum < _nPrimalRows - 1 && _realLP->number(SPxColId(_decompPrimalRowIDs[primalRowNum])) ==
3568  _realLP->number(SPxColId(_decompPrimalRowIDs[primalRowNum+1]))) ||
3569  (primalRowNum > 0 && _realLP->number(SPxColId(_decompPrimalRowIDs[primalRowNum-1])) ==
3570  _realLP->number(SPxColId(_decompPrimalRowIDs[primalRowNum]))));
3571 
3572  // determine with primalRowNum and primalRowNum+1 or primalRowNum-1 and primalRowNum have the same row id.
3573  if( _realLP->number(SPxColId(_decompPrimalRowIDs[primalRowNum-1])) ==
3574  _realLP->number(SPxColId(_decompPrimalRowIDs[primalRowNum])) )
3575  indDir = -1;
3576 
3578  _compSolver.obj(_compSolver.number(SPxColId(_decompDualColIDs[primalRowNum + indDir]))))
3579  return -SLACKCOEFF;
3580  else
3581  return SLACKCOEFF;
3582 
3583  break;
3584 
3586  return -SLACKCOEFF;
3587  break;
3589  assert((primalRowNum < _nPrimalRows - 1 && _realLP->number(SPxColId(_decompPrimalRowIDs[primalRowNum])) ==
3590  _realLP->number(SPxColId(_decompPrimalRowIDs[primalRowNum+1]))) ||
3591  (primalRowNum > 0 && _realLP->number(SPxColId(_decompPrimalRowIDs[primalRowNum-1])) ==
3592  _realLP->number(SPxColId(_decompPrimalRowIDs[primalRowNum]))));
3593  // FALLTHROUGH
3595  return SLACKCOEFF;
3596  break;
3597  default:
3598  throw SPxInternalCodeException("XDECOMPSL01 This should never happen.");
3599  }
3600  }
3601 
3602 
3603 
3604  /// gets violation of bounds; returns true on success
3605  bool SoPlex::getDecompBoundViolation(Real& maxviol, Real& sumviol)
3606  {
3607  Real feastol = realParam(SoPlex::FEASTOL);
3608 
3609  VectorReal& primal = _solReal._primal;
3610  assert(primal.dim() == _realLP->nCols());
3611 
3612  _nDecompViolBounds = 0;
3613 
3614  maxviol = 0.0;
3615  sumviol = 0.0;
3616 
3617  bool isViol = false;
3618  bool isMaxViol = false;
3619 
3620  for( int i = _realLP->nCols() - 1; i >= 0; i-- )
3621  {
3622  Real currviol = 0.0;
3623 
3624  Real viol = _realLP->lower(i) - primal[i];
3625 
3626  isViol = false;
3627  isMaxViol = false;
3628 
3629  if( viol > 0.0 )
3630  {
3631  sumviol += viol;
3632  if( viol > maxviol )
3633  {
3634  maxviol = viol;
3635  isMaxViol = true;
3636  }
3637 
3638  if( currviol < viol )
3639  currviol = viol;
3640  }
3641 
3642  if( GT(viol, 0.0, feastol) )
3643  isViol = true;
3644 
3645  viol = primal[i] - _realLP->upper(i);
3646  if( viol > 0.0 )
3647  {
3648  sumviol += viol;
3649  if( viol > maxviol )
3650  {
3651  maxviol = viol;
3652  isMaxViol = true;
3653  }
3654 
3655  if( currviol < viol )
3656  currviol = viol;
3657  }
3658 
3659  if( GT(viol, 0.0, feastol) )
3660  isViol = true;
3661 
3662  if( isViol )
3663  {
3664  // updating the violated bounds list
3665  if( isMaxViol )
3666  {
3668  _decompViolatedBounds[0] = i;
3669  }
3670  else
3672 
3673  _nDecompViolBounds++;
3674  }
3675  }
3676 
3677  return true;
3678  }
3679 
3680 
3681 
3682  /// gets violation of constraints; returns true on success
3683  bool SoPlex::getDecompRowViolation(Real& maxviol, Real& sumviol)
3684  {
3685  Real feastol = realParam(SoPlex::FEASTOL);
3686 
3687  VectorReal& primal = _solReal._primal;
3688  assert(primal.dim() == _realLP->nCols());
3689 
3690  DVectorReal activity(_realLP->nRows());
3691  _realLP->computePrimalActivity(primal, activity);
3692 
3693  _nDecompViolRows = 0;
3694 
3695  maxviol = 0.0;
3696  sumviol = 0.0;
3697 
3698  bool isViol = false;
3699  bool isMaxViol = false;
3700 
3701  for( int i = _realLP->nRows() - 1; i >= 0; i-- )
3702  {
3703  Real currviol = 0.0;
3704 
3705  isViol = false;
3706  isMaxViol = false;
3707 
3708  Real viol = _realLP->lhs(i) - activity[i];
3709  if( viol > 0.0 )
3710  {
3711  sumviol += viol;
3712  if( viol > maxviol )
3713  {
3714  maxviol = viol;
3715  isMaxViol = true;
3716  }
3717 
3718  if( viol > currviol )
3719  currviol = viol;
3720  }
3721 
3722  if( GT(viol, 0.0, feastol) )
3723  isViol = true;
3724 
3725  viol = activity[i] - _realLP->rhs(i);
3726  if( viol > 0.0 )
3727  {
3728  sumviol += viol;
3729  if( viol > maxviol )
3730  {
3731  maxviol = viol;
3732  isMaxViol = true;
3733  }
3734 
3735  if( viol > currviol )
3736  currviol = viol;
3737  }
3738 
3739  if( GT(viol, 0.0, feastol) )
3740  isViol = true;
3741 
3742  if( isViol )
3743  {
3744  // updating the violated rows list
3745  if( isMaxViol )
3746  {
3748  _decompViolatedRows[0] = i;
3749  }
3750  else
3752 
3753  _nDecompViolRows++;
3754  }
3755  }
3756 
3757  return true;
3758  }
3759 
3760 
3761 
3762  /// function call to terminate the decomposition simplex
3764  {
3765  Real maxTime = timeLimit;
3766 
3767  // check if a time limit is actually set
3768  if( maxTime < 0 || maxTime >= infinity )
3769  return false;
3770 
3771  Real currentTime = _statistics->solvingTime->time();
3772  if ( currentTime >= maxTime )
3773  {
3774  MSG_INFO2( spxout, spxout << " --- timelimit (" << _solver.getMaxTime()
3775  << ") reached" << std::endl; )
3777  return true;
3778  }
3779 
3780  return false;
3781  }
3782 
3783 
3784 
3785  /// function to retrieve the original problem row basis status from the reduced and complementary problems
3787  DataArray< SPxSolver::VarStatus >& degenerateRowStatus, int& nDegenerateRows, int& nNonBasicRows)
3788  {
3789  Real feastol = realParam(SoPlex::FEASTOL);
3790  int basicRow = 0;
3791 
3792  // looping over all rows not contained in the complementary problem
3793  for( int i = 0; i < _nElimPrimalRows; i++ )
3794  {
3795  int rowNumber = _realLP->number(_decompElimPrimalRowIDs[i]);
3796 
3797  int solverRowNum = _solver.number(_decompReducedProbRowIDs[rowNumber]);
3798  assert(solverRowNum >= 0 && solverRowNum < _solver.nRows());
3799  if( _solver.basis().desc().rowStatus(solverRowNum) == SPxBasis::Desc::P_ON_UPPER ) /*||
3800  (_solver.basis().desc().rowStatus(solverRowNum) == SPxBasis::Desc::D_ON_LOWER &&
3801  EQ(_solver.rhs(solverRowNum) - _solver.pVec()[solverRowNum], 0.0, feastol)) )*/
3802  {
3804  }
3805  else if( _solver.basis().desc().rowStatus(solverRowNum) == SPxBasis::Desc::P_ON_LOWER ) /*||
3806  (_solver.basis().desc().rowStatus(solverRowNum) == SPxBasis::Desc::D_ON_UPPER &&
3807  EQ(_solver.pVec()[solverRowNum] - _solver.lhs(solverRowNum), 0.0, feastol)) )*/
3808  {
3810  }
3811  else if( _solver.basis().desc().rowStatus(solverRowNum) == SPxBasis::Desc::P_FIXED )
3812  {
3813  _basisStatusRows[rowNumber] = SPxSolver::FIXED;
3814  }
3815  else if( _solver.basis().desc().rowStatus(solverRowNum) == SPxBasis::Desc::P_FREE )
3816  {
3817  _basisStatusRows[rowNumber] = SPxSolver::ZERO;
3818  }
3819  else
3820  {
3821  _basisStatusRows[rowNumber] = SPxSolver::BASIC;
3822  basicRow++;
3823  }
3824  }
3825 
3826  for( int i = 0; i < _nPrimalRows; i++ )
3827  {
3828  int rowNumber = _realLP->number(_decompPrimalRowIDs[i]);
3829  // this loop runs over all rows previously in the complementary problem.
3830  if( _decompReducedProbRows[rowNumber] )
3831  {
3832  int solverRowNum = _solver.number(_decompReducedProbRowIDs[rowNumber]);
3833  assert(solverRowNum >= 0 && solverRowNum < _solver.nRows());
3834  if( _solver.basis().desc().rowStatus(solverRowNum) == SPxBasis::Desc::P_ON_UPPER )
3835  {
3837  }
3838  else if( _solver.basis().desc().rowStatus(solverRowNum) == SPxBasis::Desc::D_ON_LOWER &&
3839  EQ(_solver.rhs(solverRowNum) - _solver.pVec()[solverRowNum], 0.0, feastol) )
3840  {
3841  // if a row is non basic, but is at its bound then the row number and status is stored
3842  degenerateRowNums[nDegenerateRows] = rowNumber;
3843  degenerateRowStatus[nDegenerateRows] = SPxSolver::ON_UPPER;
3844  nDegenerateRows++;
3845  }
3846  else if( _solver.basis().desc().rowStatus(solverRowNum) == SPxBasis::Desc::P_ON_LOWER )
3847  {
3849  }
3850  else if( _solver.basis().desc().rowStatus(solverRowNum) == SPxBasis::Desc::D_ON_UPPER &&
3851  EQ(_solver.pVec()[solverRowNum] - _solver.lhs(solverRowNum), 0.0, feastol) )
3852  {
3853  // if a row is non basic, but is at its bound then the row number and status is stored
3854  degenerateRowNums[nDegenerateRows] = rowNumber;
3855  degenerateRowStatus[nDegenerateRows] = SPxSolver::ON_LOWER;
3856  nDegenerateRows++;
3857  }
3858  else if( _solver.basis().desc().rowStatus(solverRowNum) == SPxBasis::Desc::P_FIXED )
3859  {
3860  _basisStatusRows[rowNumber] = SPxSolver::FIXED;
3861  }
3862  else if( _solver.basis().desc().rowStatus(solverRowNum) == SPxBasis::Desc::P_FREE )
3863  {
3864  _basisStatusRows[rowNumber] = SPxSolver::ZERO;
3865  }
3866  else
3867  {
3868  _basisStatusRows[rowNumber] = SPxSolver::BASIC;
3869  basicRow++;
3870  }
3871  }
3872  else
3873  {
3874  _basisStatusRows[rowNumber] = SPxSolver::BASIC;
3875  basicRow++;
3876  switch( _realLP->rowType(_decompPrimalRowIDs[i]) )
3877  {
3879  //assert(_realLP->number(SPxColId(_decompPrimalRowIDs[i])) ==
3880  //_realLP->number(SPxColId(_decompPrimalRowIDs[i+1])));
3881  //assert(_compSolver.obj(_compSolver.number(SPxColId(_decompDualColIDs[i]))) !=
3882  //_compSolver.obj(_compSolver.number(SPxColId(_decompDualColIDs[i + 1]))));
3883 
3884  //// NOTE: This is not correct at present. Need to modify the inequalities. Look at the dual conversion
3885  //// function to get this correct.
3886  //if( _compSolver.obj(_compSolver.number(SPxColId(_decompDualColIDs[i]))) <
3887  //_compSolver.obj(_compSolver.number(SPxColId(_decompDualColIDs[i + 1]))))
3888  //{
3889  //if( _compSolver.basis().desc().rowStatus(_compSolver.number(SPxColId(_decompDualColIDs[i]))) ==
3890  //SPxBasis::Desc::D_ON_LOWER )
3891  //{
3892  //_basisStatusRows[rowNumber] = SPxSolver::ON_LOWER;
3893  //}
3894  //else if( _compSolver.basis().desc().rowStatus(_compSolver.number(SPxColId(_decompDualColIDs[i + 1]))) ==
3895  //SPxBasis::Desc::D_ON_UPPER )
3896  //{
3897  //_basisStatusRows[rowNumber] = SPxSolver::ON_UPPER;
3898  //}
3899  //else
3900  //{
3901  //_basisStatusRows[rowNumber] = SPxSolver::BASIC;
3902  //basicRow++;
3903  //}
3904  //}
3905  //else
3906  //{
3907  //if( _compSolver.basis().desc().rowStatus(_compSolver.number(SPxColId(_decompDualColIDs[i]))) ==
3908  //SPxBasis::Desc::D_ON_UPPER )
3909  //{
3910  //_basisStatusRows[rowNumber] = SPxSolver::ON_UPPER;
3911  //}
3912  //else if( _compSolver.basis().desc().rowStatus(_compSolver.number(SPxColId(_decompDualColIDs[i + 1]))) ==
3913  //SPxBasis::Desc::D_ON_LOWER )
3914  //{
3915  //_basisStatusRows[rowNumber] = SPxSolver::ON_LOWER;
3916  //}
3917  //else
3918  //{
3919  //_basisStatusRows[rowNumber] = SPxSolver::BASIC;
3920  //basicRow++;
3921  //}
3922  //}
3923 
3924  i++;
3925  break;
3927  //assert(_realLP->number(SPxColId(_decompPrimalRowIDs[i])) ==
3928  //_realLP->number(SPxColId(_decompPrimalRowIDs[i+1])));
3929 
3930  //_basisStatusRows[rowNumber] = SPxSolver::FIXED;
3931 
3932  i++;
3933  break;
3935  //if( _compSolver.basis().desc().rowStatus(_compSolver.number(SPxColId(_decompDualColIDs[i]))) ==
3936  //SPxBasis::Desc::D_ON_LOWER )
3937  //{
3938  //_basisStatusRows[rowNumber] = SPxSolver::ON_LOWER;
3939  //}
3940  //else
3941  //{
3942  //_basisStatusRows[rowNumber] = SPxSolver::BASIC;
3943  //basicRow++;
3944  //}
3945 
3946  break;
3948  //if( _compSolver.basis().desc().rowStatus(_compSolver.number(SPxColId(_decompDualColIDs[i]))) ==
3949  //SPxBasis::Desc::D_ON_UPPER )
3950  //{
3951  //_basisStatusRows[rowNumber] = SPxSolver::ON_UPPER;
3952  //}
3953  //else
3954  //{
3955  //_basisStatusRows[rowNumber] = SPxSolver::BASIC;
3956  //basicRow++;
3957  //}
3958 
3959  break;
3960  default:
3961  throw SPxInternalCodeException("XDECOMPSL01 This should never happen.");
3962  }
3963  }
3964  }
3965 
3966  nNonBasicRows = _realLP->nRows() - basicRow - nDegenerateRows;
3967  MSG_INFO2(spxout, spxout << "Number of non-basic rows: " << nNonBasicRows << " (from "
3968  << _realLP->nRows() << ")" << std::endl );
3969  }
3970 
3971 
3972  /// function to retrieve the column status for the original problem basis from the reduced and complementary problems
3973  // all columns are currently in the reduced problem, so it is only necessary to retrieve the status from there.
3974  // However, a transformation of the columns has been made, so it is only possible to retrieve the status from the
3975  // variable bound constraints.
3977  {
3978  Real feastol = realParam(SoPlex::FEASTOL);
3979  int basicCol = 0;
3980  int numZeroDual = 0;
3981 
3982  // looping over all variable bound constraints
3983  for( int i = 0; i < _realLP->nCols(); i++ )
3984  {
3985  if( !_decompReducedProbColRowIDs[i].isValid() )
3986  continue;
3987 
3988  int rowNumber = _solver.number(_decompReducedProbColRowIDs[i]);
3989  if( _decompReducedProbColRowIDs[i].isValid() )
3990  {
3991  if( _solver.basis().desc().rowStatus(rowNumber) == SPxBasis::Desc::P_ON_UPPER ) /*||
3992  (_solver.basis().desc().rowStatus(rowNumber) == SPxBasis::Desc::D_ON_LOWER &&
3993  EQ(_solver.rhs(rowNumber) - _solver.pVec()[rowNumber], 0.0, feastol)) )*/
3994  {
3996  }
3997  else if( _solver.basis().desc().rowStatus(rowNumber) == SPxBasis::Desc::P_ON_LOWER ) /*||
3998  (_solver.basis().desc().rowStatus(rowNumber) == SPxBasis::Desc::D_ON_UPPER &&
3999  EQ(_solver.pVec()[rowNumber] - _solver.lhs(rowNumber), 0.0, feastol)) )*/
4000  {
4002  }
4003  else if( _solver.basis().desc().rowStatus(rowNumber) == SPxBasis::Desc::P_FIXED )
4004  {
4006  }
4007  else if( _solver.basis().desc().rowStatus(rowNumber) == SPxBasis::Desc::P_FREE )
4008  {
4010  }
4011  else
4012  {
4014  basicCol++;
4015  }
4016  }
4017 
4018  if( EQ(_solver.fVec()[i], 0.0, feastol) )
4019  numZeroDual++;
4020  }
4021 
4022  nNonBasicCols = _realLP->nCols() - basicCol;
4023  MSG_INFO2(spxout, spxout << "Number of non-basic columns: "
4024  << nNonBasicCols << " (from " << _realLP->nCols() << ")" << std::endl
4025  << "Number of zero dual columns: " << numZeroDual << " (from " << _realLP->nCols() << ")" << std::endl );
4026  }
4027 
4028 
4029 
4030  /// function to build a basis for the original problem as given by the solution to the reduced problem
4031  void SoPlex::_writeOriginalProblemBasis(const char* filename, NameSet* rowNames, NameSet* colNames, bool cpxFormat)
4032  {
4033  int numrows = _realLP->nRows();
4034  int numcols = _realLP->nCols();
4035  int nNonBasicRows = 0;
4036  int nNonBasicCols = 0;
4037  int nDegenerateRows = 0;
4038  DataArray< int > degenerateRowNums; // array to store the orig prob row number of degenerate rows
4039  DataArray< SPxSolver::VarStatus > degenerateRowStatus; // possible status for the degenerate rows in the orig prob
4040 
4041  // setting the basis status rows and columns to size of the original problem
4042  _basisStatusRows.reSize(numrows);
4043  _basisStatusCols.reSize(numcols);
4044 
4045  degenerateRowNums.reSize(numrows);
4046  degenerateRowStatus.reSize(numrows);
4047 
4048  // setting the row and column status for the original problem
4049  getOriginalProblemBasisRowStatus(degenerateRowNums, degenerateRowStatus, nDegenerateRows, nNonBasicRows);
4050  getOriginalProblemBasisColStatus(nNonBasicCols);
4051 
4052  // checking the consistency of the non-basic rows and columns for printing out the basis.
4053  // it is necessary to have numcols of non-basic rows and columns.
4054  // if there are not enought non-basic rows and columns, then the degenerate rows are set as non-basic.
4055  // all degenerate rows that are not changed to non-basic must be set to basic.
4056  assert(nDegenerateRows + nNonBasicRows + nNonBasicCols >= numcols);
4057  int degenRowsSetNonBasic = 0;
4058  for( int i = 0; i < nDegenerateRows; i++ )
4059  {
4060  if( nNonBasicRows + nNonBasicCols + degenRowsSetNonBasic < numcols )
4061  {
4062  _basisStatusRows[degenerateRowNums[i]] = degenerateRowStatus[i];
4063  degenRowsSetNonBasic++;
4064  }
4065  else
4066  _basisStatusRows[degenerateRowNums[i]] = SPxSolver::BASIC;
4067  }
4068 
4069  // writing the basis file for the original problem
4070  bool wasRealLPLoaded = _isRealLPLoaded;
4071  _isRealLPLoaded = false;
4072  writeBasisFile(filename, rowNames, colNames, cpxFormat);
4073  _isRealLPLoaded = wasRealLPLoaded;
4074  }
4075 } // namespace soplex
4076 #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:1977
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:2126
Rational spxAbs(const Rational &r)
Absolute.
Definition: rational.cpp:3909
int _lastSolveMode
Definition: soplex.h:1813
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:263
virtual void changeRow(int i, const LPRow &newRow, bool scale=false)
int _nCompPrimalCols
Definition: soplex.h:1773
Exception class for things that should NEVER happen.This class is derived from the SoPlex exception b...
Definition: exceptions.h:109
virtual void removeRow(int i)
Removes i &#39;th row.
Definition: spxlpbase.h:904
virtual Real shift() const
total current shift amount.
Definition: spxsolver.h:1602
int iterations() const
get number of iterations of current solution.
Definition: spxsolver.h:2091
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:562
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:410
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:1735
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:606
int numRowsReal() const
returns number of rows
Definition: soplex.cpp:797
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:1760
const VectorBase< R > & upper() const
Returns upper bound vector.
Definition: spxlpbase.h:456
const RowViolation * entry
Definition: soplex.h:1692
virtual Status getPrimal(Vector &vector) const
get solution vector for primal variables.
Definition: spxsolve.cpp:1593
upper limit on objective value
Definition: soplex.h:1301
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:1280
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:1793
void setBasis(const VarStatus rows[], const VarStatus cols[])
set the lp solver&#39;s basis.
Definition: spxsolver.cpp:1873
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:1783
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:268
DataArray< SPxRowId > _decompPrimalRowIDs
Definition: soplex.h:1745
DataArray< SPxRowId > _decompElimPrimalRowIDs
Definition: soplex.h:1747
apply standard floating-point algorithm
Definition: soplex.h:1209
int origCountRhs
Definition: soplex.h:1799
void _checkOriginalProblemOptimality(Vector primalVector, bool printViol)
checking the optimality of the original problem.
Definition: solvedbds.cpp:2694
void _removeComplementaryDualFixedPrimalVars(int *currFixedVars)
removing the dual columns related to the fixed variables
Definition: solvedbds.cpp:2844
void _setComplementaryPrimalOriginalObjective()
updating the complementary primal problem with the original objective function
Definition: solvedbds.cpp:3182
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:1794
int size() const
Number of used indices.
Definition: svectorbase.h:152
objective offset
Definition: soplex.h:1343
DataArray< SPxRowId > _decompReducedProbColRowIDs
Definition: soplex.h:1743
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:1800
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:1734
int _nDecompViolBounds
Definition: soplex.h:1759
Real sumDualDegeneracy()
get the sum of dual degeneracy
Definition: spxsolver.h:2079
DVector _transformedObj
Definition: soplex.h:1732
time limit in seconds (INFTY if unlimited)
Definition: soplex.h:1295
Status & rowStatus(int i)
Definition: spxbasis.h:239
bool isScaled() const
Returns true if and only if the LP is scaled.
Definition: spxlpbase.h:139
virtual void removeCols(int perm[])
Removes multiple columns.
Definition: spxlpbase.h:1020
bool LE(Real a, Real b, Real eps=Param::epsilon())
returns true iff a <= b + eps
Definition: spxdefines.h:398
Real getFactorTime() const
time spent in factorizations
Definition: slufactor.h:238
primal feasibility tolerance
Definition: soplex.h:1274
bool LT(Real a, Real b, Real eps=Param::epsilon())
returns true iff a < b + eps
Definition: spxdefines.h:392
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:5389
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:1595
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:2033
bool NE(Real a, Real b, Real eps=Param::epsilon())
returns true iff |a-b| > eps
Definition: spxdefines.h:386
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:642
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:630
void _disableSimplifierAndScaler()
disables simplifier and scaler
Definition: soplex.cpp:7989
void add(const LPColBase< R > &pcol)
Definition: lpcolsetbase.h:255
bool * _decompReducedProbCols
Definition: soplex.h:1738
int _nDualCols
Definition: soplex.h:1771
Timer * simplexTime
simplex time
Definition: statistics.h:91
int _nElimPrimalRows
Definition: soplex.h:1769
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:1795
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:248
virtual void removeCol(int i)
Removes i &#39;th column.
Definition: spxlpbase.h:1001
LP has been proven to be primal infeasible.
Definition: spxsolver.h:222
int getOrigVarFixedDirection(int colNum)
determining which bound the primal variables will be fixed to.
Definition: solvedbds.cpp:3200
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:5538
void remove(int n, int m)
Remove nonzeros n thru m.
Definition: svectorbase.h:387
void setDegenCompOffset(int iterOffset)
sets the offset for the number of iterations before the degeneracy is computed
Definition: spxsolver.h:2219
bool getDecompBoundViolation(Real &maxviol, Real &sumviol)
gets violation of bounds; returns true on success
Definition: solvedbds.cpp:3605
int origCountRanged
Definition: soplex.h:1800
virtual Real value()
current objective value.
Definition: spxsolver.cpp:888
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:1724
virtual void setTerminationTime(Real time=infinity)
set time limit.
Definition: spxsolver.cpp:1556
int numDecompIter
Definition: soplex.h:1782
DataArray< SPxColId > _decompCompPrimalColIDs
Definition: soplex.h:1757
virtual void changeObjOffset(const R &o)
Definition: spxlpbase.h:1747
SPxColId cId(int n) const
Returns the column identifier for column n.
Definition: spxlpbase.h:568
virtual void removeRows(int perm[])
Removes multiple rows.
Definition: spxlpbase.h:923
int origCountFreeRow
Definition: soplex.h:1801
DataArray< SPxColId > _decompReducedProbColIDs
Definition: soplex.h:1744
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:1895
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:1742
void printOriginalProblemStatistics(std::ostream &os)
stores the problem statistics of the original problem
Definition: solvedbds.cpp:3536
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:2067
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:1728
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:1756
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:3074
DataArray< SPxSolver::VarStatus > _basisStatusCols
Definition: soplex.h:1816
SPxStatus status() const
returns current SPxStatus.
Definition: spxbasis.h:425
decompStatus _currentProb
Definition: soplex.h:1804
double Real
Definition: spxdefines.h:218
bool _isRealLPLoaded
Definition: soplex.h:1598
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:3229
DVectorBase< R > _primal
Definition: solbase.h:218
void _setComplementaryDualOriginalObjective()
updating the complementary dual problem with the original objective function
Definition: solvedbds.cpp:3112
Status status() const
Status of solution process.
Definition: spxsolve.cpp:1910
Real sumPrimalDegeneracy()
get the sum of primal degeneracy
Definition: spxsolver.h:2085
bool GT(Real a, Real b, Real eps=Param::epsilon())
returns true iff a > b + eps
Definition: spxdefines.h:404
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:3683
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:2253
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:120
bool _hasBasis
Definition: soplex.h:1822
virtual void changeSense(SPxSense sns)
#define MSG_ERROR(x)
Prints out message x if the verbosity level is at least SPxOut::ERROR.
Definition: spxdefines.h:114
Real sumPrimalDegen
the sum of the rate of primal degeneracy at each iteration
Definition: statistics.h:128
UpdateVector & fVec() const
feasibility vector.
Definition: spxsolver.h:1304
virtual void addRows(const LPRowSetBase< R > &pset, bool scale=false)
Definition: spxlpbase.h:635
Class for collecting statistical information.
bool isSPxColId() const
is id a column id?
Definition: spxid.h:165
dual variable is set to its upper bound
Definition: spxbasis.h:192
solve() aborted due to commence decomposition simplex
Definition: spxsolver.h:210
solve() aborted due to time limit.
Definition: spxsolver.h:212
SPxRowId _compSlackDualRowId
Definition: soplex.h:1736
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:1244
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:1346
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:1544
R obj(int i) const
Returns objective value of column i.
Definition: spxlpbase.h:403
int origCountFreeCol
Definition: soplex.h:1796
int numNonzeros
Definition: soplex.h:1789
Real getCompSlackVarCoeff(int primalRowNum)
gets the coefficient of the slack variable in the primal complementary problem
Definition: solvedbds.cpp:3559
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:334
Verbosity getVerbosity() const
Definition: spxout.h:117
#define MINIMUM(x, y)
Definition: spxdefines.h:247
virtual void getBasis(SPxSolver::VarStatus[], SPxSolver::VarStatus[], const int rowsSize=-1, const int colsSize=-1) const =0
get optimal basis.
SLUFactor _slufactor
Definition: soplex.h:1570
variable set to its upper bound.
Definition: spxsolver.h:191
int primalDegeneratePivots()
get number of primal degenerate pivots
Definition: spxsolver.h:2073
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:5548
primal infeasibility was detected
Definition: spxsimplifier.h:84
DataArray< SPxColId > _decompPrimalColIDs
Definition: soplex.h:1746
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:1768
int boundFlips() const
get number of bound flips.
Definition: spxsolver.h:2061
int degenPivotsDual
number of dual degenerate pivots
Definition: statistics.h:124
SPxOut spxout
Definition: soplex.h:1444
infinity threshold
Definition: soplex.h:1292
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:122
void getOriginalProblemBasisColStatus(int &nNonBasicCols)
function to retrieve the column status for the original problem basis from the reduced and complement...
Definition: solvedbds.cpp:3976
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:1567
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:1382
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:1750
DualSign getOrigProbDualVariableSign(int rowNumber)
returns the expected sign of the dual variables for the original problem
Definition: solvedbds.cpp:3406
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:380
Timer * preprocessingTime
preprocessing time
Definition: statistics.h:90
UpdateVector & pVec() const
pricing vector.
Definition: spxsolver.h:1459
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:1278
virtual void addCol(const LPColBase< R > &col, bool scale=false)
Definition: spxlpbase.h:741
virtual void scale(SPxLPBase< Real > &lp, bool persistent=true)=0
scale SPxLP.
int dim() const
Dimension of vector.
Definition: vectorbase.h:215
Implementation of Sparse Linear Solver.This class implements a SLinSolver interface by using the spar...
Definition: slufactor.h:41
Starting basis has not been found yet.
Definition: spxsolver.h: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:1762
DataArray< SPxColId > _decompVarBoundDualIDs
Definition: soplex.h:1751
DataArray< SPxRowId > _decompDualRowIDs
Definition: soplex.h:1748
Everything should be within this namespace.
int numCompProbIter
Definition: soplex.h:1784
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:4031
SPxLPReal * _realLP
Definition: soplex.h:1592
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:422
Real minAbsNonzero
Definition: soplex.h:1790
DVector _decompFeasVector
Definition: soplex.h:1733
virtual void printDisplayLine(const bool force=false, const bool forceHead=false)
print display line of flying table
Definition: spxsolve.cpp:1364
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:1765
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:1772
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:116
virtual void unsimplify(const Vector &, const Vector &, const Vector &, const Vector &, const SPxSolver::VarStatus[], const SPxSolver::VarStatus[], bool isOptimal=true)=0
reconstructs an optimal solution for the unsimplified LP.
int iterations
number of iterations/pivots
Definition: statistics.h:101
primal variable is set to its lower bound
Definition: spxbasis.h:187
Real maxAbsNonzero
Definition: soplex.h:1791
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:3786
int _decompDisplayLine
Definition: soplex.h:1775
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:1569
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:3426
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:3045
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:1737
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:1815
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:1798
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:1730
Type type() const
return current Type.
Definition: spxsolver.h:484
bool boolParam(const BoolParam param) const
returns boolean parameter value
Definition: soplex.cpp:5528
the verbosity of the decomposition based simplex
Definition: soplex.h:1019
Real getSolveTime() const
time spent in solves
Definition: slufactor.h:253
virtual Status getRedCost(Vector &vector) const
get vector of reduced costs.
Definition: spxsolve.cpp:1673
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:118
Real solveTime() const
time spent in last call to solve
Definition: soplex.cpp:5044
const SVectorBase< R > & colVector(int i) const
Returns column vector of column i.
Definition: spxlpbase.h:373
int _nDualRows
Definition: soplex.h:1770
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:1818
int iterationsPrimal
number of iterations with Primal
Definition: statistics.h:102
bool _hasSolReal
Definition: soplex.h:1823
int numProbRows
Definition: soplex.h:1787
int * _decompViolatedBounds
Definition: soplex.h:1761
void _updateComplementaryDualSlackColCoeff()
updating the slack column coefficients to adjust for equality constraints
Definition: solvedbds.cpp:2763
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:1277
bool isZero(Real a, Real eps=Param::epsilon())
returns true iff |a| <= eps
Definition: spxdefines.h:416
void solve(Vector &x, const Vector &rhs)
Definition: spxbasis.h:631
const SVector & vector(int i) const
i &#39;th vector.
Definition: spxsolver.h:1138
void _identifyComplementaryDualFixedPrimalVars(int *currFixedVars)
removing the dual columns related to the fixed variables
Definition: solvedbds.cpp:2800
void _updateComplementaryDualFixedPrimalVars(int *currFixedVars)
updating the dual columns related to the fixed primal variables.
Definition: solvedbds.cpp:2907
DualSign getExpectedDualVariableSign(int rowNumber)
returns the expected sign of the dual variables for the reduced problem
Definition: solvedbds.cpp:3387
bool decompTerminate(Real timeLimit)
function call to terminate the decomposition simplex
Definition: solvedbds.cpp:3763
bool isRowBasic(int i) const
is the i &#39;th row vector basic ?
Definition: spxsolver.h:1271
void getOriginalProblemStatistics()
stores the problem statistics of the original problem
Definition: solvedbds.cpp:3468
void _enableSimplifierAndScaler()
enables simplifier and scaler according to current parameters
Definition: soplex.cpp:7940
int _nPrimalRows
Definition: soplex.h:1767
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:3335
virtual void unscaleSlacks(const SPxLPBase< Real > &lp, Vector &s) const
unscale dense slack vector given in s.
Definition: spxscaler.cpp:618
void setOutstream(SPxOut &newOutstream)
Definition: spxsolver.h:441
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:2232
virtual void setTerminationValue(Real value=infinity)
set objective limit.
Definition: spxsolver.cpp:1620
const SPxBasis & basis() const
Return current basis.
Definition: spxsolver.h:1736
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:1781
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:806
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:1593
const VectorBase< R > & lower() const
Returns (internal and possibly scaled) lower bound vector.
Definition: spxlpbase.h:483
SPxSolver::Status _status
Definition: soplex.h:1812
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:449
SPxRowId rowId(int i) const
RowId of i &#39;th inequality.
Definition: spxsolver.h:2248
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:478
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:1594
void _updateDecompComplementaryPrimalProblem(bool origObj)
update the primal complementary problem with additional columns and rows
Definition: solvedbds.cpp:2452
int numProbCols
Definition: soplex.h:1788
DataArray< SPxColId > _decompDualColIDs
Definition: soplex.h:1749
virtual void addCols(const LPColSetBase< R > &pset, bool scale=false)
Definition: spxlpbase.h:793
virtual Status getDual(Vector &vector) const
get current solution vector for dual variables.
Definition: spxsolve.cpp:1642
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:1217
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:1741
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:2097
dual infeasibility was detected
Definition: spxsimplifier.h:85
virtual Status getSlacks(Vector &vector) const
get vector of slack variables.
Definition: spxsolve.cpp:1752
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