1/* $Id: CoinWarmStartVector.hpp 1372 2011-01-03 23:31:00Z lou $ */
2// Copyright (C) 2000, International Business Machines
3// Corporation and others. All Rights Reserved.
4// This code is licensed under the terms of the Eclipse Public License (EPL).
5
6#ifndef CoinWarmStartVector_H
7#define CoinWarmStartVector_H
8
9#if defined(_MSC_VER)
10// Turn off compiler warning about long names
11# pragma warning(disable:4786)
12#endif
13
14#include <cassert>
15#include <cmath>
16
17#include "CoinHelperFunctions.hpp"
18#include "CoinWarmStart.hpp"
19
20
21//#############################################################################
22
23/** WarmStart information that is only a vector */
24
25template <typename T>
26class CoinWarmStartVector : public virtual CoinWarmStart
27{
28protected:
29 inline void gutsOfDestructor() {
30 delete[] values_;
31 }
32 inline void gutsOfCopy(const CoinWarmStartVector<T>& rhs) {
33 size_ = rhs.size_;
34 values_ = new T[size_];
35 CoinDisjointCopyN(rhs.values_, size_, values_);
36 }
37
38public:
39 /// return the size of the vector
40 int size() const { return size_; }
41 /// return a pointer to the array of vectors
42 const T* values() const { return values_; }
43
44 /** Assign the vector to be the warmstart information. In this method
45 the object assumes ownership of the pointer and upon return #vector will
46 be a NULL pointer. If copying is desirable use the constructor. */
47 void assignVector(int size, T*& vec) {
48 size_ = size;
49 delete[] values_;
50 values_ = vec;
51 vec = NULL;
52 }
53
54 CoinWarmStartVector() : size_(0), values_(NULL) {}
55
56 CoinWarmStartVector(int size, const T* vec) :
57 size_(size), values_(new T[size]) {
58 CoinDisjointCopyN(vec, size, values_);
59 }
60
61 CoinWarmStartVector(const CoinWarmStartVector& rhs) {
62 gutsOfCopy(rhs);
63 }
64
65 CoinWarmStartVector& operator=(const CoinWarmStartVector& rhs) {
66 if (this != &rhs) {
67 gutsOfDestructor();
68 gutsOfCopy(rhs);
69 }
70 return *this;
71 }
72
73 inline void swap(CoinWarmStartVector& rhs) {
74 if (this != &rhs) {
75 std::swap(size_, rhs.size_);
76 std::swap(values_, rhs.values_);
77 }
78 }
79
80 /** `Virtual constructor' */
81 virtual CoinWarmStart *clone() const override {
82 return new CoinWarmStartVector(*this);
83 }
84
85 virtual ~CoinWarmStartVector() {
86 gutsOfDestructor();
87 }
88
89 /*! \brief Clear the data
90
91 Make it appear as if the warmstart was just created using the default
92 constructor.
93 */
94 inline void clear() {
95 size_ = 0;
96 delete[] values_;
97 values_ = NULL;
98 }
99
100 /*! \name Vector warm start `diff' methods */
101 //@{
102
103 /*! \brief Generate a `diff' that can convert the warm start passed as a
104 parameter to the warm start specified by \c this.
105
106 The capabilities are limited: the basis passed as a parameter can be no
107 larger than the basis pointed to by \c this.
108 */
109
110 virtual CoinWarmStartDiff*
111 generateDiff (const CoinWarmStart *const oldCWS) const override ;
112
113 /*! \brief Apply \p diff to this warm start.
114
115 Update this warm start by applying \p diff. It's assumed that the
116 allocated capacity of the warm start is sufficiently large.
117 */
118
119 virtual void applyDiff (const CoinWarmStartDiff *const cwsdDiff) override ;
120
121 //@}
122
123private:
124 ///@name Private data members
125 //@{
126 /// the size of the vector
127 int size_;
128 /// the vector itself
129 T* values_;
130 //@}
131};
132
133//=============================================================================
134
135/*! \class CoinWarmStartVectorDiff
136 \brief A `diff' between two CoinWarmStartVector objects
137
138 This class exists in order to hide from the world the details of calculating
139 and representing a `diff' between two CoinWarmStartVector objects. For
140 convenience, assignment, cloning, and deletion are visible to the world, and
141 default and copy constructors are made available to derived classes.
142 Knowledge of the rest of this structure, and of generating and applying
143 diffs, is restricted to the friend functions
144 CoinWarmStartVector::generateDiff() and CoinWarmStartVector::applyDiff().
145
146 The actual data structure is a pair of vectors, #diffNdxs_ and #diffVals_.
147
148*/
149
150template <typename T>
151class CoinWarmStartVectorDiff : public virtual CoinWarmStartDiff
152{
153 friend CoinWarmStartDiff*
154 CoinWarmStartVector<T>::generateDiff(const CoinWarmStart *const oldCWS) const;
155 friend void
156 CoinWarmStartVector<T>::applyDiff(const CoinWarmStartDiff *const diff) ;
157
158public:
159
160 /*! \brief `Virtual constructor' */
161 virtual CoinWarmStartDiff * clone() const override {
162 return new CoinWarmStartVectorDiff(*this) ;
163 }
164
165 /*! \brief Assignment */
166 virtual CoinWarmStartVectorDiff &
167 operator= (const CoinWarmStartVectorDiff<T>& rhs) ;
168
169 /*! \brief Destructor */
170 virtual ~CoinWarmStartVectorDiff() {
171 delete[] diffNdxs_ ;
172 delete[] diffVals_ ;
173 }
174
175 inline void swap(CoinWarmStartVectorDiff& rhs) {
176 if (this != &rhs) {
177 std::swap(sze_, rhs.sze_);
178 std::swap(diffNdxs_, rhs.diffNdxs_);
179 std::swap(diffVals_, rhs.diffVals_);
180 }
181 }
182
183 /*! \brief Default constructor
184 */
185 CoinWarmStartVectorDiff () : sze_(0), diffNdxs_(nullptr), diffVals_(NULL) {}
186
187 /*! \brief Copy constructor
188
189 For convenience when copying objects containing CoinWarmStartVectorDiff
190 objects. But consider whether you should be using #clone() to retain
191 polymorphism.
192 */
193 CoinWarmStartVectorDiff(const CoinWarmStartVectorDiff<T>& rhs) ;
194
195 /*! \brief Standard constructor */
196 CoinWarmStartVectorDiff(int sze, const unsigned int* const diffNdxs,
197 const T* const diffVals) ;
198
199 /*! \brief Clear the data
200
201 Make it appear as if the diff was just created using the default
202 constructor.
203 */
204 inline void clear() {
205 sze_ = 0;
206 delete[] diffNdxs_; diffNdxs_ = NULL;
207 delete[] diffVals_; diffVals_ = NULL;
208 }
209
210private:
211
212 /*!
213 \brief Number of entries (and allocated capacity), in units of \c T.
214 */
215 int sze_ ;
216
217 /*! \brief Array of diff indices */
218
219 unsigned int* diffNdxs_ ;
220
221 /*! \brief Array of diff values */
222
223 T* diffVals_ ;
224};
225
226//##############################################################################
227
228template <typename T, typename U>
229class CoinWarmStartVectorPair : public virtual CoinWarmStart
230{
231private:
232 CoinWarmStartVector<T> t_;
233 CoinWarmStartVector<U> u_;
234
235public:
236 inline int size0() const { return t_.size(); }
237 inline int size1() const { return u_.size(); }
238 inline const T* values0() const { return t_.values(); }
239 inline const U* values1() const { return u_.values(); }
240
241 inline void assignVector0(int size, T*& vec) { t_.assignVector(size, vec); }
242 inline void assignVector1(int size, U*& vec) { u_.assignVector(size, vec); }
243
244 CoinWarmStartVectorPair() {}
245 CoinWarmStartVectorPair(int s0, const T* v0, int s1, const U* v1) :
246 t_(s0, v0), u_(s1, v1) {}
247
248 CoinWarmStartVectorPair(const CoinWarmStartVectorPair<T,U>& rhs) :
249 t_(rhs.t_), u_(rhs.u_) {}
250 CoinWarmStartVectorPair& operator=(const CoinWarmStartVectorPair<T,U>& rhs) {
251 if (this != &rhs) {
252 t_ = rhs.t_;
253 u_ = rhs.u_;
254 }
255 }
256
257 inline void swap(CoinWarmStartVectorPair<T,U>& rhs) {
258 t_.swap(rhs.t_);
259 u_.swap(rhs.u_);
260 }
261
262 virtual CoinWarmStart *clone() const override {
263 return new CoinWarmStartVectorPair(*this);
264 }
265
266 virtual ~CoinWarmStartVectorPair() {}
267
268 inline void clear() {
269 t_.clear();
270 u_.clear();
271 }
272
273 virtual CoinWarmStartDiff*
274 generateDiff (const CoinWarmStart *const oldCWS) const override ;
275
276 virtual void applyDiff (const CoinWarmStartDiff *const cwsdDiff) override ;
277};
278
279//=============================================================================
280
281template <typename T, typename U>
282class CoinWarmStartVectorPairDiff : public virtual CoinWarmStartDiff
283{
284 friend CoinWarmStartDiff*
285 CoinWarmStartVectorPair<T,U>::generateDiff(const CoinWarmStart *const oldCWS) const;
286 friend void
287 CoinWarmStartVectorPair<T,U>::applyDiff(const CoinWarmStartDiff *const diff) ;
288
289private:
290 CoinWarmStartVectorDiff<T> tdiff_;
291 CoinWarmStartVectorDiff<U> udiff_;
292
293public:
294 CoinWarmStartVectorPairDiff() {}
295 CoinWarmStartVectorPairDiff(const CoinWarmStartVectorPairDiff<T,U>& rhs) :
296 tdiff_(rhs.tdiff_), udiff_(rhs.udiff_) {}
297 ~CoinWarmStartVectorPairDiff() {}
298
299 virtual CoinWarmStartVectorPairDiff&
300 operator=(const CoinWarmStartVectorPairDiff<T,U>& rhs) {
301 tdiff_ = rhs.tdiff_;
302 udiff_ = rhs.udiff_;
303 }
304
305 virtual CoinWarmStartDiff * clone() const override {
306 return new CoinWarmStartVectorPairDiff(*this) ;
307 }
308
309 inline void swap(CoinWarmStartVectorPairDiff<T,U>& rhs) {
310 tdiff_.swap(rhs.tdiff_);
311 udiff_.swap(rhs.udiff_);
312 }
313
314 inline void clear() {
315 tdiff_.clear();
316 udiff_.clear();
317 }
318};
319
320//##############################################################################
321//#############################################################################
322
323/*
324 Generate a `diff' that can convert the warm start passed as a parameter to
325 the warm start specified by this.
326
327 The capabilities are limited: the basis passed as a parameter can be no
328 larger than the basis pointed to by this.
329*/
330
331template <typename T> CoinWarmStartDiff*
332CoinWarmStartVector<T>::generateDiff(const CoinWarmStart *const oldCWS) const
333{
334/*
335 Make sure the parameter is CoinWarmStartVector or derived class.
336*/
337 const CoinWarmStartVector<T>* oldVector =
338 dynamic_cast<const CoinWarmStartVector<T>*>(oldCWS);
339 if (!oldVector)
340 { throw CoinError("Old warm start not derived from CoinWarmStartVector.",
341 "generateDiff","CoinWarmStartVector") ; }
342 const CoinWarmStartVector<T>* newVector = this ;
343 /*
344 Make sure newVector is equal or bigger than oldVector. Calculate the worst
345 case number of diffs and allocate vectors to hold them.
346 */
347 const int oldCnt = oldVector->size() ;
348 const int newCnt = newVector->size() ;
349
350 assert(newCnt >= oldCnt) ;
351
352 unsigned int *diffNdx = new unsigned int [newCnt];
353 T* diffVal = new T[newCnt];
354 /*
355 Scan the vector vectors. For the portion of the vectors which overlap,
356 create diffs. Then add any additional entries from newVector.
357 */
358 const T*oldVal = oldVector->values() ;
359 const T*newVal = newVector->values() ;
360 int numberChanged = 0 ;
361 int i ;
362 for (i = 0 ; i < oldCnt ; i++) {
363 if (oldVal[i] != newVal[i]) {
364 diffNdx[numberChanged] = i ;
365 diffVal[numberChanged++] = newVal[i] ;
366 }
367 }
368 for ( ; i < newCnt ; i++) {
369 diffNdx[numberChanged] = i ;
370 diffVal[numberChanged++] = newVal[i] ;
371 }
372 /*
373 Create the object of our desire.
374 */
375 CoinWarmStartVectorDiff<T> *diff =
376 new CoinWarmStartVectorDiff<T>(numberChanged,diffNdx,diffVal) ;
377 /*
378 Clean up and return.
379 */
380 delete[] diffNdx ;
381 delete[] diffVal ;
382
383 return diff;
384 // return (dynamic_cast<CoinWarmStartDiff<T>*>(diff)) ;
385}
386
387
388/*
389 Apply diff to this warm start.
390
391 Update this warm start by applying diff. It's assumed that the
392 allocated capacity of the warm start is sufficiently large.
393*/
394
395template <typename T> void
396CoinWarmStartVector<T>::applyDiff (const CoinWarmStartDiff *const cwsdDiff)
397{
398 /*
399 Make sure we have a CoinWarmStartVectorDiff
400 */
401 const CoinWarmStartVectorDiff<T>* diff =
402 dynamic_cast<const CoinWarmStartVectorDiff<T>*>(cwsdDiff) ;
403 if (!diff) {
404 throw CoinError("Diff not derived from CoinWarmStartVectorDiff.",
405 "applyDiff","CoinWarmStartVector") ;
406 }
407 /*
408 Application is by straighforward replacement of words in the vector vector.
409 */
410 const int numberChanges = diff->sze_ ;
411 const unsigned int *diffNdxs = diff->diffNdxs_ ;
412 const T* diffVals = diff->diffVals_ ;
413 T* vals = this->values_ ;
414
415 for (int i = 0 ; i < numberChanges ; i++) {
416 unsigned int diffNdx = diffNdxs[i] ;
417 T diffVal = diffVals[i] ;
418 vals[diffNdx] = diffVal ;
419 }
420}
421
422//#############################################################################
423
424
425// Assignment
426
427template <typename T> CoinWarmStartVectorDiff<T>&
428CoinWarmStartVectorDiff<T>::operator=(const CoinWarmStartVectorDiff<T> &rhs)
429{
430 if (this != &rhs) {
431 if (sze_ > 0) {
432 delete[] diffNdxs_ ;
433 delete[] diffVals_ ;
434 }
435 sze_ = rhs.sze_ ;
436 if (sze_ > 0) {
437 diffNdxs_ = new unsigned int[sze_] ;
438 memcpy(diffNdxs_,rhs.diffNdxs_,sze_*sizeof(unsigned int)) ;
439 diffVals_ = new T[sze_] ;
440 memcpy(diffVals_,rhs.diffVals_,sze_*sizeof(T)) ;
441 } else {
442 diffNdxs_ = 0 ;
443 diffVals_ = 0 ;
444 }
445 }
446
447 return (*this) ;
448}
449
450
451// Copy constructor
452
453template <typename T>
454CoinWarmStartVectorDiff<T>::CoinWarmStartVectorDiff(const CoinWarmStartVectorDiff<T> &rhs)
455 : sze_(rhs.sze_),
456 diffNdxs_(nullptr),
457 diffVals_(0)
458{
459 if (sze_ > 0) {
460 diffNdxs_ = new unsigned int[sze_] ;
461 memcpy(diffNdxs_,rhs.diffNdxs_,sze_*sizeof(unsigned int)) ;
462 diffVals_ = new T[sze_] ;
463 memcpy(diffVals_,rhs.diffVals_,sze_*sizeof(T)) ;
464 }
465}
466
467/// Standard constructor
468
469template <typename T>
470CoinWarmStartVectorDiff<T>::CoinWarmStartVectorDiff
471(int sze, const unsigned int *const diffNdxs, const T *const diffVals)
472 : sze_(sze),
473 diffNdxs_(nullptr),
474 diffVals_(0)
475{
476 if (sze > 0) {
477 diffNdxs_ = new unsigned int[sze] ;
478 memcpy(diffNdxs_,diffNdxs,sze*sizeof(unsigned int)) ;
479 diffVals_ = new T[sze] ;
480 memcpy(diffVals_,diffVals,sze*sizeof(T)) ;
481 }
482}
483
484#endif
485