1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2 /* */
3 /* This file is part of the class library */
4 /* SoPlex --- the Sequential object-oriented simPlex. */
5 /* */
6 /* Copyright (C) 1996-2022 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.hpp
17 * @brief Geometric mean row/column scaling.
18 */
19 #include <assert.h>
20
(1) Event include_recursion: |
#include file "/sapmnt/home1/d029903/my_work/SCIPSoPlex_coverity/scipoptsuite-8.0.1/soplex/src/soplex/spxgeometsc.h" includes itself: spxgeometsc.h -> spxgeometsc.hpp -> spxgeometsc.h |
(2) Event caretline: |
^ |
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
29 template <class R>
30 static R computeScalingVec(
31 const SVSetBase<R>* vecset,
32 const std::vector<R>& coScaleval,
33 std::vector<R>& scaleval)
34 {
35 R pmax = 0.0;
36
37 assert(scaleval.size() == unsigned(vecset->num()));
38
39 for(int i = 0; i < vecset->num(); ++i)
40 {
41 const SVectorBase<R>& vec = (*vecset)[i];
42
43 R maxi = 0.0;
44 R mini = R(infinity);
45
46 for(int j = 0; j < vec.size(); ++j)
47 {
48 const R x = spxAbs(vec.value(j) * coScaleval[unsigned(vec.index(j))]);
49
50 if(!isZero(x))
51 {
52 if(x > maxi)
53 maxi = x;
54
55 if(x < mini)
56 mini = x;
57 }
58 }
59
60 // empty rows/cols are possible
61 if(mini == R(infinity) || maxi == 0.0)
62 {
63 mini = 1.0;
64 maxi = 1.0;
65 }
66
67 assert(mini < R(infinity));
68 assert(maxi > 0.0);
69
70 scaleval[unsigned(i)] = 1.0 / spxSqrt(mini * maxi);
71
72 const R p = maxi / mini;
73
74 if(p > pmax)
75 pmax = p;
76 }
77
78 return pmax;
79 }
80
81 template <class R>
82 SPxGeometSC<R>::SPxGeometSC(bool equilibrate, int maxIters, R minImpr, R goodEnough)
83 : SPxScaler<R>("Geometric")
84 , postequilibration(equilibrate)
85 , m_maxIterations(maxIters)
86 , m_minImprovement(minImpr)
87 , m_goodEnoughRatio(goodEnough)
88 {
89 assert(maxIters > 0);
90 assert(minImpr > 0.0 && minImpr <= 1.0);
91 assert(goodEnough >= 0.0);
92 }
93
94 template <class R>
95 SPxGeometSC<R>::SPxGeometSC(const SPxGeometSC<R>& old)
96 : SPxScaler<R>(old)
97 , postequilibration(old.postequilibration)
98 , m_maxIterations(old.m_maxIterations)
99 , m_minImprovement(old.m_minImprovement)
100 , m_goodEnoughRatio(old.m_goodEnoughRatio)
101 {
102 assert(m_maxIterations > 0);
103 assert(m_minImprovement > 0.0 && m_minImprovement <= 1.0);
104 assert(m_goodEnoughRatio >= 0.0);
105 }
106
107 template <class R>
108 SPxGeometSC<R>& SPxGeometSC<R>::operator=(const SPxGeometSC<R>& rhs)
109 {
110 if(this != &rhs)
111 {
112 SPxScaler<R>::operator=(rhs);
113 }
114
115 return *this;
116 }
117
118 template <class R>
119 void SPxGeometSC<R>::scale(SPxLPBase<R>& lp, bool persistent)
120 {
121
122 MSG_INFO1((*this->spxout), (*this->spxout) << "Geometric scaling LP" <<
123 (persistent ? " (persistent)" : "") << (postequilibration ? " with post-equilibration" : "") <<
124 std::endl;)
125
126 this->setup(lp);
127
128 /* We want to do that direction first, with the lower ratio.
129 * See SPxEquiliSC<R>::scale() for a reasoning.
130 */
131 const R colratio = this->maxColRatio(lp);
132 const R rowratio = this->maxRowRatio(lp);
133
134 const bool colFirst = colratio < rowratio;
135
136 R p0start;
137 R p1start;
138
139 if(colFirst)
140 {
141 p0start = colratio;
142 p1start = rowratio;
143 }
144 else
145 {
146 p0start = rowratio;
147 p1start = colratio;
148 }
149
150 MSG_INFO2((*this->spxout), (*this->spxout) << "before scaling:"
151 << " min= " << lp.minAbsNzo()
152 << " max= " << lp.maxAbsNzo()
153 << " col-ratio= " << colratio
154 << " row-ratio= " << rowratio
155 << std::endl;)
156
157 // perform geometric scaling only if maximum ratio is above threshold
158 bool geoscale = p1start > m_goodEnoughRatio;
159
160 if(!geoscale)
161 {
162 MSG_INFO2((*this->spxout), (*this->spxout) << "No geometric scaling done, ratio good enough" <<
163 std::endl;)
164
165 if(!postequilibration)
166 {
167 lp.setScalingInfo(true);
168 return;
169 }
170
171 MSG_INFO2((*this->spxout), (*this->spxout) << " ... but will still perform equilibrium scaling" <<
172 std::endl;)
173 }
174
175 std::vector<R> rowscale(unsigned(lp.nRows()), 1.0);
176 std::vector<R> colscale(unsigned(lp.nCols()), 1.0);
177
178 R p0 = 0.0;
179 R p1 = 0.0;
180
181 if(geoscale)
182 {
183 R p0prev = p0start;
184 R p1prev = p1start;
185
186 // we make at most maxIterations.
187 for(int count = 0; count < m_maxIterations; count++)
188 {
189 if(colFirst)
190 {
191 p0 = computeScalingVec(lp.colSet(), rowscale, colscale);
192 p1 = computeScalingVec(lp.rowSet(), colscale, rowscale);
193 }
194 else
195 {
196 p0 = computeScalingVec(lp.rowSet(), colscale, rowscale);
197 p1 = computeScalingVec(lp.colSet(), rowscale, colscale);
198 }
199
200 MSG_INFO3((*this->spxout), (*this->spxout) << "Geometric scaling round " << count
201 << " col-ratio= " << (colFirst ? p0 : p1)
202 << " row-ratio= " << (colFirst ? p1 : p0)
203 << std::endl;)
204
205 if(p0 > m_minImprovement * p0prev && p1 > m_minImprovement * p1prev)
206 break;
207
208 p0prev = p0;
209 p1prev = p1;
210 }
211
212 // perform geometric scaling only if there is enough (default 15%) improvement.
213 geoscale = (p0 <= m_minImprovement * p0start || p1 <= m_minImprovement * p1start);
214 }
215
216 if(!geoscale && !postequilibration)
217 {
218 MSG_INFO2((*this->spxout), (*this->spxout) << "No geometric scaling done." << std::endl;)
219 lp.setScalingInfo(true);
220 }
221 else
222 {
223 DataArray<int>& colscaleExp = *this->m_activeColscaleExp;
224 DataArray<int>& rowscaleExp = *this->m_activeRowscaleExp;
225
226 if(postequilibration)
227 {
228 if(!geoscale)
229 {
230 std::fill(rowscale.begin(), rowscale.end(), 1.0);
231 std::fill(colscale.begin(), colscale.end(), 1.0);
232 }
233
234 SPxEquiliSC<R>::computePostequiExpVecs(lp, rowscale, colscale, rowscaleExp, colscaleExp);
235 }
236 else
237 {
238 this->computeExpVec(colscale, colscaleExp);
239 this->computeExpVec(rowscale, rowscaleExp);
240 }
241
242 this->applyScaling(lp);
243
244 MSG_INFO3((*this->spxout), (*this->spxout) << "Row scaling min= " << this->minAbsRowscale()
245 << " max= " << this->maxAbsRowscale()
246 << std::endl
247 << "IGEOSC06 Col scaling min= " << this->minAbsColscale()
248 << " max= " << this->maxAbsColscale()
249 << std::endl;)
250
251 MSG_INFO2((*this->spxout), (*this->spxout) << "after scaling: "
252 << " min= " << lp.minAbsNzo(false)
253 << " max= " << lp.maxAbsNzo(false)
254 << " col-ratio= " << this->maxColRatio(lp)
255 << " row-ratio= " << this->maxRowRatio(lp)
256 << std::endl;)
257 }
258 }
259
260
261 } // namespace soplex
262