Merge branch 'vaskeEmFix' of git://disco.cse.ucsc.edu/libDAI into mergeVaskeEmFix
authorJoris Mooij <joris.mooij@tuebingen.mpg.de>
Tue, 8 Sep 2009 07:57:19 +0000 (09:57 +0200)
committerJoris Mooij <joris.mooij@tuebingen.mpg.de>
Tue, 8 Sep 2009 07:57:19 +0000 (09:57 +0200)
31 files changed:
ChangeLog
doxygen.conf
include/dai/bbp.h
include/dai/bipgraph.h
include/dai/cbp.h
include/dai/clustergraph.h
include/dai/daialg.h
include/dai/doc.h
include/dai/enum.h
include/dai/exceptions.h
include/dai/factor.h
include/dai/factorgraph.h
include/dai/lc.h
include/dai/prob.h
include/dai/properties.h
include/dai/util.h
scripts/regenerate-properties
src/alldai.cpp
src/bbp.cpp
src/cbp.cpp
src/daialg.cpp
src/emalg.cpp
src/evidence.cpp
src/exceptions.cpp
src/factorgraph.cpp
src/hak.cpp
src/mr.cpp
src/properties.cpp
src/treeep.cpp
src/util.cpp
tests/testdai.cpp

index 6432dcf..dbe384d 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,7 @@
+* Changed FactorGraph::clamp and DAIAlg::clamp interfaces (the variable to be
+  clamped is now indicated by its index, not as a Var) and marked the old
+  interface as obsolete
+* [Patrick Pletscher] Fixed performance issue in FactorGraph::clamp
 * [Sebastian Nowozin] MEX file dai now also optionally returns the MAP state
   (only for BP)
 * [Sebastian Nowozin] Fixed memory leak in MEX file dai
index c26af9d..00e1c70 100644 (file)
@@ -313,7 +313,7 @@ EXTRACT_STATIC         = YES
 # defined locally in source files will be included in the documentation. 
 # If set to NO only classes defined in header files are included.
 
-EXTRACT_LOCAL_CLASSES  = YES
+EXTRACT_LOCAL_CLASSES  = NO
 
 # This flag is only useful for Objective-C code. When set to YES local 
 # methods, which are defined in the implementation section but not in 
@@ -1258,7 +1258,8 @@ PREDEFINED             = DAI_WITH_BP \
                          DAI_WITH_MR \
                          DAI_WITH_CBP \
                          DAI_ACCMUT \
-                         DAI_DEBUG
+                         DAI_DEBUG \
+                         DAI_DEBASSERT
 
 # If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then 
 # this tag can be used to specify a list of macro names that should be expanded. 
