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 } 00256 00257 inline void swap(CoinWarmStartVectorPair<T,U>& rhs) { 00258 t_.swap(rhs.t_); 00259 u_.swap(rhs.u_); 00260 } 00261 00262 virtual CoinWarmStart *clone() const { 00263 return new CoinWarmStartVectorPair(*this); 00264 } 00265 00266 virtual ~CoinWarmStartVectorPair() {} 00267 00268 inline void clear() { 00269 t_.clear(); 00270 u_.clear(); 00271 } 00272 00273 virtual CoinWarmStartDiff* 00274 generateDiff (const CoinWarmStart *const oldCWS) const ; 00275 00276 virtual void applyDiff (const CoinWarmStartDiff *const cwsdDiff) ; 00277 }; 00278 00279 //============================================================================= 00280 00281 template <typename T, typename U> 00282 class CoinWarmStartVectorPairDiff : public virtual CoinWarmStartDiff 00283 { 00284 friend CoinWarmStartDiff* 00285 CoinWarmStartVectorPair<T,U>::generateDiff(const CoinWarmStart *const oldCWS) const; 00286 friend void 00287 CoinWarmStartVectorPair<T,U>::applyDiff(const CoinWarmStartDiff *const diff) ; 00288 00289 private: 00290 CoinWarmStartVectorDiff<T> tdiff_; 00291 CoinWarmStartVectorDiff<U> udiff_; 00292 00293 public: 00294 CoinWarmStartVectorPairDiff() {} 00295 CoinWarmStartVectorPairDiff(const CoinWarmStartVectorPairDiff<T,U>& rhs) : 00296 tdiff_(rhs.tdiff_), udiff_(rhs.udiff_) {} 00297 ~CoinWarmStartVectorPairDiff() {} 00298 00299 virtual CoinWarmStartVectorPairDiff& 00300 operator=(const CoinWarmStartVectorPairDiff<T,U>& rhs) { 00301 tdiff_ = rhs.tdiff_; 00302 udiff_ = rhs.udiff_; 00303 } 00304 00305 virtual CoinWarmStartDiff * clone() const { 00306 return new CoinWarmStartVectorPairDiff(*this) ; 00307 } 00308 00309 inline void swap(CoinWarmStartVectorPairDiff<T,U>& rhs) { 00310 tdiff_.swap(rhs.tdiff_); 00311 udiff_.swap(rhs.udiff_); 00312 } 00313 00314 inline void clear() { 00315 tdiff_.clear(); 00316 udiff_.clear(); 00317 } 00318 }; 00319 00320 //############################################################################## 00321 //############################################################################# 00322 00323 /* 00324 Generate a `diff' that can convert the warm start passed as a parameter to 00325 the warm start specified by this. 00326 00327 The capabilities are limited: the basis passed as a parameter can be no 00328 larger than the basis pointed to by this. 00329 */ 00330 00331 template <typename T> CoinWarmStartDiff* 00332 CoinWarmStartVector<T>::generateDiff(const CoinWarmStart *const oldCWS) const 00333 { 00334 /* 00335 Make sure the parameter is CoinWarmStartVector or derived class. 00336 */ 00337 const CoinWarmStartVector<T>* oldVector = 00338 dynamic_cast<const CoinWarmStartVector<T>*>(oldCWS); 00339 if (!oldVector) 00340 { throw CoinError("Old warm start not derived from CoinWarmStartVector.", 00341 "generateDiff","CoinWarmStartVector") ; } 00342 const CoinWarmStartVector<T>* newVector = this ; 00343 /* 00344 Make sure newVector is equal or bigger than oldVector. Calculate the worst 00345 case number of diffs and allocate vectors to hold them. 00346 */ 00347 const int oldCnt = oldVector->size() ; 00348 const int newCnt = newVector->size() ; 00349 00350 assert(newCnt >= oldCnt) ; 00351 00352 unsigned int *diffNdx = new unsigned int [newCnt]; 00353 T* diffVal = new T[newCnt]; 00354 /* 00355 Scan the vector vectors. For the portion of the vectors which overlap, 00356 create diffs. Then add any additional entries from newVector. 00357 */ 00358 const T*oldVal = oldVector->values() ; 00359 const T*newVal = newVector->values() ; 00360 int numberChanged = 0 ; 00361 int i ; 00362 for (i = 0 ; i < oldCnt ; i++) { 00363 if (oldVal[i] != newVal[i]) { 00364 diffNdx[numberChanged] = i ; 00365 diffVal[numberChanged++] = newVal[i] ; 00366 } 00367 } 00368 for ( ; i < newCnt ; i++) { 00369 diffNdx[numberChanged] = i ; 00370 diffVal[numberChanged++] = newVal[i] ; 00371 } 00372 /* 00373 Create the object of our desire. 00374 */ 00375 CoinWarmStartVectorDiff<T> *diff = 00376 new CoinWarmStartVectorDiff<T>(numberChanged,diffNdx,diffVal) ; 00377 /* 00378 Clean up and return. 00379 */ 00380 delete[] diffNdx ; 00381 delete[] diffVal ; 00382 00383 return diff; 00384 // return (dynamic_cast<CoinWarmStartDiff<T>*>(diff)) ; 00385 } 00386 00387 00388 /* 00389 Apply diff to this warm start. 00390 00391 Update this warm start by applying diff. It's assumed that the 00392 allocated capacity of the warm start is sufficiently large. 00393 */ 00394 00395 template <typename T> void 00396 CoinWarmStartVector<T>::applyDiff (const CoinWarmStartDiff *const cwsdDiff) 00397 { 00398 /* 00399 Make sure we have a CoinWarmStartVectorDiff 00400 */ 00401 const CoinWarmStartVectorDiff<T>* diff = 00402 dynamic_cast<const CoinWarmStartVectorDiff<T>*>(cwsdDiff) ; 00403 if (!diff) { 00404 throw CoinError("Diff not derived from CoinWarmStartVectorDiff.", 00405 "applyDiff","CoinWarmStartVector") ; 00406 } 00407 /* 00408 Application is by straighforward replacement of words in the vector vector. 00409 */ 00410 const int numberChanges = diff->sze_ ; 00411 const unsigned int *diffNdxs = diff->diffNdxs_ ; 00412 const T* diffVals = diff->diffVals_ ; 00413 T* vals = this->values_ ; 00414 00415 for (int i = 0 ; i < numberChanges ; i++) { 00416 unsigned int diffNdx = diffNdxs[i] ; 00417 T diffVal = diffVals[i] ; 00418 vals[diffNdx] = diffVal ; 00419 } 00420 } 00421 00422 //############################################################################# 00423 00424 00425 // Assignment 00426 00427 template <typename T> CoinWarmStartVectorDiff<T>& 00428 CoinWarmStartVectorDiff<T>::operator=(const CoinWarmStartVectorDiff<T> &rhs) 00429 { 00430 if (this != &rhs) { 00431 if (sze_ > 0) { 00432 delete[] diffNdxs_ ; 00433 delete[] diffVals_ ; 00434 } 00435 sze_ = rhs.sze_ ; 00436 if (sze_ > 0) { 00437 diffNdxs_ = new unsigned int[sze_] ; 00438 memcpy(diffNdxs_,rhs.diffNdxs_,sze_*sizeof(unsigned int)) ; 00439 diffVals_ = new T[sze_] ; 00440 memcpy(diffVals_,rhs.diffVals_,sze_*sizeof(T)) ; 00441 } else { 00442 diffNdxs_ = 0 ; 00443 diffVals_ = 0 ; 00444 } 00445 } 00446 00447 return (*this) ; 00448 } 00449 00450 00451 // Copy constructor 00452 00453 template <typename T> 00454 CoinWarmStartVectorDiff<T>::CoinWarmStartVectorDiff(const CoinWarmStartVectorDiff<T> &rhs) 00455 : sze_(rhs.sze_), 00456 diffNdxs_(0), 00457 diffVals_(0) 00458 { 00459 if (sze_ > 0) { 00460 diffNdxs_ = new unsigned int[sze_] ; 00461 memcpy(diffNdxs_,rhs.diffNdxs_,sze_*sizeof(unsigned int)) ; 00462 diffVals_ = new T[sze_] ; 00463 memcpy(diffVals_,rhs.diffVals_,sze_*sizeof(T)) ; 00464 } 00465 } 00466 00468 00469 template <typename T> 00470 CoinWarmStartVectorDiff<T>::CoinWarmStartVectorDiff 00471 (int sze, const unsigned int *const diffNdxs, const T *const diffVals) 00472 : sze_(sze), 00473 diffNdxs_(0), 00474 diffVals_(0) 00475 { 00476 if (sze > 0) { 00477 diffNdxs_ = new unsigned int[sze] ; 00478 memcpy(diffNdxs_,diffNdxs,sze*sizeof(unsigned int)) ; 00479 diffVals_ = new T[sze] ; 00480 memcpy(diffVals_,diffVals,sze*sizeof(T)) ; 00481 } 00482 } 00483 00484 #endif