1 /* This file is part of libDAI - http://www.libdai.org/
3 * Copyright (c) 2006-2011, The libDAI authors. All rights reserved.
5 * Use of this source code is governed by a BSD-style license that can be found in the LICENSE file.
10 /// \brief Defines TProb<> and Prob classes which represent (probability) vectors (e.g., probability distributions of discrete random variables)
13 #ifndef __defined_libdai_prob_h
14 #define __defined_libdai_prob_h
24 #include <dai/exceptions.h>
30 /// Function object that returns the value itself
31 template<typename T
> struct fo_id
: public std::unary_function
<T
, T
> {
33 T
operator()( const T
&x
) const {
39 /// Function object that takes the absolute value
40 template<typename T
> struct fo_abs
: public std::unary_function
<T
, T
> {
42 T
operator()( const T
&x
) const {
51 /// Function object that takes the exponent
52 template<typename T
> struct fo_exp
: public std::unary_function
<T
, T
> {
54 T
operator()( const T
&x
) const {
60 /// Function object that takes the logarithm
61 template<typename T
> struct fo_log
: public std::unary_function
<T
, T
> {
63 T
operator()( const T
&x
) const {
69 /// Function object that takes the logarithm, except that log(0) is defined to be 0
70 template<typename T
> struct fo_log0
: public std::unary_function
<T
, T
> {
71 /// Returns (\a x == 0 ? 0 : log(\a x))
72 T
operator()( const T
&x
) const {
81 /// Function object that takes the inverse
82 template<typename T
> struct fo_inv
: public std::unary_function
<T
, T
> {
84 T
operator()( const T
&x
) const {
90 /// Function object that takes the inverse, except that 1/0 is defined to be 0
91 template<typename T
> struct fo_inv0
: public std::unary_function
<T
, T
> {
92 /// Returns (\a x == 0 ? 0 : (1 / \a x))
93 T
operator()( const T
&x
) const {
102 /// Function object that returns p*log0(p)
103 template<typename T
> struct fo_plog0p
: public std::unary_function
<T
, T
> {
104 /// Returns \a p * log0(\a p)
105 T
operator()( const T
&p
) const {
106 return p
* dai::log0(p
);
111 /// Function object similar to std::divides(), but different in that dividing by zero results in zero
112 template<typename T
> struct fo_divides0
: public std::binary_function
<T
, T
, T
> {
113 /// Returns (\a y == 0 ? 0 : (\a x / \a y))
114 T
operator()( const T
&x
, const T
&y
) const {
123 /// Function object useful for calculating the KL distance
124 template<typename T
> struct fo_KL
: public std::binary_function
<T
, T
, T
> {
125 /// Returns (\a p == 0 ? 0 : (\a p * (log(\a p) - log(\a q))))
126 T
operator()( const T
&p
, const T
&q
) const {
130 return p
* (log(p
) - log(q
));
135 /// Function object useful for calculating the Hellinger distance
136 template<typename T
> struct fo_Hellinger
: public std::binary_function
<T
, T
, T
> {
137 /// Returns (sqrt(\a p) - sqrt(\a q))^2
138 T
operator()( const T
&p
, const T
&q
) const {
139 T x
= sqrt(p
) - sqrt(q
);
145 /// Function object that returns x to the power y
146 template<typename T
> struct fo_pow
: public std::binary_function
<T
, T
, T
> {
147 /// Returns (\a x ^ \a y)
148 T
operator()( const T
&x
, const T
&y
) const {
157 /// Function object that returns the maximum of two values
158 template<typename T
> struct fo_max
: public std::binary_function
<T
, T
, T
> {
159 /// Returns (\a x > y ? x : y)
160 T
operator()( const T
&x
, const T
&y
) const {
161 return (x
> y
) ? x
: y
;
166 /// Function object that returns the minimum of two values
167 template<typename T
> struct fo_min
: public std::binary_function
<T
, T
, T
> {
168 /// Returns (\a x > y ? y : x)
169 T
operator()( const T
&x
, const T
&y
) const {
170 return (x
> y
) ? y
: x
;
175 /// Function object that returns the absolute difference of x and y
176 template<typename T
> struct fo_absdiff
: public std::binary_function
<T
, T
, T
> {
177 /// Returns abs( \a x - \a y )
178 T
operator()( const T
&x
, const T
&y
) const {
179 return dai::abs( x
- y
);
184 /// Represents a vector with entries of type \a T.
185 /** It is simply a <tt>std::vector</tt><<em>T</em>> with an interface designed for dealing with probability mass functions.
187 * It is mainly used for representing measures on a finite outcome space, for example, the probability
188 * distribution of a discrete random variable. However, entries are not necessarily non-negative; it is also used to
189 * represent logarithms of probability mass functions.
191 * \tparam T Should be a scalar that is castable from and to dai::Real and should support elementary arithmetic operations.
193 template <typename T
>
196 /// Type of data structure used for storing the values
197 typedef std::vector
<T
> container_type
;
200 typedef TProb
<T
> this_type
;
203 /// The data structure that stores the values
207 /// \name Constructors and destructors
209 /// Default constructor (constructs empty vector)
212 /// Construct uniform probability distribution over \a n outcomes (i.e., a vector of length \a n with each entry set to \f$1/n\f$)
213 explicit TProb( size_t n
) : _p( n
, (T
)1 / n
) {}
215 /// Construct vector of length \a n with each entry set to \a p
216 explicit TProb( size_t n
, T p
) : _p( n
, p
) {}
218 /// Construct vector from a range
219 /** \tparam TIterator Iterates over instances that can be cast to \a T
220 * \param begin Points to first instance to be added.
221 * \param end Points just beyond last instance to be added.
222 * \param sizeHint For efficiency, the number of entries can be speficied by \a sizeHint;
223 * the value 0 can be given if the size is unknown, but this will result in a performance penalty.
225 template <typename TIterator
>
226 TProb( TIterator begin
, TIterator end
, size_t sizeHint
) : _p() {
227 _p
.reserve( sizeHint
);
228 _p
.insert( _p
.begin(), begin
, end
);
231 /// Construct vector from another vector
232 /** \tparam S type of elements in \a v (should be castable to type \a T)
233 * \param v vector used for initialization.
235 template <typename S
>
236 TProb( const std::vector
<S
> &v
) : _p() {
237 _p
.reserve( v
.size() );
238 _p
.insert( _p
.begin(), v
.begin(), v
.end() );
242 /// Constant iterator over the elements
243 typedef typename
container_type::const_iterator const_iterator
;
244 /// Iterator over the elements
245 typedef typename
container_type::iterator iterator
;
246 /// Constant reverse iterator over the elements
247 typedef typename
container_type::const_reverse_iterator const_reverse_iterator
;
248 /// Reverse iterator over the elements
249 typedef typename
container_type::reverse_iterator reverse_iterator
;
251 /// \name Iterator interface
253 /// Returns iterator that points to the first element
254 iterator
begin() { return _p
.begin(); }
255 /// Returns constant iterator that points to the first element
256 const_iterator
begin() const { return _p
.begin(); }
258 /// Returns iterator that points beyond the last element
259 iterator
end() { return _p
.end(); }
260 /// Returns constant iterator that points beyond the last element
261 const_iterator
end() const { return _p
.end(); }
263 /// Returns reverse iterator that points to the last element
264 reverse_iterator
rbegin() { return _p
.rbegin(); }
265 /// Returns constant reverse iterator that points to the last element
266 const_reverse_iterator
rbegin() const { return _p
.rbegin(); }
268 /// Returns reverse iterator that points beyond the first element
269 reverse_iterator
rend() { return _p
.rend(); }
270 /// Returns constant reverse iterator that points beyond the first element
271 const_reverse_iterator
rend() const { return _p
.rend(); }
274 /// \name Miscellaneous operations
276 void resize( size_t sz
) {
281 /// \name Get/set individual entries
283 /// Gets \a i 'th entry
284 T
get( size_t i
) const {
292 /// Sets \a i 'th entry to \a val
293 void set( size_t i
, T val
) {
294 DAI_DEBASSERT( i
< _p
.size() );
301 /// Returns a const reference to the wrapped container
302 const container_type
& p() const { return _p
; }
304 /// Returns a reference to the wrapped container
305 container_type
& p() { return _p
; }
307 /// Returns a copy of the \a i 'th entry
308 T
operator[]( size_t i
) const { return get(i
); }
310 /// Returns length of the vector (i.e., the number of entries)
311 size_t size() const { return _p
.size(); }
313 /// Accumulate all values (similar to std::accumulate) by summing
314 /** The following calculation is done:
317 * for( const_iterator it = begin(); it != end(); it++ )
322 template<typename unOp
> T
accumulateSum( T init
, unOp op
) const {
324 for( const_iterator it
= begin(); it
!= end(); it
++ )
329 /// Accumulate all values (similar to std::accumulate) by maximization/minimization
330 /** The following calculation is done (with "max" replaced by "min" if \a minimize == \c true):
333 * for( const_iterator it = begin(); it != end(); it++ )
334 * t = std::max( t, op(*it) );
338 template<typename unOp
> T
accumulateMax( T init
, unOp op
, bool minimize
) const {
341 for( const_iterator it
= begin(); it
!= end(); it
++ )
342 t
= std::min( t
, op(*it
) );
344 for( const_iterator it
= begin(); it
!= end(); it
++ )
345 t
= std::max( t
, op(*it
) );
350 /// Returns the Shannon entropy of \c *this, \f$-\sum_i p_i \log p_i\f$
351 T
entropy() const { return -accumulateSum( (T
)0, fo_plog0p
<T
>() ); }
353 /// Returns maximum value of all entries
354 T
max() const { return accumulateMax( (T
)(-INFINITY
), fo_id
<T
>(), false ); }
356 /// Returns minimum value of all entries
357 T
min() const { return accumulateMax( (T
)INFINITY
, fo_id
<T
>(), true ); }
359 /// Returns sum of all entries
360 T
sum() const { return accumulateSum( (T
)0, fo_id
<T
>() ); }
362 /// Return sum of absolute value of all entries
363 T
sumAbs() const { return accumulateSum( (T
)0, fo_abs
<T
>() ); }
365 /// Returns maximum absolute value of all entries
366 T
maxAbs() const { return accumulateMax( (T
)0, fo_abs
<T
>(), false ); }
368 /// Returns \c true if one or more entries are NaN
369 bool hasNaNs() const {
370 bool foundnan
= false;
371 for( const_iterator x
= _p
.begin(); x
!= _p
.end(); x
++ )
372 if( dai::isnan( *x
) ) {
379 /// Returns \c true if one or more entries are negative
380 bool hasNegatives() const {
381 return (std::find_if( _p
.begin(), _p
.end(), std::bind2nd( std::less
<T
>(), (T
)0 ) ) != _p
.end());
384 /// Returns a pair consisting of the index of the maximum value and the maximum value itself
385 std::pair
<size_t,T
> argmax() const {
388 for( size_t i
= 1; i
< size(); i
++ ) {
394 return std::make_pair( arg
, max
);
397 /// Returns a random index, according to the (normalized) distribution described by *this
399 Real x
= rnd_uniform() * sum();
401 for( size_t i
= 0; i
< size(); i
++ ) {
406 return( size() - 1 );
409 /// Lexicographical comparison
410 /** \pre <tt>this->size() == q.size()</tt>
412 bool operator<( const this_type
& q
) const {
413 DAI_DEBASSERT( size() == q
.size() );
414 return lexicographical_compare( begin(), end(), q
.begin(), q
.end() );
418 bool operator==( const this_type
& q
) const {
419 if( size() != q
.size() )
425 /// \name Unary transformations
427 /// Returns the result of applying operation \a op pointwise on \c *this
428 template<typename unaryOp
> this_type
pwUnaryTr( unaryOp op
) const {
430 r
._p
.reserve( size() );
431 std::transform( _p
.begin(), _p
.end(), back_inserter( r
._p
), op
);
435 /// Returns negative of \c *this
436 this_type
operator- () const { return pwUnaryTr( std::negate
<T
>() ); }
438 /// Returns pointwise absolute value
439 this_type
abs() const { return pwUnaryTr( fo_abs
<T
>() ); }
441 /// Returns pointwise exponent
442 this_type
exp() const { return pwUnaryTr( fo_exp
<T
>() ); }
444 /// Returns pointwise logarithm
445 /** If \a zero == \c true, uses <tt>log(0)==0</tt>; otherwise, <tt>log(0)==-Inf</tt>.
447 this_type
log(bool zero
=false) const {
449 return pwUnaryTr( fo_log0
<T
>() );
451 return pwUnaryTr( fo_log
<T
>() );
454 /// Returns pointwise inverse
455 /** If \a zero == \c true, uses <tt>1/0==0</tt>; otherwise, <tt>1/0==Inf</tt>.
457 this_type
inverse(bool zero
=true) const {
459 return pwUnaryTr( fo_inv0
<T
>() );
461 return pwUnaryTr( fo_inv
<T
>() );
464 /// Returns normalized copy of \c *this, using the specified norm
465 /** \throw NOT_NORMALIZABLE if the norm is zero
467 this_type
normalized( ProbNormType norm
= dai::NORMPROB
) const {
469 if( norm
== dai::NORMPROB
)
471 else if( norm
== dai::NORMLINF
)
474 DAI_THROW(NOT_NORMALIZABLE
);
477 return pwUnaryTr( std::bind2nd( std::divides
<T
>(), Z
) );
481 /// \name Unary operations
483 /// Applies unary operation \a op pointwise
484 template<typename unaryOp
> this_type
& pwUnaryOp( unaryOp op
) {
485 std::transform( _p
.begin(), _p
.end(), _p
.begin(), op
);
489 /// Draws all entries i.i.d. from a uniform distribution on [0,1)
490 this_type
& randomize() {
491 std::generate( _p
.begin(), _p
.end(), rnd_uniform
);
495 /// Sets all entries to \f$1/n\f$ where \a n is the length of the vector
496 this_type
& setUniform () {
497 fill( (T
)1 / size() );
501 /// Applies absolute value pointwise
502 this_type
& takeAbs() { return pwUnaryOp( fo_abs
<T
>() ); }
504 /// Applies exponent pointwise
505 this_type
& takeExp() { return pwUnaryOp( fo_exp
<T
>() ); }
507 /// Applies logarithm pointwise
508 /** If \a zero == \c true, uses <tt>log(0)==0</tt>; otherwise, <tt>log(0)==-Inf</tt>.
510 this_type
& takeLog(bool zero
=false) {
512 return pwUnaryOp( fo_log0
<T
>() );
514 return pwUnaryOp( fo_log
<T
>() );
517 /// Normalizes vector using the specified norm
518 /** \throw NOT_NORMALIZABLE if the norm is zero
520 T
normalize( ProbNormType norm
=dai::NORMPROB
) {
522 if( norm
== dai::NORMPROB
)
524 else if( norm
== dai::NORMLINF
)
527 DAI_THROW(NOT_NORMALIZABLE
);
534 /// \name Operations with scalars
536 /// Sets all entries to \a x
537 this_type
& fill( T x
) {
538 std::fill( _p
.begin(), _p
.end(), x
);
542 /// Adds scalar \a x to each entry
543 this_type
& operator+= (T x
) {
545 return pwUnaryOp( std::bind2nd( std::plus
<T
>(), x
) );
550 /// Subtracts scalar \a x from each entry
551 this_type
& operator-= (T x
) {
553 return pwUnaryOp( std::bind2nd( std::minus
<T
>(), x
) );
558 /// Multiplies each entry with scalar \a x
559 this_type
& operator*= (T x
) {
561 return pwUnaryOp( std::bind2nd( std::multiplies
<T
>(), x
) );
566 /// Divides each entry by scalar \a x, where division by 0 yields 0
567 this_type
& operator/= (T x
) {
569 return pwUnaryOp( std::bind2nd( fo_divides0
<T
>(), x
) );
574 /// Raises entries to the power \a x
575 this_type
& operator^= (T x
) {
577 return pwUnaryOp( std::bind2nd( fo_pow
<T
>(), x
) );
583 /// \name Transformations with scalars
585 /// Returns sum of \c *this and scalar \a x
586 this_type
operator+ (T x
) const { return pwUnaryTr( std::bind2nd( std::plus
<T
>(), x
) ); }
588 /// Returns difference of \c *this and scalar \a x
589 this_type
operator- (T x
) const { return pwUnaryTr( std::bind2nd( std::minus
<T
>(), x
) ); }
591 /// Returns product of \c *this with scalar \a x
592 this_type
operator* (T x
) const { return pwUnaryTr( std::bind2nd( std::multiplies
<T
>(), x
) ); }
594 /// Returns quotient of \c *this and scalar \a x, where division by 0 yields 0
595 this_type
operator/ (T x
) const { return pwUnaryTr( std::bind2nd( fo_divides0
<T
>(), x
) ); }
597 /// Returns \c *this raised to the power \a x
598 this_type
operator^ (T x
) const { return pwUnaryTr( std::bind2nd( fo_pow
<T
>(), x
) ); }
601 /// \name Operations with other equally-sized vectors
603 /// Applies binary operation pointwise on two vectors
604 /** \tparam binaryOp Type of function object that accepts two arguments of type \a T and outputs a type \a T
605 * \param q Right operand
606 * \param op Operation of type \a binaryOp
608 template<typename binaryOp
> this_type
& pwBinaryOp( const this_type
&q
, binaryOp op
) {
609 DAI_DEBASSERT( size() == q
.size() );
610 std::transform( _p
.begin(), _p
.end(), q
._p
.begin(), _p
.begin(), op
);
614 /// Pointwise addition with \a q
615 /** \pre <tt>this->size() == q.size()</tt>
617 this_type
& operator+= (const this_type
& q
) { return pwBinaryOp( q
, std::plus
<T
>() ); }
619 /// Pointwise subtraction of \a q
620 /** \pre <tt>this->size() == q.size()</tt>
622 this_type
& operator-= (const this_type
& q
) { return pwBinaryOp( q
, std::minus
<T
>() ); }
624 /// Pointwise multiplication with \a q
625 /** \pre <tt>this->size() == q.size()</tt>
627 this_type
& operator*= (const this_type
& q
) { return pwBinaryOp( q
, std::multiplies
<T
>() ); }
629 /// Pointwise division by \a q, where division by 0 yields 0
630 /** \pre <tt>this->size() == q.size()</tt>
631 * \see divide(const TProb<T> &)
633 this_type
& operator/= (const this_type
& q
) { return pwBinaryOp( q
, fo_divides0
<T
>() ); }
635 /// Pointwise division by \a q, where division by 0 yields +Inf
636 /** \pre <tt>this->size() == q.size()</tt>
637 * \see operator/=(const TProb<T> &)
639 this_type
& divide (const this_type
& q
) { return pwBinaryOp( q
, std::divides
<T
>() ); }
642 /** \pre <tt>this->size() == q.size()</tt>
644 this_type
& operator^= (const this_type
& q
) { return pwBinaryOp( q
, fo_pow
<T
>() ); }
647 /// \name Transformations with other equally-sized vectors
649 /// Returns the result of applying binary operation \a op pointwise on \c *this and \a q
650 /** \tparam binaryOp Type of function object that accepts two arguments of type \a T and outputs a type \a T
651 * \param q Right operand
652 * \param op Operation of type \a binaryOp
654 template<typename binaryOp
> this_type
pwBinaryTr( const this_type
&q
, binaryOp op
) const {
655 DAI_DEBASSERT( size() == q
.size() );
657 r
._p
.reserve( size() );
658 std::transform( _p
.begin(), _p
.end(), q
._p
.begin(), back_inserter( r
._p
), op
);
662 /// Returns sum of \c *this and \a q
663 /** \pre <tt>this->size() == q.size()</tt>
665 this_type
operator+ ( const this_type
& q
) const { return pwBinaryTr( q
, std::plus
<T
>() ); }
667 /// Return \c *this minus \a q
668 /** \pre <tt>this->size() == q.size()</tt>
670 this_type
operator- ( const this_type
& q
) const { return pwBinaryTr( q
, std::minus
<T
>() ); }
672 /// Return product of \c *this with \a q
673 /** \pre <tt>this->size() == q.size()</tt>
675 this_type
operator* ( const this_type
&q
) const { return pwBinaryTr( q
, std::multiplies
<T
>() ); }
677 /// Returns quotient of \c *this with \a q, where division by 0 yields 0
678 /** \pre <tt>this->size() == q.size()</tt>
679 * \see divided_by(const TProb<T> &)
681 this_type
operator/ ( const this_type
&q
) const { return pwBinaryTr( q
, fo_divides0
<T
>() ); }
683 /// Pointwise division by \a q, where division by 0 yields +Inf
684 /** \pre <tt>this->size() == q.size()</tt>
685 * \see operator/(const TProb<T> &)
687 this_type
divided_by( const this_type
&q
) const { return pwBinaryTr( q
, std::divides
<T
>() ); }
689 /// Returns \c *this to the power \a q
690 /** \pre <tt>this->size() == q.size()</tt>
692 this_type
operator^ ( const this_type
&q
) const { return pwBinaryTr( q
, fo_pow
<T
>() ); }
695 /// Performs a generalized inner product, similar to std::inner_product
696 /** \pre <tt>this->size() == q.size()</tt>
698 template<typename binOp1
, typename binOp2
> T
innerProduct( const this_type
&q
, T init
, binOp1 binaryOp1
, binOp2 binaryOp2
) const {
699 DAI_DEBASSERT( size() == q
.size() );
700 return std::inner_product( begin(), end(), q
.begin(), init
, binaryOp1
, binaryOp2
);
705 /// Returns distance between \a p and \a q, measured using distance measure \a dt
707 * \pre <tt>this->size() == q.size()</tt>
709 template<typename T
> T
dist( const TProb
<T
> &p
, const TProb
<T
> &q
, ProbDistType dt
) {
712 return p
.innerProduct( q
, (T
)0, std::plus
<T
>(), fo_absdiff
<T
>() );
714 return p
.innerProduct( q
, (T
)0, fo_max
<T
>(), fo_absdiff
<T
>() );
716 return p
.innerProduct( q
, (T
)0, std::plus
<T
>(), fo_absdiff
<T
>() ) / 2;
718 return p
.innerProduct( q
, (T
)0, std::plus
<T
>(), fo_KL
<T
>() );
720 return p
.innerProduct( q
, (T
)0, std::plus
<T
>(), fo_Hellinger
<T
>() ) / 2;
722 DAI_THROW(UNKNOWN_ENUM_VALUE
);
728 /// Writes a TProb<T> to an output stream
731 template<typename T
> std::ostream
& operator<< (std::ostream
& os
, const TProb
<T
>& p
) {
733 for( size_t i
= 0; i
< p
.size(); i
++ )
734 os
<< ((i
!= 0) ? ", " : "") << p
.get(i
);
740 /// Returns the pointwise minimum of \a a and \a b
742 * \pre <tt>this->size() == q.size()</tt>
744 template<typename T
> TProb
<T
> min( const TProb
<T
> &a
, const TProb
<T
> &b
) {
745 return a
.pwBinaryTr( b
, fo_min
<T
>() );
749 /// Returns the pointwise maximum of \a a and \a b
751 * \pre <tt>this->size() == q.size()</tt>
753 template<typename T
> TProb
<T
> max( const TProb
<T
> &a
, const TProb
<T
> &b
) {
754 return a
.pwBinaryTr( b
, fo_max
<T
>() );
758 /// Represents a vector with entries of type dai::Real.
759 typedef TProb
<Real
> Prob
;
762 } // end of namespace dai