| 1 | /* $Id: Idiot.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 | // "Idiot" as the name of this algorithm is copylefted. If you want to change |
| 7 | // the name then it should be something equally stupid (but not "Stupid") or |
| 8 | // even better something witty. |
| 9 | |
| 10 | #ifndef Idiot_H |
| 11 | #define Idiot_H |
| 12 | #ifndef OSI_IDIOT |
| 13 | #include "ClpSimplex.hpp" |
| 14 | #define OsiSolverInterface ClpSimplex |
| 15 | #else |
| 16 | #include "OsiSolverInterface.hpp" |
| 17 | typedef int CoinBigIndex; |
| 18 | #endif |
| 19 | class CoinMessageHandler; |
| 20 | class CoinMessages; |
| 21 | /// for use internally |
| 22 | typedef struct { |
| 23 | double infeas; |
| 24 | double objval; |
| 25 | double dropThis; |
| 26 | double weighted; |
| 27 | double sumSquared; |
| 28 | double djAtBeginning; |
| 29 | double djAtEnd; |
| 30 | int iteration; |
| 31 | } IdiotResult; |
| 32 | /** This class implements a very silly algorithm. It has no merit |
| 33 | apart from the fact that it gets an approximate solution to |
| 34 | some classes of problems. Better if vaguely homogeneous. |
| 35 | It works on problems where volume algorithm works and often |
| 36 | gets a better primal solution but it has no dual solution. |
| 37 | |
| 38 | It can also be used as a "crash" to get a problem started. This |
| 39 | is probably its most useful function. |
| 40 | |
| 41 | It is based on the idea that algorithms with terrible convergence |
| 42 | properties may be okay at first. Throw in some random dubious tricks |
| 43 | and the resulting code may be worth keeping as long as you don't |
| 44 | look at it. |
| 45 | |
| 46 | */ |
| 47 | |
| 48 | class Idiot { |
| 49 | |
| 50 | public: |
| 51 | |
| 52 | /**@name Constructors and destructor |
| 53 | Just a pointer to model is kept |
| 54 | */ |
| 55 | //@{ |
| 56 | /// Default constructor |
| 57 | Idiot ( ); |
| 58 | /// Constructor with model |
| 59 | Idiot ( OsiSolverInterface & model ); |
| 60 | |
| 61 | /// Copy constructor. |
| 62 | Idiot(const Idiot &); |
| 63 | /// Assignment operator. This copies the data |
| 64 | Idiot & operator=(const Idiot & rhs); |
| 65 | /// Destructor |
| 66 | ~Idiot ( ); |
| 67 | //@} |
| 68 | |
| 69 | |
| 70 | /**@name Algorithmic calls |
| 71 | */ |
| 72 | //@{ |
| 73 | /// Get an approximate solution with the idiot code |
| 74 | void solve(); |
| 75 | /// Lightweight "crash" |
| 76 | void crash(int numberPass, CoinMessageHandler * handler, |
| 77 | const CoinMessages * messages, bool doCrossover = true); |
| 78 | /** Use simplex to get an optimal solution |
| 79 | mode is how many steps the simplex crossover should take to |
| 80 | arrive to an extreme point: |
| 81 | 0 - chosen,all ever used, all |
| 82 | 1 - chosen, all |
| 83 | 2 - all |
| 84 | 3 - do not do anything - maybe basis |
| 85 | + 16 do presolves |
| 86 | */ |
| 87 | void crossOver(int mode); |
| 88 | //@} |
| 89 | |
| 90 | |
| 91 | /**@name Gets and sets of most useful data |
| 92 | */ |
| 93 | //@{ |
| 94 | /** Starting weight - small emphasizes feasibility, |
| 95 | default 1.0e-4 */ |
| 96 | inline double getStartingWeight() const { |
| 97 | return mu_; |
| 98 | } |
| 99 | inline void setStartingWeight(double value) { |
| 100 | mu_ = value; |
| 101 | } |
| 102 | /** Weight factor - weight multiplied by this when changes, |
| 103 | default 0.333 */ |
| 104 | inline double getWeightFactor() const { |
| 105 | return muFactor_; |
| 106 | } |
| 107 | inline void setWeightFactor(double value) { |
| 108 | muFactor_ = value; |
| 109 | } |
| 110 | /** Feasibility tolerance - problem essentially feasible if |
| 111 | individual infeasibilities less than this. |
| 112 | default 0.1 */ |
| 113 | inline double getFeasibilityTolerance() const { |
| 114 | return smallInfeas_; |
| 115 | } |
| 116 | inline void setFeasibilityTolerance(double value) { |
| 117 | smallInfeas_ = value; |
| 118 | } |
| 119 | /** Reasonably feasible. Dubious method concentrates more on |
| 120 | objective when sum of infeasibilities less than this. |
| 121 | Very dubious default value of (Number of rows)/20 */ |
| 122 | inline double getReasonablyFeasible() const { |
| 123 | return reasonableInfeas_; |
| 124 | } |
| 125 | inline void setReasonablyFeasible(double value) { |
| 126 | reasonableInfeas_ = value; |
| 127 | } |
| 128 | /** Exit infeasibility - exit if sum of infeasibilities less than this. |
| 129 | Default -1.0 (i.e. switched off) */ |
| 130 | inline double getExitInfeasibility() const { |
| 131 | return exitFeasibility_; |
| 132 | } |
| 133 | inline void setExitInfeasibility(double value) { |
| 134 | exitFeasibility_ = value; |
| 135 | } |
| 136 | /** Major iterations. stop after this number. |
| 137 | Default 30. Use 2-5 for "crash" 50-100 for serious crunching */ |
| 138 | inline int getMajorIterations() const { |
| 139 | return majorIterations_; |
| 140 | } |
| 141 | inline void setMajorIterations(int value) { |
| 142 | majorIterations_ = value; |
| 143 | } |
| 144 | /** Minor iterations. Do this number of tiny steps before |
| 145 | deciding whether to change weights etc. |
| 146 | Default - dubious sqrt(Number of Rows). |
| 147 | Good numbers 105 to 405 say (5 is dubious method of making sure |
| 148 | idiot is not trying to be clever which it may do every 10 minor |
| 149 | iterations) */ |
| 150 | inline int getMinorIterations() const { |
| 151 | return maxIts2_; |
| 152 | } |
| 153 | inline void setMinorIterations(int value) { |
| 154 | maxIts2_ = value; |
| 155 | } |
| 156 | // minor iterations for first time |
| 157 | inline int getMinorIterations0() const { |
| 158 | return maxIts_; |
| 159 | } |
| 160 | inline void setMinorIterations0(int value) { |
| 161 | maxIts_ = value; |
| 162 | } |
| 163 | /** Reduce weight after this many major iterations. It may |
| 164 | get reduced before this but this is a maximum. |
| 165 | Default 3. 3-10 plausible. */ |
| 166 | inline int getReduceIterations() const { |
| 167 | return maxBigIts_; |
| 168 | } |
| 169 | inline void setReduceIterations(int value) { |
| 170 | maxBigIts_ = value; |
| 171 | } |
| 172 | /// Amount of information - default of 1 should be okay |
| 173 | inline int getLogLevel() const { |
| 174 | return logLevel_; |
| 175 | } |
| 176 | inline void setLogLevel(int value) { |
| 177 | logLevel_ = value; |
| 178 | } |
| 179 | /// How lightweight - 0 not, 1 yes, 2 very lightweight |
| 180 | inline int getLightweight() const { |
| 181 | return lightWeight_; |
| 182 | } |
| 183 | inline void setLightweight(int value) { |
| 184 | lightWeight_ = value; |
| 185 | } |
| 186 | /// strategy |
| 187 | inline int getStrategy() const { |
| 188 | return strategy_; |
| 189 | } |
| 190 | inline void setStrategy(int value) { |
| 191 | strategy_ = value; |
| 192 | } |
| 193 | /// Fine tuning - okay if feasibility drop this factor |
| 194 | inline double getDropEnoughFeasibility() const { |
| 195 | return dropEnoughFeasibility_; |
| 196 | } |
| 197 | inline void setDropEnoughFeasibility(double value) { |
| 198 | dropEnoughFeasibility_ = value; |
| 199 | } |
| 200 | /// Fine tuning - okay if weighted obj drop this factor |
| 201 | inline double getDropEnoughWeighted() const { |
| 202 | return dropEnoughWeighted_; |
| 203 | } |
| 204 | inline void setDropEnoughWeighted(double value) { |
| 205 | dropEnoughWeighted_ = value; |
| 206 | } |
| 207 | //@} |
| 208 | |
| 209 | |
| 210 | /// Stuff for internal use |
| 211 | private: |
| 212 | |
| 213 | /// Does actual work |
| 214 | // allow public! |
| 215 | public: |
| 216 | void solve2(CoinMessageHandler * handler, const CoinMessages *messages); |
| 217 | private: |
| 218 | IdiotResult IdiSolve( |
| 219 | int nrows, int ncols, double * rowsol , double * colsol, |
| 220 | double * pi, double * djs, const double * origcost , |
| 221 | double * rowlower, |
| 222 | double * rowupper, const double * lower, |
| 223 | const double * upper, const double * element, |
| 224 | const int * row, const CoinBigIndex * colcc, |
| 225 | const int * length, double * lambda, |
| 226 | int maxIts, double mu, double drop, |
| 227 | double maxmin, double offset, |
| 228 | int strategy, double djTol, double djExit, double djFlag, |
| 229 | CoinThreadRandom * randomNumberGenerator); |
| 230 | int dropping(IdiotResult result, |
| 231 | double tolerance, |
| 232 | double small, |
| 233 | int *nbad); |
| 234 | IdiotResult objval(int nrows, int ncols, double * rowsol , double * colsol, |
| 235 | double * pi, double * djs, const double * cost , |
| 236 | const double * rowlower, |
| 237 | const double * rowupper, const double * lower, |
| 238 | const double * upper, const double * elemnt, |
| 239 | const int * row, const CoinBigIndex * columnStart, |
| 240 | const int * length, int , int * , |
| 241 | double * , double * , double * , |
| 242 | double * , double weight); |
| 243 | // Deals with whenUsed and slacks |
| 244 | int cleanIteration(int iteration, int ordinaryStart, int ordinaryEnd, |
| 245 | double * colsol, const double * lower, const double * upper, |
| 246 | const double * rowLower, const double * rowUpper, |
| 247 | const double * cost, const double * element, double fixTolerance, double & objChange, |
| 248 | double & infChange); |
| 249 | private: |
| 250 | /// Underlying model |
| 251 | OsiSolverInterface * model_; |
| 252 | |
| 253 | double djTolerance_; |
| 254 | double mu_; /* starting mu */ |
| 255 | double drop_; /* exit if drop over 5 checks less than this */ |
| 256 | double muFactor_; /* reduce mu by this */ |
| 257 | double stopMu_; /* exit if mu gets smaller than this */ |
| 258 | double smallInfeas_; /* feasibility tolerance */ |
| 259 | double reasonableInfeas_; /* use lambdas if feasibility less than this */ |
| 260 | double exitDrop_; /* candidate for stopping after a major iteration */ |
| 261 | double muAtExit_; /* mu on exit */ |
| 262 | double exitFeasibility_; /* exit if infeasibility less than this */ |
| 263 | double dropEnoughFeasibility_; /* okay if feasibility drop this factor */ |
| 264 | double dropEnoughWeighted_; /* okay if weighted obj drop this factor */ |
| 265 | int * whenUsed_; /* array to say what was used */ |
| 266 | int maxBigIts_; /* always reduce mu after this */ |
| 267 | int maxIts_; /* do this many iterations on first go */ |
| 268 | int majorIterations_; |
| 269 | int logLevel_; |
| 270 | int logFreq_; |
| 271 | int checkFrequency_; /* can exit after 5 * this iterations (on drop) */ |
| 272 | int lambdaIterations_; /* do at least this many lambda iterations */ |
| 273 | int maxIts2_; /* do this many iterations on subsequent goes */ |
| 274 | int strategy_; /* 0 - default strategy |
| 275 | 1 - do accelerator step but be cautious |
| 276 | 2 - do not do accelerator step |
| 277 | 4 - drop, exitDrop and djTolerance all relative |
| 278 | 8 - keep accelerator step to theta=10.0 |
| 279 | |
| 280 | 32 - Scale |
| 281 | 512 - crossover |
| 282 | 2048 - keep lambda across mu change |
| 283 | 4096 - return best solution (not last found) |
| 284 | 8192 - always do a presolve in crossover |
| 285 | 16384 - costed slacks found - so whenUsed_ longer */ |
| 286 | int lightWeight_; // 0 - normal, 1 lightweight |
| 287 | }; |
| 288 | #endif |
| 289 | |