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