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-2019 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 "soplex/spxgeometsc.h"
22 #include "soplex/spxout.h"
23 #include "soplex/spxlpbase.h"
24 #include "soplex/spxequilisc.h"
25 
26 namespace soplex
27 {
28 
30  const SVSet* vecset,
31  const std::vector<Real>& coScaleval,
32  std::vector<Real>& scaleval)
33 {
34  Real pmax = 0.0;
35 
36  assert(scaleval.size() == unsigned(vecset->num()));
37 
38  for(int i = 0; i < vecset->num(); ++i)
39  {
40  const SVector& vec = (*vecset)[i];
41 
42  Real maxi = 0.0;
43  Real mini = infinity;
44 
45  for(int j = 0; j < vec.size(); ++j)
46  {
47  const Real x = spxAbs(vec.value(j) * coScaleval[unsigned(vec.index(j))]);
48 
49  if(!isZero(x))
50  {
51  if(x > maxi)
52  maxi = x;
53 
54  if(x < mini)
55  mini = x;
56  }
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 
66  assert(mini < infinity);
67  assert(maxi > 0.0);
68 
69  scaleval[unsigned(i)] = 1.0 / spxSqrt(mini * maxi);
70 
71  const Real p = maxi / mini;
72 
73  if(p > pmax)
74  pmax = p;
75  }
76 
77  return pmax;
78 }
79 
80 
81 SPxGeometSC::SPxGeometSC(bool equilibrate, int maxIters, Real minImpr, Real goodEnough)
82  : SPxScaler("Geometric")
83  , postequilibration(equilibrate)
84  , m_maxIterations(maxIters)
85  , m_minImprovement(minImpr)
86  , m_goodEnoughRatio(goodEnough)
87 {
88  assert(maxIters > 0);
89  assert(minImpr > 0.0 && minImpr <= 1.0);
90  assert(goodEnough >= 0.0);
91 }
92 
94  : SPxScaler(old)
99 {
100  assert(m_maxIterations > 0);
101  assert(m_minImprovement > 0.0 && m_minImprovement <= 1.0);
102  assert(m_goodEnoughRatio >= 0.0);
103 }
104 
106 {
107  if(this != &rhs)
108  {
110  }
111 
112  return *this;
113 }
114 
115 void SPxGeometSC::scale(SPxLPBase<Real>& lp, bool persistent)
116 {
117 
118  MSG_INFO1((*spxout), (*spxout) << "Geometric scaling LP" << (persistent ? " (persistent)" : "") <<
119  (postequilibration ? " with post-equilibration" : "") << std::endl;)
120 
121  setup(lp);
122 
123  /* We want to do that direction first, with the lower ratio.
124  * See SPxEquiliSC::scale() for a reasoning.
125  */
126  const Real colratio = maxColRatio(lp);
127  const Real rowratio = maxRowRatio(lp);
128 
129  const bool colFirst = colratio < rowratio;
130 
131  Real p0start;
132  Real p1start;
133 
134  if(colFirst)
135  {
136  p0start = colratio;
137  p1start = rowratio;
138  }
139  else
140  {
141  p0start = rowratio;
142  p1start = colratio;
143  }
144 
145  MSG_INFO2((*spxout), (*spxout) << "before scaling:"
146  << " min= " << lp.minAbsNzo()
147  << " max= " << lp.maxAbsNzo()
148  << " col-ratio= " << colratio
149  << " row-ratio= " << rowratio
150  << std::endl;)
151 
152  // perform geometric scaling only if maximum ratio is above threshold
153  bool geoscale = p1start > m_goodEnoughRatio;
154 
155  if(!geoscale)
156  {
157  MSG_INFO2((*spxout), (*spxout) << "No geometric scaling done, ratio good enough" << std::endl;)
158 
159  if(!postequilibration)
160  {
161  lp.setScalingInfo(true);
162  return;
163  }
164 
165  MSG_INFO2((*spxout), (*spxout) << " ... but will still perform equilibrium scaling" << std::endl;)
166  }
167 
168  std::vector<Real> rowscale(unsigned(lp.nRows()), 1.0);
169  std::vector<Real> colscale(unsigned(lp.nCols()), 1.0);
170 
171  Real p0 = 0.0;
172  Real p1 = 0.0;
173 
174  if(geoscale)
175  {
176  Real p0prev = p0start;
177  Real p1prev = p1start;
178 
179  // we make at most maxIterations.
180  for(int count = 0; count < m_maxIterations; count++)
181  {
182  if(colFirst)
183  {
184  p0 = computeScalingVec(lp.colSet(), rowscale, colscale);
185  p1 = computeScalingVec(lp.rowSet(), colscale, rowscale);
186  }
187  else
188  {
189  p0 = computeScalingVec(lp.rowSet(), colscale, rowscale);
190  p1 = computeScalingVec(lp.colSet(), rowscale, colscale);
191  }
192 
193  MSG_INFO3((*spxout), (*spxout) << "Geometric scaling round " << count
194  << " col-ratio= " << (colFirst ? p0 : p1)
195  << " row-ratio= " << (colFirst ? p1 : p0)
196  << std::endl;)
197 
198  if(p0 > m_minImprovement * p0prev && p1 > m_minImprovement * p1prev)
199  break;
200 
201  p0prev = p0;
202  p1prev = p1;
203  }
204 
205  // perform geometric scaling only if there is enough (default 15%) improvement.
206  geoscale = (p0 <= m_minImprovement * p0start || p1 <= m_minImprovement * p1start);
207  }
208 
209  if(!geoscale && !postequilibration)
210  {
211  MSG_INFO2((*spxout), (*spxout) << "No geometric scaling done." << std::endl;)
212  lp.setScalingInfo(true);
213  }
214  else
215  {
216  DataArray<int>& colscaleExp = *m_activeColscaleExp;
217  DataArray<int>& rowscaleExp = *m_activeRowscaleExp;
218 
220  {
221  if(!geoscale)
222  {
223  std::fill(rowscale.begin(), rowscale.end(), 1.0);
224  std::fill(colscale.begin(), colscale.end(), 1.0);
225  }
226 
227  SPxEquiliSC::computePostequiExpVecs(lp, rowscale, colscale, rowscaleExp, colscaleExp);
228  }
229  else
230  {
231  computeExpVec(colscale, colscaleExp);
232  computeExpVec(rowscale, rowscaleExp);
233  }
234 
235  applyScaling(lp);
236 
237  MSG_INFO3((*spxout), (*spxout) << "Row scaling min= " << minAbsRowscale()
238  << " max= " << maxAbsRowscale()
239  << std::endl
240  << "IGEOSC06 Col scaling min= " << minAbsColscale()
241  << " max= " << maxAbsColscale()
242  << std::endl;)
243 
244  MSG_INFO2((*spxout), (*spxout) << "after scaling: "
245  << " min= " << lp.minAbsNzo(false)
246  << " max= " << lp.maxAbsNzo(false)
247  << " col-ratio= " << maxColRatio(lp)
248  << " row-ratio= " << maxRowRatio(lp)
249  << std::endl;)
250  }
251 }
252 
253 
254 } // namespace soplex
Rational spxAbs(const Rational &r)
Absolute.
Definition: rational.cpp:4102
virtual void setup(SPxLPBase< Real > &lp)
clear and setup scaling arrays in the LP
Definition: spxscaler.cpp:129
const Real m_goodEnoughRatio
no scaling needed if ratio is less than this.
Definition: spxgeometsc.h:46
const int m_maxIterations
maximum number of scaling iterations.
Definition: spxgeometsc.h:43
virtual R minAbsNzo(bool unscaled=true) const
Absolute smallest non-zero element in (possibly scaled) LP.
THREADLOCAL const Real infinity
Definition: spxdefines.cpp:26
virtual void scale(SPxLPBase< Real > &lp, bool persistent=true) override
Scale the loaded SPxLP.
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:153
LP geometric mean scaling.
virtual Real maxRowRatio(const SPxLPBase< Real > &lp) const
maximum ratio between absolute biggest and smallest element in any row.
Definition: spxscaler.cpp:866
R & value(int n)
Reference to value of n &#39;th nonzero.
Definition: svectorbase.h:253
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:152
DataArray< int > * m_activeColscaleExp
pointer to currently active column scaling factors
Definition: spxscaler.h:84
virtual void applyScaling(SPxLPBase< Real > &lp)
applies m_colscale and m_rowscale to the lp.
Definition: spxscaler.cpp:177
double Real
Definition: spxdefines.h:218
SPxOut * spxout
message handler
Definition: spxscaler.h:88
int & index(int n)
Reference to index of n &#39;th nonzero.
Definition: svectorbase.h:235
#define MSG_INFO2(spxout, x)
Prints out message x if the verbosity level is at least SPxOut::INFO2.
Definition: spxdefines.h:120
SPxGeometSC & operator=(const SPxGeometSC &)
assignment operator
Real spxSqrt(Real a)
returns square root
Definition: spxdefines.h:332
virtual Real maxAbsColscale() const
absolute biggest column scaling factor
Definition: spxscaler.cpp:781
virtual Real minAbsColscale() const
absolute smallest column scaling factor
Definition: spxscaler.cpp:768
#define MSG_INFO3(spxout, x)
Prints out message x if the verbosity level is at least SPxOut::INFO3.
Definition: spxdefines.h:122
void computeExpVec(const std::vector< Real > &vec, DataArray< int > &vecExp)
round vector entries to power of 2
Definition: spxscaler.cpp:903
DataArray< int > * m_activeRowscaleExp
pointer to currently active row scaling factors
Definition: spxscaler.h:85
SPxGeometSC(bool equilibrate=false, 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:81
void setScalingInfo(bool scaled)
set whether the LP is scaled or not
Definition: spxlpbase.h:146
virtual Real minAbsRowscale() const
absolute smallest row scaling factor
Definition: spxscaler.cpp:795
static void computePostequiExpVecs(const SPxLPBase< Real > &lp, const std::vector< Real > &preRowscale, const std::vector< Real > &preColscale, DataArray< int > &rowscaleExp, DataArray< int > &colscaleExp)
compute equilibrium scaling rounded to power of 2 for existing Real scaling factors (preRowscale...
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:76
virtual Real maxAbsRowscale() const
absolute biggest row scaling factor
Definition: spxscaler.cpp:808
#define MSG_INFO1(spxout, x)
Prints out message x if the verbosity level is at least SPxOut::INFO1.
Definition: spxdefines.h:118
static Real computeScalingVec(const SVSet *vecset, const std::vector< Real > &coScaleval, std::vector< Real > &scaleval)
Definition: spxgeometsc.cpp:29
int nCols() const
Returns number of columns in LP.
Definition: spxlpbase.h:158
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:412
virtual Real maxColRatio(const SPxLPBase< Real > &lp) const
maximum ratio between absolute biggest and smallest element in any column.
Definition: spxscaler.cpp:825
LP equilibrium scaling.
const SVSetBase< R > * rowSet() const
Returns the complete SVSet.
Definition: lprowsetbase.h:69
int num() const
Current number of SVectorBases.
Definition: svsetbase.h:759
virtual R maxAbsNzo(bool unscaled=true) const
Absolute biggest non-zero element in (in rational case possibly scaled) LP.
const bool postequilibration
equilibrate after geometric scaling?
Definition: spxgeometsc.h:42
const Real m_minImprovement
improvement necessary to carry on. (Bixby said Fourer said in MP 23, 274 ff. that 0...
Definition: spxgeometsc.h:45
SPxScaler & operator=(const SPxScaler &)
assignment operator
Definition: spxscaler.cpp:88