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-2018 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  for( int i = 0; i < origLP->nRows(); ++i )
35  {
36  assert(EQ(origLP->lhs(i), _realLP->lhsUnscaled(i)));
37  assert(EQ(origLP->rhs(i), _realLP->rhsUnscaled(i)));
38 
39  DSVectorReal row;
41 
42  assert(origLP->rowVector(i).size() == row.size());
43 
44  for( int j = 0; j < row.size(); ++j)
45  {
46  if( NE(row.value(j), origLP->rowVector(i).value(j)) )
47  {
48  MSG_INFO1( spxout, spxout << "DEBUG: scaling error in row " << i << ", col " << j
49  << ": orig " << origLP->rowVector(i).value(j)
50  << ", unscaled: " << row.value(j) << std::endl; )
51  correct = false;
52  }
53  }
54  }
55 
56  MSG_INFO1( spxout, spxout << "DEBUG: checking cols..." << std::endl; )
57  for( int i = 0; i < origLP->nCols(); ++i )
58  {
59  assert(EQ(origLP->lower(i), _realLP->lowerUnscaled(i)));
60  assert(EQ(origLP->upper(i), _realLP->upperUnscaled(i)));
61  assert(EQ(origLP->obj(i), _realLP->objUnscaled(i)));
62 
63  DSVectorReal col;
65 
66  assert(origLP->colVector(i).size() == col.size());
67 
68  for( int j = 0; j < col.size(); ++j)
69  {
70  if( NE(col.value(j), origLP->colVector(i).value(j), _solver.feastol()) )
71  {
72  MSG_INFO1( spxout, spxout << "DEBUG: scaling error in col " << i << ", row " << j
73  << ": orig " << origLP->colVector(i).value(j)
74  << ", unscaled: " << col.value(j) << std::endl; )
75  correct = false;
76  }
77  }
78  }
79  if( !correct )
80  {
81  MSG_INFO1( spxout, spxout << "DEBUG: scaling check failed" << std::endl; )
82  }
83  assert(correct);
84  }
85 
86 
87 
89  {
91  {
92  MSG_INFO1( spxout, spxout << "DEBUG: skipping test on non optimal bases\n" );
93  return;
94  }
95 
96  assert(&_solver == _realLP);
97  DVector** binvcol = 0;
98  DVector** binvrow = 0;
99  int* inds = 0;
100  int basisdim = _solver.nRows(); // do all operations with regard to the column basis
101  bool colrep = (_solver.rep() == SPxSolver::COLUMN);
102  spx_alloc(binvcol, basisdim);
103  spx_alloc(binvrow, basisdim);
104  spx_alloc(inds, basisdim);
105 
106  if( colrep )
107  {
108  MSG_INFO1( spxout, spxout << "DEBUG: computing columns of inverted basis matrix\n";)
109  // collect columns of the basis inverse
110  for( int i = 0; i < basisdim; ++i)
111  {
112  binvcol[i] = new DVector(basisdim);
113  binvcol[i]->clear();
114  assert(getBasisInverseColReal(i, binvcol[i]->get_ptr(), 0, 0, true));
115  }
116  }
117  MSG_INFO1( spxout, spxout << "DEBUG: computing rows of inverted basis matrix\n";)
118  // collect rows of the basis inverse
119  for( int i = 0; i < basisdim; ++i)
120  {
121  binvrow[i] = new DVector(basisdim);
122  binvrow[i]->clear();
123  assert(getBasisInverseRowReal(i, binvrow[i]->get_ptr(), 0, 0, true));
124  }
125 
126  if( colrep )
127  {
128  MSG_INFO1( spxout, spxout << "DEBUG: checking columns for identity after multiplying with basis matrix\n";)
129  // multiply with (unscaled) basis matrix and check result (should be unitvecs)
130  for( int i = 0; i < basisdim; ++i)
131  {
132  DVector result(*binvcol[i]);
133  assert(multBasis(result.get_ptr(), true));
134  Real sumerror = 0.0;
135  for( int j = 0; j < basisdim; ++j)
136  {
137  Real error = 0.0;
138  if( j != i )
139  error = spxAbs(result[j]);
140  else
141  error = spxAbs(result[j] - 1.0);
142  if( error > _solver.feastol() )
143  MSG_INFO1( spxout, spxout << "ERROR: col " << i << " " << j << ", " << result[j] << std::endl );
144  sumerror += error;
145  }
146  assert(_solver.rep() == SPxSolver::ROW || sumerror < _solver.feastol());
147  }
148  }
149 
150  MSG_INFO1( spxout, spxout << "DEBUG: checking rows for identity after multiplying with basis matrix\n";)
151  for( int i = 0; i < basisdim; ++i)
152  {
153  DVector result(*binvrow[i]);
154  assert(multBasisTranspose(result.get_ptr(), true));
155  Real sumerror = 0.0;
156  for( int j = 0; j < basisdim; ++j)
157  {
158  Real error = 0.0;
159  if( j != i )
160  error = spxAbs(result[j]);
161  else
162  error = spxAbs(result[j] - 1.0);
163  if( error > _solver.feastol() )
164  MSG_INFO1( spxout, spxout << "ERROR: row " << i << " " << j << ", " << result[j] << std::endl );
165  sumerror += error;
166  }
167  assert(sumerror < _solver.feastol());
168  }
169 
170  if( _solver.isScaled() )
171  {
172  MSG_INFO1( spxout, spxout << "DEBUG: unscaling LP\n"; )
173 // _solver.setRep(SPxSolver::COLUMN);
175 // _solver.setBasis(_basisStatusRows.get_ptr(), _basisStatusCols.get_ptr());
176 // _solver.solve();
177 
178  DVector** binvcol2 = 0;
179  DVector** binvrow2 = 0;
180  spx_alloc(binvcol2, basisdim);
181  spx_alloc(binvrow2, basisdim);
182 
183  if( colrep )
184  {
185  MSG_INFO1( spxout, spxout << "DEBUG: computing columns of inverted basis matrix again\n";)
186  // collect columns of the basis inverse
187  for( int i = 0; i < basisdim; ++i)
188  {
189  binvcol2[i] = new DVector(basisdim);
190  binvcol2[i]->clear();
191  assert(getBasisInverseColReal(i, binvcol2[i]->get_ptr(), 0, 0, false));
192  }
193  }
194 
195  MSG_INFO1( spxout, spxout << "DEBUG: computing rows of inverted basis matrix again\n";)
196  // collect rows of the basis inverse
197  for( int i = 0; i < basisdim; ++i)
198  {
199  binvrow2[i] = new DVector(basisdim);
200  binvrow2[i]->clear();
201  assert(getBasisInverseRowReal(i, binvrow2[i]->get_ptr(), 0, 0, false));
202  }
203 
204  MSG_INFO1( spxout, spxout << "DEBUG: checking rows and columns of scaled/unscaled inverted of basis matrix\n";)
205  for( int i = 0; i < basisdim; ++i)
206  {
207  Real sumerror = 0.0;
208  for( int j = 0; j < basisdim; ++j)
209  {
210  if( colrep )
211  {
212  if( NE((*binvcol[i])[j], (*binvcol2[i])[j], _solver.feastol()) )
213  {
214  MSG_INFO1( spxout, spxout << "ERROR: col " << i << " " << j << ", " << (*binvcol[i])[j] << " " << (*binvcol2[i])[j] << std::endl );
215  sumerror += spxAbs((*binvcol[i])[j] - (*binvcol2[i])[j]);
216  }
217  }
218  if( NE((*binvrow[i])[j], (*binvrow2[i])[j], _solver.feastol()) )
219  {
220  MSG_INFO1( spxout, spxout << "ERROR: row " << i << " " << j << ", " << (*binvrow[i])[j] / (*binvrow2[i])[j] << std::endl );
221  sumerror += spxAbs((*binvrow[i])[j] - (*binvrow2[i])[j]);
222  }
223  }
224  assert(sumerror < _solver.feastol());
225  }
226 
227  spx_free(binvcol2);
228  spx_free(binvrow2);
229  }
230 
231  spx_free(inds);
232  spx_free(binvrow);
233  spx_free(binvcol);
234  }
235 
236 } // namespace soplex
const VectorBase< R > & rhs() const
Returns right hand side vector.
Definition: spxlpbase.h:219
Rational spxAbs(const Rational &r)
Absolute.
Definition: rational.cpp:3908
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:4773
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:4107
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:4663
Real feastol() const
allowed primal feasibility tolerance.
Definition: spxsolver.h:784
void unscaleLPandReloadBasis()
unscales the LP and reloads the basis
Definition: spxsolver.cpp:513
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:382
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:88
rowwise representation.
Definition: spxsolver.h:106
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:219
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:4293
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:1457
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:1605
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:1582
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:1825
Representation rep() const
return the current basis representation.
Definition: spxsolver.h:487
columnwise representation.
Definition: spxsolver.h:107
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.