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