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  int l;
138  int size;
139  int nvec = vecset->num();
140  int nnzeros;
141 
142  for(int k = 0; k < nvec; ++k )
143  {
144  sum = 0.0;
145  nnzeros = 0;
146  const SVector& lpvec = (*vecset)[k];
147 
148  size = lpvec.size();
149 
150  for( l = 0; l < size; ++l)
151  {
152  a = spxAbs(lpvec.value(l));
153 
154  if( !isZero(a) )
155  {
156  sum += log2(a);
157  nnzeros++;
158  }
159  }
160 
161  if( nnzeros > 0)
162  {
163  x = (1.0 / nnzeros);
164  }
165  else
166  {
167  /* all-0 entries, so assume row is already scaled (all-1) */
168  sum = (Real) size;
169  x = 1.0 / size;
170  }
171 
172  veclogs.add(k, sum);
173 
174  vecnnzeroes.add(k, x);
175 
176  /* create new vector for facset */
177  SVector& vecnew = (*(facset.create(nnzeros)));
178 
179  for( l = 0; l < size; ++l)
180  {
181  if( !isZero(lpvec.value(l)) )
182  vecnew.add(lpvec.index(l), x);
183  }
184  vecnew.sort();
185  }
186 
187  assert(veclogs.isSetup());
188  assert(vecnnzeroes.isSetup());
189 }
190 
191 /* return name of scaler */
192 static const char* makename()
193 {
194  return "Least squares";
195 }
196 
198  : SPxScaler(makename(), false, false)
199 {}
200 
202  : SPxScaler(old)
203 {}
204 
206 {
207  if(this != &rhs)
208  {
210  }
211 
212  return *this;
213 }
214 
215 
216 void SPxLeastSqSC::setRealParam(Real param, const char* name)
217 {
218  assert(param >= 1.0);
219  acrcydivisor = param;
220 }
221 
222 void SPxLeastSqSC::setIntParam(int param, const char* name)
223 {
224  assert(param >= 0);
225  maxrounds = param;
226 }
227 
228 void SPxLeastSqSC::scale(SPxLP& lp, bool persistent)
229 {
230  MSG_INFO1( (*spxout), (*spxout) << "Least squares LP scaling" << (persistent ? " (persistent)" : "") << std::endl; )
231 
232  setup(lp);
233 
234  Real tmp;
235  Real smax;
236  Real qcurr;
237  Real qprev;
238  Real scurr;
239  Real sprev;
240  Real eprev[3];
241  int k;
242  int l;
243  int nrows = lp.nRows();
244  int ncols = lp.nCols();
245  int nnzeroes = lp.nNzos();
246  int maxscrounds = maxrounds;
247 
248  /* constant factor matrices */
249  SVSet facnrows(nrows, nrows, 1.1, 1.2);
250  SVSet facncols(ncols, ncols, 1.1, 1.2);
251 
252  /* column scaling factor vectors */
253  SSVector colscale1(ncols);
254  SSVector colscale2(ncols);
255 
256  /* row scaling factor vectors */
257  SSVector rowscale1(nrows);
258  SSVector rowscale2(nrows);
259 
260  /* residual vectors */
261  SSVector resnrows(nrows);
262  SSVector resncols(ncols);
263 
264  /* vectors to store temporary values */
265  SSVector tmprows(nrows);
266  SSVector tmpcols(ncols);
267 
268  /* vectors storing the row and column sums (respectively) of logarithms of
269  *(absolute values of) non-zero elements of left hand matrix of LP
270  */
271  SSVector rowlogs(nrows);
272  SSVector collogs(ncols);
273 
274  /* vectors storing the inverted number of non-zeros in each row and column
275  *(respectively) of left hand matrix of LP
276  */
277  SSVector rownnzeroes(nrows);
278  SSVector colnnzeroes(ncols);
279 
280  /* vector pointers */
281  SSVector* csccurr = &colscale1;
282  SSVector* cscprev = &colscale2;
283  SSVector* rsccurr = &rowscale1;
284  SSVector* rscprev = &rowscale2;
285 
286  MSG_INFO2( (*spxout), (*spxout) << "before scaling:"
287  << " min= " << lp.minAbsNzo()
288  << " max= " << lp.maxAbsNzo()
289  << " col-ratio= " << maxColRatio(lp)
290  << " row-ratio= " << maxRowRatio(lp)
291  << std::endl; )
292 
293  /* initialize scalars, vectors and matrices */
294 
295  smax = nnzeroes / acrcydivisor;
296  qcurr = 1.0;
297  qprev = 0.0;
298 
299  for(k = 0; k < 3; ++k )
300  eprev[k] = 0.0;
301 
302  initConstVecs(lp.rowSet(), facnrows, rowlogs, rownnzeroes);
303  initConstVecs(lp.colSet(), facncols, collogs, colnnzeroes);
304 
305  assert(tmprows.isSetup());
306  assert(tmpcols.isSetup());
307  assert(rowscale1.isSetup());
308  assert(rowscale2.isSetup());
309  assert(colscale1.isSetup());
310  assert(colscale2.isSetup());
311 
312  // compute first residual vector
313  resncols = collogs - tmpcols.assign2product4setup(facnrows, rowlogs);
314 
315  resncols.setup();
316  resnrows.setup();
317 
318  rowscale1.assignPWproduct4setup(rownnzeroes, rowlogs);
319  rowscale2 = rowscale1;
320 
321  scurr = resncols * tmpcols.assignPWproduct4setup(colnnzeroes, resncols);
322 
323  /* conjugate gradient loop */
324  for( k = 0; k < maxscrounds; ++k )
325  {
326  sprev = scurr;
327 
328  // is k even?
329  if( (k % 2) == 0 )
330  {
331  // not in first iteration?
332  if( k != 0 ) // true, then update row scaling factor vector
333  updateScale(rownnzeroes, resnrows, tmprows, rsccurr, rscprev, qcurr, qprev, eprev[1], eprev[2]);
334 
335  updateRes(facncols, resncols, resnrows, tmprows, eprev[0], qcurr);
336 
337  scurr = resnrows * tmprows.assignPWproduct4setup(resnrows, rownnzeroes);
338  }
339  else // k is odd
340  {
341  // update column scaling factor vector
342  updateScale(colnnzeroes, resncols, tmpcols, csccurr, cscprev, qcurr, qprev, eprev[1], eprev[2]);
343 
344  updateRes(facnrows, resnrows, resncols, tmpcols, eprev[0], qcurr);
345  scurr = resncols * (tmpcols.assignPWproduct4setup(resncols, colnnzeroes) );
346  }
347 
348  // shift eprev entries one to the right
349  for( l = 2; l > 0; --l)
350  eprev[l] = eprev[l - 1];
351 
352  eprev[0] = (qcurr * scurr) / sprev;
353 
354  tmp = qcurr;
355  qcurr = 1.0 - eprev[0];
356  qprev = tmp;
357 
358  // termination criterion met?
359  if( scurr < smax )
360  break;
361  }
362 
363  // is k even?
364  if( (k % 2) == 0 )
365  {
366  // update column scaling factor vector
367  updateScaleFinal(colnnzeroes, resncols, tmpcols, csccurr, cscprev, qprev, eprev[1], eprev[2]);
368  }
369  else // k is odd
370  {
371  // update row scaling factor vector
372  updateScaleFinal(rownnzeroes, resnrows, tmprows, rsccurr, rscprev, qprev, eprev[1], eprev[2]);
373  }
374 
375  /* compute actual scaling factors */
376 
377  SSVector rowscale = *rsccurr;
378  SSVector colscale = *csccurr;
379  DataArray < int > colscaleExp = *m_activeColscaleExp;
380  DataArray < int > rowscaleExp = *m_activeRowscaleExp;
381 
382  for( k = 0; k < nrows; ++k )
383  rowscaleExp[k] = int( rowscale[k] + ((rowscale[k] >= 0)? (+0.5) : (-0.5)) );
384 
385  for( k = 0; k < ncols; ++k )
386  colscaleExp[k] = int( colscale[k] + ((colscale[k] >= 0)? (+0.5) : (-0.5)) );
387 
388  // scale
389  applyScaling(lp);
390 
391  MSG_INFO3( (*spxout), (*spxout) << "Row scaling min= " << minAbsRowscale()
392  << " max= " << maxAbsRowscale()
393  << std::endl
394  << "Col scaling min= " << minAbsColscale()
395  << " max= " << maxAbsColscale()
396  << std::endl; )
397 
398  MSG_INFO2( (*spxout), (*spxout) << "after scaling: "
399  << " min= " << lp.minAbsNzo(false)
400  << " max= " << lp.maxAbsNzo(false)
401  << " col-ratio= " << maxColRatio(lp)
402  << " row-ratio= " << maxRowRatio(lp)
403  << std::endl; )
404 }
405 
406 } // namespace soplex
Rational spxAbs(const Rational &r)
Absolute.
Definition: rational.cpp:3909
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:214
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:116
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:118
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:114
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:422
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