[2] | 1 | // Copyright (C) 2002, International Business Machines |
---|
| 2 | // Corporation and others. All Rights Reserved. |
---|
| 3 | #ifndef ClpModel_H |
---|
| 4 | #define ClpModel_H |
---|
| 5 | |
---|
| 6 | #include <iostream> |
---|
| 7 | #include <cassert> |
---|
| 8 | #include <cmath> |
---|
| 9 | #include <vector> |
---|
| 10 | #include <string> |
---|
| 11 | // This is only in to use OsiDblParam etc |
---|
| 12 | #include "OsiSolverInterface.hpp" |
---|
| 13 | #include "ClpMatrixBase.hpp" |
---|
| 14 | #include "OsiMessageHandler.hpp" |
---|
| 15 | |
---|
| 16 | |
---|
| 17 | /** This is the base class for Linear Models |
---|
| 18 | This knows nothing about the algorithm, but it seems to |
---|
| 19 | have a reasonable amount of information |
---|
| 20 | |
---|
| 21 | I would welcome suggestions for what should be in this and |
---|
| 22 | how it relates to OsiSolverInterface. Some methods look |
---|
| 23 | very similar. |
---|
| 24 | |
---|
| 25 | */ |
---|
| 26 | |
---|
| 27 | class ClpModel { |
---|
| 28 | |
---|
| 29 | public: |
---|
| 30 | |
---|
| 31 | /**@name Constructors and destructor |
---|
| 32 | Note - copy methods copy ALL data so can chew up memory |
---|
| 33 | until other copy is freed |
---|
| 34 | */ |
---|
| 35 | //@{ |
---|
| 36 | /// Default constructor |
---|
| 37 | ClpModel ( ); |
---|
| 38 | |
---|
| 39 | /// Copy constructor. |
---|
| 40 | ClpModel(const ClpModel &); |
---|
| 41 | /// Assignment operator. This copies the data |
---|
| 42 | ClpModel & operator=(const ClpModel & rhs); |
---|
| 43 | /// Destructor |
---|
| 44 | ~ClpModel ( ); |
---|
| 45 | //@} |
---|
| 46 | |
---|
| 47 | /**@name Load model - loads some stuff and initializes others */ |
---|
| 48 | //@{ |
---|
| 49 | /** Loads a problem (the constraints on the |
---|
| 50 | rows are given by lower and upper bounds). If a pointer is 0 then the |
---|
| 51 | following values are the default: |
---|
| 52 | <ul> |
---|
| 53 | <li> <code>colub</code>: all columns have upper bound infinity |
---|
| 54 | <li> <code>collb</code>: all columns have lower bound 0 |
---|
| 55 | <li> <code>rowub</code>: all rows have upper bound infinity |
---|
| 56 | <li> <code>rowlb</code>: all rows have lower bound -infinity |
---|
| 57 | <li> <code>obj</code>: all variables have 0 objective coefficient |
---|
| 58 | </ul> |
---|
| 59 | */ |
---|
| 60 | void loadProblem ( const ClpMatrixBase& matrix, |
---|
| 61 | const double* collb, const double* colub, |
---|
| 62 | const double* obj, |
---|
| 63 | const double* rowlb, const double* rowub, |
---|
| 64 | const double * rowObjective=NULL); |
---|
| 65 | void loadProblem ( const OsiPackedMatrix& matrix, |
---|
| 66 | const double* collb, const double* colub, |
---|
| 67 | const double* obj, |
---|
| 68 | const double* rowlb, const double* rowub, |
---|
| 69 | const double * rowObjective=NULL); |
---|
| 70 | |
---|
| 71 | /** Just like the other loadProblem() method except that the matrix is |
---|
| 72 | given in a standard column major ordered format (without gaps). */ |
---|
| 73 | void loadProblem ( const int numcols, const int numrows, |
---|
| 74 | const int* start, const int* index, |
---|
| 75 | const double* value, |
---|
| 76 | const double* collb, const double* colub, |
---|
| 77 | const double* obj, |
---|
| 78 | const double* rowlb, const double* rowub, |
---|
| 79 | const double * rowObjective=NULL); |
---|
| 80 | /// Read an mps file from the given filename |
---|
| 81 | int readMps(const char *filename, |
---|
| 82 | bool keepNames=false, |
---|
| 83 | bool ignoreErrors = false); |
---|
| 84 | /// Resizes rim part of model |
---|
| 85 | void resize (int newNumberRows, int newNumberColumns); |
---|
| 86 | /// Deletes rows |
---|
| 87 | void deleteRows(int number, const int * which); |
---|
| 88 | /// Deletes columns |
---|
[8] | 89 | |
---|
[2] | 90 | void deleteColumns(int number, const int * which); |
---|
| 91 | /** Borrow model. This is so we dont have to copy large amounts |
---|
| 92 | of data around. It assumes a derived class wants to overwrite |
---|
| 93 | an empty model with a real one - while it does an algorithm */ |
---|
| 94 | void borrowModel(ClpModel & otherModel); |
---|
| 95 | /** Return model - nulls all arrays so can be deleted safely |
---|
| 96 | also updates any scalars */ |
---|
| 97 | void returnModel(ClpModel & otherModel); |
---|
| 98 | |
---|
| 99 | //@} |
---|
| 100 | /**@name gets and sets */ |
---|
| 101 | //@{ |
---|
| 102 | /// Number of rows |
---|
| 103 | inline int numberRows() const |
---|
| 104 | { return numberRows_;}; |
---|
| 105 | inline int getNumRows() const |
---|
| 106 | { return numberRows_;}; |
---|
| 107 | /// Number of columns |
---|
| 108 | inline int getNumCols() const |
---|
| 109 | { return numberColumns_;}; |
---|
| 110 | inline int numberColumns() const |
---|
| 111 | { return numberColumns_;}; |
---|
| 112 | /// Primal tolerance to use |
---|
| 113 | inline double primalTolerance() const |
---|
| 114 | { return dblParam_[OsiPrimalTolerance];} ; |
---|
| 115 | void setPrimalTolerance( double value) ; |
---|
| 116 | /// Dual tolerance to use |
---|
| 117 | inline double dualTolerance() const |
---|
| 118 | { return dblParam_[OsiDualTolerance];} ; |
---|
| 119 | void setDualTolerance( double value) ; |
---|
| 120 | /// Number of iterations |
---|
| 121 | inline int numberIterations() const |
---|
| 122 | { return numberIterations_;}; |
---|
| 123 | inline int getIterationCount() const |
---|
| 124 | { return numberIterations_;}; |
---|
| 125 | /// Maximum number of iterations |
---|
| 126 | inline int maximumIterations() const |
---|
| 127 | { return maximumIterations_;}; |
---|
| 128 | void setMaximumIterations(int value); |
---|
| 129 | /** Status of problem: |
---|
| 130 | 0 - optimal |
---|
| 131 | 1 - primal infeasible |
---|
| 132 | 2 - dual infeasible |
---|
| 133 | 3 - stopped on iterations etc |
---|
| 134 | 4 - stopped due to errors |
---|
| 135 | */ |
---|
| 136 | inline int status() const |
---|
| 137 | { return problemStatus_;}; |
---|
| 138 | /// Are there a numerical difficulties? |
---|
| 139 | bool isAbandoned() const |
---|
| 140 | { return problemStatus_==4;}; |
---|
| 141 | /// Is optimality proven? |
---|
| 142 | bool isProvenOptimal() const |
---|
| 143 | { return problemStatus_==0;}; |
---|
| 144 | /// Is primal infeasiblity proven? |
---|
| 145 | bool isProvenPrimalInfeasible() const |
---|
| 146 | { return problemStatus_==1;}; |
---|
| 147 | /// Is dual infeasiblity proven? |
---|
| 148 | bool isProvenDualInfeasible() const |
---|
| 149 | { return problemStatus_==2;}; |
---|
| 150 | /// Is the given primal objective limit reached? |
---|
| 151 | bool isPrimalObjectiveLimitReached() const |
---|
| 152 | { return false;}; // not implemented yet |
---|
| 153 | /// Is the given dual objective limit reached? |
---|
| 154 | bool isDualObjectiveLimitReached() const |
---|
| 155 | { return false;}; // not implememented yet |
---|
| 156 | /// Iteration limit reached? |
---|
| 157 | bool isIterationLimitReached() const |
---|
| 158 | { return problemStatus_==3;}; |
---|
| 159 | /// Direction of optimization (1 - minimize, -1 - maximize, 0 - ignore |
---|
| 160 | inline int optimizationDirection() const |
---|
| 161 | { return (int) optimizationDirection_;}; |
---|
| 162 | inline double getObjSense() const |
---|
| 163 | { return optimizationDirection_;}; |
---|
| 164 | void setOptimizationDirection(int value); |
---|
| 165 | /// Primal row solution |
---|
| 166 | inline double * primalRowSolution() const |
---|
| 167 | { return rowActivity_;} ; |
---|
| 168 | inline const double * getRowActivity() const |
---|
| 169 | { return rowActivity_;} ; |
---|
| 170 | /// Primal column solution |
---|
| 171 | inline double * primalColumnSolution() const |
---|
| 172 | { return columnActivity_;} ; |
---|
| 173 | inline const double * getColSolution() const |
---|
| 174 | { return columnActivity_;} ; |
---|
| 175 | /// Dual row solution |
---|
| 176 | inline double * dualRowSolution() const |
---|
| 177 | { return dual_;} ; |
---|
| 178 | inline const double * getRowPrice() const |
---|
| 179 | { return dual_;} ; |
---|
| 180 | /// Reduced costs |
---|
| 181 | inline double * dualColumnSolution() const |
---|
| 182 | { return reducedCost_;} ; |
---|
| 183 | inline const double * getReducedCost() const |
---|
| 184 | { return reducedCost_;} ; |
---|
| 185 | /// Row lower or rhs |
---|
| 186 | inline double* rowLower() const |
---|
| 187 | { return rowLower_;}; |
---|
| 188 | inline const double* getRowLower() const |
---|
| 189 | { return rowLower_;}; |
---|
| 190 | /// Row upper |
---|
| 191 | inline double* rowUpper() const |
---|
| 192 | { return rowUpper_;}; |
---|
| 193 | inline const double* getRowUpper() const |
---|
| 194 | { return rowUpper_;}; |
---|
| 195 | /// Objective |
---|
| 196 | inline double * objective() const |
---|
| 197 | { return objective_;}; |
---|
| 198 | inline const double * getObjCoefficients() const |
---|
| 199 | { return objective_;}; |
---|
| 200 | /// Row Objective |
---|
| 201 | inline double * rowObjective() const |
---|
| 202 | { return rowObjective_;}; |
---|
| 203 | /// Column Lower |
---|
| 204 | inline double * columnLower() const |
---|
| 205 | { return columnLower_;}; |
---|
| 206 | inline const double * getColLower() const |
---|
| 207 | { return columnLower_;}; |
---|
| 208 | /// Column Upper |
---|
| 209 | inline double * columnUpper() const |
---|
| 210 | { return columnUpper_;}; |
---|
| 211 | inline const double * getColUpper() const |
---|
| 212 | { return columnUpper_;}; |
---|
| 213 | /// Matrix (if not ClpPackedmatrix be careful about memory leak |
---|
| 214 | inline OsiPackedMatrix * matrix() const |
---|
| 215 | { return matrix_->getPackedMatrix();}; |
---|
| 216 | /// Row Matrix |
---|
| 217 | inline ClpMatrixBase * rowCopy() const |
---|
| 218 | { return rowCopy_;}; |
---|
| 219 | /// Clp Matrix |
---|
| 220 | inline ClpMatrixBase * clpMatrix() const |
---|
| 221 | { return matrix_;}; |
---|
| 222 | /// Objective value |
---|
| 223 | inline double objectiveValue() const |
---|
| 224 | { return objectiveValue_*optimizationDirection_ - dblParam_[OsiObjOffset];}; |
---|
| 225 | inline double getObjValue() const |
---|
| 226 | { return objectiveValue_*optimizationDirection_ - dblParam_[OsiObjOffset];}; |
---|
| 227 | /// Infeasibility/unbounded ray (NULL returned if none/wrong) |
---|
| 228 | double * infeasibilityRay() const; |
---|
| 229 | double * unboundedRay() const; |
---|
| 230 | //@} |
---|
| 231 | /**@name Message handling */ |
---|
| 232 | //@{ |
---|
| 233 | /// Pass in Message handler (not deleted at end) |
---|
| 234 | void passInMessageHandler(OsiMessageHandler * handler); |
---|
| 235 | /// Set language |
---|
| 236 | void newLanguage(OsiMessages::Language language); |
---|
| 237 | void setLanguage(OsiMessages::Language language) |
---|
| 238 | {newLanguage(language);}; |
---|
| 239 | /// Return handler |
---|
| 240 | OsiMessageHandler * messageHandler() const |
---|
| 241 | {return handler_;}; |
---|
| 242 | /// Return messages |
---|
| 243 | OsiMessages messages() const |
---|
| 244 | {return messages_;}; |
---|
| 245 | /// Return pointer to messages |
---|
| 246 | OsiMessages * messagesPointer() |
---|
| 247 | {return & messages_;}; |
---|
| 248 | /// Log level |
---|
| 249 | void setLogLevel(int value) |
---|
| 250 | {handler_->setLogLevel(value);}; |
---|
| 251 | int logLevel() const |
---|
| 252 | { return handler_->logLevel();}; |
---|
| 253 | /// length of names (0 means no names0 |
---|
| 254 | inline int lengthNames() const |
---|
| 255 | {return lengthNames_;}; |
---|
| 256 | /// Row names |
---|
| 257 | const std::vector<std::string> * rowNames() const |
---|
| 258 | {return &rowNames_;}; |
---|
| 259 | /// Column names |
---|
| 260 | const std::vector<std::string> * columnNames() const |
---|
| 261 | {return &columnNames_;}; |
---|
| 262 | //@} |
---|
| 263 | |
---|
| 264 | |
---|
| 265 | //--------------------------------------------------------------------------- |
---|
| 266 | /**@name Parameter set/get methods |
---|
| 267 | |
---|
| 268 | The set methods return true if the parameter was set to the given value, |
---|
| 269 | false otherwise. There can be various reasons for failure: the given |
---|
| 270 | parameter is not applicable for the solver (e.g., refactorization |
---|
| 271 | frequency for the volume algorithm), the parameter is not yet implemented |
---|
| 272 | for the solver or simply the value of the parameter is out of the range |
---|
| 273 | the solver accepts. If a parameter setting call returns false check the |
---|
| 274 | details of your solver. |
---|
| 275 | |
---|
| 276 | The get methods return true if the given parameter is applicable for the |
---|
| 277 | solver and is implemented. In this case the value of the parameter is |
---|
| 278 | returned in the second argument. Otherwise they return false. |
---|
| 279 | |
---|
| 280 | ** once it has been decided where solver sits this may be redone |
---|
| 281 | */ |
---|
| 282 | //@{ |
---|
| 283 | /// Set an integer parameter |
---|
| 284 | bool setIntParam(OsiIntParam key, int value) ; |
---|
| 285 | /// Set an double parameter |
---|
| 286 | bool setDblParam(OsiDblParam key, double value) ; |
---|
| 287 | /// Set an string parameter |
---|
| 288 | bool setStrParam(OsiStrParam key, const std::string & value); |
---|
| 289 | // Get an integer parameter |
---|
| 290 | inline bool getIntParam(OsiIntParam key, int& value) const { |
---|
| 291 | if (key!=OsiLastIntParam) { |
---|
| 292 | value = intParam_[key]; |
---|
| 293 | return true; |
---|
| 294 | } else { |
---|
| 295 | return false; |
---|
| 296 | } |
---|
| 297 | } |
---|
| 298 | // Get an double parameter |
---|
| 299 | inline bool getDblParam(OsiDblParam key, double& value) const { |
---|
| 300 | if (key!=OsiLastDblParam) { |
---|
| 301 | value = dblParam_[key]; |
---|
| 302 | return true; |
---|
| 303 | } else { |
---|
| 304 | return false; |
---|
| 305 | } |
---|
| 306 | } |
---|
| 307 | // Get a string parameter |
---|
| 308 | inline bool getStrParam(OsiStrParam key, std::string& value) const { |
---|
| 309 | if (key!=OsiLastStrParam) { |
---|
| 310 | value = strParam_[key]; |
---|
| 311 | return true; |
---|
| 312 | } else { |
---|
| 313 | return false; |
---|
| 314 | } |
---|
| 315 | } |
---|
| 316 | //@} |
---|
| 317 | |
---|
| 318 | /**@name private or protected methods */ |
---|
| 319 | //@{ |
---|
| 320 | private: |
---|
| 321 | /// Does most of deletion |
---|
| 322 | void gutsOfDelete(); |
---|
| 323 | /** Does most of copying |
---|
| 324 | If trueCopy false then just points to arrays */ |
---|
| 325 | void gutsOfCopy(const ClpModel & rhs, bool trueCopy=true); |
---|
| 326 | protected: |
---|
| 327 | /// gets lower and upper bounds on rows |
---|
| 328 | void getRowBound(int iRow, double& lower, double& upper) const; |
---|
| 329 | /// puts in format I like - 4 array matrix - may make row copy |
---|
| 330 | void gutsOfLoadModel ( int numberRows, int numberColumns, |
---|
| 331 | const double* collb, const double* colub, |
---|
| 332 | const double* obj, |
---|
| 333 | const double* rowlb, const double* rowub, |
---|
| 334 | const double * rowObjective=NULL); |
---|
| 335 | //@} |
---|
| 336 | |
---|
| 337 | |
---|
| 338 | ////////////////// data ////////////////// |
---|
| 339 | protected: |
---|
| 340 | |
---|
| 341 | /**@name data */ |
---|
| 342 | //@{ |
---|
| 343 | /// Direction of optimization (1 - minimize, -1 - maximize, 0 - ignore |
---|
| 344 | double optimizationDirection_; |
---|
| 345 | /// Number of rows |
---|
| 346 | int numberRows_; |
---|
| 347 | /// Number of columns |
---|
| 348 | int numberColumns_; |
---|
| 349 | /// Row activities |
---|
| 350 | double * rowActivity_; |
---|
| 351 | /// Column activities |
---|
| 352 | double * columnActivity_; |
---|
| 353 | /// Duals |
---|
| 354 | double * dual_; |
---|
| 355 | /// Reduced costs |
---|
| 356 | double * reducedCost_; |
---|
| 357 | /// Row lower |
---|
| 358 | double* rowLower_; |
---|
| 359 | /// Row upper |
---|
| 360 | double* rowUpper_; |
---|
| 361 | /// Objective |
---|
| 362 | double * objective_; |
---|
| 363 | /// Row Objective (? sign) - may be NULL |
---|
| 364 | double * rowObjective_; |
---|
| 365 | /// Column Lower |
---|
| 366 | double * columnLower_; |
---|
| 367 | /// Column Upper |
---|
| 368 | double * columnUpper_; |
---|
| 369 | /// Packed matrix |
---|
| 370 | ClpMatrixBase * matrix_; |
---|
| 371 | /// Row copy if wanted |
---|
| 372 | ClpMatrixBase * rowCopy_; |
---|
| 373 | /// Infeasible/unbounded ray |
---|
| 374 | double * ray_; |
---|
| 375 | /// Array of integer parameters |
---|
| 376 | int intParam_[OsiLastIntParam]; |
---|
| 377 | /// Array of double parameters |
---|
| 378 | double dblParam_[OsiLastDblParam]; |
---|
| 379 | /// Array of string parameters |
---|
| 380 | std::string strParam_[OsiLastDblParam]; |
---|
| 381 | /// Objective value |
---|
| 382 | double objectiveValue_; |
---|
| 383 | /// Number of iterations |
---|
| 384 | int numberIterations_; |
---|
| 385 | /// Status of problem |
---|
| 386 | int problemStatus_; |
---|
| 387 | /// Maximum number of iterations |
---|
| 388 | int maximumIterations_; |
---|
| 389 | /// Message handler |
---|
| 390 | OsiMessageHandler * handler_; |
---|
| 391 | /// Flag to say if default handler (so delete) |
---|
| 392 | bool defaultHandler_; |
---|
| 393 | /// Messages |
---|
| 394 | OsiMessages messages_; |
---|
| 395 | /// length of names (0 means no names0 |
---|
| 396 | int lengthNames_; |
---|
| 397 | /// Row names |
---|
| 398 | std::vector<std::string> rowNames_; |
---|
| 399 | /// Column names |
---|
| 400 | std::vector<std::string> columnNames_; |
---|
| 401 | //@} |
---|
| 402 | }; |
---|
| 403 | #endif |
---|