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
originalStatus(unsigned char status)42 inline int originalStatus(unsigned char status)
43 {
44      return (status & 15);
45 }
currentStatus(unsigned char status)46 inline int currentStatus(unsigned char status)
47 {
48      return (status >> 4);
49 }
setOriginalStatus(unsigned char & status,int value)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 }
setCurrentStatus(unsigned char & status,int value)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 }
setInitialStatus(unsigned char & status)60 inline void setInitialStatus(unsigned char &status)
61 {
62      status = static_cast<unsigned char>(CLP_FEASIBLE | (CLP_SAME << 4));
63 }
setSameStatus(unsigned char & status)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       */
changeInCost(int sequence,double alpha) const169      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      }
changeUpInCost(int sequence) const183      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      }
changeDownInCost(int sequence) const197      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
changeInCost(int sequence,double alpha,double & rhs)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
lower(int sequence) const271      inline double lower(int sequence) const {
272           return lower_[whichRange_[sequence] + offset_[sequence]];
273      }
274      /// Returns current upper bound
upper(int sequence) const275      inline double upper(int sequence) const {
276           return lower_[whichRange_[sequence] + offset_[sequence] + 1];
277      }
278      /// Returns current cost
cost(int sequence) const279      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
numberInfeasibilities() const288      inline int numberInfeasibilities() const {
289           return numberInfeasibilities_;
290      }
291      /// Change in cost
changeInCost() const292      inline double changeInCost() const {
293           return changeCost_;
294      }
295      /// Feasible cost
feasibleCost() const296      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
sumInfeasibilities() const302      inline double sumInfeasibilities() const {
303           return sumInfeasibilities_;
304      }
305      /// Largest infeasibility
largestInfeasibility() const306      inline double largestInfeasibility() const {
307           return largestInfeasibility_;
308      }
309      /// Average theta
averageTheta() const310      inline double averageTheta() const {
311           return averageTheta_;
312      }
setAverageTheta(double value)313      inline void setAverageTheta(double value) {
314           averageTheta_ = value;
315      }
setChangeInCost(double value)316      inline void setChangeInCost(double value) {
317           changeCost_ = value;
318      }
setMethod(int value)319      inline void setMethod(int value) {
320           method_ = value;
321      }
322      /// See if may want to look both ways
lookBothWays() const323      inline bool lookBothWays() const {
324           return bothWays_;
325      }
326      //@}
327      ///@name Private functions to deal with infeasible regions
infeasible(int i) const328      inline bool infeasible(int i) const {
329           return ((infeasible_[i>>5] >> (i & 31)) & 1) != 0;
330      }
setInfeasible(int i,bool trueFalse)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      }
statusArray() const339      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