Initialize.h
Go to the documentation of this file.
1 /*!
2  * \brief Easy initialization of vectors
3  *
4  * \author O.Krause, T.Glasmachers
5  * \date 2010-2011
6  *
7  * \par Copyright (c) 1998-2007:
8  * Institut f&uuml;r Neuroinformatik<BR>
9  * Ruhr-Universit&auml;t Bochum<BR>
10  * D-44780 Bochum, Germany<BR>
11  * Phone: +49-234-32-25558<BR>
12  * Fax: +49-234-32-14209<BR>
13  * eMail: Shark-admin@neuroinformatik.ruhr-uni-bochum.de<BR>
14  * www: http://www.neuroinformatik.ruhr-uni-bochum.de<BR>
15  * <BR>
16  *
17  *
18  * <BR><HR>
19  * This file is part of Shark. This library is free software;
20  * you can redistribute it and/or modify it under the terms of the
21  * GNU General Public License as published by the Free Software
22  * Foundation; either version 3, or (at your option) any later version.
23  *
24  * This library is distributed in the hope that it will be useful,
25  * but WITHOUT ANY WARRANTY; without even the implied warranty of
26  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27  * GNU General Public License for more details.
28  *
29  * You should have received a copy of the GNU General Public License
30  * along with this library; if not, see <http://www.gnu.org/licenses/>.
31  *
32  */
33 //===========================================================================
34 #ifndef SHARK_LINALG_IMPL_INITIALIZE_H
35 #define SHARK_LINALG_IMPL_INITIALIZE_H
36 
37 #include <shark/Core/Exception.h>
40 #include <iterator>
41 #include <boost/type_traits/remove_reference.hpp>
42 namespace shark{
43 namespace detail{
44 
45 //The following looks a bit complicated and in fact, there ARE easier solutions.
46 //However, i wanted to be able to check the sizes in debug. and this is only possible if you know
47 //1) how big the whole sequence a,b,c is
48 //2) that c is the last element.
49 //also 3) i wanted to prevent init(vec),a,b,c as initialization abuse and instead force init(vec)<<a,b,c
50 //without 1-3, one would only need to pass pointers around and just increment them at every call of operator<< or ,
51 
52 //so how does it work?
53 //when the user writes an expression like init(vec)<<a,b,c; the operators creates a complex template type which is a tree form of the expression.
54 //every operator forms a node of the tree and the arguments are the leaves. During evaluation, the tree is traversed recursively to initialize or split the vector.
55 //Construction of the TreeType: it is just a nested template where operators are represented by a Type InitializerNode<left,right>
56 //depending of the Type of the Argument, the Type of the leaf is chosen. so if a is a vector and b and c are doubles, we get something similar to
57 //Node<Node<InitializerEnd,VectorExpression >,Scalar<double> >,Scalar<double> > where InitializerEnd marks the end of the expression.
58 
59 //sometimes a wrapper is constructed using calls like vectors(). In this case, the Wrappers all have a common base class Initialize<T>, where
60 //T is the own type. e.g. class A:public Initialized<A>{}; Using this technique, only one operator overload is needed for all wrappers since the compiler
61 //will choose the version which takes canst Initializes<T>& as argument.
62 
63 ///\brief Wrapper to enable argument dependent lookup for ublas vectors in shark namespace.
64 ///
65 ///Without, the compiler is not able to find the correct operator overload. We create it using init(Vector)
66 template<class T>
67 struct ADLVector{
68  T vector;
69  ADLVector(T vector):vector(vector){}
70 };
71 
72 
73 //We implement first some wrappers which handle the different types of expressions which can be used.
74 
75 //implementation detail:
76 //there exists a convention in ublas, that only const iterators of sparse vectors are sparse, while mutable iterators
77 //iterate over all elements. This is only documented on their mailing list.
78 //so in the following...200 lines of code we will always iterate using the const iterators and use the indices when the values need to be changed.
79 
80 
81 //the following types are basic wrappers which linearizes their arguments for initialization with init()
82 //or split their part from the big vector using split(). They form the leaves of the expression-tree.
83 //Additionally they have a size element, which is used to calculate the size of the complete right side expression in debug mode
84 
85 ///\brief Wrapper representing a single arithmetic value.
86 template<class T>
87 class Scalar{
88 private:
89  T& m_value;
90 public:
91  Scalar(T& value):m_value(value){}
92  template<class Iter>
93  void init(Iter& pos)const{
94  *pos = m_value;
95  ++pos;
96  }
97  template<class Iter>
98  void split(Iter& pos){
99  m_value = *pos;
100  ++pos;
101  }
102  std::size_t size()const{
103  return 1;
104  }
105 };
106 
107 ///\brief Expression template as base class for all initializer expressions.
108 template<class Self>
110  Self& operator()(){
111  return static_cast<Self&>(*this);
112  }
113  const Self& operator()()const{
114  return static_cast<const Self&>(*this);
115  }
116 };
117 
118 ///\brief Wrapper for all kinds of vectorexpression which saves the (sparse) vector in the target vector.
119 template<class Expression>
120 class VectorExpression :public InitializerBase<VectorExpression<Expression> >{
121 private:
122  Expression m_expression;
123  typedef typename boost::remove_reference<Expression>::type::const_iterator IndexIterator;
124 public:
125  VectorExpression(Expression expression):m_expression(expression){}
126  template<class Iter>
127  void init(Iter& pos)const{
128  for(IndexIterator vecPos = m_expression.begin(); vecPos != m_expression.end();++vecPos, ++pos){
129  *pos = *vecPos;
130  }
131  }
132  template<class Iter>
133  void split(Iter& pos){
134  for(IndexIterator vecPos = m_expression.begin(); vecPos != m_expression.end();++vecPos, ++pos){
135  m_expression(vecPos.index()) = *pos;
136  }
137  }
138  std::size_t size()const{
139  IndexIterator begin = m_expression.begin();
140  IndexIterator end = m_expression.end();
141  return std::distance(begin,end);
142  }
143 };
144 
145 ///\brief Wrapper for all kinds of matrix expressions which saves the (sparse) matrix row by row in the target vector.
146 template<class Matrix>
147 class MatrixExpression:public InitializerBase<MatrixExpression<Matrix> >{
148 private:
149  Matrix& m_matrix;
150  typedef typename Matrix::const_iterator1 Iterator;
151  typedef typename Matrix::const_iterator2 IndexIterator;
152 public:
153  MatrixExpression(Matrix& matrix):m_matrix(matrix){}
154  template<class Iter>
155  void init(Iter& pos)const{
156  for(Iterator outer = m_matrix.begin1(); outer != m_matrix.end1(); ++outer){
157  for(IndexIterator inner = outer.begin(); inner != outer.end(); ++inner,++pos){
158  *pos = *inner;
159  }
160  }
161  }
162  template<class Iter>
163  void split(Iter& pos){
164  for(Iterator outer = m_matrix.begin1(); outer != m_matrix.end1(); ++outer){
165  for(IndexIterator inner = outer.begin(); inner != outer.end(); ++inner,++pos){
166  m_matrix(inner.index1(),inner.index2()) = *pos;
167  }
168  }
169  }
170  std::size_t size()const{
171  std::size_t elements = 0;
172  for(Iterator pos = m_matrix.begin1(); pos != m_matrix.end1(); ++pos){
173  IndexIterator pos1Iter=pos.begin();
174  IndexIterator pos2Iter=pos.end();
175  elements += std::distance(pos1Iter,pos2Iter);
176  }
177  return elements;
178  }
179 };
180 
181 ///\brief Wrapps a parametrizable Object so that it can be used to initialize or split a vector
182 template<class T>
183 class ParameterizableExpression :public InitializerBase<ParameterizableExpression<T> >{
184 private:
185  T& m_parameterizable;
186 public:
187  ParameterizableExpression(T& parameterizable):m_parameterizable(parameterizable){}
188  template<class Iter>
189  void init(Iter& pos)const{
190  RealVector parameters = m_parameterizable.parameterVector();
191  VectorExpression<RealVector&> vectorWriter(parameters);
192  vectorWriter.init(pos);
193  }
194  template<class Iter>
195  void split(Iter& pos){
196  RealVector parameters(size());
197  VectorExpression<RealVector&> vectorWriter(parameters);
198  vectorWriter.split(pos);
199  m_parameterizable.setParameterVector(parameters);
200  }
201  std::size_t size()const{
202  return m_parameterizable.numberOfParameters();
203  }
204 };
205 ///\brief Wrapps a pointer to a parametrizable Object so that it can be used to initialize or split a vector
206 template<class T>
208 private:
209  T* m_parameterizable;
210 public:
211  ParameterizableExpression(T* parameterizable):m_parameterizable(parameterizable){}
212  template<class Iter>
213  void init(Iter& pos)const{
214  RealVector parameters = m_parameterizable->parameterVector();
215  VectorExpression<RealVector&> vectorWriter(parameters);
216  vectorWriter.init(pos);
217  }
218  template<class Iter>
219  void split(Iter& pos){
220  RealVector parameters(size());
221  VectorExpression<RealVector&> vectorWriter(parameters);
222  vectorWriter.split(pos);
223  m_parameterizable->setParameterVector(parameters);
224  }
225  std::size_t size()const{
226  return m_parameterizable->numberOfParameters();
227  }
228 };
229 
230 template<class T>
232 private:
233  T* m_parameterizable;
234 public:
235  ParameterizableExpression(T* parameterizable):m_parameterizable(parameterizable){}
236  template<class Iter>
237  void init(Iter& pos)const{
238  RealVector parameters = m_parameterizable->parameterVector();
239  VectorExpression<RealVector&> vectorWriter(parameters);
240  vectorWriter.init(pos);
241  }
242  template<class Iter>
243  void split(Iter& pos){
244  RealVector parameters(size());
245  VectorExpression<RealVector&> vectorWriter(parameters);
246  vectorWriter.split(pos);
247  m_parameterizable->setParameterVector(parameters);
248  }
249  std::size_t size()const{
250  return m_parameterizable->numberOfParameters();
251  }
252 };
253 
254 ///\brief Wrapper representing a range of vectors or matrices like std::vector<RealVector> or std::list<SparseRealMatrix>.
255 ///
256 ///The first template parameter is the iterator of the range, the second is a wrapper which handles the write or split
257 ///operation for the underlying type. for a vector it would be VectorExpression.
258 template<class Iterator,class Wrapper>
259 class InitializerRange:public InitializerBase<InitializerRange<Iterator,Wrapper> >{
260 private:
261  Iterator m_begin;
262  Iterator m_end;
263  //if Iterator is a const_iterator of a container, we must get the const value type
264  //the only way to get the reference, which is in the case of const iterator
265  //const value_type& and remove the reference part
266  //this is done using remove_reference
267  //typedef typename boost::remove_reference<typename Iterator::reference>::type value_type;
268 public:
269  InitializerRange(Iterator begin,Iterator end):m_begin(begin),m_end(end){}
270  template<class Iter>
271  void init(Iter& pos)const{
272  for(Iterator elem = m_begin; elem!= m_end; ++elem){
273  Wrapper writer(*elem);
274  writer.init(pos);
275  }
276  }
277  template<class Iter>
278  void split(Iter& pos){
279  for(Iterator elem= m_begin; elem!= m_end; ++elem){
280  Wrapper vectorWriter(*elem);
281  vectorWriter.split(pos);
282  }
283  }
284  std::size_t size()const{
285  std::size_t elements = 0;
286  for(Iterator elem = m_begin; elem != m_end; ++elem){
287  Wrapper vectorWriter(*elem);
288  elements += vectorWriter.size();
289  }
290  return elements;
291  }
292 };
293 
294 //The following types are not used as right hand side argument in the expression, so they don't need the base class
295 
296 ///\brief Marks the end of the initializer list template.
298  template<class Iterator>
299  void init(Iterator& pos)const{}
300 
301  template<class Iterator>
302  void split(Iterator& pos){}
303 
304  std::size_t size()const{
305  return 0;
306  }
307 };
308 
309 ///\brief The InitializerNode can initialize a vector on the basis of multiple vector or scalar expressions.
310 ///
311 ///It can be used to construct a big vector out of several small ones or even single values .
312 ///Alternatively, it can split a big vector in several smaller ones.
313 ///VectorInitializer< VectorInitializer< InitializerEnd, A >, B > represents the vector (A,B)
314 template<class Parent, class Expression>
316 private:
317  Parent m_parent;
318  Expression m_expression;
319 public:
320  InitializerNode(const Parent& parent, Expression expression)
321  :m_parent(parent),m_expression(expression){}
322 
323  ///initializes the range [pos,pos+size()] with the vector (Parent,Expression)
324  template<class Iterator>
325  void init(Iterator& pos)const{
326  m_parent.init(pos);
327  m_expression.init(pos);
328  }
329 
330  ///writes the contents of the iterator into the stored expression so that is split into (Parent,Expression)
331  template<class Iterator>
332  void split(Iterator& pos){
333  m_parent.split(pos);
334  m_expression.split(pos);
335  }
336  ///this is used only while debugging the program to ensure, that there occurs no size mismatch during initialization.
337  std::size_t size()const{
338  return m_parent.size()+m_expression.size();
339  }
340 };
341 
342 //Unfortunately, due to the heterogenity of the arguments, a lot of defines need to be used to prevent double or trippling code
343 //==================CREATION OF BIG VECTORS FROM SMALL ONES============================
344 
345 
346 ///\brief VectorInitializer takes a Vector and an initialization expression to initialize the vector during destruction.
347 ///
348 ///Since we later recursively define the initialization sequence, the initialization can be disabled.
349 template<class VectorExpression,class InitExpression>
351 private:
352  InitExpression m_expression;///<expression which initializes the vector
353  mutable bool m_init;///<disables the initialization on destruction when set to false
354 public:
355  //can't be private
357 
358  VectorInitializer(VectorExpression vector,const InitExpression& expression)
359  :m_expression(expression), m_vector(vector) {
360  m_init = true;
361  }
362  ///if another initializer is constructed on the basis of this, than we disable it to
363  ///prevent double initialization
364  void disable()const{
365  m_init=false;
366  }
367  ///returns the internal initialization expression
368  const InitExpression& expression()const{
369  return m_expression;
370  }
371  ///the destructor initializes the vector
373  if(m_init){
374  SIZE_CHECK(m_vector.size() == m_expression.size());
375  typename boost::remove_reference<VectorExpression>::type::iterator iter = m_vector.begin();
376  m_expression.init(iter);
377  }
378  }
379 };
380 
381 
382 //Operator<< to begin the expression vec<<a
383 #define SHARK_INIT_INIT(Type,Argument)\
384 template<class Sink,class Source>\
385 VectorInitializer<Sink,InitializerNode<InitializerEnd, Type> > operator<<(const ADLVector<Sink>& sink,const Argument& source){\
386  typedef InitializerNode<InitializerEnd,Type > Init;\
387  return VectorInitializer<Sink, Init>(sink.vector,Init(InitializerEnd(),source()));\
388 }
389 ///\brief Begins the initialization argument with a vector as first right hand side argument.
390 SHARK_INIT_INIT(VectorExpression<const Source&>,shark::blas::vector_expression<Source>)
391 ///\brief Begins the initialization argument with a arbitrary source as first right hand side argument.
392 SHARK_INIT_INIT(Source,InitializerBase<Source>)
393 #undef SHARK_INIT_INIT
394 
395 ///\brief Begins the initialization sequence with a single scalar value.
396 template<class Sink>
397 VectorInitializer<Sink,InitializerNode<InitializerEnd,Scalar<const typename Sink::value_type> > >
398 operator<<(const ADLVector<Sink>& sink,const typename Sink::value_type& value){
400  return VectorInitializer<Sink,Init>(sink.vector,Init(InitializerEnd(),value));
401 }
402 template<class Sink>
403 VectorInitializer<Sink&,InitializerNode<InitializerEnd,Scalar<const typename Sink::value_type> > >
404 operator<<(const ADLVector<Sink&>& sink,const typename Sink::value_type& value){
406  return VectorInitializer<Sink&,Init>(sink.vector,Init(InitializerEnd(),value));
407 }
408 //operator, to complete it: vec<<a,b,c;
409 //every operator comma disables the old VectoInitializer to prevent that objects get initialized twice.
410 
411 #define SHARK_INIT_COMMA(Type, Argument)\
412 template<class Sink,class Init,class Source>\
413 VectorInitializer<Sink,InitializerNode<Init,Type > > operator,(const VectorInitializer<Sink,Init >& init,const Argument& vec){\
414  init.disable();\
415  typedef InitializerNode<Init,Type > newExpression;\
416  return VectorInitializer<Sink, newExpression>(init.m_vector,newExpression(init.expression(),vec()));\
417 }
418 ///\brief Appends a single vector expression c to the expression vec<<a,b -> vec<<a,b,c.
419 SHARK_INIT_COMMA(VectorExpression<const Source&>,shark::blas::vector_expression<Source>)
420 ///\brief Appends a initialization expression c to the expression vec<<a,b -> vec<<a,b,c.
421 SHARK_INIT_COMMA(Source,InitializerBase<Source>)
422 #undef SHARK_INIT_COMMA
423 
424 ///\brief Operator comma concatenates more vectors and values for initialization.
425 ///
426 ///Special case forsingle values.
427 template<class Sink,class Init>
428 VectorInitializer<Sink,InitializerNode<Init,Scalar<const typename Sink::value_type> > >
429 operator,(const VectorInitializer<Sink,Init >& init,const typename Sink::value_type& value){
430  init.disable();//we don't need it anymore for initialization
432  return VectorInitializer<Sink, newExpression>(init.m_vector,newExpression(init.expression(),value));
433 }
434 template<class Sink,class Init>
435 VectorInitializer<Sink&,InitializerNode<Init,Scalar<const typename Sink::value_type> > >
436 operator,(const VectorInitializer<Sink&,Init >& init,const typename Sink::value_type& value){
437  init.disable();//we don't need it anymore for initialization
439  return VectorInitializer<Sink&, newExpression>(init.m_vector,newExpression(init.expression(),value));
440 }
441 //=====================SPLITTING OF A VECTOR IN SEVERAL SMALLER ONES===========================
442 
443 //the same stuff again, only for splitting...
444 
445 ///\brief VectorSplitter takes a Vector and a mutable initialization expression to split the vector during destruction.
446 ///
447 ///Since we later recursively define the initialization sequence, the splitting can be disabled.
448 template<class VectorExpression,class SplittingExpression>
450 private:
451  SplittingExpression m_expression;///<expression which splits the vector
452  mutable bool m_init;///<disables the splitting on destruction when set to false
453 public:
454  //can't be private
456 
457  VectorSplitter(VectorExpression vector,const SplittingExpression& expression)
458  :m_expression(expression), m_vector(vector){
459  m_init = true;
460  }
461  ///if another initializer is constructed on the basis of this, than we disable it to
462  ///prevent double initialization
463  void disable()const{
464  m_init=false;
465  }
466  ///returns the internal initialization expression
467  const SplittingExpression& expression()const{
468  return m_expression;
469  }
470  ///the destructor initializes the vector
472  if(m_init){
473  SIZE_CHECK(m_vector.size() == m_expression.size());
474  typename boost::remove_reference<VectorExpression>::type::const_iterator iter = m_vector.begin();
475  m_expression.split(iter);
476  }
477  }
478 };
479 
480 //operator <<
481 #define SHARK_SPLIT_INIT(Type,Argument)\
482 template<class Source,class Sink>\
483 VectorSplitter<Source,InitializerNode<InitializerEnd, Type> >\
484 operator>>(const ADLVector<Source>& source,Argument& sink){\
485  typedef InitializerNode<InitializerEnd,Type > Init;\
486  return VectorSplitter<Source, Init>(source.vector,Init(InitializerEnd(),sink()));\
487 }
488 ///\brief Appends a single mutable vector expression.
490 ///\brief Appends an arbitrary source.
491 SHARK_SPLIT_INIT(Sink,const InitializerBase<Sink>)
492 #undef SHARK_SPLIT_INIT
493 
494 ///\brief Appends a single variable.
495 template<class Sink>
496 VectorSplitter<Sink,InitializerNode<InitializerEnd,Scalar<typename Sink::value_type> > >
497 operator>>(const ADLVector<Sink>& sink,typename Sink::value_type& value){
499  return VectorSplitter<Sink,Init>(sink.vector,Init(InitializerEnd(),value));
500 }
501 template<class Sink>
502 VectorSplitter<Sink&,InitializerNode<InitializerEnd,Scalar<typename Sink::value_type> > >
503 operator>>(const ADLVector<Sink&>& sink,typename Sink::value_type& value){
505  return VectorSplitter<Sink&,Init>(sink.vector,Init(InitializerEnd(),value));
506 }
507 //version for vector proxies...
508 #define SHARK_SPLIT_PROXY_INIT(Argument)\
509 template<class Source,class Sink>\
510 VectorSplitter<Source,InitializerNode<InitializerEnd, VectorExpression<Argument> > >\
511 operator>>(const ADLVector<Source>& source,Argument sink){\
512  typedef InitializerNode<InitializerEnd,VectorExpression<Argument> > Init;\
513  return VectorSplitter<Source, Init>(source.vector,Init(InitializerEnd(),sink));\
514 }
515 ///\brief Appends a single mutable vector expression.
517 ///\brief Appends a matrix row.
518 SHARK_SPLIT_PROXY_INIT(shark::blas::matrix_row<Sink>)
519 ///\brief Appends a matrix column.
520 SHARK_SPLIT_PROXY_INIT(shark::blas::matrix_column<Sink>)
521 #undef SHARK_SPLIT_PROXY_INIT
522 
523 
524 //operator,
525 ///\brief Appends a single vector expression.
526 template<class Source,class Init,class Sink>
527 VectorSplitter<Source,InitializerNode<Init,VectorExpression<Sink&> > >
529  source.disable();
530  typedef InitializerNode<Init,VectorExpression<Sink&> > newExpression;
531  return VectorSplitter<Source, newExpression>(source.m_vector,newExpression(source.expression(),vec()));
532 }
533 ///\brief Appends a initialization expression.
534 template<class Source,class Init,class Sink>
535 VectorSplitter<Source,InitializerNode<Init,Sink > >
537  source.disable();
538  typedef InitializerNode<Init,Sink > newExpression;
539  return VectorSplitter<Source, newExpression>(source.m_vector,newExpression(source.expression(),vec()));
540 }
541 
542 ///\brief Operator comma adds another value for splitting.
543 template<class Source,class Init>
544 VectorSplitter<Source,InitializerNode<Init,Scalar<typename Source::value_type> > >
545 operator,(const VectorSplitter<Source,Init >& source,typename Source::value_type& value){
546  source.disable();//we don't need it anymore for initialization
548  return VectorSplitter<Source, newExpression>(source.m_vector,newExpression(source.expression(),value));
549 }
550 template<class Source,class Init>
551 VectorSplitter<Source&,InitializerNode<Init,Scalar<typename Source::value_type> > >
552 operator,(const VectorSplitter<Source&,Init >& source,typename Source::value_type& value){
553  source.disable();//we don't need it anymore for initialization
555  return VectorSplitter<Source&, newExpression>(source.m_vector,newExpression(source.expression(),value));
556 }
557 #define SHARK_SPLIT_PROXY_COMMA(Argument)\
558 template<class Source,class Init,class Sink>\
559 VectorSplitter<Source,InitializerNode<Init,VectorExpression<Argument> > >\
560 operator,(const VectorSplitter<Source,Init >& source, Argument vec){\
561  source.disable();\
562  typedef InitializerNode<Init,VectorExpression<Argument> > newExpression;\
563  return VectorSplitter<Source, newExpression>(source.m_vector,newExpression(source.expression(),vec));\
564 }
566 SHARK_SPLIT_PROXY_COMMA(shark::blas::matrix_row<Sink>)
567 SHARK_SPLIT_PROXY_COMMA(shark::blas::matrix_column<Sink>)
568 #undef SHARK_SPLIT_PROXY_COMMA
569 
570 }}
571 
572 #endif