| 1 | /* $Id: CoinOslFactorization.hpp 1448 2011-06-19 15:34:41Z stefan $ */ |
| 2 | // Copyright (C) 1987, 2009, 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 | Authors |
| 8 | |
| 9 | John Forrest |
| 10 | |
| 11 | */ |
| 12 | #ifndef CoinOslFactorization_H |
| 13 | #define CoinOslFactorization_H |
| 14 | #include <iostream> |
| 15 | #include <string> |
| 16 | #include <cassert> |
| 17 | #include "CoinTypes.hpp" |
| 18 | #include "CoinIndexedVector.hpp" |
| 19 | #include "CoinDenseFactorization.hpp" |
| 20 | class CoinPackedMatrix; |
| 21 | /** This deals with Factorization and Updates |
| 22 | This is ripped off from OSL!!!!!!!!! |
| 23 | |
| 24 | I am assuming that 32 bits is enough for number of rows or columns, but CoinBigIndex |
| 25 | may be redefined to get 64 bits. |
| 26 | */ |
| 27 | |
| 28 | typedef struct {int suc, pre;} EKKHlink; |
| 29 | typedef struct _EKKfactinfo { |
| 30 | double drtpiv; |
| 31 | double demark; |
| 32 | double zpivlu; |
| 33 | double zeroTolerance; |
| 34 | double areaFactor; |
| 35 | int *xrsadr; |
| 36 | int *xcsadr; |
| 37 | int *xrnadr; |
| 38 | int *xcnadr; |
| 39 | int *krpadr; |
| 40 | int *kcpadr; |
| 41 | int *mpermu; |
| 42 | int *bitArray; |
| 43 | int * back; |
| 44 | char * nonzero; |
| 45 | double * trueStart; |
| 46 | mutable double *kadrpm; |
| 47 | int *R_etas_index; |
| 48 | int *R_etas_start; |
| 49 | double *R_etas_element; |
| 50 | |
| 51 | int *xecadr; |
| 52 | int *xeradr; |
| 53 | double *xeeadr; |
| 54 | double *xe2adr; |
| 55 | EKKHlink * kp1adr; |
| 56 | EKKHlink * kp2adr; |
| 57 | double * kw1adr; |
| 58 | double * kw2adr; |
| 59 | double * kw3adr; |
| 60 | int * hpivcoR; |
| 61 | int nrow; |
| 62 | int nrowmx; |
| 63 | int firstDoRow; |
| 64 | int firstLRow; |
| 65 | int maxinv; |
| 66 | int nnetas; |
| 67 | int iterin; |
| 68 | int iter0; |
| 69 | int invok; |
| 70 | int nbfinv; |
| 71 | int num_resets; |
| 72 | int nnentl; |
| 73 | int nnentu; |
| 74 | #ifdef CLP_REUSE_ETAS |
| 75 | int save_nnentu; |
| 76 | #endif |
| 77 | int ndenuc; |
| 78 | int npivots; /* use as xpivsq in factorization */ |
| 79 | int kmxeta; |
| 80 | int xnetal; |
| 81 | int first_dense; |
| 82 | int last_dense; |
| 83 | int iterno; |
| 84 | int numberSlacks; |
| 85 | int lastSlack; |
| 86 | int firstNonSlack; |
| 87 | int xnetalval; |
| 88 | int lstart; |
| 89 | int if_sparse_update; |
| 90 | mutable int packedMode; |
| 91 | int switch_off_sparse_update; |
| 92 | int nuspike; |
| 93 | bool rows_ok; /* replaces test using mrstrt[1] */ |
| 94 | #ifdef CLP_REUSE_ETAS |
| 95 | mutable int reintro; |
| 96 | #endif |
| 97 | int nR_etas; |
| 98 | int sortedEta; /* if vector for F-T is sorted */ |
| 99 | int lastEtaCount; |
| 100 | int ifvsol; |
| 101 | int eta_size; |
| 102 | int last_eta_size; |
| 103 | int maxNNetas; |
| 104 | } EKKfactinfo; |
| 105 | |
| 106 | class CoinOslFactorization : public CoinOtherFactorization { |
| 107 | friend void CoinOslFactorizationUnitTest( const std::string & mpsDir ); |
| 108 | |
| 109 | public: |
| 110 | |
| 111 | /**@name Constructors and destructor and copy */ |
| 112 | //@{ |
| 113 | /// Default constructor |
| 114 | CoinOslFactorization ( ); |
| 115 | /// Copy constructor |
| 116 | CoinOslFactorization ( const CoinOslFactorization &other); |
| 117 | |
| 118 | /// Destructor |
| 119 | virtual ~CoinOslFactorization ( ); |
| 120 | /// = copy |
| 121 | CoinOslFactorization & operator = ( const CoinOslFactorization & other ); |
| 122 | /// Clone |
| 123 | virtual CoinOtherFactorization * clone() const override ; |
| 124 | //@} |
| 125 | |
| 126 | /**@name Do factorization - public */ |
| 127 | //@{ |
| 128 | /// Gets space for a factorization |
| 129 | virtual void getAreas ( int numberRows, |
| 130 | int numberColumns, |
| 131 | CoinBigIndex maximumL, |
| 132 | CoinBigIndex maximumU ) override; |
| 133 | |
| 134 | /// PreProcesses column ordered copy of basis |
| 135 | virtual void preProcess ( ) override; |
| 136 | /** Does most of factorization returning status |
| 137 | 0 - OK |
| 138 | -99 - needs more memory |
| 139 | -1 - singular - use numberGoodColumns and redo |
| 140 | */ |
| 141 | virtual int factor ( ) override; |
| 142 | /// Does post processing on valid factorization - putting variables on correct rows |
| 143 | virtual void postProcess(const int * sequence, int * pivotVariable) override; |
| 144 | /// Makes a non-singular basis by replacing variables |
| 145 | virtual void makeNonSingular(int * sequence, int numberColumns) override; |
| 146 | /** When part of LP - given by basic variables. |
| 147 | Actually does factorization. |
| 148 | Arrays passed in have non negative value to say basic. |
| 149 | If status is okay, basic variables have pivot row - this is only needed |
| 150 | If status is singular, then basic variables have pivot row |
| 151 | and ones thrown out have -1 |
| 152 | returns 0 -okay, -1 singular, -2 too many in basis, -99 memory */ |
| 153 | int factorize ( const CoinPackedMatrix & matrix, |
| 154 | int rowIsBasic[], int columnIsBasic[] , |
| 155 | double areaFactor = 0.0 ); |
| 156 | //@} |
| 157 | |
| 158 | /**@name general stuff such as number of elements */ |
| 159 | //@{ |
| 160 | /// Total number of elements in factorization |
| 161 | virtual inline int numberElements ( ) const override { |
| 162 | return numberRows_*(numberColumns_+numberPivots_); |
| 163 | } |
| 164 | /// Returns array to put basis elements in |
| 165 | virtual CoinFactorizationDouble * elements() const override; |
| 166 | /// Returns pivot row |
| 167 | virtual int * pivotRow() const override; |
| 168 | /// Returns work area |
| 169 | virtual CoinFactorizationDouble * workArea() const override; |
| 170 | /// Returns int work area |
| 171 | virtual int * intWorkArea() const override; |
| 172 | /// Number of entries in each row |
| 173 | virtual int * numberInRow() const override; |
| 174 | /// Number of entries in each column |
| 175 | virtual int * numberInColumn() const override; |
| 176 | /// Returns array to put basis starts in |
| 177 | virtual CoinBigIndex * starts() const override; |
| 178 | /// Returns permute back |
| 179 | virtual int * permuteBack() const override; |
| 180 | /// Returns true if wants tableauColumn in replaceColumn |
| 181 | virtual bool wantsTableauColumn() const override; |
| 182 | /** Useful information for factorization |
| 183 | 0 - iteration number |
| 184 | whereFrom is 0 for factorize and 1 for replaceColumn |
| 185 | */ |
| 186 | virtual void setUsefulInformation(const int * info,int whereFrom) override; |
| 187 | /// Set maximum pivots |
| 188 | virtual void maximumPivots ( int value ) override; |
| 189 | |
| 190 | /// Returns maximum absolute value in factorization |
| 191 | double maximumCoefficient() const; |
| 192 | /// Condition number - product of pivots after factorization |
| 193 | double conditionNumber() const; |
| 194 | /// Get rid of all memory |
| 195 | virtual void clearArrays() override; |
| 196 | //@} |
| 197 | |
| 198 | /**@name rank one updates which do exist */ |
| 199 | //@{ |
| 200 | |
| 201 | /** Replaces one Column to basis, |
| 202 | returns 0=OK, 1=Probably OK, 2=singular, 3=no room |
| 203 | If checkBeforeModifying is true will do all accuracy checks |
| 204 | before modifying factorization. Whether to set this depends on |
| 205 | speed considerations. You could just do this on first iteration |
| 206 | after factorization and thereafter re-factorize |
| 207 | partial update already in U */ |
| 208 | virtual int replaceColumn ( CoinIndexedVector * regionSparse, |
| 209 | int pivotRow, |
| 210 | double pivotCheck , |
| 211 | bool checkBeforeModifying=false, |
| 212 | double acceptablePivot=1.0e-8) override; |
| 213 | //@} |
| 214 | |
| 215 | /**@name various uses of factorization (return code number elements) |
| 216 | which user may want to know about */ |
| 217 | //@{ |
| 218 | /** Updates one column (FTRAN) from regionSparse2 |
| 219 | Tries to do FT update |
| 220 | number returned is negative if no room |
| 221 | regionSparse starts as zero and is zero at end. |
| 222 | Note - if regionSparse2 packed on input - will be packed on output |
| 223 | */ |
| 224 | virtual int updateColumnFT ( CoinIndexedVector * regionSparse, |
| 225 | CoinIndexedVector * regionSparse2, |
| 226 | bool noPermute=false) override; |
| 227 | /** This version has same effect as above with FTUpdate==false |
| 228 | so number returned is always >=0 */ |
| 229 | virtual int updateColumn ( CoinIndexedVector * regionSparse, |
| 230 | CoinIndexedVector * regionSparse2, |
| 231 | bool noPermute=false) const override; |
| 232 | /// does FTRAN on two columns |
| 233 | virtual int updateTwoColumnsFT(CoinIndexedVector * regionSparse1, |
| 234 | CoinIndexedVector * regionSparse2, |
| 235 | CoinIndexedVector * regionSparse3, |
| 236 | bool noPermute=false) override; |
| 237 | /** Updates one column (BTRAN) from regionSparse2 |
| 238 | regionSparse starts as zero and is zero at end |
| 239 | Note - if regionSparse2 packed on input - will be packed on output |
| 240 | */ |
| 241 | virtual int updateColumnTranspose ( CoinIndexedVector * regionSparse, |
| 242 | CoinIndexedVector * regionSparse2) const override; |
| 243 | //@} |
| 244 | /// *** Below this user may not want to know about |
| 245 | |
| 246 | /**@name various uses of factorization |
| 247 | which user may not want to know about (left over from my LP code) */ |
| 248 | //@{ |
| 249 | /// Get rid of all memory |
| 250 | //inline void clearArrays() |
| 251 | //{ gutsOfDestructor();} |
| 252 | /// Returns array to put basis indices in |
| 253 | virtual int * indices() const override; |
| 254 | /// Returns permute in |
| 255 | virtual inline int * permute() const override |
| 256 | { return nullptr;/*pivotRow_*/;} |
| 257 | //@} |
| 258 | |
| 259 | /// The real work of desstructor |
| 260 | void gutsOfDestructor(bool clearFact=true); |
| 261 | /// The real work of constructor |
| 262 | void gutsOfInitialize(bool zapFact=true); |
| 263 | /// The real work of copy |
| 264 | void gutsOfCopy(const CoinOslFactorization &other); |
| 265 | |
| 266 | //@} |
| 267 | protected: |
| 268 | /** Returns accuracy status of replaceColumn |
| 269 | returns 0=OK, 1=Probably OK, 2=singular */ |
| 270 | int checkPivot(double saveFromU, double oldPivot) const; |
| 271 | ////////////////// data ////////////////// |
| 272 | protected: |
| 273 | |
| 274 | /**@name data */ |
| 275 | //@{ |
| 276 | /// Osl factorization data |
| 277 | EKKfactinfo factInfo_; |
| 278 | //@} |
| 279 | }; |
| 280 | #endif |
| 281 | |