KJB
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
prob_weight_array.h
Go to the documentation of this file.
1 /* $Id: prob_weight_array.h 18278 2014-11-25 01:42:10Z ksimek $ */
2 
3 #ifndef PROB_WEIGHT_ARRAY_H_
4 #define PROB_WEIGHT_ARRAY_H_
5 
16 #include "l_cpp/l_exception.h"
17 #include <prob_cpp/prob_util.h>
18 #include <boost/array.hpp>
19 #include <boost/bind.hpp>
20 #include <numeric>
21 #include <algorithm>
22 #include <ostream>
23 #include <cmath>
24 
25 namespace kjb
26 {
28  template<size_t D> class Weight_array;
29 
30  template<size_t D>
31  bool operator==(const Weight_array<D>& left, const Weight_array<D>& right);
32 
33  template<size_t D>
34  bool operator!=(const Weight_array<D>& left, const Weight_array<D>& right);
35 
38  template<size_t D>
39  class Weight_array
40  {
41  public:
43  typedef double Val_type;
44  typedef boost::array<Val_type, D> Data_type;
45  typedef boost::array<bool, D> Filter;
46  typedef typename Data_type::iterator iterator;
47  typedef typename Data_type::const_iterator const_iterator;
48  public:
52  : values_(), total_mass_(0), modified_(true), normalized_(false)
53  {}
54 
57  Weight_array(const Data_type& values)
58  : values_(values),
59  total_mass_(0),
60  modified_(true),
61  normalized_(false)
62  {}
63 
64  template<typename InputIter>
65  Weight_array(InputIter start, InputIter end)
66  : values_(), total_mass_(0), modified_(true), normalized_(false)
67  {
68  std::copy(start, end, values_.begin());
69  }
70 
73  const_iterator cbegin() const {return values_.begin();}
74 
77  const_iterator cend() const {return values_.end();}
78 
83  const_iterator begin() const {return cbegin();}
84 
89  const_iterator end() const {return cend();}
90 
95  iterator begin() {return values_.begin();}
96 
101  iterator end() {return values_.end();}
102 
105  Val_type total_mass() const;
106 
109  Self_t& normalize();
110 
113  Self_t& operator+=(const Self_t& right);
114 
117  Self_t& operator*=(const Self_t& right);
118 
121  Self_t& operator/=(const Self_t& right);
122 
125  Self_t& operator+=(const Val_type& offset);
126 
129  Self_t& operator*=(const Val_type& scale);
130 
133  Self_t& operator/=(const Val_type& scale);
134 
137  Self_t& operator*=(const Filter& filter);
138 
142  const Val_type& operator[](const size_t& position) const;
143 
144  template<size_t M, size_t K>
146  const Weight_array<K>& weights,
147  const boost::array<Weight_array<M>, K>& components
148  );
149  template<size_t M>
150  friend std::ostream& operator<<(
151  std::ostream& os, const Weight_array<M>& wa);
152 
155  friend bool operator==<>(const Self_t& left, const Self_t& right);
156 
159  friend bool operator!=<>(const Self_t& left, const Self_t& right);
160 
161  private:
165  void set_as_normalized()
166  {
167  total_mass_ = 1;
168  modified_ = false;
169  normalized_ = true;
170  }
171 
172  Data_type values_;
173  mutable Val_type total_mass_;
174  mutable bool modified_;
175  bool normalized_;
176  };
177 
179 
180  template<size_t D>
181  Weight_array<D> operator+(
182  const Weight_array<D>& left,
183  const Weight_array<D>& right
184  );
185 
186  template<size_t D>
187  Weight_array<D> operator*(
188  const Weight_array<D>& left,
189  const Weight_array<D>& right
190  );
191 
192  template<size_t D>
193  Weight_array<D> operator/(
194  const Weight_array<D>& left,
195  const Weight_array<D>& right
196  );
197 
198  template<size_t D>
199  Weight_array<D> operator+(
200  const Weight_array<D>& w,
201  const typename Weight_array<D>::Val_type& offset
202  );
203 
204  template<size_t D>
205  Weight_array<D> operator*(
206  const Weight_array<D>& w,
207  const typename Weight_array<D>::Val_type& scale
208  );
209 
210  template<size_t D>
211  Weight_array<D> operator/(
212  const Weight_array<D>& w,
213  const typename Weight_array<D>::Val_type& right
214  );
215 
216  template<size_t D, size_t K>
217  Weight_array<D> convex_combination(
218  const Weight_array<K>& weights,
219  const boost::array<Weight_array<D>, K>& components
220  );
221 
222 
224 
225  template<size_t D>
227  {
228  if(modified_)
229  {
230  total_mass_ = std::accumulate(begin(), end(), 0.0);
231  modified_ = false;
232  }
233  return total_mass_;
234  }
235 
236  template<size_t D>
238  {
239  if(!normalized_)
240  {
241  operator/=(total_mass());
242  set_as_normalized();
243  }
244  return *this;
245  }
246 
247  template<size_t D>
249  const Weight_array<D>& right)
250  {
251  std::transform(
252  begin(), end(), right.begin(), begin(),
253  std::plus<Val_type>()
254  );
255  modified_ = true; normalized_ = false;
256  return *this;
257  }
258 
259  template<size_t D>
261  const Weight_array<D>& right)
262  {
263  std::transform(
264  begin(), end(), right.begin(), begin(),
265  std::multiplies<Val_type>()
266  );
267  modified_ = true; normalized_ = false;
268  return *this;
269  }
270 
271  template<size_t D>
273  const Weight_array<D>& right)
274  {
275  std::transform(
276  begin(), end(), right.begin(), begin(),
277  std::divides<Val_type>()
278  );
279  modified_ = true; normalized_ = false;
280  return *this;
281  }
282 
283  template<size_t D>
285  const typename Weight_array<D>::Val_type& offset
286  )
287  {
288  std::transform(
289  begin(), end(), begin(),
290  boost::bind(std::plus<Val_type>(), _1, offset)
291  );
292  if(modified_ == false) total_mass_ += D*offset;
293  normalized_ = false;
294  return *this;
295  }
296 
297  template<size_t D>
298  Weight_array<D>& Weight_array<D>::operator*=(
299  const typename Weight_array<D>::Val_type& scale
300  )
301  {
302  std::transform(
303  begin(), end(), begin(),
304  boost::bind(std::multiplies<Val_type>(), _1, scale)
305  );
306  if(modified_ == false) total_mass_ *= scale;
307  normalized_ = false;
308  return *this;
309  }
310 
311  template<size_t D>
312  Weight_array<D>& Weight_array<D>::operator/=(
313  const typename Weight_array<D>::Val_type& scale
314  )
315  {
316  std::transform(
317  begin(), end(), begin(),
318  boost::bind(std::divides<Val_type>(), _1, scale)
319  );
320  if(modified_ == false) total_mass_ /= scale;
321  normalized_ = false;
322  return *this;
323  }
324 
325  template<size_t D>
326  Weight_array<D>& Weight_array<D>::operator*=(
327  const typename Weight_array<D>::Filter& filter
328  )
329  {
330  std::transform(
331  begin(), end(), filter.begin(), begin(),
332  boost::bind(std::multiplies<Val_type>(), _1, _2)
333  );
334  modified_ = true;
335  normalized_ = false;
336  return *this;
337  }
338 
339  template<size_t D>
341  const size_t& position
342  ) const
343  {
344  if(!(position < D))
345  {
346  KJB_THROW_2(
348  "Attempted to access nonexistent data position in "
349  "kjb::Weight_array"
350  );
351  }
352  return values_[position];
353  }
354 
356 
357  namespace
358  {
359  template<size_t D>
360  typename Weight_array<D>::Val_type abs_log_ratio(
361  typename Weight_array<D>::Val_type a,
362  typename Weight_array<D>::Val_type b
363  )
364  {
365  return abs(log(a) - log(b));
366  }
367  }
368 
369  template<size_t D>
370  bool operator==(const Weight_array<D>& left, const Weight_array<D>& right)
371  {
372  typedef Weight_array<D> Wt_arr;
373  typedef typename Wt_arr::Val_type Val_t;
374  typedef typename Wt_arr::Data_type Data_t;
375  if(left.total_mass() == 0 && right.total_mass() == 0) return true;
376  if(left.total_mass() == 0 || right.total_mass() == 0) return false;
377  Wt_arr left_normed = left;
378  Wt_arr right_normed = right;
379  left_normed.normalize();
380  right_normed.normalize();
381  Data_t diff_arr ;
382  std::transform(
383  left_normed.begin(), left_normed.end(),
384  right_normed.begin(),
385  diff_arr.begin(),
386  abs_log_ratio<D>
387  );
388  Val_t total_abs_diff =
390  diff_arr.begin(), diff_arr.end(), static_cast<Val_t>(0)
391  );
392  return total_abs_diff < D * 0.0000000000000001;
393  }
394 
395  template<size_t D>
396  bool operator!=(const Weight_array<D>& left, const Weight_array<D>& right)
397  {
398  return !(left == right);
399  }
400 
401  template<size_t D>
403  const Weight_array<D>& left,
404  const Weight_array<D>& right
405  )
406  {
407  Weight_array<D> result = left;
408  result += right;
409  return result;
410  }
411 
412  template<size_t D>
414  const Weight_array<D>& left,
415  const Weight_array<D>& right
416  )
417  {
418  Weight_array<D> result = left;
419  result *= right;
420  return result;
421  }
422 
423  template<size_t D>
425  const Weight_array<D>& left,
426  const Weight_array<D>& right
427  )
428  {
429  Weight_array<D> result = left;
430  result /= right;
431  return result;
432  }
433 
434  template<size_t D>
436  const Weight_array<D>& w,
437  const typename Weight_array<D>::Val_type& offset
438  )
439  {
440  Weight_array<D> result = w;
441  result += offset;
442  return result;
443  };
444 
445  template<size_t D>
447  const Weight_array<D>& w,
448  const typename Weight_array<D>::Val_type& scale
449  )
450  {
451  Weight_array<D> result = w;
452  result *= scale;
453  return result;
454  };
455 
456  template<size_t D>
458  const Weight_array<D>& w,
459  const typename Weight_array<D>::Val_type& normalization
460  )
461  {
462  Weight_array<D> result = w;
463  result /= normalization;
464  return result;
465  };
466 
467  template<size_t D, size_t K>
469  const Weight_array<K>& weights,
470  const boost::array<Weight_array<D>, K>& components
471  )
472  {
473  typedef Weight_array<D> WA;
474  typedef typename WA::Val_type Val_t;
475  WA result;
476  boost::array<WA, K> rescaled_components = components;
477  std::for_each(
478  rescaled_components.begin(), rescaled_components.end(),
479  boost::bind(&WA::normalize, _1)
480  );
481  std::transform(
482  rescaled_components.begin(), rescaled_components.end(),
483  weights.begin(),
484  rescaled_components.begin(),
485  boost::bind(
486  static_cast<WA& (WA::*)(const Val_t&)>(&WA::operator*=),
487  _1, _2
488  )
489  );
490  result =
492  rescaled_components.begin(), rescaled_components.end(),
493  result
494  );
495  result.normalize();
496  return result;
497  }
498 
499  template<size_t D>
500  std::ostream& operator<<(
501  std::ostream& os,
502  const Weight_array<D>& wa
503  )
504  {
505  os << "(";
506  for(typename Weight_array<D>::const_iterator it = wa.begin();
507  it != wa.end(); ++it)
508  {
509  os << (*it) << ",";
510  }
511  os << ")";
512  return os;
513  }
514 
515  template<typename T, size_t D>
516  std::ostream& operator<<(
517  std::ostream& os,
518  const boost::array<T, D>& arr
519  )
520  {
521  os << "(";
522  for(typename boost::array<T,D>::const_iterator it = arr.begin();
523  it != arr.end(); ++it)
524  {
525  os << (*it) << ",";
526  }
527  os << ")";
528  return os;
529  }
530 };//namespace kjb
531 
532 #endif
Weight_array(InputIter start, InputIter end)
Definition: prob_weight_array.h:65
friend std::ostream & operator<<(std::ostream &os, const Weight_array< M > &wa)
double accumulate(const Matrix_d< R, C, T > &mat, double init)
Definition: m_matrix_d.impl.h:432
Weight_array(const Data_type &values)
construct a Weight_array from a value array
Definition: prob_weight_array.h:57
Object thrown when an index argument exceeds the size of a container.
Definition: l_exception.h:399
boost::array< bool, D > Filter
Definition: prob_weight_array.h:45
const_iterator begin() const
get a const_iterator to the first value
Definition: prob_weight_array.h:83
Self_t & operator/=(const Self_t &right)
rescale the weights by division element-wise
Definition: prob_weight_array.h:272
boost::array< Val_type, D > Data_type
Definition: prob_weight_array.h:44
const_iterator cend() const
get a const_iterator to the last value
Definition: prob_weight_array.h:77
iterator begin()
get an iterator to the first value
Definition: prob_weight_array.h:95
Image operator+(const Image &op1, const Image &op2)
Add two images.
Definition: i_image.h:834
Self_t & operator*=(const Self_t &right)
rescale the weights element-wise
Definition: prob_weight_array.h:260
friend Weight_array< M > convex_combination(const Weight_array< K > &weights, const boost::array< Weight_array< M >, K > &components)
const_iterator end() const
get a const_iterator to the last value
Definition: prob_weight_array.h:89
iterator end()
get an iterator to the last value
Definition: prob_weight_array.h:101
Self_t & operator+=(const Self_t &right)
shift values
Definition: prob_weight_array.h:248
kjb_c::Pixel abs(const kjb_c::Pixel &p)
Take the channel-wise absolute value of a kjb_c::Pixel.
Definition: i_pixel.h:354
Weight_array< D > convex_combination(const Weight_array< K > &weights, const boost::array< Weight_array< D >, K > &components)
Definition: prob_weight_array.h:468
Data_type::const_iterator const_iterator
Definition: prob_weight_array.h:47
const_iterator cbegin() const
get a const_iterator to the first value
Definition: prob_weight_array.h:73
Data_type::iterator iterator
Definition: prob_weight_array.h:46
std::ofstream & operator<<(std::ofstream &out, const Quaternion &q)
Definition: turntable_camera.cpp:77
Image operator/(const Image &op1, double op2)
Scale an image in channel space, yielding a new image.
Definition: i_image.h:825
Filter class.
Definition: i_filter.h:36
Weight_array< D > Self_t
Definition: prob_weight_array.h:42
#define KJB_THROW_2(ex, msg)
Definition: l_exception.h:48
bool operator!=(const Int_matrix &op1, const Int_matrix::Impl_type &op2)
Test for any difference between two matrices.
Definition: l_int_matrix.h:1274
const Val_type & operator[](const size_t &position) const
access value in position position.
Definition: prob_weight_array.h:340
double Val_type
Definition: prob_weight_array.h:43
bool operator==(const Int_matrix &op1, const Int_matrix::Impl_type &op2)
Test for exact equality between two matrices.
Definition: l_int_matrix.cpp:218
Various utility functions for probabiliity-related stuff.
Weight_array()
construct an empty Weight_array
Definition: prob_weight_array.h:51
Forward declarations.
Definition: prob_weight_array.h:28
D
Definition: APPgetLargeConnectedEdges.m:106
Support for error handling exception classes in libKJB.
Self_t & normalize()
normalize the weights
Definition: prob_weight_array.h:237
void scale(kjb::Axis_aligned_rectangle_2d &box, const kjb::Vector &s)
Definition: gr_2D_bounding_box.cpp:108
Gsl_Vector operator*(double scalar, const Gsl_Vector &vector)
multiply scalar and vector, scalar written on the left side
Definition: gsl_vector.h:661
Val_type total_mass() const
get total mass
Definition: prob_weight_array.h:226