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-2017 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 #ifndef SOPLEX_LEGACY
17 #include <iostream>
18 #include <assert.h>
19 
20 #include "soplex.h"
21 #include "statistics.h"
22 
23 namespace soplex
24 {
25  /// check scaling of LP
26  void SoPlex::_checkScaling(SPxLPReal* origLP) const
27  {
28  MSG_INFO1( spxout, spxout << "DEBUG: checking correctness of scaled LP" << std::endl; )
29  assert(_realLP->nCols() == origLP->nCols());
30  assert(_realLP->nRows() == origLP->nRows());
31  assert(_realLP->isScaled() && !origLP->isScaled());
32  bool correct = true;
33 
34  MSG_INFO1( spxout, spxout << "DEBUG: checking rows..." << std::endl; )
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  for( int i = 0; i < origLP->nCols(); ++i )
59  {
60  assert(EQ(origLP->lower(i), _realLP->lowerUnscaled(i)));
61  assert(EQ(origLP->upper(i), _realLP->upperUnscaled(i)));
62  assert(EQ(origLP->obj(i), _realLP->objUnscaled(i)));
63 
64  DSVectorReal col;
66 
67  assert(origLP->colVector(i).size() == col.size());
68 
69  for( int j = 0; j < col.size(); ++j)
70  {
71  if( NE(col.value(j), origLP->colVector(i).value(j), _solver.feastol()) )
72  {
73  MSG_INFO1( spxout, spxout << "DEBUG: scaling error in col " << i << ", row " << j
74  << ": orig " << origLP->colVector(i).value(j)
75  << ", unscaled: " << col.value(j) << std::endl; )
76  correct = false;
77  }
78  }
79  }
80  if( !correct )
81  {
82  MSG_INFO1( spxout, spxout << "DEBUG: scaling check failed" << std::endl; )
83  }
84  assert(correct);
85  }
86 
87 
88 
90  {
92  {
93  MSG_INFO1( spxout, spxout << "DEBUG: skipping test on non optimal bases\n" );
94  return;
95  }
96 
97  assert(&_solver == _realLP);
98  DVector** binvcol = 0;
99  DVector** binvrow = 0;
100  int* inds = 0;
101  int basisdim = _solver.nRows(); // do all operations with regard to the column basis
102  bool colrep = (_solver.rep() == SPxSolver::COLUMN);
103  spx_alloc(binvcol, basisdim);
104  spx_alloc(binvrow, basisdim);
105  spx_alloc(inds, basisdim);
106 
107  if( colrep )
108  {
109  MSG_INFO1( spxout, spxout << "DEBUG: computing columns of inverted basis matrix\n";)
110  // collect columns of the basis inverse
111  for( int i = 0; i < basisdim; ++i)
112  {
113  binvcol[i] = new DVector(basisdim);
114  binvcol[i]->clear();
115  assert(getBasisInverseColReal(i, binvcol[i]->get_ptr(), 0, 0, true));
116  }
117  }
118  MSG_INFO1( spxout, spxout << "DEBUG: computing rows of inverted basis matrix\n";)
119  // collect rows of the basis inverse
120  for( int i = 0; i < basisdim; ++i)
121  {
122  binvrow[i] = new DVector(basisdim);
123  binvrow[i]->clear();
124  assert(getBasisInverseRowReal(i, binvrow[i]->get_ptr(), 0, 0, true));
125  }
126 
127  if( colrep )
128  {
129  MSG_INFO1( spxout, spxout << "DEBUG: checking columns for identity after multiplying with basis matrix\n";)
130  // multiply with (unscaled) basis matrix and check result (should be unitvecs)
131  for( int i = 0; i < basisdim; ++i)
132  {
133  DVector result(*binvcol[i]);
134  assert(multBasis(result.get_ptr(), true));
135  Real sumerror = 0.0;
136  for( int j = 0; j < basisdim; ++j)
137  {
138  Real error = 0.0;
139  if( j != i )
140  error = spxAbs(result[j]);
141  else
142  error = spxAbs(result[j] - 1.0);
143  if( error > _solver.feastol() )
144  MSG_INFO1( spxout, spxout << "ERROR: col " << i << " " << j << ", " << result[j] << std::endl );
145  sumerror += error;
146  }
147  assert(_solver.rep() == SPxSolver::ROW || sumerror < _solver.feastol());
148  }
149  }
150 
151  MSG_INFO1( spxout, spxout << "DEBUG: checking rows for identity after multiplying with basis matrix\n";)
152  for( int i = 0; i < basisdim; ++i)
153  {
154  DVector result(*binvrow[i]);
155  assert(multBasisTranspose(result.get_ptr(), true));
156  Real sumerror = 0.0;
157  for( int j = 0; j < basisdim; ++j)
158  {
159  Real error = 0.0;
160  if( j != i )
161  error = spxAbs(result[j]);
162  else
163  error = spxAbs(result[j] - 1.0);
164  if( error > _solver.feastol() )
165  MSG_INFO1( spxout, spxout << "ERROR: row " << i << " " << j << ", " << result[j] << std::endl );
166  sumerror += error;
167  }
168  assert(sumerror < _solver.feastol());
169  }
170 
171  if( _solver.isScaled() )
172  {
173  MSG_INFO1( spxout, spxout << "DEBUG: unscaling LP\n"; )
174 // _solver.setRep(SPxSolver::COLUMN);
176 // _solver.setBasis(_basisStatusRows.get_ptr(), _basisStatusCols.get_ptr());
177 // _solver.solve();
178 
179  DVector** binvcol2 = 0;
180  DVector** binvrow2 = 0;
181  spx_alloc(binvcol2, basisdim);
182  spx_alloc(binvrow2, basisdim);
183 
184  if( colrep )
185  {
186  MSG_INFO1( spxout, spxout << "DEBUG: computing columns of inverted basis matrix again\n";)
187  // collect columns of the basis inverse
188  for( int i = 0; i < basisdim; ++i)
189  {
190  binvcol2[i] = new DVector(basisdim);
191  binvcol2[i]->clear();
192  assert(getBasisInverseColReal(i, binvcol2[i]->get_ptr(), 0, 0, false));
193  }
194  }
195 
196  MSG_INFO1( spxout, spxout << "DEBUG: computing rows of inverted basis matrix again\n";)
197  // collect rows of the basis inverse
198  for( int i = 0; i < basisdim; ++i)
199  {
200  binvrow2[i] = new DVector(basisdim);
201  binvrow2[i]->clear();
202  assert(getBasisInverseRowReal(i, binvrow2[i]->get_ptr(), 0, 0, false));
203  }
204 
205  MSG_INFO1( spxout, spxout << "DEBUG: checking rows and columns of scaled/unscaled inverted of basis matrix\n";)
206  for( int i = 0; i < basisdim; ++i)
207  {
208  Real sumerror = 0.0;
209  for( int j = 0; j < basisdim; ++j)
210  {
211  if( colrep )
212  {
213  if( NE((*binvcol[i])[j], (*binvcol2[i])[j], _solver.feastol()) )
214  {
215  MSG_INFO1( spxout, spxout << "ERROR: col " << i << " " << j << ", " << (*binvcol[i])[j] << " " << (*binvcol2[i])[j] << std::endl );
216  sumerror += spxAbs((*binvcol[i])[j] - (*binvcol2[i])[j]);
217  }
218  }
219  if( NE((*binvrow[i])[j], (*binvrow2[i])[j], _solver.feastol()) )
220  {
221  MSG_INFO1( spxout, spxout << "ERROR: row " << i << " " << j << ", " << (*binvrow[i])[j] / (*binvrow2[i])[j] << std::endl );
222  sumerror += spxAbs((*binvrow[i])[j] - (*binvrow2[i])[j]);
223  }
224  }
225  assert(sumerror < _solver.feastol());
226  }
227 
228  spx_free(binvcol2);
229  spx_free(binvrow2);
230  }
231 
232  spx_free(inds);
233  spx_free(binvrow);
234  spx_free(binvcol);
235  }
236 
237 } // namespace soplex
238 #endif
const VectorBase< R > & rhs() const
Returns right hand side vector.
Definition: spxlpbase.h:219
Rational spxAbs(const Rational &r)
Absolute.
Definition: rational.cpp:3909
void _checkScaling(SPxLPReal *origLP) const
check scaling of LP
Definition: testsoplex.cpp:26
bool multBasisTranspose(Real *vec, bool unscale=true)
multiply with transpose of basis matrix; vec * B^T (inplace)
Definition: soplex.cpp:4770
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:4104
const VectorBase< R > & upper() const
Returns upper bound vector.
Definition: spxlpbase.h:456
int size() const
Number of used indices.
Definition: svectorbase.h:152
bool multBasis(Real *vec, bool unscale=true)
multiply with basis matrix; B * vec (inplace)
Definition: soplex.cpp:4660
Real feastol() const
allowed primal feasibility tolerance.
Definition: spxsolver.h:786
void unscaleLPandReloadBasis()
unscales the LP and reloads the basis
Definition: spxsolver.cpp:525
bool isScaled() const
Returns true if and only if the LP is scaled.
Definition: spxlpbase.h:139
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:386
R & value(int n)
Reference to value of n &#39;th nonzero.
Definition: svectorbase.h:252
void _checkBasisScaling()
check correctness of (un)scaled basis matrix operations
Definition: testsoplex.cpp:89
rowwise representation.
Definition: spxsolver.h:107
int nRows() const
Returns number of rows in LP.
Definition: spxlpbase.h:151
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:444
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:4290
Class for collecting statistical information.
R obj(int i) const
Returns objective value of column i.
Definition: spxlpbase.h:403
const VectorBase< R > & lhs() const
Returns left hand side vector.
Definition: spxlpbase.h:253
SPxOut spxout
Definition: soplex.h:1444
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:380
Everything should be within this namespace.
SPxLPReal * _realLP
Definition: soplex.h:1592
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:1569
const SVectorBase< R > & rowVector(int i) const
Gets row vector of row i.
Definition: spxlpbase.h:204
void clear()
Set vector to 0.
Definition: vectorbase.h:260
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:373
int nCols() const
Returns number of columns in LP.
Definition: spxlpbase.h:157
const VectorBase< R > & lower() const
Returns (internal and possibly scaled) lower bound vector.
Definition: spxlpbase.h:483
SPxSolver::Status _status
Definition: soplex.h:1812
Representation rep() const
return the current basis representation.
Definition: spxsolver.h:478
columnwise representation.
Definition: spxsolver.h:108
void spx_free(T &p)
Release memory.
Definition: spxalloc.h:109
void getRowVectorUnscaled(int i, DSVectorBase< Real > &vec) const
Gets unscaled row vector of row i.