ROL
ROL_PartitionedVector.hpp
Go to the documentation of this file.
1 // @HEADER
2 // ************************************************************************
3 //
4 // Rapid Optimization Library (ROL) Package
5 // Copyright (2014) Sandia Corporation
6 //
7 // Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive
8 // license for use of this work by or on behalf of the U.S. Government.
9 //
10 // Redistribution and use in source and binary forms, with or without
11 // modification, are permitted provided that the following conditions are
12 // met:
13 //
14 // 1. Redistributions of source code must retain the above copyright
15 // notice, this list of conditions and the following disclaimer.
16 //
17 // 2. Redistributions in binary form must reproduce the above copyright
18 // notice, this list of conditions and the following disclaimer in the
19 // documentation and/or other materials provided with the distribution.
20 //
21 // 3. Neither the name of the Corporation nor the names of the
22 // contributors may be used to endorse or promote products derived from
23 // this software without specific prior written permission.
24 //
25 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
26 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
28 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
29 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
30 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
31 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
32 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
33 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
34 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
35 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 //
37 // Questions? Contact lead developers:
38 // Drew Kouri (dpkouri@sandia.gov) and
39 // Denis Ridzal (dridzal@sandia.gov)
40 //
41 // ************************************************************************
42 // @HEADER
43 
44 #include "ROL_Vector.hpp"
45 
46 #include <initializer_list>
47 
48 #ifndef ROL_PARTITIONED_VECTOR_H
49 #define ROL_PARTITIONED_VECTOR_H
50 
57 namespace ROL {
58 
59 template<class Real>
60 class PartitionedVector : public Vector<Real> {
61 
62  typedef Vector<Real> V;
63  typedef ROL::Ptr<V> Vp;
65 
66 private:
67  const std::vector<Vp> vecs_;
68  mutable std::vector<Vp> dual_vecs_;
69  mutable ROL::Ptr<PV> dual_pvec_;
70 public:
71 
73 
74  PartitionedVector( const std::vector<Vp> &vecs ) : vecs_(vecs) {
75  for( size_type i=0; i<vecs_.size(); ++i ) {
76  dual_vecs_.push_back((vecs_[i]->dual()).clone());
77  }
78  }
79 
80  void set( const V &x ) {
81  const PV &xs = dynamic_cast<const PV&>(x);
82  ROL_TEST_FOR_EXCEPTION( numVectors() != xs.numVectors(),
83  std::invalid_argument,
84  "Error: Vectors must have the same number of subvectors." );
85  for( size_type i=0; i<vecs_.size(); ++i ) {
86  vecs_[i]->set(*xs.get(i));
87  }
88  }
89 
90  void plus( const V &x ) {
91  const PV &xs = dynamic_cast<const PV&>(x);
92  ROL_TEST_FOR_EXCEPTION( numVectors() != xs.numVectors(),
93  std::invalid_argument,
94  "Error: Vectors must have the same number of subvectors." );
95  for( size_type i=0; i<vecs_.size(); ++i ) {
96  vecs_[i]->plus(*xs.get(i));
97  }
98  }
99 
100  void scale( const Real alpha ) {
101  for( size_type i=0; i<vecs_.size(); ++i ) {
102  vecs_[i]->scale(alpha);
103  }
104  }
105 
106  void axpy( const Real alpha, const V &x ) {
107  const PV &xs = dynamic_cast<const PV&>(x);
108  ROL_TEST_FOR_EXCEPTION( numVectors() != xs.numVectors(),
109  std::invalid_argument,
110  "Error: Vectors must have the same number of subvectors." );
111 
112  for( size_type i=0; i<vecs_.size(); ++i ) {
113  vecs_[i]->axpy(alpha,*xs.get(i));
114  }
115  }
116 
117  Real dot( const V &x ) const {
118  const PV &xs = dynamic_cast<const PV&>(x);
119  ROL_TEST_FOR_EXCEPTION( numVectors() != xs.numVectors(),
120  std::invalid_argument,
121  "Error: Vectors must have the same number of subvectors." );
122  Real result = 0;
123  for( size_type i=0; i<vecs_.size(); ++i ) {
124  result += vecs_[i]->dot(*xs.get(i));
125  }
126  return result;
127  }
128 
129  Real norm() const {
130  Real result = 0;
131  for( size_type i=0; i<vecs_.size(); ++i ) {
132  result += std::pow(vecs_[i]->norm(),2);
133  }
134  return std::sqrt(result);
135  }
136 
137  Vp clone() const {
138  std::vector<Vp> clonevec;
139  for( size_type i=0; i<vecs_.size(); ++i ) {
140  clonevec.push_back(vecs_[i]->clone());
141  }
142  return ROL::makePtr<PV>(clonevec);
143  }
144 
145  const V& dual(void) const {
146  for( size_type i=0; i<vecs_.size(); ++i ) {
147  dual_vecs_[i]->set(vecs_[i]->dual());
148  }
149  dual_pvec_ = ROL::makePtr<PV>( dual_vecs_ );
150  return *dual_pvec_;
151  }
152 
153  Real apply(const Vector<Real> &x) const {
154  const PV &xs = dynamic_cast<const PV&>(x);
155  ROL_TEST_FOR_EXCEPTION( numVectors() != xs.numVectors(),
156  std::invalid_argument,
157  "Error: Vectors must have the same number of subvectors." );
158  Real result = 0;
159  for( size_type i=0; i<vecs_.size(); ++i ) {
160  result += vecs_[i]->apply(*xs.get(i));
161  }
162  return result;
163  }
164 
165  Vp basis( const int i ) const {
166  ROL_TEST_FOR_EXCEPTION( i >= dimension() || i<0,
167  std::invalid_argument,
168  "Error: Basis index must be between 0 and vector dimension." );
169  Vp bvec = clone();
170  // Downcast
171  PV &eb = dynamic_cast<PV&>(*bvec);
172 
173  // Iterate over subvectors
174  int begin = 0, end = 0;
175  for( size_type j=0; j<vecs_.size(); ++j ) {
176  end += vecs_[j]->dimension();
177  if( begin<= i && i<end ) {
178  eb.set(j, *(vecs_[j]->basis(i-begin)) );
179  }
180  else {
181  eb.zero(j);
182  }
183  begin = end;
184  }
185  return bvec;
186  }
187 
188  int dimension() const {
189  int total_dim = 0;
190  for( size_type j=0; j<vecs_.size(); ++j ) {
191  total_dim += vecs_[j]->dimension();
192  }
193  return total_dim;
194  }
195 
196  void zero() {
197  for( size_type j=0; j<vecs_.size(); ++j ) {
198  vecs_[j]->zero();
199  }
200  }
201 
202  // Apply the same unary function to each subvector
203  void applyUnary( const Elementwise::UnaryFunction<Real> &f ) {
204  for( size_type i=0; i<vecs_.size(); ++i ) {
205  vecs_[i]->applyUnary(f);
206  }
207  }
208 
209  // Apply the same binary function to each pair of subvectors in this vector and x
210  void applyBinary( const Elementwise::BinaryFunction<Real> &f, const V &x ) {
211  const PV &xs = dynamic_cast<const PV&>(x);
212 
213  for( size_type i=0; i<vecs_.size(); ++i ) {
214  vecs_[i]->applyBinary(f,*xs.get(i));
215  }
216  }
217 
218  Real reduce( const Elementwise::ReductionOp<Real> &r ) const {
219  Real result = r.initialValue();
220 
221  for( size_type i=0; i<vecs_.size(); ++i ) {
222  r.reduce(vecs_[i]->reduce(r),result);
223  }
224  return result;
225  }
226 
227  void setScalar( const Real C ) {
228  for (size_type i=0; i<vecs_.size(); ++i) {
229  vecs_[i]->setScalar(C);
230  }
231  }
232 
233  void randomize( const Real l = 0.0, const Real u = 1.0 ) {
234  for (size_type i=0; i<vecs_.size(); ++i) {
235  vecs_[i]->randomize(l,u);
236  }
237  }
238 
239  void print( std::ostream &outStream ) const {
240  for( size_type i=0; i<vecs_.size(); ++i ) {
241  outStream << "V[" << i << "]: ";
242  vecs_[i]->print(outStream);
243  }
244  }
245 
246  // Methods that do not exist in the base class
247  const Vector<Real>& operator[]( size_type i ) const {
248  return *(vecs_[i]);
249  }
250 
252  return *(vecs_[i]);
253  }
254 
255  ROL::Ptr<const Vector<Real> > get(size_type i) const {
256  return vecs_[i];
257  }
258 
259  ROL::Ptr<Vector<Real> > get(size_type i) {
260  return vecs_[i];
261  }
262 
263  void set(size_type i, const V &x) {
264  vecs_[i]->set(x);
265  }
266 
267  void zero(size_type i) {
268  vecs_[i]->zero();
269  }
270 
272  return vecs_.size();
273  }
274 
275 public:
276 
277  // Make a new PartitionedVector from an initializer_list of pointers to vectors
278  static Ptr<PartitionedVector> create( std::initializer_list<Vp> vs ) {
279  std::vector<Vp> subvecs{vs};
280  return ROL::makePtr<PartitionedVector>( subvecs );
281  }
282 
283  // Make a new PartitionedVector by cloning the given vector N times
284  static Ptr<PartitionedVector> create( const V& x, size_type N ) {
285  std::vector<Vp> subvecs(N);
286  for( size_type i=0; i<N; ++i ) subvecs.at(i) = x.clone();
287  return ROL::makePtr<PartitionedVector>( subvecs );
288  }
289 
290 };
291 
292 // Helper methods
293 
294 template<typename Real>
296  return static_cast<PartitionedVector<Real>&>(x);
297 }
298 
299 template<typename Real>
300 inline const PartitionedVector<Real>& partition( const Vector<Real>& x ) {
301  return static_cast<const PartitionedVector<Real>&>(x);
302 }
303 
304 template<typename Real>
305 inline Ptr<PartitionedVector<Real>> partition( const Ptr<Vector<Real>>& x ) {
306  return staticPtrCast<PartitionedVector<Real>>(x);
307 }
308 
309 template<typename Real>
310 inline Ptr<const PartitionedVector<Real>> partition( const Ptr<const Vector<Real>>& x ) {
311  return staticPtrCast<const PartitionedVector<Real>>(x);
312 }
313 
314 
315 
316 template<class Real>
317 ROL::Ptr<Vector<Real>>
318 CreatePartitionedVector( const ROL::Ptr<Vector<Real>> &a ) {
319 
320  using Vp = ROL::Ptr<Vector<Real>>;
321  using PV = PartitionedVector<Real>;
322 
323  Vp temp[] = {a};
324  return ROL::makePtr<PV>( std::vector<Vp>(temp, temp+1) );
325 }
326 
327 template<class Real>
328 ROL::Ptr<const Vector<Real> >
329 CreatePartitionedVector( const ROL::Ptr<const Vector<Real>> &a ) {
330 
331  using Vp = ROL::Ptr<const Vector<Real>>;
332  using PV = const PartitionedVector<Real>;
333 
334  Vp temp[] = {a};
335  return ROL::makePtr<PV>( std::vector<Vp>(temp, temp+1) );
336 }
337 
338 template<class Real>
339 ROL::Ptr<Vector<Real>>
341  const ROL::Ptr<Vector<Real>> &b ) {
342  using Vp = ROL::Ptr<Vector<Real>>;
343  using PV = PartitionedVector<Real>;
344 
345  Vp temp[] = {a,b};
346  return ROL::makePtr<PV>( std::vector<Vp>(temp, temp+2) );
347 }
348 
349 template<class Real>
350 ROL::Ptr<const Vector<Real> >
351 CreatePartitionedVector( const ROL::Ptr<const Vector<Real>> &a,
352  const ROL::Ptr<const Vector<Real>> &b ) {
353  using Vp = ROL::Ptr<const Vector<Real>>;
354  using PV = const PartitionedVector<Real>;
355 
356  Vp temp[] = {a,b};
357  return ROL::makePtr<PV>( std::vector<Vp>(temp, temp+2) );
358 }
359 
360 
361 template<class Real>
362 ROL::Ptr<Vector<Real>>
364  const ROL::Ptr<Vector<Real>> &b,
365  const ROL::Ptr<Vector<Real>> &c ) {
366 
367  using Vp = ROL::Ptr<Vector<Real>>;
368  using PV = PartitionedVector<Real>;
369 
370  Vp temp[] = {a,b,c};
371  return ROL::makePtr<PV>( std::vector<Vp>(temp, temp+3) );
372 }
373 
374 template<class Real>
375 ROL::Ptr<const Vector<Real> >
376 CreatePartitionedVector( const ROL::Ptr<const Vector<Real>> &a,
377  const ROL::Ptr<const Vector<Real>> &b,
378  const ROL::Ptr<const Vector<Real>> &c ) {
379 
380  using Vp = ROL::Ptr<const Vector<Real>>;
381  using PV = const PartitionedVector<Real>;
382 
383  Vp temp[] = {a,b,c};
384  return ROL::makePtr<PV>( std::vector<Vp>(temp, temp+3) );
385 }
386 
387 template<class Real>
388 ROL::Ptr<Vector<Real> >
390  const ROL::Ptr<Vector<Real>> &b,
391  const ROL::Ptr<Vector<Real>> &c,
392  const ROL::Ptr<Vector<Real>> &d ) {
393 
394 
395  typedef ROL::Ptr<Vector<Real> > Vp;
396  typedef PartitionedVector<Real> PV;
397 
398  Vp temp[] = {a,b,c,d};
399  return ROL::makePtr<PV>( std::vector<Vp>(temp, temp+4) );
400 }
401 
402 template<class Real>
403 ROL::Ptr<const Vector<Real> >
404 CreatePartitionedVector( const ROL::Ptr<const Vector<Real>> &a,
405  const ROL::Ptr<const Vector<Real>> &b,
406  const ROL::Ptr<const Vector<Real>> &c,
407  const ROL::Ptr<const Vector<Real>> &d ) {
408 
409 
410  using Vp = ROL::Ptr<const Vector<Real>>;
411  using PV = const PartitionedVector<Real>;
412 
413  Vp temp[] = {a,b,c,d};
414  return ROL::makePtr<PV>( std::vector<Vp>(temp, temp+4) );
415 }
416 
417 } // namespace ROL
418 
419 #endif // ROL_PARTITIONED_VECTOR_H
420 
PartitionedVector< Real > & partition(Vector< Real > &x)
PartitionedVector(const std::vector< Vp > &vecs)
static Ptr< PartitionedVector > create(std::initializer_list< Vp > vs)
PartitionedVector< Real > PV
typename PV< Real >::size_type size_type
virtual ROL::Ptr< Vector > clone() const =0
Clone to make a new (uninitialized) vector.
ROL::Ptr< const Vector< Real > > get(size_type i) const
Real norm() const
Returns where .
Defines the linear algebra of vector space on a generic partitioned vector.
ROL::Ptr< Vector< Real > > CreatePartitionedVector(const ROL::Ptr< Vector< Real >> &a)
const V & dual(void) const
Return dual representation of , for example, the result of applying a Riesz map, or change of basis...
Vector< Real > & operator[](size_type i)
void applyBinary(const Elementwise::BinaryFunction< Real > &f, const V &x)
void print(std::ostream &outStream) const
static Ptr< PartitionedVector > create(const V &x, size_type N)
Vp clone() const
Clone to make a new (uninitialized) vector.
Defines the linear algebra or vector space interface.
Definition: ROL_Vector.hpp:80
Real dot(const V &x) const
Compute where .
Real apply(const Vector< Real > &x) const
Apply to a dual vector. This is equivalent to the call .
void zero()
Set to zero vector.
void applyUnary(const Elementwise::UnaryFunction< Real > &f)
void setScalar(const Real C)
Set where .
PartitionedVector< Real > PV
void set(size_type i, const V &x)
void scale(const Real alpha)
Compute where .
int dimension() const
Return dimension of the vector space.
void set(const V &x)
Set where .
Vp basis(const int i) const
Return i-th basis vector.
const Vector< Real > & operator[](size_type i) const
std::vector< PV >::size_type size_type
void randomize(const Real l=0.0, const Real u=1.0)
Set vector to be uniform random between [l,u].
const std::vector< Vp > vecs_
void plus(const V &x)
Compute , where .
Real reduce(const Elementwise::ReductionOp< Real > &r) const
void axpy(const Real alpha, const V &x)
Compute where .