From 2e902b1b0b90158b1d434cfc2c2f3ce27fbd9912 Mon Sep 17 00:00:00 2001 From: Joris Mooij Date: Wed, 3 Sep 2008 17:49:42 +0200 Subject: [PATCH] * Contributions by Giuseppe Passino in dai::TProb. - removed copy constructor and assignment operators (redundant) - implementation of some methods via STL algorithms - added methods takeExp, takeLog, takeLog0 for transformation in-place - explicit constructor (prevents implicit conversion from size_t to TProb) - added operator+,+=,-,-=, with argument T (for calculations in log-scale) --- ChangeLog | 10 ++- Makefile | 2 +- include/dai/prob.h | 202 +++++++++++++++++++++------------------------ 3 files changed, 104 insertions(+), 110 deletions(-) diff --git a/ChangeLog b/ChangeLog index 396f393..42406f4 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,7 +1,8 @@ libDAI-0.2.2 (2008-??-??) ------------------------- -- Renamed DEBUG to DAI_DEBUG to avoid conflicts +* Moved everything into namespace "dai" +* Renamed DEBUG to DAI_DEBUG to avoid conflicts * Contributions by ???: - Renamed variable _N in mr.* for compatibility with g++ under cygwin * Contributions by Giuseppe Passino: @@ -9,6 +10,12 @@ libDAI-0.2.2 (2008-??-??) - moved header files in include/dai and sources in src - changed #ifndefs to GNU style - added extra warning checks (-W -Wextra) and fixed resulting warnings + - dai::TProb: + o removed copy constructor and assignment operators (redundant) + o implementation of some methods via STL algorithms + o added methods takeExp, takeLog, takeLog0 for transformation in-place + o explicit constructor (prevents implicit conversion from size_t to TProb) + o added operator+,+=,-,-=, with argument T (for calculations in log-scale) * Contributions by Christian Wojek, resulting in vast speed and memory improvements for large factor graphs: - Sparse implementation of nodes->edge conversion table _E12ind in bipgraph.h @@ -17,7 +24,6 @@ libDAI-0.2.2 (2008-??-??) - Optimization of FactorGraph constructors * FactorGraph constructors no longer check for short loops and for negative entries. Also, the normtype is now Prob::NORMPROB by default. -* Moved everything into namespace "dai" libDAI-0.2.1 (2008-05-26) diff --git a/Makefile b/Makefile index ea849fb..f845617 100644 --- a/Makefile +++ b/Makefile @@ -30,7 +30,7 @@ BOOSTFLAGS = -lboost_program_options CC = g++ # Flags for the C++ compiler -CCFLAGS = -Wall -W -Wextra -fpic -g -DDAI_DEBUG -I./include -Llib -O3 #-static #-pg #-DVERBOSE +CCFLAGS = -Wall -W -Wextra -fpic -I./include -Llib -O3 -g -DDAI_DEBUG #-static #-pg #-DVERBOSE # To enable the Matlab interface, define WITH_MATLAB = yes WITH_MATLAB = diff --git a/include/dai/prob.h b/include/dai/prob.h index 65d86de..ddba20a 100644 --- a/include/dai/prob.h +++ b/include/dai/prob.h @@ -26,8 +26,11 @@ #include #include #include -#include +#include #include +#include +#include +#include #include @@ -63,32 +66,16 @@ template class TProb { typedef enum { DISTL1, DISTLINF, DISTTV } DistType; /// Default constructor - TProb() : _p() {} + TProb() {} /// Construct uniform distribution of given length - TProb( size_t n ) : _p(std::vector(n, 1.0 / n)) {} + explicit TProb( size_t n ) : _p(std::vector(n, 1.0 / n)) {} /// Construct with given length and initial value - TProb( size_t n, Real p ) : _p(std::vector(n,(T)p)) {} + TProb( size_t n, Real p ) : _p(n, (T)p) {} /// Construct with given length and initial array - TProb( size_t n, const Real* p ) { - // Reserve-push_back is faster than resize-copy - _p.reserve( n ); - for( size_t i = 0; i < n; i++ ) - _p.push_back( p[i] ); - } - - /// Copy constructor - TProb( const TProb & x ) : _p(x._p) {} - - /// Assignment operator - TProb & operator=( const TProb &x ) { - if( this != &x ) { - _p = x._p; - } - return *this; - } + TProb( size_t n, const Real* p ) : _p(p, p + n ) {} /// Provide read access to _p const std::vector & p() const { return _p; } @@ -104,15 +91,13 @@ template class TProb { /// Set all elements to x TProb & fill(T x) { - for( size_t i = 0; i < size(); i++ ) - _p[i] = x; + std::fill( _p.begin(), _p.end(), x ); return *this; } /// Set all elements to iid random numbers from uniform(0,1) distribution TProb & randomize() { - for( size_t i = 0; i < size(); i++ ) - _p[i] = rnd_uniform(); + std::generate(_p.begin(), _p.end(), rnd_uniform); return *this; } @@ -126,13 +111,13 @@ template class TProb { for( size_t i = 0; i < size(); i++ ) if( fabs((Real)_p[i]) < epsilon ) _p[i] = 0; +// std::replace_if( _p.begin(), _p.end(), fabs((Real)boost::lambda::_1) < epsilon, 0.0 ); return *this; } /// Multiplication with T x TProb& operator*= (T x) { - for( size_t i = 0; i < size(); i++ ) - _p[i] *= x; + std::transform( _p.begin(), _p.end(), _p.begin(), std::bind2nd( std::multiplies(), x) ); return *this; } @@ -148,16 +133,41 @@ template class TProb { #ifdef DAI_DEBUG assert( x != 0.0 ); #endif - for( size_t i = 0; i < size(); i++ ) - _p[i] /= x; + std::transform( _p.begin(), _p.end(), _p.begin(), std::bind2nd( std::divides(), x ) ); return *this; } /// Return quotient of *this and T x TProb operator/ (T x) const { - TProb prod( *this ); - prod /= x; - return prod; + TProb quot( *this ); + quot /= x; + return quot; + } + + /// addition of x + TProb& operator+= (T x) { + std::transform( _p.begin(), _p.end(), _p.begin(), std::bind2nd( std::plus(), x ) ); + return *this; + } + + /// Return sum of *this with T x + TProb operator+ (T x) const { + TProb sum( *this ); + sum += x; + return sum; + } + + /// Difference by T x + TProb& operator-= (T x) { + std::transform( _p.begin(), _p.end(), _p.begin(), std::bind2nd( std::minus(), x ) ); + return *this; + } + + /// Return difference of *this and T x + TProb operator- (T x) const { + TProb diff( *this ); + diff -= x; + return diff; } /// Pointwise multiplication with q @@ -165,8 +175,7 @@ template class TProb { #ifdef DAI_DEBUG assert( size() == q.size() ); #endif - for( size_t i = 0; i < size(); i++ ) - _p[i] *= q[i]; + std::transform( _p.begin(), _p.end(), q._p.begin(), _p.begin(), std::multiplies() ); return *this; } @@ -185,8 +194,7 @@ template class TProb { #ifdef DAI_DEBUG assert( size() == q.size() ); #endif - for( size_t i = 0; i < size(); i++ ) - _p[i] += q[i]; + std::transform( _p.begin(), _p.end(), q._p.begin(), _p.begin(), std::plus() ); return *this; } @@ -195,8 +203,7 @@ template class TProb { #ifdef DAI_DEBUG assert( size() == q.size() ); #endif - for( size_t i = 0; i < size(); i++ ) - _p[i] -= q[i]; + std::transform( _p.begin(), _p.end(), q._p.begin(), _p.begin(), std::minus() ); return *this; } @@ -215,12 +222,12 @@ template class TProb { #ifdef DAI_DEBUG assert( size() == q.size() ); #endif - TProb sum( *this ); - sum -= q; - return sum; + TProb diff( *this ); + diff -= q; + return diff; } - /// Pointwise division by q + /// Pointwise division by q (division by zero yields zero) TProb& operator/= (const TProb & q) { #ifdef DAI_DEBUG assert( size() == q.size() ); @@ -229,7 +236,7 @@ template class TProb { #ifdef DAI_DEBUG // assert( q[i] != 0.0 ); #endif - if( q[i] == 0.0 ) // FIXME + if( q[i] == 0.0 ) _p[i] = 0.0; else _p[i] /= q[i]; @@ -237,13 +244,12 @@ template class TProb { return *this; } - /// Pointwise division by q, division by zero yields infinity + /// Pointwise division by q (division by zero yields infinity) TProb& divide (const TProb & q) { #ifdef DAI_DEBUG assert( size() == q.size() ); #endif - for( size_t i = 0; i < size(); i++ ) - _p[i] /= q[i]; + std::transform( _p.begin(), _p.end(), q._p.begin(), _p.begin(), std::divides() ); return *this; } @@ -276,49 +282,55 @@ template class TProb { /// Return *this to the power of a (pointwise) TProb& operator^= (Real a) { - if( a != 1.0 ) { - for( size_t i = 0; i < size(); i++ ) - _p[i] = std::pow( _p[i], a ); - } + if( a != 1.0 ) + std::transform( _p.begin(), _p.end(), _p.begin(), std::bind2nd( std::ptr_fun(std::pow), a) ); return *this; } /// Pointwise power of a TProb operator^ (Real a) const { - TProb power; - if( a != 1.0 ) { - power._p.reserve( size() ); - for( size_t i = 0; i < size(); i++ ) - power._p.push_back( std::pow( _p[i], a ) ); - } else - power = *this; + TProb power(*this); + power ^= a; return power; } /// Pointwise exp - TProb exp() const { - TProb e; - e._p.reserve( size() ); + const TProb& takeExp() { + std::transform( _p.begin(), _p.end(), _p.begin(), std::ptr_fun(std::exp) ); + return *this; + } + + /// Pointwise log + const TProb& takeLog() { + std::transform( _p.begin(), _p.end(), _p.begin(), std::ptr_fun(std::log) ); + return *this; + } + + /// Pointwise log (or 0 if == 0) + const TProb& takeLog0() { for( size_t i = 0; i < size(); i++ ) - e._p.push_back( std::exp( _p[i] ) ); + _p[i] = ( (_p[i] == 0.0) ? 0.0 : std::log( _p[i] ) ); + return *this; + } + + /// Pointwise exp + TProb exp() const { + TProb e(*this); + e.takeExp(); return e; } /// Pointwise log TProb log() const { - TProb l; - l._p.reserve( size() ); - for( size_t i = 0; i < size(); i++ ) - l._p.push_back( std::log( _p[i] ) ); + TProb l(*this); + l.takeLog(); return l; } /// Pointwise log (or 0 if == 0) TProb log0() const { - TProb l0; - l0._p.reserve( size() ); - for( size_t i = 0; i < size(); i++ ) - l0._p.push_back( (_p[i] == 0.0) ? 0.0 : std::log( _p[i] ) ); + TProb l0(*this); + l0.takeLog0(); return l0; } @@ -378,15 +390,13 @@ template class TProb { /// Return sum of all entries T totalSum() const { - T Z = 0.0; - for( size_t i = 0; i < size(); i++ ) - Z += _p[i]; + T Z = std::accumulate( _p.begin(), _p.end(), (T)0 ); return Z; } /// Converts entries to Real and returns maximum absolute value T maxAbs() const { - T Z = 0.0; + T Z = 0; for( size_t i = 0; i < size(); i++ ) { Real mag = fabs( (Real) _p[i] ); if( mag > Z ) @@ -397,11 +407,7 @@ template class TProb { /// Returns maximum value T max() const { - T Z = 0.0; - for( size_t i = 0; i < size(); i++ ) { - if( _p[i] > Z ) - Z = _p[i]; - } + T Z = *std::max_element( _p.begin(), _p.end() ); return Z; } @@ -415,47 +421,30 @@ template class TProb { #ifdef DAI_DEBUG assert( Z != 0.0 ); #endif - T Zi = 1.0 / Z; - for( size_t i = 0; i < size(); i++ ) - _p[i] *= Zi; + *this /= Z; return Z; } /// Return normalized copy of *this, using the specified norm TProb normalized( NormType norm ) const { - T Z = 0.0; - if( norm == NORMPROB ) - Z = totalSum(); - else if( norm == NORMLINF ) - Z = maxAbs(); -#ifdef DAI_DEBUG - assert( Z != 0.0 ); -#endif - Z = 1.0 / Z; - - TProb result; - result._p.reserve( size() ); - for( size_t i = 0; i < size(); i++ ) - result._p.push_back( _p[i] * Z ); + TProb result(*this); + result.normalize( norm ); return result; } /// Returns true if one or more entries are NaN bool hasNaNs() const { - bool NaNs = false; - for( size_t i = 0; i < size() && !NaNs; i++ ) - if( isnan( _p[i] ) ) - NaNs = true; - return NaNs; + return (std::find_if( _p.begin(), _p.end(), isnan ) != _p.end()); } /// Returns true if one or more entries are negative bool hasNegatives() const { - bool Negatives = false; - for( size_t i = 0; i < size() && !Negatives; i++ ) - if( _p[i] < 0.0 ) - Negatives = true; - return Negatives; + return (std::find_if( _p.begin(), _p.end(), std::bind2nd( std::less(), 0.0 ) ) != _p.end()); + } + + /// Returns true if one or more entries are non-positive (causes problems with logscale) + bool hasNonPositives() const { + return (std::find_if( _p.begin(), _p.end(), std::bind2nd( std::less_equal(), 0.0 ) ) != _p.end()); } /// Returns (complex) entropy @@ -467,8 +456,7 @@ template class TProb { } friend std::ostream& operator<< (std::ostream& os, const TProb& P) { - for( size_t i = 0; i < P.size(); i++ ) - os << P._p[i] << " "; + std::copy( P._p.begin(), P._p.end(), std::ostream_iterator(os, " ") ); os << std::endl; return os; } -- 2.20.1