00001 // Copyright (C) 2000, International Business Machines 00002 // Corporation and others. All Rights Reserved. 00003 #ifndef OsiCuts_H 00004 #define OsiCuts_H 00005 00006 #if defined(_MSC_VER) 00007 // Turn off compiler warning about long names 00008 # pragma warning(disable:4786) 00009 #endif 00010 00011 #include <cmath> 00012 #include <cfloat> 00013 #include "OsiCollections.hpp" 00014 #include "OsiRowCut.hpp" 00015 #include "OsiColCut.hpp" 00016 #include "CoinFloatEqual.hpp" 00017 00020 class OsiCuts { 00021 friend void OsiCutsUnitTest(); 00022 00023 public: 00031 class iterator { 00032 friend class OsiCuts; 00033 public: 00034 iterator(OsiCuts& cuts); 00035 iterator(const iterator & src); 00036 iterator & operator=( const iterator& rhs); 00037 ~iterator (); 00038 OsiCut* operator*() const { return cutP_; } 00039 iterator operator++(); 00040 00041 iterator operator++(int) 00042 { 00043 iterator temp = *this; 00044 ++*this; 00045 return temp; 00046 } 00047 00048 bool operator==(const iterator& it) const { 00049 return (colCutIndex_+rowCutIndex_)==(it.colCutIndex_+it.rowCutIndex_); 00050 } 00051 00052 bool operator!=(const iterator& it) const { 00053 return !((*this)==it); 00054 } 00055 00056 bool operator<(const iterator& it) const { 00057 return (colCutIndex_+rowCutIndex_)<(it.colCutIndex_+it.rowCutIndex_); 00058 } 00059 00060 private: 00061 iterator(); 00062 // *THINK* : how to inline these without sticking the code here (ugly...) 00063 iterator begin(); 00064 iterator end(); 00065 OsiCuts& cuts_; 00066 int rowCutIndex_; 00067 int colCutIndex_; 00068 OsiCut * cutP_; 00069 }; 00070 00075 class const_iterator { 00076 friend class OsiCuts; 00077 public: 00078 typedef std::bidirectional_iterator_tag iterator_category; 00079 typedef OsiCut* value_type; 00080 typedef size_t difference_type; 00081 typedef OsiCut ** pointer; 00082 typedef OsiCut *& reference; 00083 00084 public: 00085 const_iterator(const OsiCuts& cuts); 00086 const_iterator(const const_iterator & src); 00087 const_iterator & operator=( const const_iterator& rhs); 00088 ~const_iterator (); 00089 const OsiCut* operator*() const { return cutP_; } 00090 00091 const_iterator operator++(); 00092 00093 const_iterator operator++(int) 00094 { 00095 const_iterator temp = *this; 00096 ++*this; 00097 return temp; 00098 } 00099 00100 bool operator==(const const_iterator& it) const { 00101 return (colCutIndex_+rowCutIndex_)==(it.colCutIndex_+it.rowCutIndex_); 00102 } 00103 00104 bool operator!=(const const_iterator& it) const { 00105 return !((*this)==it); 00106 } 00107 00108 bool operator<(const const_iterator& it) const { 00109 return (colCutIndex_+rowCutIndex_)<(it.colCutIndex_+it.rowCutIndex_); 00110 } 00111 private: 00112 inline const_iterator(); 00113 // *THINK* : how to inline these without sticking the code here (ugly...) 00114 const_iterator begin(); 00115 const_iterator end(); 00116 const OsiCuts * cutsPtr_; 00117 int rowCutIndex_; 00118 int colCutIndex_; 00119 const OsiCut * cutP_; 00120 }; 00122 00123 //------------------------------------------------------------------- 00124 // 00125 // Cuts class definition begins here: 00126 // 00127 //------------------------------------------------------------------- 00128 00132 inline void insert( const OsiRowCut & rc ); 00135 void insertIfNotDuplicate( OsiRowCut & rc , CoinAbsFltEq treatAsSame=CoinAbsFltEq(1.0e-12) ); 00138 void insertIfNotDuplicate( OsiRowCut & rc , CoinRelFltEq treatAsSame ); 00140 inline void insert( const OsiColCut & cc ); 00141 00147 inline void insert( OsiRowCut * & rcPtr ); 00153 inline void insert( OsiColCut * & ccPtr ); 00154 #if 0 00155 inline void insert( OsiCut * & cPtr ); 00156 #endif 00157 00159 inline void insert(const OsiCuts & cs); 00160 00162 00165 00166 inline int sizeRowCuts() const; 00168 inline int sizeColCuts() const; 00170 inline int sizeCuts() const; 00172 00175 00176 inline void printCuts() const; 00178 00181 00182 inline OsiRowCut * rowCutPtr(int i); 00184 inline const OsiRowCut * rowCutPtr(int i) const; 00186 inline OsiColCut * colCutPtr(int i); 00188 inline const OsiColCut * colCutPtr(int i) const; 00189 00191 inline OsiRowCut & rowCut(int i); 00193 inline const OsiRowCut & rowCut(int i) const; 00195 inline OsiColCut & colCut(int i); 00197 inline const OsiColCut & colCut(int i) const; 00198 00200 inline const OsiCut * mostEffectiveCutPtr() const; 00202 inline OsiCut * mostEffectiveCutPtr(); 00204 00207 00208 inline void eraseRowCut(int i); 00210 inline void eraseColCut(int i); 00217 inline void dumpCuts() ; 00225 inline void eraseAndDumpCuts(const std::vector<int> to_erase) ; 00227 00230 00231 inline void sort(); 00233 00234 00245 00246 inline iterator begin() { iterator it(*this); it.begin(); return it; } 00248 inline const_iterator begin() const { const_iterator it(*this); it.begin(); return it; } 00250 inline iterator end() { iterator it(*this); it.end(); return it; } 00252 inline const_iterator end() const { const_iterator it(*this); it.end(); return it; } 00254 00255 00258 00259 OsiCuts (); 00260 00262 OsiCuts ( const OsiCuts &); 00263 00265 OsiCuts & operator=( const OsiCuts& rhs); 00266 00268 virtual ~OsiCuts (); 00270 00271 private: 00272 //*@name Function operator for sorting cuts by efectiveness */ 00274 class OsiCutCompare 00275 { 00276 public: 00278 inline bool operator()(const OsiCut * c1P,const OsiCut * c2P) 00279 { return c1P->effectiveness() > c2P->effectiveness(); } 00280 }; 00282 00285 00286 void gutsOfCopy( const OsiCuts & source ); 00288 void gutsOfDestructor(); 00290 00293 00294 OsiVectorRowCutPtr rowCutPtrs_; 00296 OsiVectorColCutPtr colCutPtrs_; 00298 00299 }; 00300 00301 00302 //------------------------------------------------------------------- 00303 // insert cuts into collection 00304 //------------------------------------------------------------------- 00305 void OsiCuts::insert( const OsiRowCut & rc ) 00306 { 00307 OsiRowCut * newCutPtr = rc.clone(); 00308 //assert(dynamic_cast<OsiRowCut*>(newCutPtr) != NULL ); 00309 rowCutPtrs_.push_back(static_cast<OsiRowCut*>(newCutPtr)); 00310 } 00311 void OsiCuts::insert( const OsiColCut & cc ) 00312 { 00313 OsiColCut * newCutPtr = cc.clone(); 00314 //assert(dynamic_cast<OsiColCut*>(newCutPtr) != NULL ); 00315 colCutPtrs_.push_back(static_cast<OsiColCut*>(newCutPtr)); 00316 } 00317 00318 void OsiCuts::insert( OsiRowCut* & rcPtr ) 00319 { 00320 rowCutPtrs_.push_back(rcPtr); 00321 rcPtr = NULL; 00322 } 00323 void OsiCuts::insert( OsiColCut* &ccPtr ) 00324 { 00325 colCutPtrs_.push_back(ccPtr); 00326 ccPtr = NULL; 00327 } 00328 #if 0 00329 void OsiCuts::insert( OsiCut* & cPtr ) 00330 { 00331 OsiRowCut * rcPtr = dynamic_cast<OsiRowCut*>(cPtr); 00332 if ( rcPtr != NULL ) { 00333 insert( rcPtr ); 00334 cPtr = rcPtr; 00335 } 00336 else { 00337 OsiColCut * ccPtr = dynamic_cast<OsiColCut*>(cPtr); 00338 assert( ccPtr != NULL ); 00339 insert( ccPtr ); 00340 cPtr = ccPtr; 00341 } 00342 } 00343 #endif 00344 00345 // LANNEZ SEBASTIEN added Thu May 25 01:22:51 EDT 2006 00346 void OsiCuts::insert(const OsiCuts & cs) 00347 { 00348 for (OsiCuts::const_iterator it = cs.begin (); it != cs.end (); it++) 00349 { 00350 const OsiRowCut * rCut = dynamic_cast <const OsiRowCut * >(*it); 00351 const OsiColCut * cCut = dynamic_cast <const OsiColCut * >(*it); 00352 assert (rCut || cCut); 00353 if (rCut) 00354 insert (*rCut); 00355 else 00356 insert (*cCut); 00357 } 00358 } 00359 00360 //------------------------------------------------------------------- 00361 // sort 00362 //------------------------------------------------------------------- 00363 void OsiCuts::sort() 00364 { 00365 std::sort(colCutPtrs_.begin(),colCutPtrs_.end(),OsiCutCompare()); 00366 std::sort(rowCutPtrs_.begin(),rowCutPtrs_.end(),OsiCutCompare()); 00367 } 00368 00369 00370 //------------------------------------------------------------------- 00371 // Get number of in collections 00372 //------------------------------------------------------------------- 00373 int OsiCuts::sizeRowCuts() const { return rowCutPtrs_.size(); } 00374 int OsiCuts::sizeColCuts() const { return colCutPtrs_.size(); } 00375 int OsiCuts::sizeCuts() const { return sizeRowCuts()+sizeColCuts(); } 00376 00377 //---------------------------------------------------------------- 00378 // Get i'th cut from the collection 00379 //---------------------------------------------------------------- 00380 const OsiRowCut * OsiCuts::rowCutPtr(int i) const { return rowCutPtrs_[i]; } 00381 const OsiColCut * OsiCuts::colCutPtr(int i) const { return colCutPtrs_[i]; } 00382 OsiRowCut * OsiCuts::rowCutPtr(int i) { return rowCutPtrs_[i]; } 00383 OsiColCut * OsiCuts::colCutPtr(int i) { return colCutPtrs_[i]; } 00384 00385 const OsiRowCut & OsiCuts::rowCut(int i) const { return *rowCutPtr(i); } 00386 const OsiColCut & OsiCuts::colCut(int i) const { return *colCutPtr(i); } 00387 OsiRowCut & OsiCuts::rowCut(int i) { return *rowCutPtr(i); } 00388 OsiColCut & OsiCuts::colCut(int i) { return *colCutPtr(i); } 00389 00390 //---------------------------------------------------------------- 00391 // Get most effective cut from collection 00392 //---------------------------------------------------------------- 00393 const OsiCut * OsiCuts::mostEffectiveCutPtr() const 00394 { 00395 const_iterator b=begin(); 00396 const_iterator e=end(); 00397 return *(std::min_element(b,e,OsiCutCompare())); 00398 } 00399 OsiCut * OsiCuts::mostEffectiveCutPtr() 00400 { 00401 iterator b=begin(); 00402 iterator e=end(); 00403 //return *(std::min_element(b,e,OsiCutCompare())); 00404 OsiCut * retVal = NULL; 00405 double maxEff = DBL_MIN; 00406 for ( OsiCuts::iterator it=b; it!=e; ++it ) { 00407 if (maxEff < (*it)->effectiveness() ) { 00408 maxEff = (*it)->effectiveness(); 00409 retVal = *it; 00410 } 00411 } 00412 return retVal; 00413 } 00414 00415 //---------------------------------------------------------------- 00416 // Print all cuts 00417 //---------------------------------------------------------------- 00418 void 00419 OsiCuts::printCuts() const 00420 { 00421 // do all column cuts first 00422 int i; 00423 int numberColCuts=sizeColCuts(); 00424 for (i=0;i<numberColCuts;i++) { 00425 const OsiColCut * cut = colCutPtr(i); 00426 cut->print(); 00427 } 00428 int numberRowCuts=sizeRowCuts(); 00429 for (i=0;i<numberRowCuts;i++) { 00430 const OsiRowCut * cut = rowCutPtr(i); 00431 cut->print(); 00432 } 00433 } 00434 00435 //---------------------------------------------------------------- 00436 // Erase i'th cut from the collection 00437 //---------------------------------------------------------------- 00438 void OsiCuts::eraseRowCut(int i) 00439 { 00440 delete rowCutPtrs_[i]; 00441 rowCutPtrs_.erase( rowCutPtrs_.begin()+i ); 00442 } 00443 void OsiCuts::eraseColCut(int i) 00444 { 00445 delete colCutPtrs_[i]; 00446 colCutPtrs_.erase( colCutPtrs_.begin()+i ); 00447 } 00448 void OsiCuts::dumpCuts() 00449 { 00450 rowCutPtrs_.clear() ; 00451 } 00452 void OsiCuts::eraseAndDumpCuts(const std::vector<int> to_erase) 00453 { 00454 for (unsigned i=0; i<to_erase.size(); i++) { 00455 delete rowCutPtrs_[to_erase[i]]; 00456 } 00457 rowCutPtrs_.clear(); 00458 } 00459 00460 //############################################################################# 00466 void 00467 OsiCutsUnitTest(); 00468 00469 #endif