Scippy

SoPlex

Sequential object-oriented simPlex

testsoplex.cpp
Go to the documentation of this file.
1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2 /* */
3 /* This file is part of the class library */
4 /* SoPlex --- the Sequential object-oriented simPlex. */
5 /* */
6 /* Copyright (C) 1996-2019 Konrad-Zuse-Zentrum */
7 /* fuer Informationstechnik Berlin */
8 /* */
9 /* SoPlex is distributed under the terms of the ZIB Academic Licence. */
10 /* */
11 /* You should have received a copy of the ZIB Academic License */
12 /* along with SoPlex; see the file COPYING. If not email to soplex@zib.de. */
13 /* */
14 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
15 
16 #include <iostream>
17 #include <assert.h>
18 
19 #include "soplex.h"
20 #include "soplex/statistics.h"
21 
22 namespace soplex
23 {
24 /// check scaling of LP
25 void SoPlex::_checkScaling(SPxLPReal* origLP) const
26 {
27  MSG_INFO1(spxout, spxout << "DEBUG: checking correctness of scaled LP" << std::endl;)
28  assert(_realLP->nCols() == origLP->nCols());
29  assert(_realLP->nRows() == origLP->nRows());
30  assert(_realLP->isScaled() && !origLP->isScaled());
31  bool correct = true;
32 
33  MSG_INFO1(spxout, spxout << "DEBUG: checking rows..." << std::endl;)
34 
35  for(int i = 0; i < origLP->nRows(); ++i)
36  {
37  assert(EQ(origLP->lhs(i), _realLP->lhsUnscaled(i)));
38  assert(EQ(origLP->rhs(i), _realLP->rhsUnscaled(i)));
39 
40  DSVectorReal row;
42 
43  assert(origLP->rowVector(i).size() == row.size());
44 
45  for(int j = 0; j < row.size(); ++j)
46  {
47  if(NE(row.value(j), origLP->rowVector(i).value(j)))
48  {
49  MSG_INFO1(spxout, spxout << "DEBUG: scaling error in row " << i << ", col " << j
50  << ": orig " << origLP->rowVector(i).value(j)
51  << ", unscaled: " << row.value(j) << std::endl;)
52  correct = false;
53  }
54  }
55  }
56 
57  MSG_INFO1(spxout, spxout << "DEBUG: checking cols..." << std::endl;)
58 
59  for(int i = 0; i < origLP->nCols(); ++i)
60  {
61  assert(EQ(origLP->lower(i), _realLP->lowerUnscaled(i)));
62  assert(EQ(origLP->upper(i), _realLP->upperUnscaled(i)));
63  assert(EQ(origLP->obj(i), _realLP->objUnscaled(i)));
64 
65  DSVectorReal col;
67 
68  assert(origLP->colVector(i).size() == col.size());
69 
70  for(int j = 0; j < col.size(); ++j)
71  {
72  if(NE(col.value(j), origLP->colVector(i).value(j), _solver.feastol()))
73  {
74  MSG_INFO1(spxout, spxout << "DEBUG: scaling error in col " << i << ", row " << j
75  << ": orig " << origLP->colVector(i).value(j)
76  << ", unscaled: " << col.value(j) << std::endl;)
77  correct = false;
78  }
79  }
80  }
81 
82  if(!correct)
83  {
84  MSG_INFO1(spxout, spxout << "DEBUG: scaling check failed" << std::endl;)
85  }
86 
87  assert(correct);
88 }
89 
90 
91 
93 {
95  {
96  MSG_INFO1(spxout, spxout << "DEBUG: skipping test on non optimal bases\n");
97  return;
98  }
99 
100  assert(&_solver == _realLP);
101  DVector** binvcol = 0;
102  DVector** binvrow = 0;
103  int* inds = 0;
104  int basisdim = _solver.nRows(); // do all operations with regard to the column basis
105  bool colrep = (_solver.rep() == SPxSolver::COLUMN);
106  spx_alloc(binvcol, basisdim);
107  spx_alloc(binvrow, basisdim);
108  spx_alloc(inds, basisdim);
109 
110  if(colrep)
111  {
112  MSG_INFO1(spxout, spxout << "DEBUG: computing columns of inverted basis matrix\n";)
113 
114  // collect columns of the basis inverse
115  for(int i = 0; i < basisdim; ++i)
116  {
117  binvcol[i] = new DVector(basisdim);
118  binvcol[i]->clear();
119  assert(getBasisInverseColReal(i, binvcol[i]->get_ptr(), 0, 0, true));
120  }
121  }
122 
123  MSG_INFO1(spxout, spxout << "DEBUG: computing rows of inverted basis matrix\n";)
124 
125  // collect rows of the basis inverse
126  for(int i = 0; i < basisdim; ++i)
127  {
128  binvrow[i] = new DVector(basisdim);
129  binvrow[i]->clear();
130  assert(getBasisInverseRowReal(i, binvrow[i]->get_ptr(), 0, 0, true));
131  }
132 
133  if(colrep)
134  {
136  "DEBUG: checking columns for identity after multiplying with basis matrix\n";)
137 
138  // multiply with (unscaled) basis matrix and check result (should be unitvecs)
139  for(int i = 0; i < basisdim; ++i)
140  {
141  DVector result(*binvcol[i]);
142  assert(multBasis(result.get_ptr(), true));
143  Real sumerror = 0.0;
144 
145  for(int j = 0; j < basisdim; ++j)
146  {
147  Real error = 0.0;
148 
149  if(j != i)
150  error = spxAbs(result[j]);
151  else
152  error = spxAbs(result[j] - 1.0);
153 
154  if(error > _solver.feastol())
155  MSG_INFO1(spxout, spxout << "ERROR: col " << i << " " << j << ", " << result[j] << std::endl);
156 
157  sumerror += error;
158  }
159 
160  assert(_solver.rep() == SPxSolver::ROW || sumerror < _solver.feastol());
161  }
162  }
163 
165  "DEBUG: checking rows for identity after multiplying with basis matrix\n";)
166 
167  for(int i = 0; i < basisdim; ++i)
168  {
169  DVector result(*binvrow[i]);
170  assert(multBasisTranspose(result.get_ptr(), true));
171  Real sumerror = 0.0;
172 
173  for(int j = 0; j < basisdim; ++j)
174  {
175  Real error = 0.0;
176 
177  if(j != i)
178  error = spxAbs(result[j]);
179  else
180  error = spxAbs(result[j] - 1.0);
181 
182  if(error > _solver.feastol())
183  MSG_INFO1(spxout, spxout << "ERROR: row " << i << " " << j << ", " << result[j] << std::endl);
184 
185  sumerror += error;
186  }
187 
188  assert(sumerror < _solver.feastol());
189  }
190 
191  if(_solver.isScaled())
192  {
193  MSG_INFO1(spxout, spxout << "DEBUG: unscaling LP\n";)
194  // _solver.setRep(SPxSolver::COLUMN);
196  // _solver.setBasis(_basisStatusRows.get_ptr(), _basisStatusCols.get_ptr());
197  // _solver.solve();
198 
199  DVector** binvcol2 = 0;
200  DVector** binvrow2 = 0;
201  spx_alloc(binvcol2, basisdim);
202  spx_alloc(binvrow2, basisdim);
203 
204  if(colrep)
205  {
206  MSG_INFO1(spxout, spxout << "DEBUG: computing columns of inverted basis matrix again\n";)
207 
208  // collect columns of the basis inverse
209  for(int i = 0; i < basisdim; ++i)
210  {
211  binvcol2[i] = new DVector(basisdim);
212  binvcol2[i]->clear();
213  assert(getBasisInverseColReal(i, binvcol2[i]->get_ptr(), 0, 0, false));
214  }
215  }
216 
217  MSG_INFO1(spxout, spxout << "DEBUG: computing rows of inverted basis matrix again\n";)
218 
219  // collect rows of the basis inverse
220  for(int i = 0; i < basisdim; ++i)
221  {
222  binvrow2[i] = new DVector(basisdim);
223  binvrow2[i]->clear();
224  assert(getBasisInverseRowReal(i, binvrow2[i]->get_ptr(), 0, 0, false));
225  }
226 
228  "DEBUG: checking rows and columns of scaled/unscaled inverted of basis matrix\n";)
229 
230  for(int i = 0; i < basisdim; ++i)
231  {
232  Real sumerror = 0.0;
233 
234  for(int j = 0; j < basisdim; ++j)
235  {
236  if(colrep)
237  {
238  if(NE((*binvcol[i])[j], (*binvcol2[i])[j], _solver.feastol()))
239  {
240  MSG_INFO1(spxout, spxout << "ERROR: col " << i << " " << j << ", " << (*binvcol[i])[j] << " " <<
241  (*binvcol2[i])[j] << std::endl);
242  sumerror += spxAbs((*binvcol[i])[j] - (*binvcol2[i])[j]);
243  }
244  }
245 
246  if(NE((*binvrow[i])[j], (*binvrow2[i])[j], _solver.feastol()))
247  {
248  MSG_INFO1(spxout, spxout << "ERROR: row " << i << " " << j << ", " << (*binvrow[i])[j] /
249  (*binvrow2[i])[j] << std::endl);
250  sumerror += spxAbs((*binvrow[i])[j] - (*binvrow2[i])[j]);
251  }
252  }
253 
254  assert(sumerror < _solver.feastol());
255  }
256 
257  spx_free(binvcol2);
258  spx_free(binvrow2);
259  }
260 
261  spx_free(inds);
262  spx_free(binvrow);
263  spx_free(binvcol);
264 }
265 
266 } // namespace soplex
const VectorBase< R > & rhs() const
Returns right hand side vector.
Definition: spxlpbase.h:221
Rational spxAbs(const Rational &r)
Absolute.
Definition: rational.cpp:4102
void _checkScaling(SPxLPReal *origLP) const
check scaling of LP
Definition: testsoplex.cpp:25
bool multBasisTranspose(Real *vec, bool unscale=true)
multiply with transpose of basis matrix; vec * B^T (inplace)
Definition: soplex.cpp:4972
bool getBasisInverseRowReal(int r, Real *coef, int *inds=NULL, int *ninds=NULL, bool unscale=true)
computes row r of basis inverse; returns true on success
Definition: soplex.cpp:4284
const VectorBase< R > & upper() const
Returns upper bound vector.
Definition: spxlpbase.h:461
int size() const
Number of used indices.
Definition: svectorbase.h:153
bool multBasis(Real *vec, bool unscale=true)
multiply with basis matrix; B * vec (inplace)
Definition: soplex.cpp:4857
Real feastol() const
allowed primal feasibility tolerance.
Definition: spxsolver.h:803
void unscaleLPandReloadBasis()
unscales the LP and reloads the basis
Definition: spxsolver.cpp:534
bool isScaled() const
Returns true if and only if the LP is scaled.
Definition: spxlpbase.h:140
R rhsUnscaled(int i) const
Returns unscaled right hand side of row number i.
bool NE(Real a, Real b, Real eps=Param::epsilon())
returns true iff |a-b| > eps
Definition: spxdefines.h:382
R & value(int n)
Reference to value of n &#39;th nonzero.
Definition: svectorbase.h:253
void _checkBasisScaling()
check correctness of (un)scaled basis matrix operations
Definition: testsoplex.cpp:92
rowwise representation.
Definition: spxsolver.h:107
int nRows() const
Returns number of rows in LP.
Definition: spxlpbase.h:152
void spx_alloc(T &p, int n=1)
Allocate memory.
Definition: spxalloc.h:48
R * get_ptr()
Conversion to C-style pointer.
Definition: vectorbase.h:446
R objUnscaled(int i) const
Returns unscaled objective value of column i.
double Real
Definition: spxdefines.h:218
void getColVectorUnscaled(int i, DSVectorBase< Real > &vec) const
Gets column vector of column i.
R upperUnscaled(int i) const
Returns unscaled upper bound of column i.
LP has been solved to optimality.
Definition: spxsolver.h:220
bool getBasisInverseColReal(int c, Real *coef, int *inds=NULL, int *ninds=NULL, bool unscale=true)
computes column c of basis inverse; returns true on success
Definition: soplex.cpp:4476
Class for collecting statistical information.
R obj(int i) const
Returns objective value of column i.
Definition: spxlpbase.h:407
const VectorBase< R > & lhs() const
Returns left hand side vector.
Definition: spxlpbase.h:255
SPxOut spxout
Definition: soplex.h:1476
R lhsUnscaled(int i) const
Returns unscaled left hand side of row number i.
Preconfigured SoPlex LP solver.
bool EQ(Real a, Real b, Real eps=Param::epsilon())
returns true iff |a-b| <= eps
Definition: spxdefines.h:376
Everything should be within this namespace.
SPxLPReal * _realLP
Definition: soplex.h:1626
Saving LPs in a form suitable for SoPlex.Class SPxLPBase provides the data structures required for sa...
Definition: spxlpbase.h:80
R lowerUnscaled(int i) const
Returns unscaled lower bound of column i.
SPxSolver _solver
Definition: soplex.h:1602
const SVectorBase< R > & rowVector(int i) const
Gets row vector of row i.
Definition: spxlpbase.h:206
void clear()
Set vector to 0.
Definition: vectorbase.h:262
DVectorBase< Real > DVector
Definition: dvector.h:28
#define MSG_INFO1(spxout, x)
Prints out message x if the verbosity level is at least SPxOut::INFO1.
Definition: spxdefines.h:118
const SVectorBase< R > & colVector(int i) const
Returns column vector of column i.
Definition: spxlpbase.h:377
int nCols() const
Returns number of columns in LP.
Definition: spxlpbase.h:158
const VectorBase< R > & lower() const
Returns (internal and possibly scaled) lower bound vector.
Definition: spxlpbase.h:488
SPxSolver::Status _status
Definition: soplex.h:1857
Representation rep() const
return the current basis representation.
Definition: spxsolver.h:506
columnwise representation.
Definition: spxsolver.h:108
void spx_free(T &p)
Release memory.
Definition: spxalloc.h:110
void getRowVectorUnscaled(int i, DSVectorBase< Real > &vec) const
Gets unscaled row vector of row i.