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