index 2973471..736ffcd 100644 (file)
@@ -343,6 +343,10 @@ Real getCostFn( const InfAlg &fg, bbp_cfn_t cfn_type, const std::vector<size_t>
 
 /// Function to test the validity of adjoints computed by BBP given a state for each variable using numerical derivatives.
 /** Factors containing a variable are multiplied by psi_1 adjustments to verify accuracy of _adj_psi_V.
+ *  \param bp BP object.
+ *  \param state Global state of all variables.
+ *  \param bbp_props BBP Properties.
+ *  \param cfn Cost function to be used.
  *  \param h controls size of perturbation.
  */
 double numericBBPTest( const InfAlg &bp, const std::vector<size_t> *state, const PropertySet &bbp_props, bbp_cfn_t cfn, double h );
index 15845de..83053d4 100644 (file)
@@ -146,6 +146,7 @@ class BipartiteGraph {
             std::vector<size_t> ind2;       // indices of nodes of type 2
         };
 
+        // OBSOLETE
         /// @name Backwards compatibility layer (to be removed soon)
         //@{
         /// Enable backwards compatibility layer?
@@ -184,65 +185,49 @@ class BipartiteGraph {
 
         /// Returns constant reference to the _i2'th neighbor of node i1 of type 1
         const Neighbor & nb1( size_t i1, size_t _i2 ) const { 
-#ifdef DAI_DEBUG
-            assert( i1 < _nb1.size() );
-            assert( _i2 < _nb1[i1].size() );
-#endif
+            DAI_DEBASSERT( i1 < _nb1.size() );
+            DAI_DEBASSERT( _i2 < _nb1[i1].size() );
             return _nb1[i1][_i2]; 
         }
         /// Returns reference to the _i2'th neighbor of node i1 of type 1
         Neighbor & nb1( size_t i1, size_t _i2 ) {
-#ifdef DAI_DEBUG
-            assert( i1 < _nb1.size() );
-            assert( _i2 < _nb1[i1].size() );
-#endif
+            DAI_DEBASSERT( i1 < _nb1.size() );
+            DAI_DEBASSERT( _i2 < _nb1[i1].size() );
             return _nb1[i1][_i2]; 
         }
 
         /// Returns constant reference to the _i1'th neighbor of node i2 of type 2
         const Neighbor & nb2( size_t i2, size_t _i1 ) const { 
-#ifdef DAI_DEBUG
-            assert( i2 < _nb2.size() );
-            assert( _i1 < _nb2[i2].size() );
-#endif
+            DAI_DEBASSERT( i2 < _nb2.size() );
+            DAI_DEBASSERT( _i1 < _nb2[i2].size() );
             return _nb2[i2][_i1]; 
         }
         /// Returns reference to the _i1'th neighbor of node i2 of type 2
         Neighbor & nb2( size_t i2, size_t _i1 ) { 
-#ifdef DAI_DEBUG
-            assert( i2 < _nb2.size() );
-            assert( _i1 < _nb2[i2].size() );
-#endif
+            DAI_DEBASSERT( i2 < _nb2.size() );
+            DAI_DEBASSERT( _i1 < _nb2[i2].size() );
             return _nb2[i2][_i1]; 
         }
 
         /// Returns constant reference to all neighbors of node i1 of type 1
         const Neighbors & nb1( size_t i1 ) const { 
-#ifdef DAI_DEBUG
-            assert( i1 < _nb1.size() );
-#endif
+            DAI_DEBASSERT( i1 < _nb1.size() );
             return _nb1[i1]; 
         }
         /// Returns reference to all neighbors of node of i1 type 1
         Neighbors & nb1( size_t i1 ) { 
-#ifdef DAI_DEBUG
-            assert( i1 < _nb1.size() );
-#endif
+            DAI_DEBASSERT( i1 < _nb1.size() );
             return _nb1[i1]; 
         }
 
         /// Returns constant reference to all neighbors of node i2 of type 2
         const Neighbors & nb2( size_t i2 ) const { 
-#ifdef DAI_DEBUG
-            assert( i2 < _nb2.size() );
-#endif
+            DAI_DEBASSERT( i2 < _nb2.size() );
             return _nb2[i2]; 
         }
         /// Returns reference to all neighbors of node i2 of type 2
         Neighbors & nb2( size_t i2 ) { 
-#ifdef DAI_DEBUG
-            assert( i2 < _nb2.size() );
-#endif
+            DAI_DEBASSERT( i2 < _nb2.size() );
             return _nb2[i2]; 
         }
 
@@ -373,6 +358,7 @@ class BipartiteGraph {
         /// Writes this BipartiteGraph to an output stream in GraphViz .dot syntax
         void printDot( std::ostream& os ) const;
 
+        // OBSOLETE
         /// @name Backwards compatibility layer (to be removed soon)
         //@{
         void indexEdges() {
index 2a562e1..d0a03d7 100644 (file)
@@ -209,7 +209,7 @@ class CBP : public DAIAlgFG {
             double rec_tol;
             /// Maximum number of levels of recursion (\a recurse is REC_FIXED)
             size_t max_levels;
-            /// If choose=CHOOSE_BBP and maximum adjoint is less than this value, don't recurse
+            /// If choose==CHOOSE_BBP and maximum adjoint is less than this value, don't recurse
             double min_max_adj;
             /// Heuristic for choosing clamping variable
             ChooseMethodType choose;
index 654fbbc..cbea8ca 100644 (file)
@@ -68,9 +68,7 @@ namespace dai {
             
             /// Returns true if cluster I is not contained in a larger cluster
             bool isMaximal( size_t I ) const {
-#ifdef DAI_DEBUG
-                assert( I < G.nr2() );
-#endif
+                DAI_DEBASSERT( I < G.nr2() );
                 const VarSet & clI = clusters[I];
                 bool maximal = true;
                 // The following may not be optimal, since it may repeatedly test the same cluster *J
index 4dbae3a..2d5274f 100644 (file)
@@ -98,8 +98,14 @@ class InfAlg {
          */
         virtual double run() = 0;
 
-        /// Clamp variable n to value i (i.e. multiply with a Kronecker delta \f$\delta_{x_n, i}\f$)
-        virtual void clamp( const Var & n, size_t i, bool backup = false ) = 0;
+        /// Clamp variable with index i to value x (i.e. multiply with a Kronecker delta \f$\delta_{x_i, x}\f$)
+        /** If backup == true, make a backup of all factors that are changed
+         */
+        virtual void clamp( size_t i, size_t x, bool backup = false ) = 0;
+
+        // OBSOLETE
+        /// Only for backwards compatibility (to be removed soon)
+        virtual void clamp( const Var &v, size_t x, bool backup = false ) = 0;
 
         /// Set all factors interacting with var(i) to 1
         virtual void makeCavity( size_t i, bool backup = false ) = 0;
@@ -158,8 +164,15 @@ class DAIAlg : public InfAlg, public GRM {
         /// Restore Factors involving ns
         void restoreFactors( const VarSet &ns ) { GRM::restoreFactors( ns ); }
 
-        /// Clamp variable n to value i (i.e. multiply with a Kronecker delta \f$\delta_{x_n, i}\f$)
-        void clamp( const Var & n, size_t i, bool backup = false ) { GRM::clamp( n, i, backup ); }
+        /// Clamp variable with index i to value x (i.e. multiply with a Kronecker delta \f$\delta_{x_i, x}\f$)
+        void clamp( size_t i, size_t x, bool backup = false ) { GRM::clamp( i, x, backup ); }
+
+        // OBSOLETE
+        /// Only for backwards compatibility (to be removed soon)
+        void clamp( const Var &v, size_t x, bool backup = false ) { 
+            GRM::clamp( v, x, backup );
+            std::cerr << "Warning: this DAIAlg<...>::clamp(const Var&,...) interface is obsolete!" << std::endl;
+        }
 
         /// Set all factors interacting with var(i) to 1
         void makeCavity( size_t i, bool backup = false ) { GRM::makeCavity( i, backup ); }
index e7f9071..1e5686b 100644 (file)
@@ -93,7 +93,7 @@
  *
  *  \section discuss_templates Polymorphism by template parameterization
  *  Instead of polymorphism by inheritance, use polymorphism by template parameterization. 
- *  For example, the real reason for introducing the complicated inheritance scheme of InfAlg
+ *  For example, the real reason for introducing the complicated inheritance scheme of dai::InfAlg
  *  was for functions like dai::calcMarginal. Instead, one could use a template function:
  *  \code
  *  template<typename InfAlg>
  *  \date October 10, 2008
  *
  *  \section about About libDAI
- *  libDAI is a free/open source C++ library (licensed under GPL) that provides
+ *  libDAI is a free/open source C++ library (licensed under GPLv2+) that provides
  *  implementations of various (approximate) inference methods for discrete 
  *  graphical models. libDAI supports arbitrary factor graphs with discrete 
  *  variables; this includes discrete Markov Random Fields and Bayesian 
  *  Networks.
  *
- *  The library is targeted at researchers; to be able to use the library, a 
+ *  The library is targeted at researchers. To be able to use the library, a 
  *  good understanding of graphical models is needed. 
  *
  *  \section limitations Limitations
  *  various inference methods. In particular, it contains no GUI, currently 
  *  only supports its own file format for input and output (although support 
  *  for standard file formats may be added later), and provides very limited
- *  visualization functionalities.
+ *  visualization functionalities. The only learning method supported currently
+ *  is EM for learning factor parameters.
  *
  *  \section features Features
  *  Currently, libDAI supports the following (approximate) inference methods:
index 491cd35..637291e 100644 (file)
         x(value w) : v(w) {}\
 \
         x(char const *w) {\
-            static char const* labelstring = #val0 "," #__VA_ARGS__ ",";\
+            static char const* labelstring = #val0 "," #__VA_ARGS__;\
             size_t pos_begin = 0;\
             size_t i = 0;\
-            for( size_t pos_end = 0; labelstring[pos_end] != '\0'; pos_end++ )\
-                if( (labelstring[pos_end] == ',') ) {\
+            for( size_t pos_end = 0; ; pos_end++ ) {\
+                if( (labelstring[pos_end] == ',') || (labelstring[pos_end] == '\0') ) {\
                     if( (strlen( w ) == pos_end - pos_begin) && (strncmp( labelstring + pos_begin, w, pos_end - pos_begin ) == 0) ) {\
                         v = (value)i;\
                         return;\
                         pos_begin = pos_end + 1;\
                     }\
                 }\
-            DAI_THROW(UNKNOWN_ENUM_VALUE);\
+                if( labelstring[pos_end] == '\0' )\
+                    break;\
+            }\
+            DAI_THROWE(UNKNOWN_ENUM_VALUE,"'" + std::string(w) + "' is not in [" + std::string(labelstring) + "]");\
         }\
 \
         operator value() const { return v; }\
index 6023df0..bf5c338 100644 (file)
@@ -32,6 +32,7 @@
 #include <exception>
 #include <stdexcept>
 #include <string>
+#include <iostream>
 
 
 /// Used by DAI_THROW
 /// Used by DAI_THROW
 #define DAI_TOSTRING(x) DAI_QUOTE(x)
 
-/// Macro that simplifies throwing an exceptions with a useful error message
+/// Macro that simplifies throwing an exception with a useful error message.
 /** \param cod Corresponds to one of the enum values in dai::Exception::codes
  *
- * Example:
+ *  Example:
  *  \code
  *  DAI_THROW(NOT_IMPLEMENTED);
  *  \endcode
  */
 #define DAI_THROW(cod) throw dai::Exception(dai::Exception::cod, std::string(__FILE__ ", line " DAI_TOSTRING(__LINE__)))
 
+/// Macro that simplifies throwing an exception with a useful error message. It also allows for writing a detailed error message to stderr.
+/** \param cod Corresponds to one of the enum values in dai::Exception::codes
+ *  \param msg Detailed error message that will be written to std::cerr.
+ *
+ *  Example:
+ *  \code
+ *  DAI_THROWE(NOT_IMPLEMENTED,"Detailed error message");
+ *  \endcode
+ */
+#define DAI_THROWE(cod,msg) throw dai::Exception(dai::Exception::cod, std::string(__FILE__ ", line " DAI_TOSTRING(__LINE__)), msg)
+
 
 namespace dai {
 
@@ -71,18 +83,20 @@ class Exception : public std::runtime_error {
                    FACTORGRAPH_NOT_CONNECTED,
                    IMPOSSIBLE_TYPECAST,
                    INTERNAL_ERROR,
+                   RUNTIME_ERROR,
                    NOT_NORMALIZABLE,
                    INVALID_EVIDENCE_FILE,
-                   INVALID_EVIDENCE_LINE,
-                   INVALID_EVIDENCE_OBSERVATION,
-                   INVALID_SHARED_PARAMETERS_ORDER,
-                   INVALID_SHARED_PARAMETERS_INPUT_LINE,
+                   INVALID_EMALG_FILE,
                    UNKNOWN_PARAMETER_ESTIMATION_METHOD,
+                   OBJECT_NOT_FOUND,
                    NUM_ERRORS};  // NUM_ERRORS should be the last entry
 
         /// Constructor
-        Exception( Code _code, const std::string& msg="" ) : std::runtime_error(ErrorStrings[_code] + " [" +  msg + "]"), errorcode(_code) {}
-
+        Exception( Code _code, const std::string& msg="", const std::string& detailedMsg="" ) : std::runtime_error(ErrorStrings[_code] + " [" +  msg + "]"), errorcode(_code) { 
+            if( !detailedMsg.empty() ) 
+                std::cerr << "ERROR: " << detailedMsg << std::endl; 
+        }
+        
         /// Copy constructor
         Exception( const Exception &e ) : std::runtime_error(e), errorcode(e.errorcode) {}
 
index 1427002..6b04966 100644 (file)
 #include <dai/prob.h>
 #include <dai/varset.h>
 #include <dai/index.h>
+#include <dai/util.h>
 
 
 namespace dai {
 
 
-/// Function object similar to std::divides(), but different in that dividing by zero results in zero
+// Function object similar to std::divides(), but different in that dividing by zero results in zero
 template<typename T> struct divides0 : public std::binary_function<T, T, T> {
+    // Returns (j == 0 ? 0 : (i/j))
     T operator()(const T& i, const T& j) const {
         if( j == (T)0 )
             return (T)0;
@@ -109,9 +111,7 @@ template <typename T> class TFactor {
 
         /// Constructs TFactor depending on variables in ns, with values set to the TProb p
         TFactor( const VarSet& ns, const TProb<T>& p ) : _vs(ns), _p(p) {
-#ifdef DAI_DEBUG
-            assert( _vs.nrStates() == _p.size() );
-#endif
+            DAI_DEBASSERT( _vs.nrStates() == _p.size() );
         }
         TFactor( const std::vector< Var >& vars, const std::vector< T >& p ) : _vs(vars.begin(), vars.end(), vars.size()), _p(p.size()) {
             Permute permindex(vars);
@@ -460,6 +460,7 @@ template<typename T> TFactor<T> TFactor<T>::maxMarginal(const VarSet & ns, bool
 }
 
 
+/// Apply binary operator pointwise on two factors
 template<typename T, typename binaryOp> TFactor<T> pointwiseOp( const TFactor<T> &f, const TFactor<T> &g, binaryOp op ) {
     if( f.vars() == g.vars() ) { // optimizate special case
         TFactor<T> result(f); 
@@ -481,11 +482,9 @@ template<typename T, typename binaryOp> TFactor<T> pointwiseOp( const TFactor<T>
 
 
 template<typename T> T TFactor<T>::strength( const Var &i, const Var &j ) const {
-#ifdef DAI_DEBUG
-    assert( _vs.contains( i ) );
-    assert( _vs.contains( j ) );
-    assert( i != j );
-#endif
+    DAI_DEBASSERT( _vs.contains( i ) );
+    DAI_DEBASSERT( _vs.contains( j ) );
+    DAI_DEBASSERT( i != j );
     VarSet ij(i, j);
 
     T max = 0.0;
@@ -531,9 +530,7 @@ template<typename T> Real dist( const TFactor<T> &f, const TFactor<T> &g, Prob::
     if( f.vars().empty() || g.vars().empty() )
         return -1;
     else {
-#ifdef DAI_DEBUG
-        assert( f.vars() == g.vars() );
-#endif
+        DAI_DEBASSERT( f.vars() == g.vars() );
         return dist( f.p(), g.p(), dt );
     }
 }
index 5beae95..4e53ae4 100644 (file)
@@ -157,9 +157,10 @@ class FactorGraph {
         Neighbor & nbF( size_t I, size_t _i ) { return G.nb2(I)[_i]; }
 
         /// Returns the index of a particular variable
-        size_t findVar( const Var & n ) const {
+        size_t findVar( const Var &n ) const {
             size_t i = find( vars().begin(), vars().end(), n ) - vars().begin();
-            assert( i != nrVars() );
+            if( i == nrVars() )
+                DAI_THROW(OBJECT_NOT_FOUND);
             return i;
         }
 
@@ -172,12 +173,13 @@ class FactorGraph {
         }
 
         /// Returns index of the first factor that depends on the variables
-        size_t findFactor(const VarSet &ns) const {
+        size_t findFactor( const VarSet &ns ) const {
             size_t I;
             for( I = 0; I < nrFactors(); I++ )
                 if( factor(I).vars() == ns )
                     break;
-            assert( I != nrFactors() );
+            if( I == nrFactors() )
+                DAI_THROW(OBJECT_NOT_FOUND);
             return I;
         }
 
@@ -212,10 +214,17 @@ class FactorGraph {
             }
         }
 
-        /// Clamp variable n to value i (i.e. multiply with a Kronecker delta \f$\delta_{x_n, i}\f$)
+        /// Clamp variable with index i to value x (i.e. multiply with a Kronecker delta \f$\delta_{x_i, x}\f$)
         /** If backup == true, make a backup of all factors that are changed
          */
-        virtual void clamp( const Var & n, size_t i, bool backup = false );
+        virtual void clamp( size_t i, size_t x, bool backup = false );
+
+        // OBSOLETE
+        /// Only for backwards compatibility (to be removed soon)
+        virtual void clamp( const Var &v, size_t x, bool backup = false ) { 
+            std::cerr << "Warning: this FactorGraph::clamp(const Var&,...) interface is obsolete!" << std::endl;
+            clamp( findVar(v), x, backup );
+        }
 
         /// Clamp a variable in a factor graph to have one out of a list of values
         /** If backup == true, make a backup of all factors that are changed
@@ -249,10 +258,10 @@ class FactorGraph {
         bool isBinary() const;
 
         /// Reads a FactorGraph from a file
-        void ReadFromFile(const char *filename);
+        void ReadFromFile( const char *filename );
 
         /// Writes a FactorGraph to a file
-        void WriteToFile(const char *filename, size_t precision=15) const;
+        void WriteToFile( const char *filename, size_t precision=15 ) const;
 
         /// Writes a FactorGraph to a GraphViz .dot file
         void printDot( std::ostream& os ) const;
@@ -260,11 +269,11 @@ class FactorGraph {
         /// Returns the cliques in this FactorGraph
         std::vector<VarSet> Cliques() const;
 
-        /// Clamp variable v_i to value state (i.e. multiply with a Kronecker delta \f$\delta_{x_{v_i},x}\f$);
+        /// Clamp variable v to value x (i.e. multiply with a Kronecker delta \f$\delta_{x_v,x}\f$);
         /** This version changes the factor graph structure and thus returns a newly constructed FactorGraph
          *  and keeps the current one constant, contrary to clamp()
          */
-        FactorGraph clamped( const Var & v_i, size_t x ) const;
+        FactorGraph clamped( const Var &v, size_t x ) const;
 
         /// Returns a copy of *this, where all factors that are subsumed by some larger factor are merged with the larger factors.
         FactorGraph maximalFactors() const;
@@ -280,10 +289,12 @@ class FactorGraph {
         /// Restores all factors connected to a set of variables from their backups
         void restoreFactors( const VarSet &ns );
 
-        // Friends
-        friend std::ostream& operator << (std::ostream& os, const FactorGraph& fg);
-        friend std::istream& operator >> (std::istream& is, FactorGraph& fg);
+        /// Writes a FactorGraph to an output stream
+        friend std::ostream& operator<< (std::ostream &os, const FactorGraph &fg );
+        /// Reads a FactorGraph from an input stream
+        friend std::istream& operator>> (std::istream &is, FactorGraph &fg );
 
+        // OBSOLETE
         /// @name Backwards compatibility layer (to be removed soon)
         //@{
         size_t VV2E(size_t n1, size_t n2) const { return G.VV2E(n1,n2); }
index 536dc8d..1acdab6 100644 (file)
@@ -119,6 +119,7 @@ class LC : public DAIAlgFG {
         virtual size_t Iterations() const { return _iters; }
         //@}
 
+        Factor beliefV( size_t i ) const { return _beliefs[i]; }
 
         /// @name Additional interface specific for LC
         //@{ 
index 4b85374..d7e483f 100644 (file)
@@ -180,9 +180,7 @@ template <typename T> class TProb {
 
         /// Divides each entry by scalar x
         TProb<T>& operator/= (T x) {
-#ifdef DAI_DEBUG
-            assert( x != 0.0 );
-#endif
+            DAI_DEBASSERT( x != 0.0 );
             std::transform( _p.begin(), _p.end(), _p.begin(), std::bind2nd( std::divides<T>(), x ) );
             return *this;
         }
@@ -222,9 +220,7 @@ template <typename T> class TProb {
 
         /// Lexicographical comparison (sizes should be identical)
         bool operator<= (const TProb<T> & q) const {
-#ifdef DAI_DEBUG
-            assert( size() == q.size() );
-#endif
+            DAI_DEBASSERT( size() == q.size() );
             for( size_t i = 0; i < size(); i++ )
                 if( !(_p[i] <= q[i]) )
                     return false;
@@ -233,18 +229,14 @@ template <typename T> class TProb {
 
         /// Pointwise multiplication with q (sizes should be identical)
         TProb<T>& operator*= (const TProb<T> & q) {
-#ifdef DAI_DEBUG
-            assert( size() == q.size() );
-#endif
+            DAI_DEBASSERT( size() == q.size() );
             std::transform( _p.begin(), _p.end(), q._p.begin(), _p.begin(), std::multiplies<T>() );
             return *this;
         }
         
         /// Return product of *this with q (sizes should be identical)
         TProb<T> operator* (const TProb<T> & q) const {
-#ifdef DAI_DEBUG
-            assert( size() == q.size() );
-#endif
+            DAI_DEBASSERT( size() == q.size() );
             TProb<T> prod( *this );
             prod *= q;
             return prod;
@@ -252,18 +244,14 @@ template <typename T> class TProb {
 
         /// Pointwise addition with q (sizes should be identical)
         TProb<T>& operator+= (const TProb<T> & q) {
-#ifdef DAI_DEBUG
-            assert( size() == q.size() );
-#endif
+            DAI_DEBASSERT( size() == q.size() );
             std::transform( _p.begin(), _p.end(), q._p.begin(), _p.begin(), std::plus<T>() );
             return *this;
         }
         
         /// Returns sum of *this and q (sizes should be identical)
         TProb<T> operator+ (const TProb<T> & q) const {
-#ifdef DAI_DEBUG
-            assert( size() == q.size() );
-#endif
+            DAI_DEBASSERT( size() == q.size() );
             TProb<T> sum( *this );
             sum += q;
             return sum;
@@ -271,18 +259,14 @@ template <typename T> class TProb {
         
         /// Pointwise subtraction of q (sizes should be identical)
         TProb<T>& operator-= (const TProb<T> & q) {
-#ifdef DAI_DEBUG
-            assert( size() == q.size() );
-#endif
+            DAI_DEBASSERT( size() == q.size() );
             std::transform( _p.begin(), _p.end(), q._p.begin(), _p.begin(), std::minus<T>() );
             return *this;
         }
-        
+
         /// Return *this minus q (sizes should be identical)
-        TProb<T> operator- (const TProb<T> & q) const {
-#ifdef DAI_DEBUG
-            assert( size() == q.size() );
-#endif
+        Prob<T> operator- (const TProb<T> & q) const {
+            DAI_DEBASSERT( size() == q.size() );
             TProb<T> diff( *this );
             diff -= q;
             return diff;
@@ -290,9 +274,7 @@ template <typename T> class TProb {
 
         /// Pointwise division by q, where division by 0 yields 0 (sizes should be identical)
         TProb<T>& operator/= (const TProb<T> & q) {
-#ifdef DAI_DEBUG
-            assert( size() == q.size() );
-#endif
+            DAI_DEBASSERT( size() == q.size() );
             for( size_t i = 0; i < size(); i++ ) {
                 if( q[i] == 0.0 )
                     _p[i] = 0.0;
@@ -304,18 +286,14 @@ template <typename T> class TProb {
         
         /// Pointwise division by q, where division by 0 yields +Inf (sizes should be identical)
         TProb<T>& divide (const TProb<T> & q) {
-#ifdef DAI_DEBUG
-            assert( size() == q.size() );
-#endif
+            DAI_DEBASSERT( size() == q.size() );
             std::transform( _p.begin(), _p.end(), q._p.begin(), _p.begin(), std::divides<T>() );
             return *this;
         }
         
         /// Returns quotient of *this with q (sizes should be identical)
         TProb<T> operator/ (const TProb<T> & q) const {
-#ifdef DAI_DEBUG
-            assert( size() == q.size() );
-#endif
+            DAI_DEBASSERT( size() == q.size() );
             TProb<T> quot( *this );
             quot /= q;
             return quot;
@@ -521,9 +499,7 @@ template <typename T> class TProb {
 /** \relates TProb
  */
 template<typename T> Real dist( const TProb<T> &p, const TProb<T> &q, typename TProb<T>::DistType dt ) {
-#ifdef DAI_DEBUG
-    assert( p.size() == q.size() );
-#endif
+    DAI_DEBASSERT( p.size() == q.size() );
     Real result = 0.0;
     switch( dt ) {
         case TProb<T>::DISTL1:
index 9539d5c..8db7907 100644 (file)
@@ -38,6 +38,7 @@
 #include <typeinfo>
 #include <dai/exceptions.h>
 #include <dai/util.h>
+#include <boost/lexical_cast.hpp>
 
 
 namespace dai {
@@ -87,9 +88,8 @@ class PropertySet : private std::map<PropertyKey, PropertyValue> {
         /// Set properties according to those in newProps, overriding properties that already exist with new values
         PropertySet & Set( const PropertySet &newProps ) {
             const std::map<PropertyKey, PropertyValue> *m = &newProps;
-            foreach(value_type i, *m) {
-                Set(i.first, i.second);
-            }
+            foreach(value_type i, *m)
+                Set( i.first, i.second );
             return *this;
         }
 
@@ -99,9 +99,8 @@ class PropertySet : private std::map<PropertyKey, PropertyValue> {
             try {
                 return boost::any_cast<ValueType>(Get(key));
             } catch( const boost::bad_any_cast & ) {
-                std::cerr << "Cannot cast property " << key << " to ";
-                std::cerr << typeid(ValueType).name() << std::endl;
-                return boost::any_cast<ValueType>(Get(key));
+                DAI_THROWE(IMPOSSIBLE_TYPECAST,"Cannot cast value of property '" + key + "' to desired type.");
+                return ValueType();
             }
         }
 
@@ -111,13 +110,11 @@ class PropertySet : private std::map<PropertyKey, PropertyValue> {
             PropertyValue val = Get(key);
             if( val.type() != typeid(ValueType) ) {
                 assert( val.type() == typeid(std::string) );
-
-                std::stringstream ss;
-                ss << GetAs<std::string>(key);
-                ValueType result;
-                ss >> result;
-
-                Set(key, result);
+                try {
+                    Set(key, boost::lexical_cast<ValueType>(GetAs<std::string>(key)));
+                } catch(boost::bad_lexical_cast &) {
+                    DAI_THROWE(IMPOSSIBLE_TYPECAST,"Cannot cast value of property '" + key + "' from string to desired type.");
+                }
             }
         }
 
@@ -128,26 +125,23 @@ class PropertySet : private std::map<PropertyKey, PropertyValue> {
             if( val.type() == typeid(ValueType) ) {
                 return boost::any_cast<ValueType>(val);
             } else if( val.type() == typeid(std::string) ) {
-                std::stringstream ss;
-                ss << GetAs<std::string>(key);
-                ValueType result;
-                ss >> result;
-                return result;
-            } else {
-                DAI_THROW(IMPOSSIBLE_TYPECAST);
-                return ValueType();
-            }
+                try {
+                    return boost::lexical_cast<ValueType>(GetAs<std::string>(key));
+                } catch(boost::bad_lexical_cast &) {
+                    DAI_THROWE(IMPOSSIBLE_TYPECAST,"Cannot cast value of property '" + key + "' from string to desired type.");
+                }
+            } else
+                DAI_THROWE(IMPOSSIBLE_TYPECAST,"Cannot cast value of property '" + key + "' from string to desired type.");
+            return ValueType();
         }
 
         /// Converts a property from ValueType to string (if necessary)
         template<typename ValueType>
         PropertySet & setAsString(const PropertyKey &key, ValueType &val) { 
-            if( val.type() == typeid(std::string) ) {
-                return Set(key, val);
-            } else {
-                std::stringstream ss (std::stringstream::out);
-                ss << val;
-                return Set(key, ss.str());
+            try {
+                return Set( key, boost::lexical_cast<std::string>(val) );
+            } catch( boost::bad_lexical_cast & ) {
+                DAI_THROWE(IMPOSSIBLE_TYPECAST,"Cannot cast value of property '" + key + "' to string.");
             }
         }
 
@@ -176,8 +170,10 @@ class PropertySet : private std::map<PropertyKey, PropertyValue> {
             return res;
         }
 
-        // Friends
+        /// Writes a PropertySet object to an output stream
         friend std::ostream& operator<< (std::ostream & os, const PropertySet & ps);
+
+        /// Reads a PropertySet object from an input stream, storing values as strings
         friend std::istream& operator>> (std::istream& is, PropertySet & ps);
 };
 
index 89c1dee..3f61623 100644 (file)
 #define __defined_libdai_util_h
 
 
+#include <string>
 #include <vector>
 #include <set>
 #include <map>
 #include <iostream>
-#include <cstdio>
 #include <boost/foreach.hpp>
 #include <boost/functional/hash.hpp>
 #include <algorithm>
 #define DAI_PV(x) do {std::cerr << #x "= " << (x) << std::endl;} while(0)
 /// "Debugging message": Prints a message (only if DAI_DEBUG is defined)
 #define DAI_DMSG(str) do {std::cerr << str << std::endl;} while(0)
+/// Assertion if DAI_DEBUG is defined
+#define DAI_DEBASSERT(x) do {assert(x);} while(0)
 #else
 #define DAI_PV(x) do {} while(0)
 #define DAI_DMSG(str) do {} while(0)
+#define DAI_DEBASSERT(X) do {} while(0)
 #endif
 
 /// Produces accessor and mutator methods according to the common pattern.
@@ -187,6 +190,9 @@ std::vector<T> concat( const std::vector<T>& u, const std::vector<T>& v ) {
     return w;
 }
 
+/// Split a string into tokens
+void tokenizeString( const std::string& s, std::vector<std::string>& outTokens, const std::string& delim="\t\n" );
+
 /// Used to keep track of the progress made by iterative algorithms
 class Diffs : public std::vector<double> {
     private:
@@ -221,8 +227,7 @@ class Diffs : public std::vector<double> {
                 } else {
                     _maxpos = begin();
                 }
-            }
-            else {
+            } else {
                 if( _pos == end() )
                     _pos = begin();
                 if( _maxpos == _pos ) {
@@ -240,12 +245,6 @@ class Diffs : public std::vector<double> {
 };
 
 
-/// Split a string into tokens
-void tokenizeString( const std::string& s,
-                   std::vector<std::string>& outTokens,
-                   const std::string& delim="\t\n" );
-
-
 } // end of namespace dai
 
 
index 1c3b45a..f3601b9 100755 (executable)
@@ -194,7 +194,6 @@ void ${class}::Properties::set(const PropertySet &opts)
 {
     const std::set<PropertyKey> &keys = opts.allKeys();
     std::set<PropertyKey>::const_iterator i;
-    bool die=false;
     for(i=keys.begin(); i!=keys.end(); i++) {
 EOF
   for my $v (@vars) {
@@ -204,29 +203,20 @@ EOF
 EOF
   }
   $stext .= <<EOF;
-        cerr << "$class: Unknown property " << *i << endl;
-        die=true;
-    }
-    if(die) {
-        DAI_THROW(UNKNOWN_PROPERTY_TYPE);
+        DAI_THROWE(UNKNOWN_PROPERTY_TYPE, "$class: Unknown property " + *i);
     }
 EOF
   for my $v (@vars) {
     my ($type,$name,$default,$cmt) = @$v;
     if(!defined $default) {
       $stext .= <<EOF;
-    if(!opts.hasKey("$name")) {
-        cerr << "$class: Missing property \\\"$name\\\" for method \\\"\Q$class\E\\\"" << endl;
-        die=true;
-    }
+    if(!opts.hasKey("$name"))
+        DAI_THROWE(NOT_ALL_PROPERTIES_SPECIFIED,"$class: Missing property \\\"$name\\\" for method \\\"\Q$class\E\\\"");
 EOF
     }
 
   }
   $stext .= <<EOF;
-    if(die) {
-        DAI_THROW(NOT_ALL_PROPERTIES_SPECIFIED);
-    }
 EOF
   for my $v (@vars) {
     my ($type,$name,$default,$cmt) = @$v;
index 3c5fbba..1e8733f 100644 (file)
@@ -71,7 +71,7 @@ InfAlg *newInfAlg( const std::string &name, const FactorGraph &fg, const Propert
     if( name == CBP::Name )
         return new CBP (fg, opts);
 #endif
-    DAI_THROW(UNKNOWN_DAI_ALGORITHM);
+    DAI_THROWE(UNKNOWN_DAI_ALGORITHM,"Unknown libDAI algorithm: " + name);
 }
 
 
index 7314a26..15e3672 100644 (file)
@@ -31,6 +31,7 @@ namespace dai {
 using namespace std;
 
 
+/// Convenience typedef
 typedef BipartiteGraph::Neighbor Neighbor;
 
 
@@ -57,6 +58,7 @@ std::vector<size_t> getGibbsState( const InfAlg &ia, size_t iters ) {
 }
 
 
+/// Returns the entry of the I'th factor corresponding to a global state
 size_t getFactorEntryForState( const FactorGraph &fg, size_t I, const vector<size_t> &state ) {
     size_t f_entry = 0;
     for( int _j = fg.nbF(I).size() - 1; _j >= 0; _j-- ) {
@@ -729,10 +731,8 @@ void BBP::run() {
             const BP *bp = static_cast<const BP*>(_ia);
             vector<pair<size_t, size_t> > sentMessages = bp->getSentMessages();
             size_t totalMessages = sentMessages.size();
-            if( totalMessages == 0 ) {
-                cerr << "Asked for updates = " << updates << " but no BP messages; did you forget to set recordSentMessages?" << endl;
-                DAI_THROW(INTERNAL_ERROR);
-            }
+            if( totalMessages == 0 )
+                DAI_THROWE(INTERNAL_ERROR, "Asked for updates=" + std::string(updates) + " but no BP messages; did you forget to set recordSentMessages?");
             if( updates==UT::SEQ_BP_FWD )
                 reverse( sentMessages.begin(), sentMessages.end() );
 //          DAI_PV(sentMessages.size());
@@ -1031,7 +1031,7 @@ void initBBPCostFnAdj( BBP &bbp, const InfAlg &ia, bbp_cfn_t cfn_type, const vec
                         delta[state[i]] = exp(b); 
                         break;
                     default: 
-                        DAI_THROW(INTERNAL_ERROR);
+                        DAI_THROW(UNKNOWN_ENUM_VALUE);
                 }
                 b1_adj.push_back( delta );
             }
@@ -1069,7 +1069,7 @@ void initBBPCostFnAdj( BBP &bbp, const InfAlg &ia, bbp_cfn_t cfn_type, const vec
                         delta[x_I] = exp( b );
                         break;
                     default: 
-                        DAI_THROW(INTERNAL_ERROR);
+                        DAI_THROW(UNKNOWN_ENUM_VALUE);
                 }
                 b2_adj.push_back( delta );
             }
@@ -1116,7 +1116,7 @@ Real getCostFn( const InfAlg &ia, bbp_cfn_t cfn_type, const vector<size_t> *stat
                         cf += exp( b );
                         break;
                     default:
-                        DAI_THROW(INTERNAL_ERROR);
+                        DAI_THROW(UNKNOWN_ENUM_VALUE);
                 }
             }
             break;
@@ -1140,13 +1140,12 @@ Real getCostFn( const InfAlg &ia, bbp_cfn_t cfn_type, const vector<size_t> *stat
                         cf += exp( b );
                         break;
                     default:
-                        DAI_THROW(INTERNAL_ERROR);
+                        DAI_THROW(UNKNOWN_ENUM_VALUE);
                 }
             }
             break;
         } default: 
-            cerr << "Unknown cost function " << cfn_type << endl;
-            DAI_THROW(UNKNOWN_ENUM_VALUE);
+            DAI_THROWE(UNKNOWN_ENUM_VALUE, "Unknown cost function " + std::string(cfn_type));
     }
     return cf;
 }
@@ -1164,42 +1163,24 @@ void BBP::Properties::set(const PropertySet &opts)
 {
     const std::set<PropertyKey> &keys = opts.allKeys();
     std::set<PropertyKey>::const_iterator i;
-    bool die=false;
     for(i=keys.begin(); i!=keys.end(); i++) {
         if(*i == "verbose") continue;
         if(*i == "maxiter") continue;
         if(*i == "tol") continue;
         if(*i == "damping") continue;
         if(*i == "updates") continue;
-        cerr << "BBP: Unknown property " << *i << endl;
-        die=true;
-    }
-    if(die) {
-        DAI_THROW(UNKNOWN_PROPERTY_TYPE);
-    }
-    if(!opts.hasKey("verbose")) {
-        cerr << "BBP: Missing property \"verbose\" for method \"BBP\"" << endl;
-        die=true;
-    }
-    if(!opts.hasKey("maxiter")) {
-        cerr << "BBP: Missing property \"maxiter\" for method \"BBP\"" << endl;
-        die=true;
-    }
-    if(!opts.hasKey("tol")) {
-        cerr << "BBP: Missing property \"tol\" for method \"BBP\"" << endl;
-        die=true;
-    }
-    if(!opts.hasKey("damping")) {
-        cerr << "BBP: Missing property \"damping\" for method \"BBP\"" << endl;
-        die=true;
-    }
-    if(!opts.hasKey("updates")) {
-        cerr << "BBP: Missing property \"updates\" for method \"BBP\"" << endl;
-        die=true;
-    }
-    if(die) {
-        DAI_THROW(NOT_ALL_PROPERTIES_SPECIFIED);
+        DAI_THROWE(UNKNOWN_PROPERTY_TYPE, "BBP: Unknown property " + *i);
     }
+    if(!opts.hasKey("verbose"))
+        DAI_THROWE(NOT_ALL_PROPERTIES_SPECIFIED,"BBP: Missing property \"verbose\" for method \"BBP\"");
+    if(!opts.hasKey("maxiter"))
+        DAI_THROWE(NOT_ALL_PROPERTIES_SPECIFIED,"BBP: Missing property \"maxiter\" for method \"BBP\"");
+    if(!opts.hasKey("tol"))
+        DAI_THROWE(NOT_ALL_PROPERTIES_SPECIFIED,"BBP: Missing property \"tol\" for method \"BBP\"");
+    if(!opts.hasKey("damping"))
+        DAI_THROWE(NOT_ALL_PROPERTIES_SPECIFIED,"BBP: Missing property \"damping\" for method \"BBP\"");
+    if(!opts.hasKey("updates"))
+        DAI_THROWE(NOT_ALL_PROPERTIES_SPECIFIED,"BBP: Missing property \"updates\" for method \"BBP\"");
     verbose = opts.getStringAs<size_t>("verbose");
     maxiter = opts.getStringAs<size_t>("maxiter");
     tol = opts.getStringAs<double>("tol");
@@ -1222,7 +1203,7 @@ string BBP::Properties::toString() const {
     s << "maxiter=" << maxiter << ",";
     s << "tol=" << tol << ",";
     s << "damping=" << damping << ",";
-    s << "updates=" << updates << ",";
+    s << "updates=" << updates;
     s << "]";
     return s.str();
 }
index a5b82f0..a4a5511 100644 (file)
@@ -349,7 +349,7 @@ bool CBP::chooseNextClampVar( InfAlg *bp, vector<size_t> &clamped_vars_list, siz
                 if( bp->beliefV(k)[xk] < tiny ) 
                     continue;
                 InfAlg *bp1 = bp->clone();
-                bp1->clamp( var(k), xk );
+                bp1->clamp( k, xk );
                 bp1->init( var(k) );
                 bp1->run();
                 Real cost = 0;
@@ -405,7 +405,7 @@ bool CBP::chooseNextClampVar( InfAlg *bp, vector<size_t> &clamped_vars_list, siz
             assert(/*0<=xi &&*/ xi < factor(i).states() );
         DAI_IFVERB(2, "CHOOSE_BBP (num clamped = " << clamped_vars_list.size() << ") chose " << i << " state " << xi << endl);
     } else
-        DAI_THROW(INTERNAL_ERROR);
+        DAI_THROW(UNKNOWN_ENUM_VALUE);
     clamped_vars_list.push_back( i );
     return true;
 }
@@ -535,7 +535,6 @@ void CBP::Properties::set(const PropertySet &opts)
 {
     const std::set<PropertyKey> &keys = opts.allKeys();
     std::set<PropertyKey>::const_iterator i;
-    bool die=false;
     for(i=keys.begin(); i!=keys.end(); i++) {
         if(*i == "verbose") continue;
         if(*i == "tol") continue;
@@ -551,55 +550,28 @@ void CBP::Properties::set(const PropertySet &opts)
         if(*i == "bbp_cfn") continue;
         if(*i == "rand_seed") continue;
         if(*i == "clamp_outfile") continue;
-        cerr << "CBP: Unknown property " << *i << endl;
-        die=true;
-    }
-    if(die) {
-        DAI_THROW(UNKNOWN_PROPERTY_TYPE);
-    }
-    if(!opts.hasKey("tol")) {
-        cerr << "CBP: Missing property \"tol\" for method \"CBP\"" << endl;
-        die=true;
-    }
-    if(!opts.hasKey("updates")) {
-        cerr << "CBP: Missing property \"updates\" for method \"CBP\"" << endl;
-        die=true;
-    }
-    if(!opts.hasKey("maxiter")) {
-        cerr << "CBP: Missing property \"maxiter\" for method \"CBP\"" << endl;
-        die=true;
-    }
-    if(!opts.hasKey("rec_tol")) {
-        cerr << "CBP: Missing property \"rec_tol\" for method \"CBP\"" << endl;
-        die=true;
-    }
-    if(!opts.hasKey("min_max_adj")) {
-        cerr << "CBP: Missing property \"min_max_adj\" for method \"CBP\"" << endl;
-        die=true;
-    }
-    if(!opts.hasKey("choose")) {
-        cerr << "CBP: Missing property \"choose\" for method \"CBP\"" << endl;
-        die=true;
-    }
-    if(!opts.hasKey("recursion")) {
-        cerr << "CBP: Missing property \"recursion\" for method \"CBP\"" << endl;
-        die=true;
-    }
-    if(!opts.hasKey("clamp")) {
-        cerr << "CBP: Missing property \"clamp\" for method \"CBP\"" << endl;
-        die=true;
-    }
-    if(!opts.hasKey("bbp_props")) {
-        cerr << "CBP: Missing property \"bbp_props\" for method \"CBP\"" << endl;
-        die=true;
-    }
-    if(!opts.hasKey("bbp_cfn")) {
-        cerr << "CBP: Missing property \"bbp_cfn\" for method \"CBP\"" << endl;
-        die=true;
-    }
-    if(die) {
-        DAI_THROW(NOT_ALL_PROPERTIES_SPECIFIED);
+        DAI_THROWE(UNKNOWN_PROPERTY_TYPE, "CBP: Unknown property " + *i);
     }
+    if(!opts.hasKey("tol"))
+        DAI_THROWE(NOT_ALL_PROPERTIES_SPECIFIED,"CBP: Missing property \"tol\" for method \"CBP\"");
+    if(!opts.hasKey("updates"))
+        DAI_THROWE(NOT_ALL_PROPERTIES_SPECIFIED,"CBP: Missing property \"updates\" for method \"CBP\"");
+    if(!opts.hasKey("maxiter"))
+        DAI_THROWE(NOT_ALL_PROPERTIES_SPECIFIED,"CBP: Missing property \"maxiter\" for method \"CBP\"");
+    if(!opts.hasKey("rec_tol"))
+        DAI_THROWE(NOT_ALL_PROPERTIES_SPECIFIED,"CBP: Missing property \"rec_tol\" for method \"CBP\"");
+    if(!opts.hasKey("min_max_adj"))
+        DAI_THROWE(NOT_ALL_PROPERTIES_SPECIFIED,"CBP: Missing property \"min_max_adj\" for method \"CBP\"");
+    if(!opts.hasKey("choose"))
+        DAI_THROWE(NOT_ALL_PROPERTIES_SPECIFIED,"CBP: Missing property \"choose\" for method \"CBP\"");
+    if(!opts.hasKey("recursion"))
+        DAI_THROWE(NOT_ALL_PROPERTIES_SPECIFIED,"CBP: Missing property \"recursion\" for method \"CBP\"");
+    if(!opts.hasKey("clamp"))
+        DAI_THROWE(NOT_ALL_PROPERTIES_SPECIFIED,"CBP: Missing property \"clamp\" for method \"CBP\"");
+    if(!opts.hasKey("bbp_props"))
+        DAI_THROWE(NOT_ALL_PROPERTIES_SPECIFIED,"CBP: Missing property \"bbp_props\" for method \"CBP\"");
+    if(!opts.hasKey("bbp_cfn"))
+        DAI_THROWE(NOT_ALL_PROPERTIES_SPECIFIED,"CBP: Missing property \"bbp_cfn\" for method \"CBP\"");
     if(opts.hasKey("verbose")) {
         verbose = opts.getStringAs<size_t>("verbose");
     } else {
index ce18883..47f61eb 100644 (file)
@@ -33,13 +33,17 @@ using namespace std;
 /// Calculates the marginal of obj on ns by clamping all variables in ns and calculating logZ for each joined state.
 /*  reInit should be set to true if at least one of the possible clamped states would be invalid (leading to a factor graph with zero partition sum).
  */
-Factor calcMarginal( const InfAlg & obj, const VarSet & ns, bool reInit ) {
+Factor calcMarginal( const InfAlg &obj, const VarSet &ns, bool reInit ) {
     Factor Pns (ns);
     
     InfAlg *clamped = obj.clone();
     if( !reInit )
         clamped->init();
 
+    map<Var,size_t> varindices;
+    for( VarSet::const_iterator n = ns.begin(); n != ns.end(); n++ )
+        varindices[*n] = obj.fg().findVar( *n );
+
     Real logZ0 = -INFINITY;
     for( State s(ns); s.valid(); s++ ) {
         // save unclamped factors connected to ns
@@ -47,7 +51,7 @@ Factor calcMarginal( const InfAlg & obj, const VarSet & ns, bool reInit ) {
 
         // set clamping Factors to delta functions
         for( VarSet::const_iterator n = ns.begin(); n != ns.end(); n++ )
-            clamped->clamp( *n, s(*n) );
+            clamped->clamp( varindices[*n], s(*n) );
         
         // run DAIAlg, calc logZ, store in Pns
         if( reInit )
@@ -93,8 +97,11 @@ vector<Factor> calcPairBeliefs( const InfAlg & obj, const VarSet& ns, bool reIni
     size_t N = ns.size();
     vector<Var> vns;
     vns.reserve( N );
-    for( VarSet::const_iterator n = ns.begin(); n != ns.end(); n++ )
+    map<Var,size_t> varindices;
+    for( VarSet::const_iterator n = ns.begin(); n != ns.end(); n++ ) {
         vns.push_back( *n );
+        varindices[*n] = obj.fg().findVar( *n );
+    }
 
     vector<Factor> pairbeliefs;
     pairbeliefs.reserve( N * N );
@@ -113,7 +120,7 @@ vector<Factor> calcPairBeliefs( const InfAlg & obj, const VarSet& ns, bool reIni
     for( size_t j = 0; j < N; j++ ) {
         // clamp Var j to its possible values
         for( size_t j_val = 0; j_val < vns[j].states(); j_val++ ) {
-            clamped->clamp( vns[j], j_val, true );
+            clamped->clamp( varindices[vns[j]], j_val, true );
             if( reInit )
                 clamped->init();
             else
@@ -195,6 +202,10 @@ vector<Factor> calcPairBeliefsNew( const InfAlg & obj, const VarSet& ns, bool re
     if( !reInit )
         clamped->init();
 
+    map<Var,size_t> varindices;
+    for( VarSet::const_iterator n = ns.begin(); n != ns.end(); n++ )
+        varindices[*n] = obj.fg().findVar( *n );
+
     Real logZ0 = 0.0;
     VarSet::const_iterator nj = ns.begin();
     for( long j = 0; j < (long)ns.size() - 1; j++, nj++ ) {
@@ -207,9 +218,9 @@ vector<Factor> calcPairBeliefsNew( const InfAlg & obj, const VarSet& ns, bool re
                 for( size_t k_val = 0; k_val < nk->states(); k_val++ ) {
                     // save unclamped factors connected to ns
                     clamped->backupFactors( ns );
-            
-                    clamped->clamp( *nj, j_val );
-                    clamped->clamp( *nk, k_val );
+
+                    clamped->clamp( varindices[*nj], j_val );
+                    clamped->clamp( varindices[*nk], k_val );
                     if( reInit )
                         clamped->init();
                     else
index e0fcab3..62102ef 100644 (file)
@@ -40,7 +40,7 @@ ParameterEstimation* ParameterEstimation::construct( const std::string &method,
         loadDefaultRegistry();
     std::map<std::string, ParamEstFactory>::iterator i = _registry->find(method);
     if( i == _registry->end() )
-        DAI_THROW(UNKNOWN_PARAMETER_ESTIMATION_METHOD);
+        DAI_THROWE(UNKNOWN_PARAMETER_ESTIMATION_METHOD, "Unknown parameter estimation method: " + method);
     ParamEstFactory factory = i->second;
     return factory(p);
 }
@@ -59,8 +59,7 @@ ParameterEstimation* CondProbEstimation::factory( const PropertySet &p ) {
 CondProbEstimation::CondProbEstimation( size_t target_dimension, const Prob &pseudocounts ) 
   : _target_dim(target_dimension), _stats(pseudocounts), _initial_stats(pseudocounts) 
 {
-    if( _stats.size() % _target_dim )
-        DAI_THROW(MALFORMED_PROPERTY);
+    assert( !(_stats.size() % _target_dim) );
 }
 
 
@@ -115,16 +114,14 @@ Permute SharedParameters::calculatePermutation( const std::vector<Var> &varorder
 void SharedParameters::setPermsAndVarSetsFromVarOrders() {
     if( _varorders.size() == 0 )
         return;
-    if( _estimation == NULL )
-        DAI_THROW(INVALID_SHARED_PARAMETERS_ORDER);
+    assert( _estimation != NULL );
 
     // Construct the permutation objects and the varsets
     for( FactorOrientations::const_iterator foi = _varorders.begin(); foi != _varorders.end(); ++foi ) {
         VarSet vs;
         _perms[foi->first] = calculatePermutation( foi->second, vs );
         _varsets[foi->first] = vs;
-        if( _estimation->probSize() != vs.nrStates() )
-            DAI_THROW(INVALID_SHARED_PARAMETERS_ORDER);
+        assert( _estimation->probSize() == vs.nrStates() );
     }
 }
 
@@ -154,14 +151,14 @@ SharedParameters::SharedParameters( std::istream &is, const FactorGraph &fg_varl
 
         // Lookup the factor in the factorgraph
         if( fields.size() < 1 )
-            DAI_THROW(INVALID_SHARED_PARAMETERS_INPUT_LINE);
+            DAI_THROW(INVALID_EMALG_FILE);
         std::istringstream iss;
         iss.str( fields[0] );
         size_t factor;
         iss >> factor;
         const VarSet &vs = fg_varlookup.factor(factor).vars();
         if( fields.size() != vs.size() + 1 )
-            DAI_THROW(INVALID_SHARED_PARAMETERS_INPUT_LINE);
+            DAI_THROW(INVALID_EMALG_FILE);
 
         // Construct the vector of Vars
         std::vector<Var> var_order;
@@ -176,7 +173,7 @@ SharedParameters::SharedParameters( std::istream &is, const FactorGraph &fg_varl
                 if( vsi->label() == label ) 
                     break;
             if( vsi == vs.end() )
-                DAI_THROW(INVALID_SHARED_PARAMETERS_INPUT_LINE);
+                DAI_THROW(INVALID_EMALG_FILE);
             var_order.push_back( *vsi );
         }
         _varorders[factor] = var_order;
index e003807..69fe9ae 100644 (file)
@@ -37,7 +37,7 @@ void Observation::addObservation( Var node, size_t setting ) {
 
 void Observation::applyEvidence( InfAlg &alg ) const {
     for( std::map<Var, size_t>::const_iterator i = _obs.begin(); i != _obs.end(); ++i )
-        alg.clamp( i->first, i->second );
+        alg.clamp( alg.fg().findVar(i->first), i->second );
 }
   
 
@@ -62,7 +62,7 @@ void Evidence::addEvidenceTabFile( std::istream &is, std::map<std::string, Var>
     tokenizeString( line, header_fields );
     std::vector<std::string>::const_iterator p_field = header_fields.begin();
     if( p_field == header_fields.end() ) 
-        DAI_THROW(INVALID_EVIDENCE_LINE);
+        DAI_THROW(INVALID_EVIDENCE_FILE);
 
     std::vector<Var> vars;
     for( ; p_field != header_fields.end(); ++p_field ) {
@@ -77,16 +77,16 @@ void Evidence::addEvidenceTabFile( std::istream &is, std::map<std::string, Var>
         std::vector<std::string> fields;
         tokenizeString( line, fields );
         if( fields.size() != vars.size() ) 
-            DAI_THROW(INVALID_EVIDENCE_LINE);
+            DAI_THROW(INVALID_EVIDENCE_FILE);
         
         Observation sampleData;
         for( size_t i = 0; i < vars.size(); ++i ) {
             if( fields[i].size() > 0 ) { // skip if missing observation
                 if( fields[i].find_first_not_of("0123456789") != std::string::npos )
-                    DAI_THROW(INVALID_EVIDENCE_OBSERVATION);
+                    DAI_THROW(INVALID_EVIDENCE_FILE);
                 size_t state = atoi( fields[i].c_str() );
                 if( state >= vars[i].states() )
-                    DAI_THROW(INVALID_EVIDENCE_OBSERVATION);
+                    DAI_THROW(INVALID_EVIDENCE_FILE);
                 sampleData.addObservation( vars[i], state );
             }
         }
index 84b2e22..b39353e 100644 (file)
@@ -40,13 +40,12 @@ namespace dai {
         "FactorGraph is not connected",
         "Impossible typecast",
         "Internal error",
+        "Runtime error",
         "Quantity not normalizable",
-        "Cannot parse Evidence file",
-        "Cannot parse Evidence line",
-        "Invalid observation in Evidence file",
-        "Invalid variable order in SharedParameters",
-        "Variable order line in EM file is invalid",
-        "Unrecognized parameter estimation method"
+        "Invalid Evidence file",
+        "Invalid Expectation-Maximization file",
+        "Unrecognized parameter estimation method",
+        "Requested object not found"
     }; 
 
 
index d8b9fea..b41e577 100644 (file)
@@ -32,6 +32,7 @@
 #include <dai/factorgraph.h>
 #include <dai/util.h>
 #include <dai/exceptions.h>
+#include <boost/lexical_cast.hpp>
 
 
 namespace dai {
@@ -83,7 +84,7 @@ void FactorGraph::constructGraph( size_t nrEdges ) {
 
 
 /// Writes a FactorGraph to an output stream
-ostream& operator << (ostream& os, const FactorGraph& fg) {
+std::ostream& operator<< ( std::ostream &os, const FactorGraph &fg ) {
     os << fg.nrFactors() << endl;
 
     for( size_t I = 0; I < fg.nrFactors(); I++ ) {
@@ -110,7 +111,7 @@ ostream& operator << (ostream& os, const FactorGraph& fg) {
 
 
 /// Reads a FactorGraph from an input stream
-istream& operator >> (istream& is, FactorGraph& fg) {
+std::istream& operator>> ( std::istream& is, FactorGraph &fg ) {
     long verbose = 0;
 
     vector<Factor> facs;
@@ -121,7 +122,7 @@ istream& operator >> (istream& is, FactorGraph& fg) {
         getline(is,line);
     is >> nr_Factors;
     if( is.fail() )
-        DAI_THROW(INVALID_FACTORGRAPH_FILE);
+        DAI_THROWE(INVALID_FACTORGRAPH_FILE,"Cannot read number of factors");
     if( verbose >= 2 )
         cerr << "Reading " << nr_Factors << " factors..." << endl;
 
@@ -169,7 +170,7 @@ istream& operator >> (istream& is, FactorGraph& fg) {
             if( vdi != vardims.end() ) {
                 // check whether dimensions are consistent
                 if( vdi->second != dims[mi] )
-                    DAI_THROW(INVALID_FACTORGRAPH_FILE);
+                    DAI_THROWE(INVALID_FACTORGRAPH_FILE,"Variable with label " + boost::lexical_cast<string>(labels[mi]) + " has inconsistent dimensions.");
             } else
                 vardims[labels[mi]] = dims[mi];
             I_vars |= Var(labels[mi], dims[mi]);
@@ -262,7 +263,7 @@ void FactorGraph::ReadFromFile( const char *filename ) {
         infile >> *this;
         infile.close();
     } else
-        DAI_THROW(CANNOT_READ_FILE);
+        DAI_THROWE(CANNOT_READ_FILE,"Cannot read from file " + std::string(filename));
 }
 
 
@@ -274,7 +275,7 @@ void FactorGraph::WriteToFile( const char *filename, size_t precision ) const {
         outfile << *this;
         outfile.close();
     } else
-        DAI_THROW(CANNOT_WRITE_FILE);
+        DAI_THROWE(CANNOT_WRITE_FILE,"Cannot write to file " + std::string(filename));
 }
 
 
@@ -310,20 +311,14 @@ vector<VarSet> FactorGraph::Cliques() const {
 }
 
 
-void FactorGraph::clamp( const Var & n, size_t i, bool backup ) {
-    assert( i <= n.states() );
-
-    // Multiply each factor that contains the variable with a delta function
-
-    Factor delta_n_i(n,0.0);
-    delta_n_i[i] = 1.0;
+void FactorGraph::clamp( size_t i, size_t x, bool backup ) {
+    assert( x <= var(i).states() );
+    Factor mask( var(i), 0.0 );
+    mask[x] = 1.0;
 
     map<size_t, Factor> newFacs;
-    // For all factors that contain n
-    for( size_t I = 0; I < nrFactors(); I++ ) 
-        if( factor(I).vars().contains( n ) )
-            // Multiply it with a delta function
-            newFacs[I] = factor(I) * delta_n_i;
+       foreach( const BipartiteGraph::Neighbor &I, nbV(i) )
+        newFacs[I] = factor(I) * mask;
     setFactors( newFacs, backup );
 
     return;
@@ -340,10 +335,8 @@ void FactorGraph::clampVar( size_t i, const vector<size_t> &is, bool backup ) {
     }
 
     map<size_t, Factor> newFacs;
-    for( size_t I = 0; I < nrFactors(); I++ ) 
-        if( factor(I).vars().contains( n ) ) {
-            newFacs[I] = factor(I) * mask_n;
-        }
+       foreach( const BipartiteGraph::Neighbor &I, nbV(i) )
+        newFacs[I] = factor(I) * mask_n;
     setFactors( newFacs, backup );
 }
 
@@ -364,7 +357,7 @@ void FactorGraph::clampFactor( size_t I, const vector<size_t> &is, bool backup )
 void FactorGraph::backupFactor( size_t I ) {
     map<size_t,Factor>::iterator it = _backup.find( I );
     if( it != _backup.end() )
-        DAI_THROW( MULTIPLE_UNDO );
+        DAI_THROW(MULTIPLE_UNDO);
     _backup[I] = factor(I);
 }
 
@@ -428,14 +421,14 @@ bool FactorGraph::isBinary() const {
 }
 
 
-FactorGraph FactorGraph::clamped( const Var & v_i, size_t state ) const {
+FactorGraph FactorGraph::clamped( const Var &v, size_t state ) const {
     Real zeroth_order = 1.0;
     vector<Factor> clamped_facs;
     for( size_t I = 0; I < nrFactors(); I++ ) {
         VarSet v_I = factor(I).vars();
         Factor new_factor;
-        if( v_I.intersects( v_i ) )
-            new_factor = factor(I).slice( v_i, state );
+        if( v_I.intersects( v ) )
+            new_factor = factor(I).slice( v, state );
         else
             new_factor = factor(I);
 
index 250e9d9..44878f7 100644 (file)
@@ -161,7 +161,7 @@ HAK::HAK(const FactorGraph & fg, const PropertySet &opts) : DAIAlgRG(), _Qa(), _
                 cerr << *cli << endl;
         }
     } else
-        DAI_THROW(INTERNAL_ERROR);
+        DAI_THROW(UNKNOWN_ENUM_VALUE);
 
     RegionGraph rg(fg,cl);
     RegionGraph::operator=(rg);
index 1888b48..61ed067 100644 (file)
@@ -499,11 +499,11 @@ void MR::init_cor() {
     for( size_t i = 0; i < nrVars(); i++ ) {
         vector<Factor> pairq;
         if( props.inits == Properties::InitType::CLAMPING ) {
-            BP bpcav(*this, PropertySet()("updates", string("SEQMAX"))("tol", string("1e-9"))("maxiter", string("10000UL"))("verbose", string("0UL"))("logdomain", string("0")));
+            BP bpcav(*this, PropertySet()("updates", string("SEQMAX"))("tol", 1.0e-9)("maxiter", 10000UL)("verbose", 0UL)("logdomain", false));
             bpcav.makeCavity( i );
             pairq = calcPairBeliefs( bpcav, delta(i), false );
         } else if( props.inits == Properties::InitType::EXACT ) {
-            JTree jtcav(*this, PropertySet()("updates", string("HUGIN"))("verbose", string("0UL")) );
+            JTree jtcav(*this, PropertySet()("updates", string("HUGIN"))("verbose", 0UL) );
             jtcav.makeCavity( i );
             pairq = calcPairBeliefs( jtcav, delta(i), false );
         }
index bf6d7a0..1629b84 100644 (file)
@@ -60,7 +60,7 @@ std::ostream& operator<< (std::ostream & os, const PropertySet & ps) {
 
 
 /// Reads a PropertySet object from an input stream, storing values as strings
-std::istream& operator >> (std::istream& is, PropertySet & ps) {
+std::istream& operator>> (std::istream& is, PropertySet & ps) {
     ps = PropertySet();
 
     std::string s;
@@ -68,7 +68,7 @@ std::istream& operator >> (std::istream& is, PropertySet & ps) {
 
     // Check whether s is of the form "[.*]"
     if( (s.length() < 2) || (s.at(0) != '[') || (s.at(s.length()-1)) != ']' )
-        DAI_THROW(MALFORMED_PROPERTY);
+        DAI_THROWE(MALFORMED_PROPERTY,"Malformed PropertySet: " + s);
 
     size_t N = s.length() - 1;
     for( size_t token_start = 1; token_start < N; ) {
@@ -78,10 +78,10 @@ std::istream& operator >> (std::istream& is, PropertySet & ps) {
         for( token_end = token_start + 1; token_end < N; token_end++ )
             if( s[token_end] == '=' )
                 break;
-        if( token_end == N )
-            DAI_THROW(MALFORMED_PROPERTY);
         // we found a key
         std::string key = s.substr(token_start, token_end - token_start);
+        if( token_end == N )
+            DAI_THROWE(MALFORMED_PROPERTY,"Malformed Property: " + key);
 
         token_start = token_end + 1;
         // scan until matching ',' is found
@@ -95,7 +95,7 @@ std::istream& operator >> (std::istream& is, PropertySet & ps) {
                 break;
         }
         if( !(level == 0) )
-            DAI_THROW(MALFORMED_PROPERTY);
+            DAI_THROWE(MALFORMED_PROPERTY,"Malformed Property: " + s.substr(token_start, token_end - token_start));
         // we found a vlue
         std::string value = s.substr(token_start, token_end - token_start);
 
index 2c88f98..b9e19e3 100644 (file)
@@ -247,7 +247,7 @@ TreeEP::TreeEP( const FactorGraph &fg, const PropertySet &opts ) : JTree(fg, opt
             // find maximal spanning tree
             ConstructRG( MaxSpanningTreePrims( wg ) );
         } else
-            DAI_THROW(INTERNAL_ERROR);
+            DAI_THROW(UNKNOWN_ENUM_VALUE);
     }
 }
 
index b5e1d34..f679a6a 100644 (file)
@@ -73,19 +73,22 @@ double toc() {
 #endif
 }
 
-// This is a typedef for a random number generator.
-// Try boost::mt19937 or boost::ecuyer1988 instead of boost::minstd_rand
-typedef boost::minstd_rand _rnd_gen_type;
+/// Type of global random number generator
+typedef boost::minstd_rand _rnd_gen_type;  // Try boost::mt19937 or boost::ecuyer1988 instead of boost::minstd_rand
 
+/// Global random number generator
 _rnd_gen_type _rnd_gen(42U);
 
-// Define a uniform random number distribution which produces
-// values between 0 and 1 (0 inclusive, 1 exclusive).
+/// Uniform distribution with values between 0 and 1 (0 inclusive, 1 exclusive).
 boost::uniform_real<> _uni_dist(0,1);
+
+/// Global uniform random random number 
 boost::variate_generator<_rnd_gen_type&, boost::uniform_real<> > _uni_rnd(_rnd_gen, _uni_dist);
 
-// Define a normal distribution with mean 0 and standard deviation 1.
+/// Normal distribution with mean 0 and standard deviation 1.
 boost::normal_distribution<> _normal_dist;
+
+/// Global random number generator with standard normal distribution
 boost::variate_generator<_rnd_gen_type&, boost::normal_distribution<> > _normal_rnd(_rnd_gen, _normal_dist);
 
 
@@ -105,10 +108,7 @@ int rnd_int( int min, int max ) {
     return (int)floor(_uni_rnd() * (max + 1 - min) + min);
 }
 
-void tokenizeString(const std::string& s,
-                    std::vector<std::string>& outTokens,
-                    const std::string& delim)
-{
+void tokenizeString(const std::string& s, std::vector<std::string>& outTokens, const std::string& delim) {
     size_t start = 0;
     while (start < s.size()) {
         size_t end = s.find_first_of(delim, start);
index 918ec52..1600fe6 100644 (file)
@@ -197,7 +197,7 @@ pair<string, PropertySet> parseMethod( const string &_s, const map<string,string
         if( ps.first == DAINames[n] )
             break;
     if( strlen( DAINames[n] ) == 0 && (ps.first != "LDPC") )
-        throw std::runtime_error(string("Unknown DAI algorithm \"") + ps.first + string("\" in \"") + _s + string("\""));
+        DAI_THROWE(UNKNOWN_DAI_ALGORITHM,string("Unknown DAI algorithm \"") + ps.first + string("\" in \"") + _s + string("\""));
 
     return ps;
 }
@@ -274,7 +274,7 @@ int main( int argc, char *argv[] ) {
                     if( (!line.empty()) && (line[0] != '#') ) {
                         string::size_type pos = line.find(':',0);
                         if( pos == string::npos )
-                            throw string("Invalid alias");
+                            DAI_THROWE(RUNTIME_ERROR,"Invalid alias");
                         else {
                             string::size_type posl = line.substr(0, pos).find_last_not_of(" \t");
                             string key = line.substr(0, posl + 1);
@@ -286,7 +286,7 @@ int main( int argc, char *argv[] ) {
                 }
                 infile.close();
             } else
-                throw string("Error opening aliases file");
+                DAI_THROWE(RUNTIME_ERROR,"Error opening aliases file");
         }
 
         FactorGraph fg;