Scippy

SoPlex

Sequential object-oriented simPlex

spxgeometsc.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 spxgeometsc.cpp
17  * @brief Geometric mean row/column scaling.
18  */
19 #include <assert.h>
20 
21 #include "spxgeometsc.h"
22 #include "spxout.h"
23 #include "spxlpbase.h"
24 
25 namespace soplex
26 {
27 /**@param maxIters arbitrary small number, we choose 8
28  @param minImpr Bixby said Fourer said in MP 23, 274 ff. that 0.9 is a good value.
29  @param goodEnough if the max/min ratio is already less then 1000/1 we do not scale.
30 */
31 
33  const SVSet* vecset,
34  const DataArray<Real>& coScaleval,
35  DataArray<Real>& scaleval)
36  {
37 
38  Real pmax = 0.0;
39 
40  for( int i = 0; i < vecset->num(); ++i )
41  {
42  const SVector& vec = (*vecset)[i];
43 
44  Real maxi = 0.0;
45  Real mini = infinity;
46 
47  for( int j = 0; j < vec.size(); ++j )
48  {
49  Real x = spxAbs(vec.value(j) * coScaleval[vec.index(j)]);
50 
51  if (!isZero(x))
52  {
53  if (x > maxi)
54  maxi = x;
55  if (x < mini)
56  mini = x;
57  }
58  }
59  // empty rows/cols are possible
60  if (mini == infinity || maxi == 0.0)
61  {
62  mini = 1.0;
63  maxi = 1.0;
64  }
65  assert(mini < infinity);
66  assert(maxi > 0.0);
67 
68  scaleval[i] = 1.0 / spxSqrt(mini * maxi);
69 
70  Real p = maxi / mini;
71 
72  if (p > pmax)
73  pmax = p;
74  }
75  return pmax;
76  }
77 
78 
79 SPxGeometSC::SPxGeometSC(int maxIters, Real minImpr, Real goodEnough)
80  : SPxScaler("Geometric")
81  , m_maxIterations(maxIters)
82  , m_minImprovement(minImpr)
83  , m_goodEnoughRatio(goodEnough)
84 {}
85 
87  : SPxScaler(old)
91 {}
92 
94 {
95  if (this != &rhs)
96  {
98  }
99 
100  return *this;
101 }
102 
103 void SPxGeometSC::scale(SPxLPBase<Real>& lp, bool persistent)
104 {
105 
106  MSG_INFO1( (*spxout), (*spxout) << "Geometric scaling LP" << (persistent ? " (persistent)" : "") << std::endl; )
107 
108  Real pstart = 0.0;
109  Real p0 = 0.0;
110  Real p1 = 0.0;
111 
112  setup(lp);
113 
114  /* We want to do that direction first, with the lower ratio.
115  * See SPxEquiliSC::scale() for a reasoning.
116  */
117  Real colratio = maxColRatio(lp);
118  Real rowratio = maxRowRatio(lp);
119 
120  DataArray < Real > rowscale(lp.nRows(), lp.nRows(), 1.2);
121  DataArray < Real > colscale(lp.nCols(), lp.nCols(), 1.2);
122 
123  bool colFirst = colratio < rowratio;
124 
125  MSG_INFO2( (*spxout), (*spxout) << "before scaling:"
126  << " min= " << lp.minAbsNzo()
127  << " max= " << lp.maxAbsNzo()
128  << " col-ratio= " << colratio
129  << " row-ratio= " << rowratio
130  << std::endl; )
131 
132  // We make at most maxIterations.
133  for( int count = 0; count < m_maxIterations; count++ )
134  {
135  if (colFirst)
136  {
137  p0 = computeScalingVec(lp.colSet(), rowscale, colscale);
138  p1 = computeScalingVec(lp.rowSet(), colscale, rowscale);
139  }
140  else
141  {
142  p0 = computeScalingVec(lp.rowSet(), colscale, rowscale);
143  p1 = computeScalingVec(lp.colSet(), rowscale, colscale);
144  }
145  MSG_INFO3( (*spxout), (*spxout) << "Geometric scaling round " << count
146  << " col-ratio= " << (colFirst ? p0 : p1)
147  << " row-ratio= " << (colFirst ? p1 : p0)
148  << std::endl; )
149 
150  // record start value, this is done with m_col/rowscale = 1.0, so it is the
151  // value from the "original" (as passed to the scaler) LP.
152  if (count == 0)
153  {
154  pstart = p0;
155  // are we already good enough ?
156  if (pstart < m_goodEnoughRatio)
157  break;
158  }
159  else // do not test at the first iteration, then abort if no improvement.
160  if (p1 > m_minImprovement * p0)
161  break;
162  }
163 
164  // we scale only if either:
165  // - we had at the beginning a ratio worse than 1000/1
166  // - we have at least a 15% improvement.
167  if( pstart < m_goodEnoughRatio || p1 > pstart * m_minImprovement )
168  {
169  MSG_INFO2( (*spxout), (*spxout) << "No scaling done." << std::endl; )
170  }
171  else
172  {
173  DataArray < int > colscaleExp = *m_activeColscaleExp;
174  DataArray < int > rowscaleExp = *m_activeRowscaleExp;
175 
176  int i;
177  for( i = 0; i < lp.nCols(); ++i )
178  {
179  frexp(colscale[i], &(colscaleExp[i]));
180  colscaleExp[i] -= 1;
181  }
182 
183  for( i = 0; i < lp.nRows(); ++i )
184  {
185  frexp(rowscale[i], &(rowscaleExp[i]));
186  rowscaleExp[i] -= 1;
187  }
188 
189  applyScaling(lp);
190 
191  MSG_INFO3( (*spxout), (*spxout) << "Row scaling min= " << minAbsRowscale()
192  << " max= " << maxAbsRowscale()
193  << std::endl
194  << "IGEOSC06 Col scaling min= " << minAbsColscale()
195  << " max= " << maxAbsColscale()
196  << std::endl; )
197 
198  MSG_INFO2( (*spxout), (*spxout) << "after scaling: "
199  << " min= " << lp.minAbsNzo(false)
200  << " max= " << lp.maxAbsNzo(false)
201  << " col-ratio= " << maxColRatio(lp)
202  << " row-ratio= " << maxRowRatio(lp)
203  << std::endl; )
204  }
205 }
206 
207 } // namespace soplex
Rational spxAbs(const Rational &r)
Absolute.
Definition: rational.cpp:3909
virtual void setup(SPxLPBase< Real > &lp)
clear and setup scaling arrays in the LP
Definition: spxscaler.cpp:124
const Real m_goodEnoughRatio
no scaling needed if ratio is less than this.
Definition: spxgeometsc.h:44
const int m_maxIterations
maximum number of scaling iterations.
Definition: spxgeometsc.h:42
virtual R minAbsNzo(bool unscaled=true) const
Absolute smallest non-zero element in (possibly scaled) LP.
THREADLOCAL const Real infinity
Definition: spxdefines.cpp:26
Geometric mean row/column scaling.This SPxScaler implementation performs geometric mean scaling of th...
Definition: spxgeometsc.h:35
int size() const
Number of used indices.
Definition: svectorbase.h:152
LP geometric mean scaling.
SPxGeometSC(int maxIters=8, Real minImpr=0.85, Real goodEnough=1e3)
default constructor (this scaler makes no use of inherited members m_colFirst and m_doBoth) ...
Definition: spxgeometsc.cpp:79
virtual void scale(SPxLPBase< Real > &lp, bool persistent=true)
Scale the loaded SPxLP.
virtual Real maxRowRatio(const SPxLPBase< Real > &lp) const
maximum ratio between absolute biggest and smallest element in any row.
Definition: spxscaler.cpp:854
R & value(int n)
Reference to value of n &#39;th nonzero.
Definition: svectorbase.h:254
static Real computeScalingVec(const SVSet *vecset, const DataArray< Real > &coScaleval, DataArray< Real > &scaleval)
Definition: spxgeometsc.cpp:32
Saving LPs in a form suitable for SoPlex.
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
virtual void applyScaling(SPxLPBase< Real > &lp)
applies m_colscale and m_rowscale to the lp.
Definition: spxscaler.cpp:171
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
SPxGeometSC & operator=(const SPxGeometSC &)
assignment operator
Definition: spxgeometsc.cpp:93
Real spxSqrt(Real a)
returns square root
Definition: spxdefines.h:340
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
#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
virtual Real minAbsRowscale() const
absolute smallest row scaling factor
Definition: spxscaler.cpp:790
Everything should be within this namespace.
LP scaler abstract base class.Instances of classes derived from SPxScaler may be loaded to SoPlex in ...
Definition: spxscaler.h:75
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
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
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.
const Real m_minImprovement
improvement necessary to carry on.
Definition: spxgeometsc.h:43
SPxScaler & operator=(const SPxScaler &)
assignment operator
Definition: spxscaler.cpp:84