Scippy

SoPlex

Sequential object-oriented simPlex

spxleastsqsc.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 /**@file spxleastsqsc.cpp
17  * @brief LP least squares scaling.
18  */
19 #include <cmath>
20 #include <assert.h>
21 #include "spxleastsqsc.h"
22 #include "spxout.h"
23 #include "basevectors.h"
24 #include "svsetbase.h"
25 #include "svectorbase.h"
26 #include "ssvectorbase.h"
27 
28 namespace soplex
29 {
30 
31 /* update scaling vector */
32 static inline void updateScale(
33  const SSVector vecnnzeroes,
34  const SSVector resnvec,
35  SSVector& tmpvec,
36  SSVector*& psccurr,
37  SSVector*& pscprev,
38  Real qcurr,
39  Real qprev,
40  Real eprev1,
41  Real eprev2)
42 {
43  assert(psccurr != NULL);
44  assert(pscprev != NULL);
45  assert(qcurr * qprev != 0.0);
46 
47  Real fac = -(eprev1 * eprev2);
48 
49  SSVector* pssv;
50 
51  *pscprev -= *psccurr;
52 
53  if( isZero(fac) )
54  (*pscprev).clear();
55  else
56  *pscprev *= fac;
57 
58  *pscprev += tmpvec.assignPWproduct4setup(resnvec, vecnnzeroes);
59 
60  *pscprev *= 1.0 / (qcurr * qprev);
61  *pscprev += *psccurr;
62 
63  /* swap pointers */
64  pssv = psccurr;
65  psccurr = pscprev;
66  pscprev = pssv;
67 }
68 
69 /* update scaling vector after main loop */
70 static inline void updateScaleFinal(
71  const SSVector vecnnzeroes,
72  const SSVector resnvec,
73  SSVector& tmpvec,
74  SSVector*& psccurr,
75  SSVector*& pscprev,
76  Real q,
77  Real eprev1,
78  Real eprev2)
79 {
80  assert(q != 0);
81  assert(psccurr != NULL);
82  assert(pscprev != NULL);
83 
84  Real fac = -(eprev1 * eprev2);
85 
86  *pscprev -= *psccurr;
87 
88  if( isZero(fac) )
89  (*pscprev).clear();
90  else
91  *pscprev *= fac;
92 
93  *pscprev += tmpvec.assignPWproduct4setup(resnvec, vecnnzeroes);
94  *pscprev *= 1.0 / q;
95  *pscprev += *psccurr;
96 
97  psccurr = pscprev;
98 }
99 
100 /* update residual vector */
101 static inline void updateRes(
102  const SVSet facset,
103  const SSVector resvecprev,
104  SSVector& resvec,
105  SSVector& tmpvec,
106  Real eprev,
107  Real qcurr)
108 {
109  assert(qcurr != 0);
110 
111  if( isZero(eprev) )
112  resvec.clear();
113  else
114  resvec *= eprev;
115 
116  tmpvec.assign2product4setup(facset, resvecprev);
117  tmpvec.setup();
118  resvec += tmpvec;
119 
120  resvec *= (-1.0 / qcurr);
121  resvec.setup();
122 }
123 
124 
125 /* initialize constant vectors and matrices */
126 static void initConstVecs(
127  const SVSet* vecset,
128  SVSet& facset,
129  SSVector& veclogs,
130  SSVector& vecnnzeroes)
131 {
132  assert(vecset != NULL);
133 
134  Real a;
135  Real x;
136  Real sum;
137  Real log2_inv = 1.0/log(2.0);
138  int l;
139  int size;
140  int nvec = vecset->num();
141  int nnzeros;
142 
143  for(int k = 0; k < nvec; ++k )
144  {
145  sum = 0.0;
146  nnzeros = 0;
147  const SVector& lpvec = (*vecset)[k];
148 
149  size = lpvec.size();
150 
151  for( l = 0; l < size; ++l)
152  {
153  a = spxAbs(lpvec.value(l));
154 
155  if( !isZero(a) )
156  {
157  sum += log(double(a)) * log2_inv;
158  nnzeros++;
159  }
160  }
161 
162  if( nnzeros > 0)
163  {
164  x = (1.0 / nnzeros);
165  }
166  else
167  {
168  /* all-0 entries, so assume row is already scaled (all-1) */
169  sum = (Real) size;
170  x = 1.0 / size;
171  }
172 
173  veclogs.add(k, sum);
174 
175  vecnnzeroes.add(k, x);
176 
177  /* create new vector for facset */
178  SVector& vecnew = (*(facset.create(nnzeros)));
179 
180  for( l = 0; l < size; ++l)
181  {
182  if( !isZero(lpvec.value(l)) )
183  vecnew.add(lpvec.index(l), x);
184  }
185  vecnew.sort();
186  }
187 
188  assert(veclogs.isSetup());
189  assert(vecnnzeroes.isSetup());
190 }
191 
192 /* return name of scaler */
193 static const char* makename()
194 {
195  return "Least squares";
196 }
197 
199  : SPxScaler(makename(), false, false), acrcydivisor(ACCURACY_DIVISOR), maxrounds(MAX_ROUNDS)
200 {}
201 
204 {}
205 
207 {
208  if(this != &rhs)
209  {
211  }
212 
213  return *this;
214 }
215 
216 
217 void SPxLeastSqSC::setRealParam(Real param, const char* name)
218 {
219  assert(param >= 1.0);
220  acrcydivisor = param;
221 }
222 
223 void SPxLeastSqSC::setIntParam(int param, const char* name)
224 {
225  assert(param >= 0);
226  maxrounds = param;
227 }
228 
229 void SPxLeastSqSC::scale(SPxLP& lp, bool persistent)
230 {
231  MSG_INFO1( (*spxout), (*spxout) << "Least squares LP scaling" << (persistent ? " (persistent)" : "") << std::endl; )
232 
233  setup(lp);
234 
235  Real tmp;
236  Real smax;
237  Real qcurr;
238  Real qprev;
239  Real scurr;
240  Real sprev;
241  Real eprev[3];
242  int k;
243  int l;
244  int nrows = lp.nRows();
245  int ncols = lp.nCols();
246  int nnzeroes = lp.nNzos();
247  int maxscrounds = maxrounds;
248 
249  /* constant factor matrices */
250  SVSet facnrows(nrows, nrows, 1.1, 1.2);
251  SVSet facncols(ncols, ncols, 1.1, 1.2);
252 
253  /* column scaling factor vectors */
254  SSVector colscale1(ncols);
255  SSVector colscale2(ncols);
256 
257  /* row scaling factor vectors */
258  SSVector rowscale1(nrows);
259  SSVector rowscale2(nrows);
260 
261  /* residual vectors */
262  SSVector resnrows(nrows);
263  SSVector resncols(ncols);
264 
265  /* vectors to store temporary values */
266  SSVector tmprows(nrows);
267  SSVector tmpcols(ncols);
268 
269  /* vectors storing the row and column sums (respectively) of logarithms of
270  *(absolute values of) non-zero elements of left hand matrix of LP
271  */
272  SSVector rowlogs(nrows);
273  SSVector collogs(ncols);
274 
275  /* vectors storing the inverted number of non-zeros in each row and column
276  *(respectively) of left hand matrix of LP
277  */
278  SSVector rownnzeroes(nrows);
279  SSVector colnnzeroes(ncols);
280 
281  /* vector pointers */
282  SSVector* csccurr = &colscale1;
283  SSVector* cscprev = &colscale2;
284  SSVector* rsccurr = &rowscale1;
285  SSVector* rscprev = &rowscale2;
286 
287  MSG_INFO2( (*spxout), (*spxout) << "before scaling:"
288  << " min= " << lp.minAbsNzo()
289  << " max= " << lp.maxAbsNzo()
290  << " col-ratio= " << maxColRatio(lp)
291  << " row-ratio= " << maxRowRatio(lp)
292  << std::endl; )
293 
294  /* initialize scalars, vectors and matrices */
295 
296  smax = nnzeroes / acrcydivisor;
297  qcurr = 1.0;
298  qprev = 0.0;
299 
300  for(k = 0; k < 3; ++k )
301  eprev[k] = 0.0;
302 
303  initConstVecs(lp.rowSet(), facnrows, rowlogs, rownnzeroes);
304  initConstVecs(lp.colSet(), facncols, collogs, colnnzeroes);
305 
306  assert(tmprows.isSetup());
307  assert(tmpcols.isSetup());
308  assert(rowscale1.isSetup());
309  assert(rowscale2.isSetup());
310  assert(colscale1.isSetup());
311  assert(colscale2.isSetup());
312 
313  // compute first residual vector
314  resncols = collogs - tmpcols.assign2product4setup(facnrows, rowlogs);
315 
316  resncols.setup();
317  resnrows.setup();
318 
319  rowscale1.assignPWproduct4setup(rownnzeroes, rowlogs);
320  rowscale2 = rowscale1;
321 
322  scurr = resncols * tmpcols.assignPWproduct4setup(colnnzeroes, resncols);
323 
324  /* conjugate gradient loop */
325  for( k = 0; k < maxscrounds; ++k )
326  {
327  sprev = scurr;
328 
329  // is k even?
330  if( (k % 2) == 0 )
331  {
332  // not in first iteration?
333  if( k != 0 ) // true, then update row scaling factor vector
334  updateScale(rownnzeroes, resnrows, tmprows, rsccurr, rscprev, qcurr, qprev, eprev[1], eprev[2]);
335 
336  updateRes(facncols, resncols, resnrows, tmprows, eprev[0], qcurr);
337 
338  scurr = resnrows * tmprows.assignPWproduct4setup(resnrows, rownnzeroes);
339  }
340  else // k is odd
341  {
342  // update column scaling factor vector
343  updateScale(colnnzeroes, resncols, tmpcols, csccurr, cscprev, qcurr, qprev, eprev[1], eprev[2]);
344 
345  updateRes(facnrows, resnrows, resncols, tmpcols, eprev[0], qcurr);
346  scurr = resncols * (tmpcols.assignPWproduct4setup(resncols, colnnzeroes) );
347  }
348 
349  // shift eprev entries one to the right
350  for( l = 2; l > 0; --l)
351  eprev[l] = eprev[l - 1];
352 
353  eprev[0] = (qcurr * scurr) / sprev;
354 
355  tmp = qcurr;
356  qcurr = 1.0 - eprev[0];
357  qprev = tmp;
358 
359  // termination criterion met?
360  if( scurr < smax )
361  break;
362  }
363 
364  // is k even?
365  if( (k % 2) == 0 )
366  {
367  // update column scaling factor vector
368  updateScaleFinal(colnnzeroes, resncols, tmpcols, csccurr, cscprev, qprev, eprev[1], eprev[2]);
369  }
370  else // k is odd
371  {
372  // update row scaling factor vector
373  updateScaleFinal(rownnzeroes, resnrows, tmprows, rsccurr, rscprev, qprev, eprev[1], eprev[2]);
374  }
375 
376  /* compute actual scaling factors */
377 
378  SSVector rowscale = *rsccurr;
379  SSVector colscale = *csccurr;
380  DataArray < int > colscaleExp = *m_activeColscaleExp;
381  DataArray < int > rowscaleExp = *m_activeRowscaleExp;
382 
383  for( k = 0; k < nrows; ++k )
384  rowscaleExp[k] = int( rowscale[k] + ((rowscale[k] >= 0)? (+0.5) : (-0.5)) );
385 
386  for( k = 0; k < ncols; ++k )
387  colscaleExp[k] = int( colscale[k] + ((colscale[k] >= 0)? (+0.5) : (-0.5)) );
388 
389  // scale
390  applyScaling(lp);
391 
392  MSG_INFO3( (*spxout), (*spxout) << "Row scaling min= " << minAbsRowscale()
393  << " max= " << maxAbsRowscale()
394  << std::endl
395  << "Col scaling min= " << minAbsColscale()
396  << " max= " << maxAbsColscale()
397  << std::endl; )
398 
399  MSG_INFO2( (*spxout), (*spxout) << "after scaling: "
400  << " min= " << lp.minAbsNzo(false)
401  << " max= " << lp.maxAbsNzo(false)
402  << " col-ratio= " << maxColRatio(lp)
403  << " row-ratio= " << maxRowRatio(lp)
404  << std::endl; )
405 }
406 
407 } // namespace soplex
Rational spxAbs(const Rational &r)
Absolute.
Definition: rational.cpp:3909
#define ACCURACY_DIVISOR
Definition: spxleastsqsc.h:28
static void initConstVecs(const SVSet *vecset, SVSet &facset, SSVector &veclogs, SSVector &vecnnzeroes)
virtual void setup(SPxLPBase< Real > &lp)
clear and setup scaling arrays in the LP
Definition: spxscaler.cpp:124
bool isSetup() const
Returns setup status.
Definition: ssvectorbase.h:120
virtual R minAbsNzo(bool unscaled=true) const
Absolute smallest non-zero element in (possibly scaled) LP.
static const char * makename(bool doBoth)
Definition: spxequilisc.cpp:29
int size() const
Number of used indices.
Definition: svectorbase.h:152
static void updateRes(const SVSet facset, const SSVector resvecprev, SSVector &resvec, SSVector &tmpvec, Real eprev, Real qcurr)
Set of sparse vectors.
Least squares scaling.This SPxScaler implementation performs least squares scaling as suggested by Cu...
Definition: spxleastsqsc.h:38
virtual Real maxRowRatio(const SPxLPBase< Real > &lp) const
maximum ratio between absolute biggest and smallest element in any row.
Definition: spxscaler.cpp:854
SVectorBase< R > * create(int idxmax=0)
Creates new SVectorBase in set.
Definition: svsetbase.h:428
R & value(int n)
Reference to value of n &#39;th nonzero.
Definition: svectorbase.h:254
SPxLeastSqSC()
default constructor (this scaler makes no use of inherited member m_colFirst)
static void updateScale(const SSVector vecnnzeroes, const SSVector resnvec, SSVector &tmpvec, SSVector *&psccurr, SSVector *&pscprev, Real qcurr, Real qprev, Real eprev1, Real eprev2)
Wrapper for different output streams and verbosity levels.
int nRows() const
Returns number of rows in LP.
Definition: spxlpbase.h:151
DataArray< int > * m_activeColscaleExp
pointer to currently active column scaling factors
Definition: spxscaler.h:83
int nNzos() const
Returns number of nonzeros in LP.
Definition: spxlpbase.h:163
virtual void applyScaling(SPxLPBase< Real > &lp)
applies m_colscale and m_rowscale to the lp.
Definition: spxscaler.cpp:171
virtual void scale(SPxLP &lp, bool persistent=true)
Scale the loaded SPxLP.
double Real
Definition: spxdefines.h:215
SPxOut * spxout
message handler
Definition: spxscaler.h:87
int & index(int n)
Reference to index of n &#39;th nonzero.
Definition: svectorbase.h:236
#define MSG_INFO2(spxout, x)
Prints out message x if the verbosity level is at least SPxOut::INFO2.
Definition: spxdefines.h:117
#define MAX_ROUNDS
Definition: spxleastsqsc.h:27
void clear()
Clears vector.
Definition: ssvectorbase.h:599
virtual Real maxAbsColscale() const
absolute biggest column scaling factor
Definition: spxscaler.cpp:776
virtual Real minAbsColscale() const
absolute smallest column scaling factor
Definition: spxscaler.cpp:763
virtual void setIntParam(int param, const char *name)
set int param (maximal conjugate gradient rounds)
#define MSG_INFO3(spxout, x)
Prints out message x if the verbosity level is at least SPxOut::INFO3.
Definition: spxdefines.h:119
DataArray< int > * m_activeRowscaleExp
pointer to currently active row scaling factors
Definition: spxscaler.h:84
void add(int i, const R &v)
Append one nonzero (i,v).
Definition: svectorbase.h:272
virtual Real minAbsRowscale() const
absolute smallest row scaling factor
Definition: spxscaler.cpp:790
LP least squares scaling.
Collection of dense, sparse, and semi-sparse vectors.
static void updateScaleFinal(const SSVector vecnnzeroes, const SSVector resnvec, SSVector &tmpvec, SSVector *&psccurr, SSVector *&pscprev, Real q, Real eprev1, Real eprev2)
Everything should be within this namespace.
SPxLeastSqSC & operator=(const SPxLeastSqSC &)
assignment operator
void setup()
Initializes nonzero indices for elements with absolute values above epsilon and sets all other elemen...
Definition: ssvectorbase.h:132
Sparse vectors.
virtual void setRealParam(Real param, const char *name)
set real param (conjugate gradient accuracy)
Semi sparse vector.
LP scaler abstract base class.Instances of classes derived from SPxScaler may be loaded to SoPlex in ...
Definition: spxscaler.h:75
void sort()
Sort nonzeros to increasing indices.
Definition: svectorbase.h:402
virtual Real maxAbsRowscale() const
absolute biggest row scaling factor
Definition: spxscaler.cpp:803
#define MSG_INFO1(spxout, x)
Prints out message x if the verbosity level is at least SPxOut::INFO1.
Definition: spxdefines.h:115
int nCols() const
Returns number of columns in LP.
Definition: spxlpbase.h:157
SSVectorBase< R > & assignPWproduct4setup(const SSVectorBase< S > &x, const SSVectorBase< T > &y)
Assigns pair wise vector product to SSVectorBase.
Definition: basevectors.h:511
const SVSetBase< R > * colSet() const
Returns the complete SVSetBase.
Definition: lpcolsetbase.h:68
bool isZero(Real a, Real eps=Param::epsilon())
returns true iff |a| <= eps
Definition: spxdefines.h:411
virtual Real maxColRatio(const SPxLPBase< Real > &lp) const
maximum ratio between absolute biggest and smallest element in any column.
Definition: spxscaler.cpp:820
const SVSetBase< R > * rowSet() const
Returns the complete SVSet.
Definition: lprowsetbase.h:69
void add(int i, R x)
Adds nonzero (i, x) to SSVectorBase.
Definition: ssvectorbase.h:208
int num() const
Current number of SVectorBases.
Definition: svsetbase.h:746
virtual R maxAbsNzo(bool unscaled=true) const
Absolute biggest non-zero element in (in rational case possibly scaled) LP.
SPxScaler & operator=(const SPxScaler &)
assignment operator
Definition: spxscaler.cpp:84
SSVectorBase< R > & assign2product4setup(const SVSetBase< S > &A, const SSVectorBase< T > &x)
Assigns SSVectorBase to for a setup x.
Definition: basevectors.h:602