CoinUtils
trunk
|
00001 /* $Id$ */ 00002 // Copyright (C) 2000, International Business Machines 00003 // Corporation and others. All Rights Reserved. 00004 // This code is licensed under the terms of the Eclipse Public License (EPL). 00005 00006 #ifndef CoinWarmStartVector_H 00007 #define CoinWarmStartVector_H 00008 00009 #if defined(_MSC_VER) 00010 // Turn off compiler warning about long names 00011 # pragma warning(disable:4786) 00012 #endif 00013 00014 #include <cassert> 00015 #include <cmath> 00016 00017 #include "CoinHelperFunctions.hpp" 00018 #include "CoinWarmStart.hpp" 00019 00020 00021 //############################################################################# 00022 00025 template <typename T> 00026 class CoinWarmStartVector : public virtual CoinWarmStart 00027 { 00028 protected: 00029 inline void gutsOfDestructor() { 00030 delete[] values_; 00031 } 00032 inline void gutsOfCopy(const CoinWarmStartVector<T>& rhs) { 00033 size_ = rhs.size_; 00034 values_ = new T[size_]; 00035 CoinDisjointCopyN(rhs.values_, size_, values_); 00036 } 00037 00038 public: 00040 int size() const { return size_; } 00042 const T* values() const { return values_; } 00043 00047 void assignVector(int size, T*& vec) { 00048 size_ = size; 00049 delete[] values_; 00050 values_ = vec; 00051 vec = NULL; 00052 } 00053 00054 CoinWarmStartVector() : size_(0), values_(NULL) {} 00055 00056 CoinWarmStartVector(int size, const T* vec) : 00057 size_(size), values_(new T[size]) { 00058 CoinDisjointCopyN(vec, size, values_); 00059 } 00060 00061 CoinWarmStartVector(const CoinWarmStartVector& rhs) { 00062 gutsOfCopy(rhs); 00063 } 00064 00065 CoinWarmStartVector& operator=(const CoinWarmStartVector& rhs) { 00066 if (this != &rhs) { 00067 gutsOfDestructor(); 00068 gutsOfCopy(rhs); 00069 } 00070 return *this; 00071 } 00072 00073 inline void swap(CoinWarmStartVector& rhs) { 00074 if (this != &rhs) { 00075 std::swap(size_, rhs.size_); 00076 std::swap(values_, rhs.values_); 00077 } 00078 } 00079 00081 virtual CoinWarmStart *clone() const { 00082 return new CoinWarmStartVector(*this); 00083 } 00084 00085 virtual ~CoinWarmStartVector() { 00086 gutsOfDestructor(); 00087 } 00088 00094 inline void clear() { 00095 size_ = 0; 00096 delete[] values_; 00097 values_ = NULL; 00098 } 00099 00102 00110 virtual CoinWarmStartDiff* 00111 generateDiff (const CoinWarmStart *const oldCWS) const ; 00112 00119 virtual void applyDiff (const CoinWarmStartDiff *const cwsdDiff) ; 00120 00122 00123 private: 00125 00126 00127 int size_; 00129 T* values_; 00131 }; 00132 00133 //============================================================================= 00134 00150 template <typename T> 00151 class CoinWarmStartVectorDiff : public virtual CoinWarmStartDiff 00152 { 00153 friend CoinWarmStartDiff* 00154 CoinWarmStartVector<T>::generateDiff(const CoinWarmStart *const oldCWS) const; 00155 friend void 00156 CoinWarmStartVector<T>::applyDiff(const CoinWarmStartDiff *const diff) ; 00157 00158 public: 00159 00161 virtual CoinWarmStartDiff * clone() const { 00162 return new CoinWarmStartVectorDiff(*this) ; 00163 } 00164 00166 virtual CoinWarmStartVectorDiff & 00167 operator= (const CoinWarmStartVectorDiff<T>& rhs) ; 00168 00170 virtual ~CoinWarmStartVectorDiff() { 00171 delete[] diffNdxs_ ; 00172 delete[] diffVals_ ; 00173 } 00174 00175 inline void swap(CoinWarmStartVectorDiff& rhs) { 00176 if (this != &rhs) { 00177 std::swap(sze_, rhs.sze_); 00178 std::swap(diffNdxs_, rhs.diffNdxs_); 00179 std::swap(diffVals_, rhs.diffVals_); 00180 } 00181 } 00182 00185 CoinWarmStartVectorDiff () : sze_(0), diffNdxs_(0), diffVals_(NULL) {} 00186 00193 CoinWarmStartVectorDiff(const CoinWarmStartVectorDiff<T>& rhs) ; 00194 00196 CoinWarmStartVectorDiff(int sze, const unsigned int* const diffNdxs, 00197 const T* const diffVals) ; 00198 00204 inline void clear() { 00205 sze_ = 0; 00206 delete[] diffNdxs_; diffNdxs_ = NULL; 00207 delete[] diffVals_; diffVals_ = NULL; 00208 } 00209 00210 private: 00211 00215 int sze_ ; 00216 00219 unsigned int* diffNdxs_ ; 00220 00223 T* diffVals_ ; 00224 }; 00225 00226 //############################################################################## 00227 00228 template <typename T, typename U> 00229 class CoinWarmStartVectorPair : public virtual CoinWarmStart 00230 { 00231 private: 00232 CoinWarmStartVector<T> t_; 00233 CoinWarmStartVector<U> u_; 00234 00235 public: 00236 inline int size0() const { return t_.size(); } 00237 inline int size1() const { return u_.size(); } 00238 inline const T* values0() const { return t_.values(); } 00239 inline const U* values1() const { return u_.values(); } 00240 00241 inline void assignVector0(int size, T*& vec) { t_.assignVector(size, vec); } 00242 inline void assignVector1(int size, U*& vec) { u_.assignVector(size, vec); } 00243 00244 CoinWarmStartVectorPair() {} 00245 CoinWarmStartVectorPair(int s0, const T* v0, int s1, const U* v1) : 00246 t_(s0, v0), u_(s1, v1) {} 00247 00248 CoinWarmStartVectorPair(const CoinWarmStartVectorPair<T,U>& rhs) : 00249 t_(rhs.t_), u_(rhs.u_) {} 00250 CoinWarmStartVectorPair& operator=(const CoinWarmStartVectorPair<T,U>& rhs) { 00251 if (this != &rhs) { 00252 t_ = rhs.t_; 00253 u_ = rhs.u_; 00254 } 00255 return *this; 00256 } 00257 00258 inline void swap(CoinWarmStartVectorPair<T,U>& rhs) { 00259 t_.swap(rhs.t_); 00260 u_.swap(rhs.u_); 00261 } 00262 00263 virtual CoinWarmStart *clone() const { 00264 return new CoinWarmStartVectorPair(*this); 00265 } 00266 00267 virtual ~CoinWarmStartVectorPair() {} 00268 00269 inline void clear() { 00270 t_.clear(); 00271 u_.clear(); 00272 } 00273 00274 virtual CoinWarmStartDiff* 00275 generateDiff (const CoinWarmStart *const oldCWS) const ; 00276 00277 virtual void applyDiff (const CoinWarmStartDiff *const cwsdDiff) ; 00278 }; 00279 00280 //============================================================================= 00281 00282 template <typename T, typename U> 00283 class CoinWarmStartVectorPairDiff : public virtual CoinWarmStartDiff 00284 { 00285 friend CoinWarmStartDiff* 00286 CoinWarmStartVectorPair<T,U>::generateDiff(const CoinWarmStart *const oldCWS) const; 00287 friend void 00288 CoinWarmStartVectorPair<T,U>::applyDiff(const CoinWarmStartDiff *const diff) ; 00289 00290 private: 00291 CoinWarmStartVectorDiff<T> tdiff_; 00292 CoinWarmStartVectorDiff<U> udiff_; 00293 00294 public: 00295 CoinWarmStartVectorPairDiff() {} 00296 CoinWarmStartVectorPairDiff(const CoinWarmStartVectorPairDiff<T,U>& rhs) : 00297 tdiff_(rhs.tdiff_), udiff_(rhs.udiff_) {} 00298 virtual ~CoinWarmStartVectorPairDiff() {} 00299 00300 virtual CoinWarmStartVectorPairDiff& 00301 operator=(const CoinWarmStartVectorPairDiff<T,U>& rhs) { 00302 if (this != &rhs) { 00303 tdiff_ = rhs.tdiff_; 00304 udiff_ = rhs.udiff_; 00305 } 00306 return *this; 00307 } 00308 00309 virtual CoinWarmStartDiff * clone() const { 00310 return new CoinWarmStartVectorPairDiff(*this) ; 00311 } 00312 00313 inline void swap(CoinWarmStartVectorPairDiff<T,U>& rhs) { 00314 tdiff_.swap(rhs.tdiff_); 00315 udiff_.swap(rhs.udiff_); 00316 } 00317 00318 inline void clear() { 00319 tdiff_.clear(); 00320 udiff_.clear(); 00321 } 00322 }; 00323 00324 //############################################################################## 00325 //############################################################################# 00326 00327 /* 00328 Generate a `diff' that can convert the warm start passed as a parameter to 00329 the warm start specified by this. 00330 00331 The capabilities are limited: the basis passed as a parameter can be no 00332 larger than the basis pointed to by this. 00333 */ 00334 00335 template <typename T> CoinWarmStartDiff* 00336 CoinWarmStartVector<T>::generateDiff(const CoinWarmStart *const oldCWS) const 00337 { 00338 /* 00339 Make sure the parameter is CoinWarmStartVector or derived class. 00340 */ 00341 const CoinWarmStartVector<T>* oldVector = 00342 dynamic_cast<const CoinWarmStartVector<T>*>(oldCWS); 00343 if (!oldVector) 00344 { throw CoinError("Old warm start not derived from CoinWarmStartVector.", 00345 "generateDiff","CoinWarmStartVector") ; } 00346 const CoinWarmStartVector<T>* newVector = this ; 00347 /* 00348 Make sure newVector is equal or bigger than oldVector. Calculate the worst 00349 case number of diffs and allocate vectors to hold them. 00350 */ 00351 const int oldCnt = oldVector->size() ; 00352 const int newCnt = newVector->size() ; 00353 00354 assert(newCnt >= oldCnt) ; 00355 00356 unsigned int *diffNdx = new unsigned int [newCnt]; 00357 T* diffVal = new T[newCnt]; 00358 /* 00359 Scan the vector vectors. For the portion of the vectors which overlap, 00360 create diffs. Then add any additional entries from newVector. 00361 */ 00362 const T*oldVal = oldVector->values() ; 00363 const T*newVal = newVector->values() ; 00364 int numberChanged = 0 ; 00365 int i ; 00366 for (i = 0 ; i < oldCnt ; i++) { 00367 if (oldVal[i] != newVal[i]) { 00368 diffNdx[numberChanged] = i ; 00369 diffVal[numberChanged++] = newVal[i] ; 00370 } 00371 } 00372 for ( ; i < newCnt ; i++) { 00373 diffNdx[numberChanged] = i ; 00374 diffVal[numberChanged++] = newVal[i] ; 00375 } 00376 /* 00377 Create the object of our desire. 00378 */ 00379 CoinWarmStartVectorDiff<T> *diff = 00380 new CoinWarmStartVectorDiff<T>(numberChanged,diffNdx,diffVal) ; 00381 /* 00382 Clean up and return. 00383 */ 00384 delete[] diffNdx ; 00385 delete[] diffVal ; 00386 00387 return diff; 00388 // return (dynamic_cast<CoinWarmStartDiff<T>*>(diff)) ; 00389 } 00390 00391 00392 /* 00393 Apply diff to this warm start. 00394 00395 Update this warm start by applying diff. It's assumed that the 00396 allocated capacity of the warm start is sufficiently large. 00397 */ 00398 00399 template <typename T> void 00400 CoinWarmStartVector<T>::applyDiff (const CoinWarmStartDiff *const cwsdDiff) 00401 { 00402 /* 00403 Make sure we have a CoinWarmStartVectorDiff 00404 */ 00405 const CoinWarmStartVectorDiff<T>* diff = 00406 dynamic_cast<const CoinWarmStartVectorDiff<T>*>(cwsdDiff) ; 00407 if (!diff) { 00408 throw CoinError("Diff not derived from CoinWarmStartVectorDiff.", 00409 "applyDiff","CoinWarmStartVector") ; 00410 } 00411 /* 00412 Application is by straighforward replacement of words in the vector vector. 00413 */ 00414 const int numberChanges = diff->sze_ ; 00415 const unsigned int *diffNdxs = diff->diffNdxs_ ; 00416 const T* diffVals = diff->diffVals_ ; 00417 T* vals = this->values_ ; 00418 00419 for (int i = 0 ; i < numberChanges ; i++) { 00420 unsigned int diffNdx = diffNdxs[i] ; 00421 T diffVal = diffVals[i] ; 00422 vals[diffNdx] = diffVal ; 00423 } 00424 } 00425 00426 //############################################################################# 00427 00428 00429 // Assignment 00430 00431 template <typename T> CoinWarmStartVectorDiff<T>& 00432 CoinWarmStartVectorDiff<T>::operator=(const CoinWarmStartVectorDiff<T> &rhs) 00433 { 00434 if (this != &rhs) { 00435 if (sze_ > 0) { 00436 delete[] diffNdxs_ ; 00437 delete[] diffVals_ ; 00438 } 00439 sze_ = rhs.sze_ ; 00440 if (sze_ > 0) { 00441 diffNdxs_ = new unsigned int[sze_] ; 00442 memcpy(diffNdxs_,rhs.diffNdxs_,sze_*sizeof(unsigned int)) ; 00443 diffVals_ = new T[sze_] ; 00444 memcpy(diffVals_,rhs.diffVals_,sze_*sizeof(T)) ; 00445 } else { 00446 diffNdxs_ = 0 ; 00447 diffVals_ = 0 ; 00448 } 00449 } 00450 00451 return (*this) ; 00452 } 00453 00454 00455 // Copy constructor 00456 00457 template <typename T> 00458 CoinWarmStartVectorDiff<T>::CoinWarmStartVectorDiff(const CoinWarmStartVectorDiff<T> &rhs) 00459 : sze_(rhs.sze_), 00460 diffNdxs_(0), 00461 diffVals_(0) 00462 { 00463 if (sze_ > 0) { 00464 diffNdxs_ = new unsigned int[sze_] ; 00465 memcpy(diffNdxs_,rhs.diffNdxs_,sze_*sizeof(unsigned int)) ; 00466 diffVals_ = new T[sze_] ; 00467 memcpy(diffVals_,rhs.diffVals_,sze_*sizeof(T)) ; 00468 } 00469 } 00470 00472 00473 template <typename T> 00474 CoinWarmStartVectorDiff<T>::CoinWarmStartVectorDiff 00475 (int sze, const unsigned int *const diffNdxs, const T *const diffVals) 00476 : sze_(sze), 00477 diffNdxs_(0), 00478 diffVals_(0) 00479 { 00480 if (sze > 0) { 00481 diffNdxs_ = new unsigned int[sze] ; 00482 memcpy(diffNdxs_,diffNdxs,sze*sizeof(unsigned int)) ; 00483 diffVals_ = new T[sze] ; 00484 memcpy(diffVals_,diffVals,sze*sizeof(T)) ; 00485 } 00486 } 00487 00488 #endif