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); 00212 inline OsiRowCut * rowCutPtrAndZap(int i); 00219 inline void dumpCuts() ; 00227 inline void eraseAndDumpCuts(const std::vector<int> to_erase) ; 00229 00232 00233 inline void sort(); 00235 00236 00247 00248 inline iterator begin() { iterator it(*this); it.begin(); return it; } 00250 inline const_iterator begin() const { const_iterator it(*this); it.begin(); return it; } 00252 inline iterator end() { iterator it(*this); it.end(); return it; } 00254 inline const_iterator end() const { const_iterator it(*this); it.end(); return it; } 00256 00257 00260 00261 OsiCuts (); 00262 00264 OsiCuts ( const OsiCuts &); 00265 00267 OsiCuts & operator=( const OsiCuts& rhs); 00268 00270 virtual ~OsiCuts (); 00272 00273 private: 00274 //*@name Function operator for sorting cuts by efectiveness */ 00276 class OsiCutCompare 00277 { 00278 public: 00280 inline bool operator()(const OsiCut * c1P,const OsiCut * c2P) 00281 { return c1P->effectiveness() > c2P->effectiveness(); } 00282 }; 00284 00287 00288 void gutsOfCopy( const OsiCuts & source ); 00290 void gutsOfDestructor(); 00292 00295 00296 OsiVectorRowCutPtr rowCutPtrs_; 00298 OsiVectorColCutPtr colCutPtrs_; 00300 00301 }; 00302 00303 00304 //------------------------------------------------------------------- 00305 // insert cuts into collection 00306 //------------------------------------------------------------------- 00307 void OsiCuts::insert( const OsiRowCut & rc ) 00308 { 00309 OsiRowCut * newCutPtr = rc.clone(); 00310 //assert(dynamic_cast<OsiRowCut*>(newCutPtr) != NULL ); 00311 rowCutPtrs_.push_back(static_cast<OsiRowCut*>(newCutPtr)); 00312 } 00313 void OsiCuts::insert( const OsiColCut & cc ) 00314 { 00315 OsiColCut * newCutPtr = cc.clone(); 00316 //assert(dynamic_cast<OsiColCut*>(newCutPtr) != NULL ); 00317 colCutPtrs_.push_back(static_cast<OsiColCut*>(newCutPtr)); 00318 } 00319 00320 void OsiCuts::insert( OsiRowCut* & rcPtr ) 00321 { 00322 rowCutPtrs_.push_back(rcPtr); 00323 rcPtr = NULL; 00324 } 00325 void OsiCuts::insert( OsiColCut* &ccPtr ) 00326 { 00327 colCutPtrs_.push_back(ccPtr); 00328 ccPtr = NULL; 00329 } 00330 #if 0 00331 void OsiCuts::insert( OsiCut* & cPtr ) 00332 { 00333 OsiRowCut * rcPtr = dynamic_cast<OsiRowCut*>(cPtr); 00334 if ( rcPtr != NULL ) { 00335 insert( rcPtr ); 00336 cPtr = rcPtr; 00337 } 00338 else { 00339 OsiColCut * ccPtr = dynamic_cast<OsiColCut*>(cPtr); 00340 assert( ccPtr != NULL ); 00341 insert( ccPtr ); 00342 cPtr = ccPtr; 00343 } 00344 } 00345 #endif 00346 00347 // LANNEZ SEBASTIEN added Thu May 25 01:22:51 EDT 2006 00348 void OsiCuts::insert(const OsiCuts & cs) 00349 { 00350 for (OsiCuts::const_iterator it = cs.begin (); it != cs.end (); it++) 00351 { 00352 const OsiRowCut * rCut = dynamic_cast <const OsiRowCut * >(*it); 00353 const OsiColCut * cCut = dynamic_cast <const OsiColCut * >(*it); 00354 assert (rCut || cCut); 00355 if (rCut) 00356 insert (*rCut); 00357 else 00358 insert (*cCut); 00359 } 00360 } 00361 00362 //------------------------------------------------------------------- 00363 // sort 00364 //------------------------------------------------------------------- 00365 void OsiCuts::sort() 00366 { 00367 std::sort(colCutPtrs_.begin(),colCutPtrs_.end(),OsiCutCompare()); 00368 std::sort(rowCutPtrs_.begin(),rowCutPtrs_.end(),OsiCutCompare()); 00369 } 00370 00371 00372 //------------------------------------------------------------------- 00373 // Get number of in collections 00374 //------------------------------------------------------------------- 00375 int OsiCuts::sizeRowCuts() const { return rowCutPtrs_.size(); } 00376 int OsiCuts::sizeColCuts() const { return colCutPtrs_.size(); } 00377 int OsiCuts::sizeCuts() const { return sizeRowCuts()+sizeColCuts(); } 00378 00379 //---------------------------------------------------------------- 00380 // Get i'th cut from the collection 00381 //---------------------------------------------------------------- 00382 const OsiRowCut * OsiCuts::rowCutPtr(int i) const { return rowCutPtrs_[i]; } 00383 const OsiColCut * OsiCuts::colCutPtr(int i) const { return colCutPtrs_[i]; } 00384 OsiRowCut * OsiCuts::rowCutPtr(int i) { return rowCutPtrs_[i]; } 00385 OsiColCut * OsiCuts::colCutPtr(int i) { return colCutPtrs_[i]; } 00386 00387 const OsiRowCut & OsiCuts::rowCut(int i) const { return *rowCutPtr(i); } 00388 const OsiColCut & OsiCuts::colCut(int i) const { return *colCutPtr(i); } 00389 OsiRowCut & OsiCuts::rowCut(int i) { return *rowCutPtr(i); } 00390 OsiColCut & OsiCuts::colCut(int i) { return *colCutPtr(i); } 00391 00392 //---------------------------------------------------------------- 00393 // Get most effective cut from collection 00394 //---------------------------------------------------------------- 00395 const OsiCut * OsiCuts::mostEffectiveCutPtr() const 00396 { 00397 const_iterator b=begin(); 00398 const_iterator e=end(); 00399 return *(std::min_element(b,e,OsiCutCompare())); 00400 } 00401 OsiCut * OsiCuts::mostEffectiveCutPtr() 00402 { 00403 iterator b=begin(); 00404 iterator e=end(); 00405 //return *(std::min_element(b,e,OsiCutCompare())); 00406 OsiCut * retVal = NULL; 00407 double maxEff = DBL_MIN; 00408 for ( OsiCuts::iterator it=b; it!=e; ++it ) { 00409 if (maxEff < (*it)->effectiveness() ) { 00410 maxEff = (*it)->effectiveness(); 00411 retVal = *it; 00412 } 00413 } 00414 return retVal; 00415 } 00416 00417 //---------------------------------------------------------------- 00418 // Print all cuts 00419 //---------------------------------------------------------------- 00420 void 00421 OsiCuts::printCuts() const 00422 { 00423 // do all column cuts first 00424 int i; 00425 int numberColCuts=sizeColCuts(); 00426 for (i=0;i<numberColCuts;i++) { 00427 const OsiColCut * cut = colCutPtr(i); 00428 cut->print(); 00429 } 00430 int numberRowCuts=sizeRowCuts(); 00431 for (i=0;i<numberRowCuts;i++) { 00432 const OsiRowCut * cut = rowCutPtr(i); 00433 cut->print(); 00434 } 00435 } 00436 00437 //---------------------------------------------------------------- 00438 // Erase i'th cut from the collection 00439 //---------------------------------------------------------------- 00440 void OsiCuts::eraseRowCut(int i) 00441 { 00442 delete rowCutPtrs_[i]; 00443 rowCutPtrs_.erase( rowCutPtrs_.begin()+i ); 00444 } 00445 void OsiCuts::eraseColCut(int i) 00446 { 00447 delete colCutPtrs_[i]; 00448 colCutPtrs_.erase( colCutPtrs_.begin()+i ); 00449 } 00451 OsiRowCut * 00452 OsiCuts::rowCutPtrAndZap(int i) 00453 { 00454 OsiRowCut * cut = rowCutPtrs_[i]; 00455 rowCutPtrs_[i]=NULL; 00456 rowCutPtrs_.erase( rowCutPtrs_.begin()+i ); 00457 return cut; 00458 } 00459 void OsiCuts::dumpCuts() 00460 { 00461 rowCutPtrs_.clear() ; 00462 } 00463 void OsiCuts::eraseAndDumpCuts(const std::vector<int> to_erase) 00464 { 00465 for (unsigned i=0; i<to_erase.size(); i++) { 00466 delete rowCutPtrs_[to_erase[i]]; 00467 } 00468 rowCutPtrs_.clear(); 00469 } 00470 00471 //############################################################################# 00477 void 00478 OsiCutsUnitTest(); 00479 00480 #endif