1 | /* $Id: CoinDenseFactorization.hpp 1448 2011-06-19 15:34:41Z stefan $ */ |
2 | // Copyright (C) 2008, International Business Machines |
3 | // Corporation and others. All Rights Reserved. |
4 | // This code is licensed under the terms of the Eclipse Public License (EPL). |
5 | |
6 | |
7 | /* |
8 | Authors |
9 | |
10 | John Forrest |
11 | |
12 | */ |
13 | #ifndef CoinDenseFactorization_H |
14 | #define CoinDenseFactorization_H |
15 | |
16 | #include <iostream> |
17 | #include <string> |
18 | #include <cassert> |
19 | #include "CoinTypes.hpp" |
20 | #include "CoinIndexedVector.hpp" |
21 | #include "CoinFactorization.hpp" |
22 | class CoinPackedMatrix; |
23 | /// Abstract base class which also has some scalars so can be used from Dense or Simp |
24 | class CoinOtherFactorization { |
25 | |
26 | public: |
27 | |
28 | /**@name Constructors and destructor and copy */ |
29 | //@{ |
30 | /// Default constructor |
31 | CoinOtherFactorization ( ); |
32 | /// Copy constructor |
33 | CoinOtherFactorization ( const CoinOtherFactorization &other); |
34 | |
35 | /// Destructor |
36 | virtual ~CoinOtherFactorization ( ); |
37 | /// = copy |
38 | CoinOtherFactorization & operator = ( const CoinOtherFactorization & other ); |
39 | |
40 | /// Clone |
41 | virtual CoinOtherFactorization * clone() const = 0; |
42 | //@} |
43 | |
44 | /**@name general stuff such as status */ |
45 | //@{ |
46 | /// Returns status |
47 | inline int status ( ) const { |
48 | return status_; |
49 | } |
50 | /// Sets status |
51 | inline void setStatus ( int value) |
52 | { status_=value; } |
53 | /// Returns number of pivots since factorization |
54 | inline int pivots ( ) const { |
55 | return numberPivots_; |
56 | } |
57 | /// Sets number of pivots since factorization |
58 | inline void setPivots ( int value ) |
59 | { numberPivots_=value; } |
60 | /// Set number of Rows after factorization |
61 | inline void setNumberRows(int value) |
62 | { numberRows_ = value; } |
63 | /// Number of Rows after factorization |
64 | inline int numberRows ( ) const { |
65 | return numberRows_; |
66 | } |
67 | /// Total number of columns in factorization |
68 | inline int numberColumns ( ) const { |
69 | return numberColumns_; |
70 | } |
71 | /// Number of good columns in factorization |
72 | inline int numberGoodColumns ( ) const { |
73 | return numberGoodU_; |
74 | } |
75 | /// Allows change of pivot accuracy check 1.0 == none >1.0 relaxed |
76 | inline void relaxAccuracyCheck(double value) |
77 | { relaxCheck_ = value;} |
78 | inline double getAccuracyCheck() const |
79 | { return relaxCheck_;} |
80 | /// Maximum number of pivots between factorizations |
81 | inline int maximumPivots ( ) const { |
82 | return maximumPivots_ ; |
83 | } |
84 | /// Set maximum pivots |
85 | virtual void maximumPivots ( int value ); |
86 | |
87 | /// Pivot tolerance |
88 | inline double pivotTolerance ( ) const { |
89 | return pivotTolerance_ ; |
90 | } |
91 | void pivotTolerance ( double value ); |
92 | /// Zero tolerance |
93 | inline double zeroTolerance ( ) const { |
94 | return zeroTolerance_ ; |
95 | } |
96 | void zeroTolerance ( double value ); |
97 | #ifndef COIN_FAST_CODE |
98 | /// Whether slack value is +1 or -1 |
99 | inline double slackValue ( ) const { |
100 | return slackValue_ ; |
101 | } |
102 | void slackValue ( double value ); |
103 | #endif |
104 | /// Returns array to put basis elements in |
105 | virtual CoinFactorizationDouble * elements() const; |
106 | /// Returns pivot row |
107 | virtual int * pivotRow() const; |
108 | /// Returns work area |
109 | virtual CoinFactorizationDouble * workArea() const; |
110 | /// Returns int work area |
111 | virtual int * intWorkArea() const; |
112 | /// Number of entries in each row |
113 | virtual int * numberInRow() const; |
114 | /// Number of entries in each column |
115 | virtual int * numberInColumn() const; |
116 | /// Returns array to put basis starts in |
117 | virtual CoinBigIndex * starts() const; |
118 | /// Returns permute back |
119 | virtual int * permuteBack() const; |
120 | /** Get solve mode e.g. 0 C++ code, 1 Lapack, 2 choose |
121 | If 4 set then values pass |
122 | if 8 set then has iterated |
123 | */ |
124 | inline int solveMode() const |
125 | { return solveMode_ ;} |
126 | /** Set solve mode e.g. 0 C++ code, 1 Lapack, 2 choose |
127 | If 4 set then values pass |
128 | if 8 set then has iterated |
129 | */ |
130 | inline void setSolveMode(int value) |
131 | { solveMode_ = value;} |
132 | /// Returns true if wants tableauColumn in replaceColumn |
133 | virtual bool wantsTableauColumn() const; |
134 | /** Useful information for factorization |
135 | 0 - iteration number |
136 | whereFrom is 0 for factorize and 1 for replaceColumn |
137 | */ |
138 | virtual void setUsefulInformation(const int * info,int whereFrom); |
139 | /// Get rid of all memory |
140 | virtual void clearArrays() {} |
141 | //@} |
142 | /**@name virtual general stuff such as permutation */ |
143 | //@{ |
144 | /// Returns array to put basis indices in |
145 | virtual int * indices() const = 0; |
146 | /// Returns permute in |
147 | virtual int * permute() const = 0; |
148 | /// Total number of elements in factorization |
149 | virtual int numberElements ( ) const = 0; |
150 | //@} |
151 | /**@name Do factorization - public */ |
152 | //@{ |
153 | /// Gets space for a factorization |
154 | virtual void getAreas ( int numberRows, |
155 | int numberColumns, |
156 | CoinBigIndex maximumL, |
157 | CoinBigIndex maximumU ) = 0; |
158 | |
159 | /// PreProcesses column ordered copy of basis |
160 | virtual void preProcess ( ) = 0; |
161 | /** Does most of factorization returning status |
162 | 0 - OK |
163 | -99 - needs more memory |
164 | -1 - singular - use numberGoodColumns and redo |
165 | */ |
166 | virtual int factor ( ) = 0; |
167 | /// Does post processing on valid factorization - putting variables on correct rows |
168 | virtual void postProcess(const int * sequence, int * pivotVariable) = 0; |
169 | /// Makes a non-singular basis by replacing variables |
170 | virtual void makeNonSingular(int * sequence, int numberColumns) = 0; |
171 | //@} |
172 | |
173 | /**@name rank one updates which do exist */ |
174 | //@{ |
175 | |
176 | /** Replaces one Column to basis, |
177 | returns 0=OK, 1=Probably OK, 2=singular, 3=no room |
178 | If checkBeforeModifying is true will do all accuracy checks |
179 | before modifying factorization. Whether to set this depends on |
180 | speed considerations. You could just do this on first iteration |
181 | after factorization and thereafter re-factorize |
182 | partial update already in U */ |
183 | virtual int replaceColumn ( CoinIndexedVector * regionSparse, |
184 | int pivotRow, |
185 | double pivotCheck , |
186 | bool checkBeforeModifying=false, |
187 | double acceptablePivot=1.0e-8)=0; |
188 | //@} |
189 | |
190 | /**@name various uses of factorization (return code number elements) |
191 | which user may want to know about */ |
192 | //@{ |
193 | /** Updates one column (FTRAN) from regionSparse2 |
194 | Tries to do FT update |
195 | number returned is negative if no room |
196 | regionSparse starts as zero and is zero at end. |
197 | Note - if regionSparse2 packed on input - will be packed on output |
198 | */ |
199 | virtual int updateColumnFT ( CoinIndexedVector * regionSparse, |
200 | CoinIndexedVector * regionSparse2, |
201 | bool noPermute=false) = 0; |
202 | /** This version has same effect as above with FTUpdate==false |
203 | so number returned is always >=0 */ |
204 | virtual int updateColumn ( CoinIndexedVector * regionSparse, |
205 | CoinIndexedVector * regionSparse2, |
206 | bool noPermute=false) const = 0; |
207 | /// does FTRAN on two columns |
208 | virtual int updateTwoColumnsFT(CoinIndexedVector * regionSparse1, |
209 | CoinIndexedVector * regionSparse2, |
210 | CoinIndexedVector * regionSparse3, |
211 | bool noPermute=false) = 0; |
212 | /** Updates one column (BTRAN) from regionSparse2 |
213 | regionSparse starts as zero and is zero at end |
214 | Note - if regionSparse2 packed on input - will be packed on output |
215 | */ |
216 | virtual int updateColumnTranspose ( CoinIndexedVector * regionSparse, |
217 | CoinIndexedVector * regionSparse2) const = 0; |
218 | //@} |
219 | |
220 | ////////////////// data ////////////////// |
221 | protected: |
222 | |
223 | /**@name data */ |
224 | //@{ |
225 | /// Pivot tolerance |
226 | double pivotTolerance_; |
227 | /// Zero tolerance |
228 | double zeroTolerance_; |
229 | #ifndef COIN_FAST_CODE |
230 | /// Whether slack value is +1 or -1 |
231 | double slackValue_; |
232 | #else |
233 | #ifndef slackValue_ |
234 | #define slackValue_ -1.0 |
235 | #endif |
236 | #endif |
237 | /// Relax check on accuracy in replaceColumn |
238 | double relaxCheck_; |
239 | /// Number of elements after factorization |
240 | CoinBigIndex factorElements_; |
241 | /// Number of Rows in factorization |
242 | int numberRows_; |
243 | /// Number of Columns in factorization |
244 | int numberColumns_; |
245 | /// Number factorized in U (not row singletons) |
246 | int numberGoodU_; |
247 | /// Maximum number of pivots before factorization |
248 | int maximumPivots_; |
249 | /// Number pivots since last factorization |
250 | int numberPivots_; |
251 | /// Status of factorization |
252 | int status_; |
253 | /// Maximum rows ever (i.e. use to copy arrays etc) |
254 | int maximumRows_; |
255 | /// Maximum length of iterating area |
256 | CoinBigIndex maximumSpace_; |
257 | /// Pivot row |
258 | int * pivotRow_; |
259 | /** Elements of factorization and updates |
260 | length is maxR*maxR+maxSpace |
261 | will always be long enough so can have nR*nR ints in maxSpace |
262 | */ |
263 | CoinFactorizationDouble * elements_; |
264 | /// Work area of numberRows_ |
265 | CoinFactorizationDouble * workArea_; |
266 | /** Solve mode e.g. 0 C++ code, 1 Lapack, 2 choose |
267 | If 4 set then values pass |
268 | if 8 set then has iterated |
269 | */ |
270 | int solveMode_; |
271 | //@} |
272 | }; |
273 | /** This deals with Factorization and Updates |
274 | This is a simple dense version so other people can write a better one |
275 | |
276 | I am assuming that 32 bits is enough for number of rows or columns, but CoinBigIndex |
277 | may be redefined to get 64 bits. |
278 | */ |
279 | |
280 | |
281 | |
282 | class CoinDenseFactorization : public CoinOtherFactorization { |
283 | friend void CoinDenseFactorizationUnitTest( const std::string & mpsDir ); |
284 | |
285 | public: |
286 | |
287 | /**@name Constructors and destructor and copy */ |
288 | //@{ |
289 | /// Default constructor |
290 | CoinDenseFactorization ( ); |
291 | /// Copy constructor |
292 | CoinDenseFactorization ( const CoinDenseFactorization &other); |
293 | |
294 | /// Destructor |
295 | virtual ~CoinDenseFactorization ( ); |
296 | /// = copy |
297 | CoinDenseFactorization & operator = ( const CoinDenseFactorization & other ); |
298 | /// Clone |
299 | virtual CoinOtherFactorization * clone() const override ; |
300 | //@} |
301 | |
302 | /**@name Do factorization - public */ |
303 | //@{ |
304 | /// Gets space for a factorization |
305 | virtual void getAreas ( int numberRows, |
306 | int numberColumns, |
307 | CoinBigIndex maximumL, |
308 | CoinBigIndex maximumU ) override; |
309 | |
310 | /// PreProcesses column ordered copy of basis |
311 | virtual void preProcess ( ) override; |
312 | /** Does most of factorization returning status |
313 | 0 - OK |
314 | -99 - needs more memory |
315 | -1 - singular - use numberGoodColumns and redo |
316 | */ |
317 | virtual int factor ( ) override; |
318 | /// Does post processing on valid factorization - putting variables on correct rows |
319 | virtual void postProcess(const int * sequence, int * pivotVariable) override; |
320 | /// Makes a non-singular basis by replacing variables |
321 | virtual void makeNonSingular(int * sequence, int numberColumns) override; |
322 | //@} |
323 | |
324 | /**@name general stuff such as number of elements */ |
325 | //@{ |
326 | /// Total number of elements in factorization |
327 | virtual inline int numberElements ( ) const override { |
328 | return numberRows_*(numberColumns_+numberPivots_); |
329 | } |
330 | /// Returns maximum absolute value in factorization |
331 | double maximumCoefficient() const; |
332 | //@} |
333 | |
334 | /**@name rank one updates which do exist */ |
335 | //@{ |
336 | |
337 | /** Replaces one Column to basis, |
338 | returns 0=OK, 1=Probably OK, 2=singular, 3=no room |
339 | If checkBeforeModifying is true will do all accuracy checks |
340 | before modifying factorization. Whether to set this depends on |
341 | speed considerations. You could just do this on first iteration |
342 | after factorization and thereafter re-factorize |
343 | partial update already in U */ |
344 | virtual int replaceColumn ( CoinIndexedVector * regionSparse, |
345 | int pivotRow, |
346 | double pivotCheck , |
347 | bool checkBeforeModifying=false, |
348 | double acceptablePivot=1.0e-8) override; |
349 | //@} |
350 | |
351 | /**@name various uses of factorization (return code number elements) |
352 | which user may want to know about */ |
353 | //@{ |
354 | /** Updates one column (FTRAN) from regionSparse2 |
355 | Tries to do FT update |
356 | number returned is negative if no room |
357 | regionSparse starts as zero and is zero at end. |
358 | Note - if regionSparse2 packed on input - will be packed on output |
359 | */ |
360 | virtual inline int updateColumnFT ( CoinIndexedVector * regionSparse, |
361 | CoinIndexedVector * regionSparse2, |
362 | bool = false) override |
363 | { return updateColumn(regionSparse,regionSparse2);} |
364 | /** This version has same effect as above with FTUpdate==false |
365 | so number returned is always >=0 */ |
366 | virtual int updateColumn ( CoinIndexedVector * regionSparse, |
367 | CoinIndexedVector * regionSparse2, |
368 | bool noPermute=false) const override; |
369 | /// does FTRAN on two columns |
370 | virtual int updateTwoColumnsFT(CoinIndexedVector * regionSparse1, |
371 | CoinIndexedVector * regionSparse2, |
372 | CoinIndexedVector * regionSparse3, |
373 | bool noPermute=false) override; |
374 | /** Updates one column (BTRAN) from regionSparse2 |
375 | regionSparse starts as zero and is zero at end |
376 | Note - if regionSparse2 packed on input - will be packed on output |
377 | */ |
378 | virtual int updateColumnTranspose ( CoinIndexedVector * regionSparse, |
379 | CoinIndexedVector * regionSparse2) const override; |
380 | //@} |
381 | /// *** Below this user may not want to know about |
382 | |
383 | /**@name various uses of factorization |
384 | which user may not want to know about (left over from my LP code) */ |
385 | //@{ |
386 | /// Get rid of all memory |
387 | inline void clearArrays() override |
388 | { gutsOfDestructor();} |
389 | /// Returns array to put basis indices in |
390 | virtual inline int * indices() const override |
391 | { return reinterpret_cast<int *> (elements_+numberRows_*numberRows_);} |
392 | /// Returns permute in |
393 | virtual inline int * permute() const override |
394 | { return nullptr;/*pivotRow_*/;} |
395 | //@} |
396 | |
397 | /// The real work of desstructor |
398 | void gutsOfDestructor(); |
399 | /// The real work of constructor |
400 | void gutsOfInitialize(); |
401 | /// The real work of copy |
402 | void gutsOfCopy(const CoinDenseFactorization &other); |
403 | |
404 | //@} |
405 | protected: |
406 | /** Returns accuracy status of replaceColumn |
407 | returns 0=OK, 1=Probably OK, 2=singular */ |
408 | int checkPivot(double saveFromU, double oldPivot) const; |
409 | ////////////////// data ////////////////// |
410 | protected: |
411 | |
412 | /**@name data */ |
413 | //@{ |
414 | //@} |
415 | }; |
416 | #endif |
417 | |