1 | /* $Id: ClpNonLinearCost.hpp 1665 2011-01-04 17:55:54Z lou $ */ |
2 | // Copyright (C) 2002, 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 ClpNonLinearCost_H |
7 | #define ClpNonLinearCost_H |
8 | |
9 | |
10 | #include "CoinPragma.hpp" |
11 | |
12 | class ClpSimplex; |
13 | class CoinIndexedVector; |
14 | |
15 | /** Trivial class to deal with non linear costs |
16 | |
17 | I don't make any explicit assumptions about convexity but I am |
18 | sure I do make implicit ones. |
19 | |
20 | One interesting idea for normal LP's will be to allow non-basic |
21 | variables to come into basis as infeasible i.e. if variable at |
22 | lower bound has very large positive reduced cost (when problem |
23 | is infeasible) could it reduce overall problem infeasibility more |
24 | by bringing it into basis below its lower bound. |
25 | |
26 | Another feature would be to automatically discover when problems |
27 | are convex piecewise linear and re-formulate to use non-linear. |
28 | I did some work on this many years ago on "grade" problems, but |
29 | while it improved primal interior point algorithms were much better |
30 | for that particular problem. |
31 | */ |
32 | /* status has original status and current status |
33 | 0 - below lower so stored is upper |
34 | 1 - in range |
35 | 2 - above upper so stored is lower |
36 | 4 - (for current) - same as original |
37 | */ |
38 | #define CLP_BELOW_LOWER 0 |
39 | #define CLP_FEASIBLE 1 |
40 | #define CLP_ABOVE_UPPER 2 |
41 | #define CLP_SAME 4 |
42 | inline int originalStatus(unsigned char status) |
43 | { |
44 | return (status & 15); |
45 | } |
46 | inline int currentStatus(unsigned char status) |
47 | { |
48 | return (status >> 4); |
49 | } |
50 | inline void setOriginalStatus(unsigned char & status, int value) |
51 | { |
52 | status = static_cast<unsigned char>(status & ~15); |
53 | status = static_cast<unsigned char>(status | value); |
54 | } |
55 | inline void setCurrentStatus(unsigned char &status, int value) |
56 | { |
57 | status = static_cast<unsigned char>(status & ~(15 << 4)); |
58 | status = static_cast<unsigned char>(status | (value << 4)); |
59 | } |
60 | inline void setInitialStatus(unsigned char &status) |
61 | { |
62 | status = static_cast<unsigned char>(CLP_FEASIBLE | (CLP_SAME << 4)); |
63 | } |
64 | inline void setSameStatus(unsigned char &status) |
65 | { |
66 | status = static_cast<unsigned char>(status & ~(15 << 4)); |
67 | status = static_cast<unsigned char>(status | (CLP_SAME << 4)); |
68 | } |
69 | // Use second version to get more speed |
70 | //#define FAST_CLPNON |
71 | #ifndef FAST_CLPNON |
72 | #define CLP_METHOD1 ((method_&1)!=0) |
73 | #define CLP_METHOD2 ((method_&2)!=0) |
74 | #else |
75 | #define CLP_METHOD1 (false) |
76 | #define CLP_METHOD2 (true) |
77 | #endif |
78 | class ClpNonLinearCost { |
79 | |
80 | public: |
81 | |
82 | public: |
83 | |
84 | /**@name Constructors, destructor */ |
85 | //@{ |
86 | /// Default constructor. |
87 | ClpNonLinearCost(); |
88 | /** Constructor from simplex. |
89 | This will just set up wasteful arrays for linear, but |
90 | later may do dual analysis and even finding duplicate columns . |
91 | */ |
92 | ClpNonLinearCost(ClpSimplex * model, int method = 1); |
93 | /** Constructor from simplex and list of non-linearities (columns only) |
94 | First lower of each column has to match real lower |
95 | Last lower has to be <= upper (if == then cost ignored) |
96 | This could obviously be changed to make more user friendly |
97 | */ |
98 | ClpNonLinearCost(ClpSimplex * model, const int * starts, |
99 | const double * lower, const double * cost); |
100 | /// Destructor |
101 | ~ClpNonLinearCost(); |
102 | // Copy |
103 | ClpNonLinearCost(const ClpNonLinearCost&); |
104 | // Assignment |
105 | ClpNonLinearCost& operator=(const ClpNonLinearCost&); |
106 | //@} |
107 | |
108 | |
109 | /**@name Actual work in primal */ |
110 | //@{ |
111 | /** Changes infeasible costs and computes number and cost of infeas |
112 | Puts all non-basic (non free) variables to bounds |
113 | and all free variables to zero if oldTolerance is non-zero |
114 | - but does not move those <= oldTolerance away*/ |
115 | void checkInfeasibilities(double oldTolerance = 0.0); |
116 | /** Changes infeasible costs for each variable |
117 | The indices are row indices and need converting to sequences |
118 | */ |
119 | void checkInfeasibilities(int numberInArray, const int * index); |
120 | /** Puts back correct infeasible costs for each variable |
121 | The input indices are row indices and need converting to sequences |
122 | for costs. |
123 | On input array is empty (but indices exist). On exit just |
124 | changed costs will be stored as normal CoinIndexedVector |
125 | */ |
126 | void checkChanged(int numberInArray, CoinIndexedVector * update); |
127 | /** Goes through one bound for each variable. |
128 | If multiplier*work[iRow]>0 goes down, otherwise up. |
129 | The indices are row indices and need converting to sequences |
130 | Temporary offsets may be set |
131 | Rhs entries are increased |
132 | */ |
133 | void goThru(int numberInArray, double multiplier, |
134 | const int * index, const double * work, |
135 | double * rhs); |
136 | /** Takes off last iteration (i.e. offsets closer to 0) |
137 | */ |
138 | void goBack(int numberInArray, const int * index, |
139 | double * rhs); |
140 | /** Puts back correct infeasible costs for each variable |
141 | The input indices are row indices and need converting to sequences |
142 | for costs. |
143 | At the end of this all temporary offsets are zero |
144 | */ |
145 | void goBackAll(const CoinIndexedVector * update); |
146 | /// Temporary zeroing of feasible costs |
147 | void zapCosts(); |
148 | /// Refreshes costs always makes row costs zero |
149 | void refreshCosts(const double * columnCosts); |
150 | /// Puts feasible bounds into lower and upper |
151 | void feasibleBounds(); |
152 | /** Sets bounds and cost for one variable |
153 | Returns change in cost |
154 | May need to be inline for speed */ |
155 | double setOne(int sequence, double solutionValue); |
156 | /** Sets bounds and infeasible cost and true cost for one variable |
157 | This is for gub and column generation etc */ |
158 | void setOne(int sequence, double solutionValue, double lowerValue, double upperValue, |
159 | double costValue = 0.0); |
160 | /** Sets bounds and cost for outgoing variable |
161 | may change value |
162 | Returns direction */ |
163 | int setOneOutgoing(int sequence, double &solutionValue); |
164 | /// Returns nearest bound |
165 | double nearest(int sequence, double solutionValue); |
166 | /** Returns change in cost - one down if alpha >0.0, up if <0.0 |
167 | Value is current - new |
168 | */ |
169 | inline double changeInCost(int sequence, double alpha) const { |
170 | double returnValue = 0.0; |
171 | if (CLP_METHOD1) { |
172 | int iRange = whichRange_[sequence] + offset_[sequence]; |
173 | if (alpha > 0.0) |
174 | returnValue = cost_[iRange] - cost_[iRange-1]; |
175 | else |
176 | returnValue = cost_[iRange] - cost_[iRange+1]; |
177 | } |
178 | if (CLP_METHOD2) { |
179 | returnValue = (alpha > 0.0) ? infeasibilityWeight_ : -infeasibilityWeight_; |
180 | } |
181 | return returnValue; |
182 | } |
183 | inline double changeUpInCost(int sequence) const { |
184 | double returnValue = 0.0; |
185 | if (CLP_METHOD1) { |
186 | int iRange = whichRange_[sequence] + offset_[sequence]; |
187 | if (iRange + 1 != start_[sequence+1] && !infeasible(iRange + 1)) |
188 | returnValue = cost_[iRange] - cost_[iRange+1]; |
189 | else |
190 | returnValue = -1.0e100; |
191 | } |
192 | if (CLP_METHOD2) { |
193 | returnValue = -infeasibilityWeight_; |
194 | } |
195 | return returnValue; |
196 | } |
197 | inline double changeDownInCost(int sequence) const { |
198 | double returnValue = 0.0; |
199 | if (CLP_METHOD1) { |
200 | int iRange = whichRange_[sequence] + offset_[sequence]; |
201 | if (iRange != start_[sequence] && !infeasible(iRange - 1)) |
202 | returnValue = cost_[iRange] - cost_[iRange-1]; |
203 | else |
204 | returnValue = 1.0e100; |
205 | } |
206 | if (CLP_METHOD2) { |
207 | returnValue = infeasibilityWeight_; |
208 | } |
209 | return returnValue; |
210 | } |
211 | /// This also updates next bound |
212 | inline double changeInCost(int sequence, double alpha, double &rhs) { |
213 | double returnValue = 0.0; |
214 | #ifdef NONLIN_DEBUG |
215 | double saveRhs = rhs; |
216 | #endif |
217 | if (CLP_METHOD1) { |
218 | int iRange = whichRange_[sequence] + offset_[sequence]; |
219 | if (alpha > 0.0) { |
220 | assert(iRange - 1 >= start_[sequence]); |
221 | offset_[sequence]--; |
222 | rhs += lower_[iRange] - lower_[iRange-1]; |
223 | returnValue = alpha * (cost_[iRange] - cost_[iRange-1]); |
224 | } else { |
225 | assert(iRange + 1 < start_[sequence+1] - 1); |
226 | offset_[sequence]++; |
227 | rhs += lower_[iRange+2] - lower_[iRange+1]; |
228 | returnValue = alpha * (cost_[iRange] - cost_[iRange+1]); |
229 | } |
230 | } |
231 | if (CLP_METHOD2) { |
232 | #ifdef NONLIN_DEBUG |
233 | double saveRhs1 = rhs; |
234 | rhs = saveRhs; |
235 | #endif |
236 | unsigned char iStatus = status_[sequence]; |
237 | int iWhere = currentStatus(iStatus); |
238 | if (iWhere == CLP_SAME) |
239 | iWhere = originalStatus(iStatus); |
240 | // rhs always increases |
241 | if (iWhere == CLP_FEASIBLE) { |
242 | if (alpha > 0.0) { |
243 | // going below |
244 | iWhere = CLP_BELOW_LOWER; |
245 | rhs = COIN_DBL_MAX; |
246 | } else { |
247 | // going above |
248 | iWhere = CLP_ABOVE_UPPER; |
249 | rhs = COIN_DBL_MAX; |
250 | } |
251 | } else if (iWhere == CLP_BELOW_LOWER) { |
252 | assert (alpha < 0); |
253 | // going feasible |
254 | iWhere = CLP_FEASIBLE; |
255 | rhs += bound_[sequence] - model_->upperRegion()[sequence]; |
256 | } else { |
257 | assert (iWhere == CLP_ABOVE_UPPER); |
258 | // going feasible |
259 | iWhere = CLP_FEASIBLE; |
260 | rhs += model_->lowerRegion()[sequence] - bound_[sequence]; |
261 | } |
262 | setCurrentStatus(status_[sequence], iWhere); |
263 | #ifdef NONLIN_DEBUG |
264 | assert(saveRhs1 == rhs); |
265 | #endif |
266 | returnValue = fabs(alpha) * infeasibilityWeight_; |
267 | } |
268 | return returnValue; |
269 | } |
270 | /// Returns current lower bound |
271 | inline double lower(int sequence) const { |
272 | return lower_[whichRange_[sequence] + offset_[sequence]]; |
273 | } |
274 | /// Returns current upper bound |
275 | inline double upper(int sequence) const { |
276 | return lower_[whichRange_[sequence] + offset_[sequence] + 1]; |
277 | } |
278 | /// Returns current cost |
279 | inline double cost(int sequence) const { |
280 | return cost_[whichRange_[sequence] + offset_[sequence]]; |
281 | } |
282 | //@} |
283 | |
284 | |
285 | /**@name Gets and sets */ |
286 | //@{ |
287 | /// Number of infeasibilities |
288 | inline int numberInfeasibilities() const { |
289 | return numberInfeasibilities_; |
290 | } |
291 | /// Change in cost |
292 | inline double changeInCost() const { |
293 | return changeCost_; |
294 | } |
295 | /// Feasible cost |
296 | inline double feasibleCost() const { |
297 | return feasibleCost_; |
298 | } |
299 | /// Feasible cost with offset and direction (i.e. for reporting) |
300 | double feasibleReportCost() const; |
301 | /// Sum of infeasibilities |
302 | inline double sumInfeasibilities() const { |
303 | return sumInfeasibilities_; |
304 | } |
305 | /// Largest infeasibility |
306 | inline double largestInfeasibility() const { |
307 | return largestInfeasibility_; |
308 | } |
309 | /// Average theta |
310 | inline double averageTheta() const { |
311 | return averageTheta_; |
312 | } |
313 | inline void setAverageTheta(double value) { |
314 | averageTheta_ = value; |
315 | } |
316 | inline void setChangeInCost(double value) { |
317 | changeCost_ = value; |
318 | } |
319 | inline void setMethod(int value) { |
320 | method_ = value; |
321 | } |
322 | /// See if may want to look both ways |
323 | inline bool lookBothWays() const { |
324 | return bothWays_; |
325 | } |
326 | //@} |
327 | ///@name Private functions to deal with infeasible regions |
328 | inline bool infeasible(int i) const { |
329 | return ((infeasible_[i>>5] >> (i & 31)) & 1) != 0; |
330 | } |
331 | inline void setInfeasible(int i, bool trueFalse) { |
332 | unsigned int & value = infeasible_[i>>5]; |
333 | int bit = i & 31; |
334 | if (trueFalse) |
335 | value |= (1 << bit); |
336 | else |
337 | value &= ~(1 << bit); |
338 | } |
339 | inline unsigned char * statusArray() const { |
340 | return status_; |
341 | } |
342 | /// For debug |
343 | void validate(); |
344 | //@} |
345 | |
346 | private: |
347 | /**@name Data members */ |
348 | //@{ |
349 | /// Change in cost because of infeasibilities |
350 | double changeCost_; |
351 | /// Feasible cost |
352 | double feasibleCost_; |
353 | /// Current infeasibility weight |
354 | double infeasibilityWeight_; |
355 | /// Largest infeasibility |
356 | double largestInfeasibility_; |
357 | /// Sum of infeasibilities |
358 | double sumInfeasibilities_; |
359 | /// Average theta - kept here as only for primal |
360 | double averageTheta_; |
361 | /// Number of rows (mainly for checking and copy) |
362 | int numberRows_; |
363 | /// Number of columns (mainly for checking and copy) |
364 | int numberColumns_; |
365 | /// Starts for each entry (columns then rows) |
366 | int * start_; |
367 | /// Range for each entry (columns then rows) |
368 | int * whichRange_; |
369 | /// Temporary range offset for each entry (columns then rows) |
370 | int * offset_; |
371 | /** Lower bound for each range (upper bound is next lower). |
372 | For various reasons there is always an infeasible range |
373 | at bottom - even if lower bound is - infinity */ |
374 | double * lower_; |
375 | /// Cost for each range |
376 | double * cost_; |
377 | /// Model |
378 | ClpSimplex * model_; |
379 | // Array to say which regions are infeasible |
380 | unsigned int * infeasible_; |
381 | /// Number of infeasibilities found |
382 | int numberInfeasibilities_; |
383 | // new stuff |
384 | /// Contains status at beginning and current |
385 | unsigned char * status_; |
386 | /// Bound which has been replaced in lower_ or upper_ |
387 | double * bound_; |
388 | /// Feasible cost array |
389 | double * cost2_; |
390 | /// Method 1 old, 2 new, 3 both! |
391 | int method_; |
392 | /// If all non-linear costs convex |
393 | bool convex_; |
394 | /// If we should look both ways for djs |
395 | bool bothWays_; |
396 | //@} |
397 | }; |
398 | |
399 | #endif |
400 | |