1 | /* $Id: CoinSimpFactorization.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 | This is a simple factorization of the LP Basis |
8 | */ |
9 | #ifndef CoinSimpFactorization_H |
10 | #define CoinSimpFactorization_H |
11 | |
12 | #include <iostream> |
13 | #include <string> |
14 | #include <cassert> |
15 | #include "CoinTypes.hpp" |
16 | #include "CoinIndexedVector.hpp" |
17 | #include "CoinDenseFactorization.hpp" |
18 | class CoinPackedMatrix; |
19 | |
20 | |
21 | /// pointers used during factorization |
22 | class FactorPointers{ |
23 | public: |
24 | double *rowMax; |
25 | int *firstRowKnonzeros; |
26 | int *prevRow; |
27 | int *nextRow; |
28 | int *firstColKnonzeros; |
29 | int *prevColumn; |
30 | int *nextColumn; |
31 | int *newCols; |
32 | //constructor |
33 | FactorPointers( int numRows, int numCols, int *UrowLengths_, int *UcolLengths_ ); |
34 | // destructor |
35 | ~ FactorPointers(); |
36 | }; |
37 | |
38 | class CoinSimpFactorization : public CoinOtherFactorization { |
39 | friend void CoinSimpFactorizationUnitTest( const std::string & mpsDir ); |
40 | |
41 | public: |
42 | |
43 | /**@name Constructors and destructor and copy */ |
44 | //@{ |
45 | /// Default constructor |
46 | CoinSimpFactorization ( ); |
47 | /// Copy constructor |
48 | CoinSimpFactorization ( const CoinSimpFactorization &other); |
49 | |
50 | /// Destructor |
51 | virtual ~CoinSimpFactorization ( ); |
52 | /// = copy |
53 | CoinSimpFactorization & operator = ( const CoinSimpFactorization & other ); |
54 | /// Clone |
55 | virtual CoinOtherFactorization * clone() const override ; |
56 | //@} |
57 | |
58 | /**@name Do factorization - public */ |
59 | //@{ |
60 | /// Gets space for a factorization |
61 | virtual void getAreas ( int numberRows, |
62 | int numberColumns, |
63 | CoinBigIndex maximumL, |
64 | CoinBigIndex maximumU ) override; |
65 | |
66 | /// PreProcesses column ordered copy of basis |
67 | virtual void preProcess ( ) override; |
68 | /** Does most of factorization returning status |
69 | 0 - OK |
70 | -99 - needs more memory |
71 | -1 - singular - use numberGoodColumns and redo |
72 | */ |
73 | virtual int factor ( ) override; |
74 | /// Does post processing on valid factorization - putting variables on correct rows |
75 | virtual void postProcess(const int * sequence, int * pivotVariable) override; |
76 | /// Makes a non-singular basis by replacing variables |
77 | virtual void makeNonSingular(int * sequence, int numberColumns) override; |
78 | //@} |
79 | |
80 | /**@name general stuff such as status */ |
81 | //@{ |
82 | /// Total number of elements in factorization |
83 | virtual inline int numberElements ( ) const override { |
84 | return numberRows_*(numberColumns_+numberPivots_); |
85 | } |
86 | /// Returns maximum absolute value in factorization |
87 | double maximumCoefficient() const; |
88 | //@} |
89 | |
90 | /**@name rank one updates which do exist */ |
91 | //@{ |
92 | |
93 | /** Replaces one Column to basis, |
94 | returns 0=OK, 1=Probably OK, 2=singular, 3=no room |
95 | If checkBeforeModifying is true will do all accuracy checks |
96 | before modifying factorization. Whether to set this depends on |
97 | speed considerations. You could just do this on first iteration |
98 | after factorization and thereafter re-factorize |
99 | partial update already in U */ |
100 | virtual int replaceColumn ( CoinIndexedVector * regionSparse, |
101 | int pivotRow, |
102 | double pivotCheck , |
103 | bool checkBeforeModifying=false, |
104 | double acceptablePivot=1.0e-8) override; |
105 | //@} |
106 | |
107 | /**@name various uses of factorization (return code number elements) |
108 | which user may want to know about */ |
109 | //@{ |
110 | /** Updates one column (FTRAN) from regionSparse2 |
111 | Tries to do FT update |
112 | number returned is negative if no room |
113 | regionSparse starts as zero and is zero at end. |
114 | Note - if regionSparse2 packed on input - will be packed on output |
115 | */ |
116 | |
117 | virtual int updateColumnFT ( CoinIndexedVector * regionSparse, |
118 | CoinIndexedVector * regionSparse2, |
119 | bool noPermute=false) override; |
120 | |
121 | /** This version has same effect as above with FTUpdate==false |
122 | so number returned is always >=0 */ |
123 | virtual int updateColumn ( CoinIndexedVector * regionSparse, |
124 | CoinIndexedVector * regionSparse2, |
125 | bool noPermute=false) const override; |
126 | /// does FTRAN on two columns |
127 | virtual int updateTwoColumnsFT(CoinIndexedVector * regionSparse1, |
128 | CoinIndexedVector * regionSparse2, |
129 | CoinIndexedVector * regionSparse3, |
130 | bool noPermute=false) override; |
131 | /// does updatecolumn if save==true keeps column for replace column |
132 | int upColumn ( CoinIndexedVector * regionSparse, |
133 | CoinIndexedVector * regionSparse2, |
134 | bool noPermute=false, bool save=false) const; |
135 | /** Updates one column (BTRAN) from regionSparse2 |
136 | regionSparse starts as zero and is zero at end |
137 | Note - if regionSparse2 packed on input - will be packed on output |
138 | */ |
139 | virtual int updateColumnTranspose ( CoinIndexedVector * regionSparse, |
140 | CoinIndexedVector * regionSparse2) const override; |
141 | /// does updateColumnTranspose, the other is a wrapper |
142 | int upColumnTranspose ( CoinIndexedVector * regionSparse, |
143 | CoinIndexedVector * regionSparse2) const; |
144 | //@} |
145 | /// *** Below this user may not want to know about |
146 | |
147 | /**@name various uses of factorization |
148 | which user may not want to know about (left over from my LP code) */ |
149 | //@{ |
150 | /// Get rid of all memory |
151 | inline void clearArrays() override |
152 | { gutsOfDestructor();} |
153 | /// Returns array to put basis indices in |
154 | inline int * indices() const override |
155 | { return reinterpret_cast<int *> (elements_+numberRows_*numberRows_);} |
156 | /// Returns permute in |
157 | virtual inline int * permute() const override |
158 | { return pivotRow_;} |
159 | //@} |
160 | |
161 | /// The real work of destructor |
162 | void gutsOfDestructor(); |
163 | /// The real work of constructor |
164 | void gutsOfInitialize(); |
165 | /// The real work of copy |
166 | void gutsOfCopy(const CoinSimpFactorization &other); |
167 | |
168 | |
169 | /// calls factorization |
170 | void factorize(int numberOfRows, |
171 | int numberOfColumns, |
172 | const int colStarts[], |
173 | const int indicesRow[], |
174 | const double elements[]); |
175 | /// main loop of factorization |
176 | int mainLoopFactor (FactorPointers &pointers ); |
177 | /// copies L by rows |
178 | void copyLbyRows(); |
179 | /// copies U by columns |
180 | void copyUbyColumns(); |
181 | /// finds a pivot element using Markowitz count |
182 | int findPivot(FactorPointers &pointers, int &r, int &s, bool &ifSlack); |
183 | /// finds a pivot in a shortest column |
184 | int findPivotShCol(FactorPointers &pointers, int &r, int &s); |
185 | /// finds a pivot in the first column available |
186 | int findPivotSimp(FactorPointers &pointers, int &r, int &s); |
187 | /// does Gauss elimination |
188 | void GaussEliminate(FactorPointers &pointers, int &r, int &s); |
189 | /// finds short row that intersects a given column |
190 | int findShortRow(const int column, const int length, int &minRow, |
191 | int &minRowLength, FactorPointers &pointers); |
192 | /// finds short column that intersects a given row |
193 | int findShortColumn(const int row, const int length, int &minCol, |
194 | int &minColLength, FactorPointers &pointers); |
195 | /// finds maximum absolute value in a row |
196 | double findMaxInRrow(const int row, FactorPointers &pointers); |
197 | /// does pivoting |
198 | void pivoting(const int pivotRow, const int pivotColumn, |
199 | const double invPivot, FactorPointers &pointers); |
200 | /// part of pivoting |
201 | void updateCurrentRow(const int pivotRow, const int row, |
202 | const double multiplier, FactorPointers &pointers, |
203 | int &newNonZeros); |
204 | /// allocates more space for L |
205 | void increaseLsize(); |
206 | /// allocates more space for a row of U |
207 | void increaseRowSize(const int row, const int newSize); |
208 | /// allocates more space for a column of U |
209 | void increaseColSize(const int column, const int newSize, const bool b); |
210 | /// allocates more space for rows of U |
211 | void enlargeUrow(const int numNewElements); |
212 | /// allocates more space for columns of U |
213 | void enlargeUcol(const int numNewElements, const bool b); |
214 | /// finds a given row in a column |
215 | int findInRow(const int row, const int column); |
216 | /// finds a given column in a row |
217 | int findInColumn(const int column, const int row); |
218 | /// declares a row inactive |
219 | void removeRowFromActSet(const int row, FactorPointers &pointers); |
220 | /// declares a column inactive |
221 | void removeColumnFromActSet(const int column, FactorPointers &pointers); |
222 | /// allocates space for U |
223 | void allocateSpaceForU(); |
224 | /// allocates several working arrays |
225 | void allocateSomeArrays(); |
226 | /// initializes some numbers |
227 | void (); |
228 | /// solves L x = b |
229 | void Lxeqb(double *b) const; |
230 | /// same as above but with two rhs |
231 | void Lxeqb2(double *b1, double *b2) const; |
232 | /// solves U x = b |
233 | void Uxeqb(double *b, double *sol) const; |
234 | /// same as above but with two rhs |
235 | void Uxeqb2(double *b1, double *sol1, double *sol2, double *b2) const; |
236 | /// solves x L = b |
237 | void xLeqb(double *b) const; |
238 | /// solves x U = b |
239 | void xUeqb(double *b, double *sol) const; |
240 | /// updates factorization after a Simplex iteration |
241 | int LUupdate(int newBasicCol); |
242 | /// creates a new eta vector |
243 | void newEta(int row, int numNewElements); |
244 | /// makes a copy of row permutations |
245 | void copyRowPermutations(); |
246 | /// solves H x = b, where H is a product of eta matrices |
247 | void Hxeqb(double *b) const; |
248 | /// same as above but with two rhs |
249 | void Hxeqb2(double *b1, double *b2) const; |
250 | /// solves x H = b |
251 | void xHeqb(double *b) const; |
252 | /// does FTRAN |
253 | void ftran(double *b, double *sol, bool save) const; |
254 | /// same as above but with two columns |
255 | void ftran2(double *b1, double *sol1, double *b2, double *sol2) const; |
256 | /// does BTRAN |
257 | void btran(double *b, double *sol) const; |
258 | ///--------------------------------------- |
259 | |
260 | |
261 | |
262 | //@} |
263 | protected: |
264 | /** Returns accuracy status of replaceColumn |
265 | returns 0=OK, 1=Probably OK, 2=singular */ |
266 | int checkPivot(double saveFromU, double oldPivot) const; |
267 | ////////////////// data ////////////////// |
268 | protected: |
269 | |
270 | /**@name data */ |
271 | //@{ |
272 | /// work array (should be initialized to zero) |
273 | double *denseVector_; |
274 | /// work array |
275 | double *workArea2_; |
276 | /// work array |
277 | double *workArea3_; |
278 | /// array of labels (should be initialized to zero) |
279 | int *vecLabels_; |
280 | /// array of indices |
281 | int *indVector_; |
282 | |
283 | /// auxiliary vector |
284 | double *auxVector_; |
285 | /// auxiliary vector |
286 | int *auxInd_; |
287 | |
288 | /// vector to keep for LUupdate |
289 | double *vecKeep_; |
290 | /// indices of this vector |
291 | int *indKeep_; |
292 | /// number of nonzeros |
293 | mutable int keepSize_; |
294 | |
295 | |
296 | |
297 | /// Starts of the rows of L |
298 | int *LrowStarts_; |
299 | /// Lengths of the rows of L |
300 | int *LrowLengths_; |
301 | /// L by rows |
302 | double *Lrows_; |
303 | /// indices in the rows of L |
304 | int *LrowInd_; |
305 | /// Size of Lrows_; |
306 | int LrowSize_; |
307 | /// Capacity of Lrows_ |
308 | int LrowCap_; |
309 | |
310 | /// Starts of the columns of L |
311 | int *LcolStarts_; |
312 | /// Lengths of the columns of L |
313 | int *LcolLengths_; |
314 | /// L by columns |
315 | double *Lcolumns_; |
316 | /// indices in the columns of L |
317 | int *LcolInd_; |
318 | /// numbers of elements in L |
319 | int LcolSize_; |
320 | /// maximum capacity of L |
321 | int LcolCap_; |
322 | |
323 | |
324 | /// Starts of the rows of U |
325 | int *UrowStarts_; |
326 | /// Lengths of the rows of U |
327 | int *UrowLengths_; |
328 | #ifdef COIN_SIMP_CAPACITY |
329 | /// Capacities of the rows of U |
330 | int *UrowCapacities_; |
331 | #endif |
332 | /// U by rows |
333 | double *Urows_; |
334 | /// Indices in the rows of U |
335 | int *UrowInd_; |
336 | /// maximum capacity of Urows |
337 | int UrowMaxCap_; |
338 | /// number of used places in Urows |
339 | int UrowEnd_; |
340 | /// first row in U |
341 | int firstRowInU_; |
342 | /// last row in U |
343 | int lastRowInU_; |
344 | /// previous row in U |
345 | int *prevRowInU_; |
346 | /// next row in U |
347 | int *nextRowInU_; |
348 | |
349 | /// Starts of the columns of U |
350 | int *UcolStarts_; |
351 | /// Lengths of the columns of U |
352 | int *UcolLengths_; |
353 | #ifdef COIN_SIMP_CAPACITY |
354 | /// Capacities of the columns of U |
355 | int *UcolCapacities_; |
356 | #endif |
357 | /// U by columns |
358 | double *Ucolumns_; |
359 | /// Indices in the columns of U |
360 | int *UcolInd_; |
361 | /// previous column in U |
362 | int *prevColInU_; |
363 | /// next column in U |
364 | int *nextColInU_; |
365 | /// first column in U |
366 | int firstColInU_; |
367 | /// last column in U |
368 | int lastColInU_; |
369 | /// maximum capacity of Ucolumns_ |
370 | int UcolMaxCap_; |
371 | /// last used position in Ucolumns_ |
372 | int UcolEnd_; |
373 | /// indicator of slack variables |
374 | int *colSlack_; |
375 | |
376 | /// inverse values of the elements of diagonal of U |
377 | double *invOfPivots_; |
378 | |
379 | /// permutation of columns |
380 | int *colOfU_; |
381 | /// position of column after permutation |
382 | int *colPosition_; |
383 | /// permutations of rows |
384 | int *rowOfU_; |
385 | /// position of row after permutation |
386 | int *rowPosition_; |
387 | /// permutations of rows during LUupdate |
388 | int *secRowOfU_; |
389 | /// position of row after permutation during LUupdate |
390 | int *secRowPosition_; |
391 | |
392 | /// position of Eta vector |
393 | int *EtaPosition_; |
394 | /// Starts of eta vectors |
395 | int *EtaStarts_; |
396 | /// Lengths of eta vectors |
397 | int *EtaLengths_; |
398 | /// columns of eta vectors |
399 | int *EtaInd_; |
400 | /// elements of eta vectors |
401 | double *Eta_; |
402 | /// number of elements in Eta_ |
403 | int EtaSize_; |
404 | /// last eta row |
405 | int lastEtaRow_; |
406 | /// maximum number of eta vectors |
407 | int maxEtaRows_; |
408 | /// Capacity of Eta_ |
409 | int EtaMaxCap_; |
410 | |
411 | /// minimum storage increase |
412 | int minIncrease_; |
413 | /// maximum size for the diagonal of U after update |
414 | double updateTol_; |
415 | /// do Shul heuristic |
416 | bool doSuhlHeuristic_; |
417 | /// maximum of U |
418 | double maxU_; |
419 | /// bound on the growth rate |
420 | double maxGrowth_; |
421 | /// maximum of A |
422 | double maxA_; |
423 | /// maximum number of candidates for pivot |
424 | int pivotCandLimit_; |
425 | /// number of slacks in basis |
426 | int numberSlacks_; |
427 | /// number of slacks in irst basis |
428 | int firstNumberSlacks_; |
429 | //@} |
430 | }; |
431 | #endif |
432 | |