1 | /* $Id: ClpDynamicMatrix.hpp 1760 2011-07-02 13:15:55Z stefan $ */ |
2 | // Copyright (C) 2004, 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 | #ifndef ClpDynamicMatrix_H |
7 | #define ClpDynamicMatrix_H |
8 | |
9 | |
10 | #include "CoinPragma.hpp" |
11 | |
12 | #include "ClpPackedMatrix.hpp" |
13 | class ClpSimplex; |
14 | /** This implements a dynamic matrix when we have a limit on the number of |
15 | "interesting rows". This version inherits from ClpPackedMatrix and knows that |
16 | the real matrix is gub. A later version could use shortest path to generate columns. |
17 | |
18 | */ |
19 | |
20 | class ClpDynamicMatrix : public ClpPackedMatrix { |
21 | |
22 | public: |
23 | /// enums for status of various sorts |
24 | enum DynamicStatus { |
25 | soloKey = 0x00, |
26 | inSmall = 0x01, |
27 | atUpperBound = 0x02, |
28 | atLowerBound = 0x03 |
29 | }; |
30 | /**@name Main functions provided */ |
31 | //@{ |
32 | /// Partial pricing |
33 | virtual void partialPricing(ClpSimplex * model, double start, double end, |
34 | int & bestSequence, int & numberWanted); |
35 | |
36 | /** |
37 | update information for a pivot (and effective rhs) |
38 | */ |
39 | virtual int updatePivot(ClpSimplex * model, double oldInValue, double oldOutValue); |
40 | /** Returns effective RHS offset if it is being used. This is used for long problems |
41 | or big dynamic or anywhere where going through full columns is |
42 | expensive. This may re-compute */ |
43 | virtual double * rhsOffset(ClpSimplex * model, bool forceRefresh = false, |
44 | bool check = false); |
45 | |
46 | using ClpPackedMatrix::times ; |
47 | /** Return <code>y + A * scalar *x</code> in <code>y</code>. |
48 | @pre <code>x</code> must be of size <code>numColumns()</code> |
49 | @pre <code>y</code> must be of size <code>numRows()</code> */ |
50 | virtual void times(double scalar, |
51 | const double * x, double * y) const; |
52 | /// Modifies rhs offset |
53 | void modifyOffset(int sequence, double amount); |
54 | /// Gets key value when none in small |
55 | double keyValue(int iSet) const; |
56 | /** |
57 | mode=0 - Set up before "updateTranspose" and "transposeTimes" for duals using extended |
58 | updates array (and may use other if dual values pass) |
59 | mode=1 - Update dual solution after "transposeTimes" using extended rows. |
60 | mode=2 - Compute all djs and compute key dual infeasibilities |
61 | mode=3 - Report on key dual infeasibilities |
62 | mode=4 - Modify before updateTranspose in partial pricing |
63 | */ |
64 | virtual void dualExpanded(ClpSimplex * model, CoinIndexedVector * array, |
65 | double * other, int mode); |
66 | /** |
67 | mode=0 - Create list of non-key basics in pivotVariable_ using |
68 | number as numberBasic in and out |
69 | mode=1 - Set all key variables as basic |
70 | mode=2 - return number extra rows needed, number gives maximum number basic |
71 | mode=3 - before replaceColumn |
72 | mode=4 - return 1 if can do primal, 2 if dual, 3 if both |
73 | mode=5 - save any status stuff (when in good state) |
74 | mode=6 - restore status stuff |
75 | mode=7 - flag given variable (normally sequenceIn) |
76 | mode=8 - unflag all variables |
77 | mode=9 - synchronize costs |
78 | mode=10 - return 1 if there may be changing bounds on variable (column generation) |
79 | mode=11 - make sure set is clean (used when a variable rejected - but not flagged) |
80 | mode=12 - after factorize but before permute stuff |
81 | mode=13 - at end of simplex to delete stuff |
82 | */ |
83 | virtual int generalExpanded(ClpSimplex * model, int mode, int & number); |
84 | /** Purely for column generation and similar ideas. Allows |
85 | matrix and any bounds or costs to be updated (sensibly). |
86 | Returns non-zero if any changes. |
87 | */ |
88 | virtual int refresh(ClpSimplex * model); |
89 | /** Creates a variable. This is called after partial pricing and will modify matrix. |
90 | Will update bestSequence. |
91 | */ |
92 | virtual void createVariable(ClpSimplex * model, int & bestSequence); |
93 | /// Returns reduced cost of a variable |
94 | virtual double reducedCost( ClpSimplex * model, int sequence) const; |
95 | /// Does gub crash |
96 | void gubCrash(); |
97 | /// Writes out model (without names) |
98 | void writeMps(const char * name); |
99 | /// Populates initial matrix from dynamic status |
100 | void initialProblem(); |
101 | /** Adds in a column to gub structure (called from descendant) and returns sequence */ |
102 | int addColumn(int numberEntries, const int * row, const double * element, |
103 | double cost, double lower, double upper, int iSet, |
104 | DynamicStatus status); |
105 | /** If addColumn forces compression then this allows descendant to know what to do. |
106 | If >=0 then entry stayed in, if -1 then entry went out to lower bound.of zero. |
107 | Entries at upper bound (really nonzero) never go out (at present). |
108 | */ |
109 | virtual void packDown(const int * , int ) {} |
110 | /// Gets lower bound (to simplify coding) |
111 | inline double columnLower(int sequence) const { |
112 | if (columnLower_) return columnLower_[sequence]; |
113 | else return 0.0; |
114 | } |
115 | /// Gets upper bound (to simplify coding) |
116 | inline double columnUpper(int sequence) const { |
117 | if (columnUpper_) return columnUpper_[sequence]; |
118 | else return COIN_DBL_MAX; |
119 | } |
120 | |
121 | //@} |
122 | |
123 | |
124 | |
125 | /**@name Constructors, destructor */ |
126 | //@{ |
127 | /** Default constructor. */ |
128 | ClpDynamicMatrix(); |
129 | /** This is the real constructor. |
130 | It assumes factorization frequency will not be changed. |
131 | This resizes model !!!! |
132 | The contents of original matrix in model will be taken over and original matrix |
133 | will be sanitized so can be deleted (to avoid a very small memory leak) |
134 | */ |
135 | ClpDynamicMatrix(ClpSimplex * model, int numberSets, |
136 | int numberColumns, const int * starts, |
137 | const double * lower, const double * upper, |
138 | const CoinBigIndex * startColumn, const int * row, |
139 | const double * element, const double * cost, |
140 | const double * columnLower = NULL, const double * columnUpper = NULL, |
141 | const unsigned char * status = NULL, |
142 | const unsigned char * dynamicStatus = NULL); |
143 | |
144 | /** Destructor */ |
145 | virtual ~ClpDynamicMatrix(); |
146 | //@} |
147 | |
148 | /**@name Copy method */ |
149 | //@{ |
150 | /** The copy constructor. */ |
151 | ClpDynamicMatrix(const ClpDynamicMatrix&); |
152 | /** The copy constructor from an CoinPackedMatrix. */ |
153 | ClpDynamicMatrix(const CoinPackedMatrix&); |
154 | |
155 | ClpDynamicMatrix& operator=(const ClpDynamicMatrix&); |
156 | /// Clone |
157 | virtual ClpMatrixBase * clone() const ; |
158 | //@} |
159 | /**@name gets and sets */ |
160 | //@{ |
161 | /// Status of row slacks |
162 | inline ClpSimplex::Status getStatus(int sequence) const { |
163 | return static_cast<ClpSimplex::Status> (status_[sequence] & 7); |
164 | } |
165 | inline void setStatus(int sequence, ClpSimplex::Status status) { |
166 | unsigned char & st_byte = status_[sequence]; |
167 | st_byte = static_cast<unsigned char>(st_byte & ~7); |
168 | st_byte = static_cast<unsigned char>(st_byte | status); |
169 | } |
170 | /// Whether flagged slack |
171 | inline bool flaggedSlack(int i) const { |
172 | return (status_[i] & 8) != 0; |
173 | } |
174 | inline void setFlaggedSlack(int i) { |
175 | status_[i] = static_cast<unsigned char>(status_[i] | 8); |
176 | } |
177 | inline void unsetFlaggedSlack(int i) { |
178 | status_[i] = static_cast<unsigned char>(status_[i] & ~8); |
179 | } |
180 | /// Number of sets (dynamic rows) |
181 | inline int numberSets() const { |
182 | return numberSets_; |
183 | } |
184 | /// Number of possible gub variables |
185 | inline int numberGubEntries() const |
186 | { return startSet_[numberSets_];} |
187 | /// Sets |
188 | inline int * startSets() const |
189 | { return startSet_;} |
190 | /// Whether flagged |
191 | inline bool flagged(int i) const { |
192 | return (dynamicStatus_[i] & 8) != 0; |
193 | } |
194 | inline void setFlagged(int i) { |
195 | dynamicStatus_[i] = static_cast<unsigned char>(dynamicStatus_[i] | 8); |
196 | } |
197 | inline void unsetFlagged(int i) { |
198 | dynamicStatus_[i] = static_cast<unsigned char>(dynamicStatus_[i] & ~8); |
199 | } |
200 | inline void setDynamicStatus(int sequence, DynamicStatus status) { |
201 | unsigned char & st_byte = dynamicStatus_[sequence]; |
202 | st_byte = static_cast<unsigned char>(st_byte & ~7); |
203 | st_byte = static_cast<unsigned char>(st_byte | status); |
204 | } |
205 | inline DynamicStatus getDynamicStatus(int sequence) const { |
206 | return static_cast<DynamicStatus> (dynamicStatus_[sequence] & 7); |
207 | } |
208 | /// Saved value of objective offset |
209 | inline double objectiveOffset() const { |
210 | return objectiveOffset_; |
211 | } |
212 | /// Starts of each column |
213 | inline CoinBigIndex * startColumn() const { |
214 | return startColumn_; |
215 | } |
216 | /// rows |
217 | inline int * row() const { |
218 | return row_; |
219 | } |
220 | /// elements |
221 | inline double * element() const { |
222 | return element_; |
223 | } |
224 | /// costs |
225 | inline double * cost() const { |
226 | return cost_; |
227 | } |
228 | /// ids of active columns (just index here) |
229 | inline int * id() const { |
230 | return id_; |
231 | } |
232 | /// Optional lower bounds on columns |
233 | inline double * columnLower() const { |
234 | return columnLower_; |
235 | } |
236 | /// Optional upper bounds on columns |
237 | inline double * columnUpper() const { |
238 | return columnUpper_; |
239 | } |
240 | /// Lower bounds on sets |
241 | inline double * lowerSet() const { |
242 | return lowerSet_; |
243 | } |
244 | /// Upper bounds on sets |
245 | inline double * upperSet() const { |
246 | return upperSet_; |
247 | } |
248 | /// size |
249 | inline int numberGubColumns() const { |
250 | return numberGubColumns_; |
251 | } |
252 | /// first free |
253 | inline int firstAvailable() const { |
254 | return firstAvailable_; |
255 | } |
256 | /// first dynamic |
257 | inline int firstDynamic() const { |
258 | return firstDynamic_; |
259 | } |
260 | /// number of columns in dynamic model |
261 | inline int lastDynamic() const { |
262 | return lastDynamic_; |
263 | } |
264 | /// number of rows in original model |
265 | inline int numberStaticRows() const { |
266 | return numberStaticRows_; |
267 | } |
268 | /// size of working matrix (max) |
269 | inline int numberElements() const { |
270 | return numberElements_; |
271 | } |
272 | inline int * keyVariable() const { |
273 | return keyVariable_; |
274 | } |
275 | /// Switches off dj checking each factorization (for BIG models) |
276 | void switchOffCheck(); |
277 | /// Status region for gub slacks |
278 | inline unsigned char * gubRowStatus() const { |
279 | return status_; |
280 | } |
281 | /// Status region for gub variables |
282 | inline unsigned char * dynamicStatus() const { |
283 | return dynamicStatus_; |
284 | } |
285 | /// Returns which set a variable is in |
286 | int whichSet (int sequence) const; |
287 | //@} |
288 | |
289 | |
290 | protected: |
291 | /**@name Data members |
292 | The data members are protected to allow access for derived classes. */ |
293 | //@{ |
294 | /// Sum of dual infeasibilities |
295 | double sumDualInfeasibilities_; |
296 | /// Sum of primal infeasibilities |
297 | double sumPrimalInfeasibilities_; |
298 | /// Sum of Dual infeasibilities using tolerance based on error in duals |
299 | double sumOfRelaxedDualInfeasibilities_; |
300 | /// Sum of Primal infeasibilities using tolerance based on error in primals |
301 | double sumOfRelaxedPrimalInfeasibilities_; |
302 | /// Saved best dual on gub row in pricing |
303 | double savedBestGubDual_; |
304 | /// Saved best set in pricing |
305 | int savedBestSet_; |
306 | /// Backward pointer to pivot row !!! |
307 | int * backToPivotRow_; |
308 | /// Key variable of set (only accurate if none in small problem) |
309 | mutable int * keyVariable_; |
310 | /// Backward pointer to extra row |
311 | int * toIndex_; |
312 | // Reverse pointer from index to set |
313 | int * fromIndex_; |
314 | /// Number of sets (dynamic rows) |
315 | int numberSets_; |
316 | /// Number of active sets |
317 | int numberActiveSets_; |
318 | /// Saved value of objective offset |
319 | double objectiveOffset_; |
320 | /// Lower bounds on sets |
321 | double * lowerSet_; |
322 | /// Upper bounds on sets |
323 | double * upperSet_; |
324 | /// Status of slack on set |
325 | unsigned char * status_; |
326 | /// Pointer back to model |
327 | ClpSimplex * model_; |
328 | /// first free |
329 | int firstAvailable_; |
330 | /// first free when iteration started |
331 | int firstAvailableBefore_; |
332 | /// first dynamic |
333 | int firstDynamic_; |
334 | /// number of columns in dynamic model |
335 | int lastDynamic_; |
336 | /// number of rows in original model |
337 | int numberStaticRows_; |
338 | /// size of working matrix (max) |
339 | int numberElements_; |
340 | /// Number of dual infeasibilities |
341 | int numberDualInfeasibilities_; |
342 | /// Number of primal infeasibilities |
343 | int numberPrimalInfeasibilities_; |
344 | /** If pricing will declare victory (i.e. no check every factorization). |
345 | -1 - always check |
346 | 0 - don't check |
347 | 1 - in don't check mode but looks optimal |
348 | */ |
349 | int noCheck_; |
350 | /// Infeasibility weight when last full pass done |
351 | double infeasibilityWeight_; |
352 | /// size |
353 | int numberGubColumns_; |
354 | /// current maximum number of columns (then compress) |
355 | int maximumGubColumns_; |
356 | /// current maximum number of elemnts (then compress) |
357 | int maximumElements_; |
358 | /// Start of each set |
359 | int * startSet_; |
360 | /// next in chain |
361 | int * next_; |
362 | /// Starts of each column |
363 | CoinBigIndex * startColumn_; |
364 | /// rows |
365 | int * row_; |
366 | /// elements |
367 | double * element_; |
368 | /// costs |
369 | double * cost_; |
370 | /// ids of active columns (just index here) |
371 | int * id_; |
372 | /// for status and which bound |
373 | unsigned char * dynamicStatus_; |
374 | /// Optional lower bounds on columns |
375 | double * columnLower_; |
376 | /// Optional upper bounds on columns |
377 | double * columnUpper_; |
378 | //@} |
379 | }; |
380 | |
381 | #endif |
382 | |