00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00014
00015
00016 #ifndef __defined_libdai_prob_h
00017 #define __defined_libdai_prob_h
00018
00019
00020 #include <cmath>
00021 #include <vector>
00022 #include <ostream>
00023 #include <algorithm>
00024 #include <numeric>
00025 #include <functional>
00026 #include <dai/util.h>
00027 #include <dai/exceptions.h>
00028
00029
00030 namespace dai {
00031
00032
00034 template<typename T> struct fo_id : public std::unary_function<T, T> {
00036 T operator()( const T &x ) const {
00037 return x;
00038 }
00039 };
00040
00041
00043 template<typename T> struct fo_abs : public std::unary_function<T, T> {
00045 T operator()( const T &x ) const {
00046 if( x < (T)0 )
00047 return -x;
00048 else
00049 return x;
00050 }
00051 };
00052
00053
00055 template<typename T> struct fo_exp : public std::unary_function<T, T> {
00057 T operator()( const T &x ) const {
00058 return exp( x );
00059 }
00060 };
00061
00062
00064 template<typename T> struct fo_log : public std::unary_function<T, T> {
00066 T operator()( const T &x ) const {
00067 return log( x );
00068 }
00069 };
00070
00071
00073 template<typename T> struct fo_log0 : public std::unary_function<T, T> {
00075 T operator()( const T &x ) const {
00076 if( x )
00077 return log( x );
00078 else
00079 return 0;
00080 }
00081 };
00082
00083
00085 template<typename T> struct fo_inv : public std::unary_function<T, T> {
00087 T operator()( const T &x ) const {
00088 return 1 / x;
00089 }
00090 };
00091
00092
00094 template<typename T> struct fo_inv0 : public std::unary_function<T, T> {
00096 T operator()( const T &x ) const {
00097 if( x )
00098 return 1 / x;
00099 else
00100 return 0;
00101 }
00102 };
00103
00104
00106 template<typename T> struct fo_plog0p : public std::unary_function<T, T> {
00108 T operator()( const T &p ) const {
00109 return p * dai::log0(p);
00110 }
00111 };
00112
00113
00115 template<typename T> struct fo_divides0 : public std::binary_function<T, T, T> {
00117 T operator()( const T &x, const T &y ) const {
00118 if( y == (T)0 )
00119 return (T)0;
00120 else
00121 return x / y;
00122 }
00123 };
00124
00125
00127 template<typename T> struct fo_KL : public std::binary_function<T, T, T> {
00129 T operator()( const T &p, const T &q ) const {
00130 if( p == (T)0 )
00131 return (T)0;
00132 else
00133 return p * (log(p) - log(q));
00134 }
00135 };
00136
00137
00139 template<typename T> struct fo_Hellinger : public std::binary_function<T, T, T> {
00141 T operator()( const T &p, const T &q ) const {
00142 T x = sqrt(p) - sqrt(q);
00143 return x * x;
00144 }
00145 };
00146
00147
00149 template<typename T> struct fo_pow : public std::binary_function<T, T, T> {
00151 T operator()( const T &x, const T &y ) const {
00152 if( y != 1 )
00153 return pow( x, y );
00154 else
00155 return x;
00156 }
00157 };
00158
00159
00161 template<typename T> struct fo_max : public std::binary_function<T, T, T> {
00163 T operator()( const T &x, const T &y ) const {
00164 return (x > y) ? x : y;
00165 }
00166 };
00167
00168
00170 template<typename T> struct fo_min : public std::binary_function<T, T, T> {
00172 T operator()( const T &x, const T &y ) const {
00173 return (x > y) ? y : x;
00174 }
00175 };
00176
00177
00179 template<typename T> struct fo_absdiff : public std::binary_function<T, T, T> {
00181 T operator()( const T &x, const T &y ) const {
00182 return dai::abs( x - y );
00183 }
00184 };
00185
00186
00188
00196 template <typename T>
00197 class TProb {
00198 public:
00200 typedef std::vector<T> container_type;
00201
00203 typedef TProb<T> this_type;
00204
00205 private:
00207 container_type _p;
00208
00209 public:
00211
00212
00213 TProb() : _p() {}
00214
00216 explicit TProb( size_t n ) : _p( n, (T)1 / n ) {}
00217
00219 explicit TProb( size_t n, T p ) : _p( n, p ) {}
00220
00222
00228 template <typename TIterator>
00229 TProb( TIterator begin, TIterator end, size_t sizeHint ) : _p() {
00230 _p.reserve( sizeHint );
00231 _p.insert( _p.begin(), begin, end );
00232 }
00233
00235
00238 template <typename S>
00239 TProb( const std::vector<S> &v ) : _p() {
00240 _p.reserve( v.size() );
00241 _p.insert( _p.begin(), v.begin(), v.end() );
00242 }
00244
00246 typedef typename container_type::const_iterator const_iterator;
00248 typedef typename container_type::iterator iterator;
00250 typedef typename container_type::const_reverse_iterator const_reverse_iterator;
00252 typedef typename container_type::reverse_iterator reverse_iterator;
00253
00255
00256
00257 iterator begin() { return _p.begin(); }
00259 const_iterator begin() const { return _p.begin(); }
00260
00262 iterator end() { return _p.end(); }
00264 const_iterator end() const { return _p.end(); }
00265
00267 reverse_iterator rbegin() { return _p.rbegin(); }
00269 const_reverse_iterator rbegin() const { return _p.rbegin(); }
00270
00272 reverse_iterator rend() { return _p.rend(); }
00274 const_reverse_iterator rend() const { return _p.rend(); }
00276
00278
00279 void resize( size_t sz ) {
00280 _p.resize( sz );
00281 }
00283
00285
00286
00287 T get( size_t i ) const {
00288 #ifdef DAI_DEBUG
00289 return _p.at(i);
00290 #else
00291 return _p[i];
00292 #endif
00293 }
00294
00296 void set( size_t i, T val ) {
00297 DAI_DEBASSERT( i < _p.size() );
00298 _p[i] = val;
00299 }
00301
00303
00304
00305 const container_type& p() const { return _p; }
00306
00308 container_type& p() { return _p; }
00309
00311 T operator[]( size_t i ) const { return get(i); }
00312
00314 size_t size() const { return _p.size(); }
00315
00317
00325 template<typename unOp> T accumulateSum( T init, unOp op ) const {
00326 T t = op(init);
00327 for( const_iterator it = begin(); it != end(); it++ )
00328 t += op(*it);
00329 return t;
00330 }
00331
00333
00341 template<typename unOp> T accumulateMax( T init, unOp op, bool minimize ) const {
00342 T t = op(init);
00343 if( minimize ) {
00344 for( const_iterator it = begin(); it != end(); it++ )
00345 t = std::min( t, op(*it) );
00346 } else {
00347 for( const_iterator it = begin(); it != end(); it++ )
00348 t = std::max( t, op(*it) );
00349 }
00350 return t;
00351 }
00352
00354 T entropy() const { return -accumulateSum( (T)0, fo_plog0p<T>() ); }
00355
00357 T max() const { return accumulateMax( (T)(-INFINITY), fo_id<T>(), false ); }
00358
00360 T min() const { return accumulateMax( (T)INFINITY, fo_id<T>(), true ); }
00361
00363 T sum() const { return accumulateSum( (T)0, fo_id<T>() ); }
00364
00366 T sumAbs() const { return accumulateSum( (T)0, fo_abs<T>() ); }
00367
00369 T maxAbs() const { return accumulateMax( (T)0, fo_abs<T>(), false ); }
00370
00372 bool hasNaNs() const {
00373 bool foundnan = false;
00374 for( const_iterator x = _p.begin(); x != _p.end(); x++ )
00375 if( dai::isnan( *x ) ) {
00376 foundnan = true;
00377 break;
00378 }
00379 return foundnan;
00380 }
00381
00383 bool hasNegatives() const {
00384 return (std::find_if( _p.begin(), _p.end(), std::bind2nd( std::less<T>(), (T)0 ) ) != _p.end());
00385 }
00386
00388 std::pair<size_t,T> argmax() const {
00389 T max = _p[0];
00390 size_t arg = 0;
00391 for( size_t i = 1; i < size(); i++ ) {
00392 if( _p[i] > max ) {
00393 max = _p[i];
00394 arg = i;
00395 }
00396 }
00397 return std::make_pair( arg, max );
00398 }
00399
00401 size_t draw() {
00402 Real x = rnd_uniform() * sum();
00403 T s = 0;
00404 for( size_t i = 0; i < size(); i++ ) {
00405 s += get(i);
00406 if( s > x )
00407 return i;
00408 }
00409 return( size() - 1 );
00410 }
00411
00413
00415 bool operator<( const this_type& q ) const {
00416 DAI_DEBASSERT( size() == q.size() );
00417 return lexicographical_compare( begin(), end(), q.begin(), q.end() );
00418 }
00419
00421 bool operator==( const this_type& q ) const {
00422 if( size() != q.size() )
00423 return false;
00424 return p() == q.p();
00425 }
00427
00429
00430
00431 template<typename unaryOp> this_type pwUnaryTr( unaryOp op ) const {
00432 this_type r;
00433 r._p.reserve( size() );
00434 std::transform( _p.begin(), _p.end(), back_inserter( r._p ), op );
00435 return r;
00436 }
00437
00439 this_type operator- () const { return pwUnaryTr( std::negate<T>() ); }
00440
00442 this_type abs() const { return pwUnaryTr( fo_abs<T>() ); }
00443
00445 this_type exp() const { return pwUnaryTr( fo_exp<T>() ); }
00446
00448
00450 this_type log(bool zero=false) const {
00451 if( zero )
00452 return pwUnaryTr( fo_log0<T>() );
00453 else
00454 return pwUnaryTr( fo_log<T>() );
00455 }
00456
00458
00460 this_type inverse(bool zero=true) const {
00461 if( zero )
00462 return pwUnaryTr( fo_inv0<T>() );
00463 else
00464 return pwUnaryTr( fo_inv<T>() );
00465 }
00466
00468
00470 this_type normalized( ProbNormType norm = dai::NORMPROB ) const {
00471 T Z = 0;
00472 if( norm == dai::NORMPROB )
00473 Z = sum();
00474 else if( norm == dai::NORMLINF )
00475 Z = maxAbs();
00476 if( Z == (T)0 ) {
00477 DAI_THROW(NOT_NORMALIZABLE);
00478 return *this;
00479 } else
00480 return pwUnaryTr( std::bind2nd( std::divides<T>(), Z ) );
00481 }
00483
00485
00486
00487 template<typename unaryOp> this_type& pwUnaryOp( unaryOp op ) {
00488 std::transform( _p.begin(), _p.end(), _p.begin(), op );
00489 return *this;
00490 }
00491
00493 this_type& randomize() {
00494 std::generate( _p.begin(), _p.end(), rnd_uniform );
00495 return *this;
00496 }
00497
00499 this_type& setUniform () {
00500 fill( (T)1 / size() );
00501 return *this;
00502 }
00503
00505 this_type& takeAbs() { return pwUnaryOp( fo_abs<T>() ); }
00506
00508 this_type& takeExp() { return pwUnaryOp( fo_exp<T>() ); }
00509
00511
00513 this_type& takeLog(bool zero=false) {
00514 if( zero ) {
00515 return pwUnaryOp( fo_log0<T>() );
00516 } else
00517 return pwUnaryOp( fo_log<T>() );
00518 }
00519
00521
00523 T normalize( ProbNormType norm=dai::NORMPROB ) {
00524 T Z = 0;
00525 if( norm == dai::NORMPROB )
00526 Z = sum();
00527 else if( norm == dai::NORMLINF )
00528 Z = maxAbs();
00529 if( Z == (T)0 )
00530 DAI_THROW(NOT_NORMALIZABLE);
00531 else
00532 *this /= Z;
00533 return Z;
00534 }
00536
00538
00539
00540 this_type& fill( T x ) {
00541 std::fill( _p.begin(), _p.end(), x );
00542 return *this;
00543 }
00544
00546 this_type& operator+= (T x) {
00547 if( x != 0 )
00548 return pwUnaryOp( std::bind2nd( std::plus<T>(), x ) );
00549 else
00550 return *this;
00551 }
00552
00554 this_type& operator-= (T x) {
00555 if( x != 0 )
00556 return pwUnaryOp( std::bind2nd( std::minus<T>(), x ) );
00557 else
00558 return *this;
00559 }
00560
00562 this_type& operator*= (T x) {
00563 if( x != 1 )
00564 return pwUnaryOp( std::bind2nd( std::multiplies<T>(), x ) );
00565 else
00566 return *this;
00567 }
00568
00570 this_type& operator/= (T x) {
00571 if( x != 1 )
00572 return pwUnaryOp( std::bind2nd( fo_divides0<T>(), x ) );
00573 else
00574 return *this;
00575 }
00576
00578 this_type& operator^= (T x) {
00579 if( x != (T)1 )
00580 return pwUnaryOp( std::bind2nd( fo_pow<T>(), x) );
00581 else
00582 return *this;
00583 }
00585
00587
00588
00589 this_type operator+ (T x) const { return pwUnaryTr( std::bind2nd( std::plus<T>(), x ) ); }
00590
00592 this_type operator- (T x) const { return pwUnaryTr( std::bind2nd( std::minus<T>(), x ) ); }
00593
00595 this_type operator* (T x) const { return pwUnaryTr( std::bind2nd( std::multiplies<T>(), x ) ); }
00596
00598 this_type operator/ (T x) const { return pwUnaryTr( std::bind2nd( fo_divides0<T>(), x ) ); }
00599
00601 this_type operator^ (T x) const { return pwUnaryTr( std::bind2nd( fo_pow<T>(), x ) ); }
00603
00605
00606
00607
00611 template<typename binaryOp> this_type& pwBinaryOp( const this_type &q, binaryOp op ) {
00612 DAI_DEBASSERT( size() == q.size() );
00613 std::transform( _p.begin(), _p.end(), q._p.begin(), _p.begin(), op );
00614 return *this;
00615 }
00616
00618
00620 this_type& operator+= (const this_type & q) { return pwBinaryOp( q, std::plus<T>() ); }
00621
00623
00625 this_type& operator-= (const this_type & q) { return pwBinaryOp( q, std::minus<T>() ); }
00626
00628
00630 this_type& operator*= (const this_type & q) { return pwBinaryOp( q, std::multiplies<T>() ); }
00631
00633
00636 this_type& operator/= (const this_type & q) { return pwBinaryOp( q, fo_divides0<T>() ); }
00637
00639
00642 this_type& divide (const this_type & q) { return pwBinaryOp( q, std::divides<T>() ); }
00643
00645
00647 this_type& operator^= (const this_type & q) { return pwBinaryOp( q, fo_pow<T>() ); }
00649
00651
00652
00653
00657 template<typename binaryOp> this_type pwBinaryTr( const this_type &q, binaryOp op ) const {
00658 DAI_DEBASSERT( size() == q.size() );
00659 TProb<T> r;
00660 r._p.reserve( size() );
00661 std::transform( _p.begin(), _p.end(), q._p.begin(), back_inserter( r._p ), op );
00662 return r;
00663 }
00664
00666
00668 this_type operator+ ( const this_type& q ) const { return pwBinaryTr( q, std::plus<T>() ); }
00669
00671
00673 this_type operator- ( const this_type& q ) const { return pwBinaryTr( q, std::minus<T>() ); }
00674
00676
00678 this_type operator* ( const this_type &q ) const { return pwBinaryTr( q, std::multiplies<T>() ); }
00679
00681
00684 this_type operator/ ( const this_type &q ) const { return pwBinaryTr( q, fo_divides0<T>() ); }
00685
00687
00690 this_type divided_by( const this_type &q ) const { return pwBinaryTr( q, std::divides<T>() ); }
00691
00693
00695 this_type operator^ ( const this_type &q ) const { return pwBinaryTr( q, fo_pow<T>() ); }
00697
00699
00701 template<typename binOp1, typename binOp2> T innerProduct( const this_type &q, T init, binOp1 binaryOp1, binOp2 binaryOp2 ) const {
00702 DAI_DEBASSERT( size() == q.size() );
00703 return std::inner_product( begin(), end(), q.begin(), init, binaryOp1, binaryOp2 );
00704 }
00705 };
00706
00707
00709
00712 template<typename T> T dist( const TProb<T> &p, const TProb<T> &q, ProbDistType dt ) {
00713 switch( dt ) {
00714 case DISTL1:
00715 return p.innerProduct( q, (T)0, std::plus<T>(), fo_absdiff<T>() );
00716 case DISTLINF:
00717 return p.innerProduct( q, (T)0, fo_max<T>(), fo_absdiff<T>() );
00718 case DISTTV:
00719 return p.innerProduct( q, (T)0, std::plus<T>(), fo_absdiff<T>() ) / 2;
00720 case DISTKL:
00721 return p.innerProduct( q, (T)0, std::plus<T>(), fo_KL<T>() );
00722 case DISTHEL:
00723 return p.innerProduct( q, (T)0, std::plus<T>(), fo_Hellinger<T>() ) / 2;
00724 default:
00725 DAI_THROW(UNKNOWN_ENUM_VALUE);
00726 return INFINITY;
00727 }
00728 }
00729
00730
00732
00734 template<typename T> std::ostream& operator<< (std::ostream& os, const TProb<T>& p) {
00735 os << "(";
00736 for( size_t i = 0; i < p.size(); i++ )
00737 os << ((i != 0) ? ", " : "") << p.get(i);
00738 os << ")";
00739 return os;
00740 }
00741
00742
00744
00747 template<typename T> TProb<T> min( const TProb<T> &a, const TProb<T> &b ) {
00748 return a.pwBinaryTr( b, fo_min<T>() );
00749 }
00750
00751
00753
00756 template<typename T> TProb<T> max( const TProb<T> &a, const TProb<T> &b ) {
00757 return a.pwBinaryTr( b, fo_max<T>() );
00758 }
00759
00760
00762 typedef TProb<Real> Prob;
00763
00764
00765 }
00766
00767
00768 #endif