Removed stuff from InfAlg, moved it to individual inference algorithms
authorJoris Mooij <jorism@marvin.jorismooij.nl>
Sun, 21 Sep 2008 07:28:02 +0000 (09:28 +0200)
committerJoris Mooij <jorism@marvin.jorismooij.nl>
Sun, 21 Sep 2008 07:28:02 +0000 (09:28 +0200)
- Renamed Properties -> PropertySet
- Removed Properties framework from InfAlg and added properties,
encapsulated in a struct called Properties, to each inference algorithm
- Moved maxdiff functionality from InfAlg to individual inference algorithms

22 files changed:
example.cpp
include/dai/alldai.h
include/dai/bp.h
include/dai/daialg.h
include/dai/hak.h
include/dai/jtree.h
include/dai/lc.h
include/dai/mf.h
include/dai/mr.h
include/dai/properties.h
include/dai/treeep.h
src/alldai.cpp
src/bp.cpp
src/daialg.cpp
src/hak.cpp
src/jtree.cpp
src/lc.cpp
src/mf.cpp
src/mr.cpp
src/properties.cpp
src/treeep.cpp
tests/test.cpp

index 527bf70..cca85a8 100644 (file)
@@ -44,7 +44,7 @@ int main( int argc, char *argv[] ) {
             double  tol = 1e-9;
             size_t  verb = 1;
 
-            Properties opts;
+            PropertySet opts;
             opts.Set("maxiter",maxiter);
             opts.Set("tol",tol);
             opts.Set("verbose",verb);
index 87bb1d8..4d5e178 100644 (file)
@@ -25,6 +25,7 @@
 
 #include <string>
 #include <dai/daialg.h>
+#include <dai/properties.h>
 #ifdef WITH_BP
     #include <dai/bp.h>
 #endif
@@ -54,7 +55,7 @@ namespace dai {
 /// newInfAlg constructs a new approximate inference algorithm named name for the
 /// FactorGraph fg with optionts opts and returns a pointer to the new object.
 /// The caller needs to delete it (maybe some sort of smart_ptr might be useful here).
-InfAlg *newInfAlg( const std::string &name, const FactorGraph &fg, const Properties &opts );
+InfAlg *newInfAlg( const std::string &name, const FactorGraph &fg, const PropertySet &opts );
 
 
 /// DAINames contains the names of all approximate inference algorithms
index 9bb1b51..890b72b 100644 (file)
@@ -26,6 +26,7 @@
 #include <string>
 #include <dai/daialg.h>
 #include <dai/factorgraph.h>
+#include <dai/properties.h>
 #include <dai/enum.h>
 
 
@@ -41,30 +42,38 @@ class BP : public DAIAlgFG {
             Prob   newMessage;
             double residual;
         };
-
         std::vector<std::vector<EdgeProp> > edges;
-        bool logDomain;
-
+    
     public:
-        ENUM4(UpdateType,SEQFIX,SEQRND,SEQMAX,PARALL)
-        UpdateType Updates() const { return GetPropertyAs<UpdateType>("updates"); }
+        struct Properties {
+            size_t verbose;
+            size_t maxiter;
+            double tol;
+            bool logdomain;
+            ENUM4(UpdateType,SEQFIX,SEQRND,SEQMAX,PARALL)
+            UpdateType updates;
+        } props;
+        double maxdiff;
 
-        // default constructor
-        BP() : DAIAlgFG(), edges(), logDomain(false) {};
-        // copy constructor
-        BP(const BP & x) : DAIAlgFG(x), edges(x.edges), logDomain(x.logDomain) {};
+    public:
+        /// Default constructor
+        BP() : DAIAlgFG(), edges(), props(), maxdiff(0.0) {};
+        /// Copy constructor
+        BP( const BP & x ) : DAIAlgFG(x), edges(x.edges), props(x.props), maxdiff(x.maxdiff) {};
+        /// Clone *this
         BP* clone() const { return new BP(*this); }
-        // construct BP object from FactorGraph
-        BP(const FactorGraph & fg, const Properties &opts) : DAIAlgFG(fg, opts), edges(), logDomain(false) {
-            assert( checkProperties() );
+        /// Construct from FactorGraph fg and PropertySet opts
+        BP( const FactorGraph & fg, const PropertySet &opts ) : DAIAlgFG(fg), edges(), props(), maxdiff(0.0) {
+            setProperties( opts );
             create();
         }
-        // assignment operator
-        BP & operator=(const BP & x) {
-            if(this!=&x) {
-                DAIAlgFG::operator=(x);
+        /// Assignment operator
+        BP& operator=( const BP & x ) {
+            if( this != &x ) {
+                DAIAlgFG::operator=( x );
                 edges = x.edges;
-                logDomain = x.logDomain;
+                props = x.props;
+                maxdiff = x.maxdiff;
             }
             return *this;
         }
@@ -79,13 +88,14 @@ class BP : public DAIAlgFG {
         const ind_t & index(size_t i, size_t _I) const { return edges[i][_I].index; }
         double & residual(size_t i, size_t _I) { return edges[i][_I].residual; }
         const double & residual(size_t i, size_t _I) const { return edges[i][_I].residual; }
-        void findMaxResidual( size_t &i, size_t &_I );
 
         std::string identify() const;
         void create();
         void init();
-        void calcNewMessage( size_t i, size_t _I );
         double run();
+
+        void findMaxResidual( size_t &i, size_t &_I );
+        void calcNewMessage( size_t i, size_t _I );
         Factor beliefV (size_t i) const;
         Factor beliefF (size_t I) const;
         Factor belief (const Var &n) const;
@@ -95,7 +105,10 @@ class BP : public DAIAlgFG {
 
         void init( const VarSet &ns );
         void undoProbs( const VarSet &ns ) { FactorGraph::undoProbs(ns); init(ns); }
-        bool checkProperties();
+
+        void setProperties( const PropertySet &opts );
+        PropertySet getProperties() const;
+        double maxDiff() const { return maxdiff; }
 };
 
 
index 97d0dc0..fdb0ee7 100644 (file)
@@ -28,7 +28,6 @@
 #include <vector>
 #include <dai/factorgraph.h>
 #include <dai/regiongraph.h>
-#include <dai/properties.h>
 
 
 namespace dai {
@@ -38,87 +37,14 @@ namespace dai {
 /// A InfAlg object represents a discrete factorized probability distribution over multiple variables 
 /// together with an inference algorithm.
 class InfAlg {
-    private:
-        /// Properties of the algorithm (replaces _tol, _maxiter, _verbose)
-        Properties              _properties;
-
-        /// Maximum difference encountered so far
-        double                  _maxdiff;
-
-
     public:
-        /// Default constructor
-        InfAlg() : _properties(), _maxdiff(0.0) {}
-        
-        /// Constructor with options
-        InfAlg( const Properties &opts ) : _properties(opts), _maxdiff(0.0) {}
-        
-        /// Copy constructor
-        InfAlg( const InfAlg & x ) : _properties(x._properties), _maxdiff(x._maxdiff) {}
-
         /// Clone (virtual copy constructor)
         virtual InfAlg* clone() const = 0;
 
-        /// Assignment operator
-        InfAlg & operator=( const InfAlg & x ) {
-            if( this != &x ) {
-                _properties = x._properties;
-                _maxdiff    = x._maxdiff;
-            }
-            return *this;
-        }
-        
         /// Virtual desctructor
         // (this is needed because this class contains virtual functions)
         virtual ~InfAlg() {}
         
-        /// Returns true if a property with the given key is present
-        bool HasProperty(const PropertyKey &key) const { return _properties.hasKey(key); }
-
-        /// Gets a property
-        const PropertyValue & GetProperty(const PropertyKey &key) const { return _properties.Get(key); }
-        /// Gets a property, casted as ValueType
-        template<typename ValueType>
-        ValueType GetPropertyAs(const PropertyKey &key) const { return _properties.GetAs<ValueType>(key); }
-
-        /// Sets a property 
-        void SetProperty(const PropertyKey &key, const PropertyValue &val) { _properties[key] = val; }
-
-        /// Converts a property from string to ValueType, if necessary
-        template<typename ValueType>
-        void ConvertPropertyTo(const PropertyKey &key) { _properties.ConvertTo<ValueType>(key); }
-
-        /// Gets all properties
-        const Properties & GetProperties() const { return _properties; }
-
-        /// Sets properties
-        void SetProperties(const Properties &p) { _properties = p; }
-
-        /// Sets tolerance
-        void Tol( double tol ) { SetProperty("tol", tol); }
-        /// Gets tolerance
-        double Tol() const { return GetPropertyAs<double>("tol"); }
-
-        /// Sets maximum number of iterations
-        void MaxIter( size_t maxiter ) { SetProperty("maxiter", maxiter); }
-        /// Gets maximum number of iterations
-        size_t MaxIter() const { return GetPropertyAs<size_t>("maxiter"); }
-
-        /// Sets verbosity
-        void Verbose( size_t verbose ) { SetProperty("verbose", verbose); }
-        /// Gets verbosity
-        size_t Verbose() const { return GetPropertyAs<size_t>("verbose"); }
-
-        /// Sets maximum difference encountered so far
-        void MaxDiff( double maxdiff ) { _maxdiff = maxdiff; }
-        /// Gets maximum difference encountered so far
-        double MaxDiff() const { return _maxdiff; }
-        /// Updates maximum difference encountered so far
-        void updateMaxDiff( double maxdiff ) { if( maxdiff > _maxdiff ) _maxdiff = maxdiff; }
-        /// Sets maximum difference encountered so far to zero
-        void clearMaxDiff() { _maxdiff = 0.0; }
-
         /// Identifies itself for logging purposes
         virtual std::string identify() const = 0;
 
@@ -186,9 +112,8 @@ class InfAlg {
         /// Factor I has been updated
         virtual void updatedFactor( size_t I ) = 0;
 
-        /// Checks whether all necessary properties have been set
-        /// and casts string-valued properties to other values if necessary
-        virtual bool checkProperties() = 0;
+        /// Return maximum difference between beliefs in the last pass
+        virtual double maxDiff() const = 0;
 };
 
 
@@ -198,12 +123,9 @@ class DAIAlg : public InfAlg, public T {
         /// Default constructor
         DAIAlg() : InfAlg(), T() {}
         
-        /// Construct DAIAlg with empty T but using the specified properties
-        DAIAlg( const Properties &opts ) : InfAlg( opts ), T() {}
+        /// Construct from T
+        DAIAlg( const T &t ) : InfAlg(), T(t) {}
 
-        /// Construct DAIAlg using the specified properties
-        DAIAlg( const T & t, const Properties &opts ) : InfAlg( opts ), T(t) {}
-        
         /// Copy constructor
         DAIAlg( const DAIAlg & x ) : InfAlg(x), T(x) {}
 
index f1adfc4..a874950 100644 (file)
@@ -27,6 +27,7 @@
 #include <dai/daialg.h>
 #include <dai/regiongraph.h>
 #include <dai/enum.h>
+#include <dai/properties.h>
 
 
 namespace dai {
@@ -39,42 +40,51 @@ class HAK : public DAIAlgRG {
         std::vector<Factor>                _Qb;
         std::vector<std::vector<Factor> >  _muab;
         std::vector<std::vector<Factor> >  _muba;
+
+    public:
+        struct Properties {
+            size_t verbose;
+            size_t maxiter;
+            double tol;
+            ENUM3(ClustersType,MIN,DELTA,LOOP)
+            ClustersType clusters;
+            bool doubleloop;
+            size_t loopdepth;
+        } props;
+        double maxdiff;
         
     public:
         /// Default constructor
-        HAK() : DAIAlgRG() {};
+        HAK() : DAIAlgRG(), _Qa(), _Qb(), _muab(), _muba(), props(), maxdiff() {}
 
         /// Copy constructor
-        HAK(const HAK & x) : DAIAlgRG(x), _Qa(x._Qa), _Qb(x._Qb), _muab(x._muab), _muba(x._muba) {};
+        HAK(const HAK & x) : DAIAlgRG(x), _Qa(x._Qa), _Qb(x._Qb), _muab(x._muab), _muba(x._muba), props(x.props), maxdiff(x.maxdiff) {}
 
         /// Clone function
         HAK* clone() const { return new HAK(*this); }
         
         /// Construct from RegionGraph
-        HAK(const RegionGraph & rg, const Properties &opts);
+        HAK(const RegionGraph & rg, const PropertySet &opts);
 
         /// Construct from RactorGraph using "clusters" option
-        HAK(const FactorGraph & fg, const Properties &opts);
+        HAK(const FactorGraph & fg, const PropertySet &opts);
 
         /// Assignment operator
         HAK & operator=(const HAK & x) {
             if( this != &x ) {
                 DAIAlgRG::operator=(x);
-                _Qa         = x._Qa;
-                _Qb         = x._Qb;
-                _muab       = x._muab;
-                _muba       = x._muba;
+                _Qa    = x._Qa;
+                _Qb    = x._Qb;
+                _muab  = x._muab;
+                _muba  = x._muba;
+                props  = x.props;
+                maxdiff = x.maxdiff;
             }
             return *this;
         }
         
         static const char *Name;
 
-        ENUM3(ClustersType,MIN,DELTA,LOOP)
-        ClustersType Clusters() const { return GetPropertyAs<ClustersType>("clusters"); }
-        bool DoubleLoop() { return GetPropertyAs<bool>("doubleloop"); }
-        size_t LoopDepth() { return GetPropertyAs<size_t>("loopdepth"); }
-
         Factor & muab( size_t alpha, size_t _beta ) { return _muab[alpha][_beta]; }
         Factor & muba( size_t alpha, size_t _beta ) { return _muba[alpha][_beta]; }
         const Factor& Qa( size_t alpha ) const { return _Qa[alpha]; };
@@ -92,7 +102,9 @@ class HAK : public DAIAlgRG {
 
         void init( const VarSet &ns );
         void undoProbs( const VarSet &ns ) { RegionGraph::undoProbs( ns ); init( ns ); }
-        bool checkProperties();
+        void setProperties( const PropertySet &opts );
+        PropertySet getProperties() const;
+        double maxDiff() const { return maxdiff; }
 
     private:
         void constructMessages();
index e6bf12f..74f76b3 100644 (file)
@@ -32,6 +32,7 @@
 #include <dai/clustergraph.h>
 #include <dai/weightedgraph.h>
 #include <dai/enum.h>
+#include <dai/properties.h>
 
 
 namespace dai {
@@ -45,13 +46,16 @@ class JTree : public DAIAlgRG {
         std::vector<std::vector<Factor> >  _mes;
         double               _logZ;
 
-
     public:
-        ENUM2(UpdateType,HUGIN,SHSH)
-        UpdateType Updates() const { return GetPropertyAs<UpdateType>("updates"); }
+        struct Properties {
+            size_t verbose;
+            ENUM2(UpdateType,HUGIN,SHSH)
+            UpdateType updates;
+        } props;
 
-        JTree() : DAIAlgRG(), _RTree(), _Qa(), _Qb(), _mes(), _logZ() {};
-        JTree( const JTree& x ) : DAIAlgRG(x), _RTree(x._RTree), _Qa(x._Qa), _Qb(x._Qb), _mes(x._mes), _logZ(x._logZ) {};
+    public:
+        JTree() : DAIAlgRG(), _RTree(), _Qa(), _Qb(), _mes(), _logZ(), props() {}
+        JTree( const JTree& x ) : DAIAlgRG(x), _RTree(x._RTree), _Qa(x._Qa), _Qb(x._Qb), _mes(x._mes), _logZ(x._logZ), props(x.props) {}
         JTree* clone() const { return new JTree(*this); }
         JTree & operator=( const JTree& x ) {
             if( this != &x ) {
@@ -61,10 +65,11 @@ class JTree : public DAIAlgRG {
                 _Qb     = x._Qb;
                 _mes    = x._mes;
                 _logZ   = x._logZ;
+                props   = x.props;
             }
             return *this;
         }
-        JTree( const FactorGraph &fg, const Properties &opts, bool automatic=true );
+        JTree( const FactorGraph &fg, const PropertySet &opts, bool automatic=true );
         void GenerateJT( const std::vector<VarSet> &Cliques );
 
         Factor & message( size_t alpha, size_t _beta ) { return _mes[alpha][_beta]; }   
@@ -72,7 +77,7 @@ class JTree : public DAIAlgRG {
 
         static const char *Name;
         std::string identify() const;
-        void init() { assert( checkProperties() ); }
+        void init() {}
         void runHUGIN();
         void runShaferShenoy();
         double run();
@@ -86,7 +91,9 @@ class JTree : public DAIAlgRG {
 
         size_t findEfficientTree( const VarSet& ns, DEdgeVec &Tree, size_t PreviousRoot=(size_t)-1 ) const;
         Factor calcMarginal( const VarSet& ns );
-        bool checkProperties();
+        void setProperties( const PropertySet &opts );
+        PropertySet getProperties() const;
+        double maxDiff() const { return 0.0; }
 };
 
 
index 231b043..57037d9 100644 (file)
@@ -27,6 +27,7 @@
 #include <dai/daialg.h>
 #include <dai/enum.h>
 #include <dai/factorgraph.h>
+#include <dai/properties.h>
 
 
 namespace dai {
@@ -43,21 +44,29 @@ class LC : public DAIAlgFG {
         std::vector<Factor>      _beliefs;
 
     public:
-        ENUM6(CavityType,FULL,PAIR,PAIR2,PAIRINT,PAIRCUM,UNIFORM)
-        ENUM3(UpdateType,SEQFIX,SEQRND,NONE)
+        struct Properties {
+            size_t verbose;
+            size_t maxiter;
+            double tol;
+            ENUM6(CavityType,FULL,PAIR,PAIR2,PAIRINT,PAIRCUM,UNIFORM)
+            CavityType cavity;
+            ENUM3(UpdateType,SEQFIX,SEQRND,NONE)
+            UpdateType updates;
+            std::string cavainame;
+            PropertySet cavaiopts;
+            bool reinit;
+        } props;
+        double maxdiff;
 
-        CavityType Cavity() const { return GetPropertyAs<CavityType>("cavity"); }
-        UpdateType Updates() const { return GetPropertyAs<UpdateType>("updates"); }
-        bool reInit() const { return GetPropertyAs<bool>("reinit"); }
-        
+    public:
         /// Default constructor
-        LC() : DAIAlgFG() {};
+        LC() : DAIAlgFG(), _pancakes(), _cavitydists(), _phis(), _beliefs(), props(), maxdiff() {}
         /// Copy constructor
-        LC(const LC & x) : DAIAlgFG(x), _pancakes(x._pancakes), _cavitydists(x._cavitydists), _phis(x._phis), _beliefs(x._beliefs) {};
+        LC(const LC & x) : DAIAlgFG(x), _pancakes(x._pancakes), _cavitydists(x._cavitydists), _phis(x._phis), _beliefs(x._beliefs), props(x.props), maxdiff(x.maxdiff) {}
         /// Clone function
         LC* clone() const { return new LC(*this); }
         /// Construct LC object from a FactorGraph and parameters
-        LC(const FactorGraph & fg, const Properties &opts);
+        LC( const FactorGraph & fg, const PropertySet &opts );
         /// Assignment operator
         LC& operator=(const LC & x) {
             if( this != &x ) {
@@ -66,13 +75,15 @@ class LC : public DAIAlgFG {
                 _cavitydists    = x._cavitydists;
                 _phis           = x._phis;
                 _beliefs        = x._beliefs;
+                props           = x.props;
+                maxdiff         = x.maxdiff;
             }
             return *this;
         }
 
         static const char *Name;
-        double CalcCavityDist( size_t i, const std::string &name, const Properties &opts );
-        double InitCavityDists( const std::string &name, const Properties &opts );
+        double CalcCavityDist( size_t i, const std::string &name, const PropertySet &opts );
+        double InitCavityDists( const std::string &name, const PropertySet &opts );
         long SetCavityDists( std::vector<Factor> &Q );
 
         void init();
@@ -85,15 +96,18 @@ class LC : public DAIAlgFG {
         std::vector<Factor> beliefs() const { return _beliefs; }
         Complex logZ() const { return NAN; }
         void CalcBelief (size_t i);
-        const Factor & belief (size_t i) const { return _beliefs[i]; };
-        const Factor & pancake (size_t i) const { return _pancakes[i]; };
-        const Factor & cavitydist (size_t i) const { return _cavitydists[i]; };
+        const Factor &belief (size_t i) const { return _beliefs[i]; };
+        const Factor &pancake (size_t i) const { return _pancakes[i]; };
+        const Factor &cavitydist (size_t i) const { return _cavitydists[i]; };
 
         void clamp( const Var &/*n*/, size_t /*i*/ ) { assert( 0 == 1 ); }
         void undoProbs( const VarSet &/*ns*/ ) { assert( 0 == 1 ); }
         void saveProbs( const VarSet &/*ns*/ ) { assert( 0 == 1 ); }
         virtual void makeCavity(const Var & /*n*/) { assert( 0 == 1 ); }
-        bool checkProperties();
+
+        void setProperties( const PropertySet &opts );
+        PropertySet getProperties() const;
+        double maxDiff() const { return maxdiff; }
 };
 
 
index 7f35546..01d6721 100644 (file)
@@ -26,6 +26,7 @@
 #include <string>
 #include <dai/daialg.h>
 #include <dai/factorgraph.h>
+#include <dai/properties.h>
 
 
 namespace dai {
@@ -34,23 +35,33 @@ namespace dai {
 class MF : public DAIAlgFG {
     protected:
         std::vector<Factor>  _beliefs;
+
+    public:
+        struct Properties {
+            size_t verbose;
+            size_t maxiter;
+            double tol;
+        } props;
+        double maxdiff;
         
     public:
         // default constructor
-        MF() : DAIAlgFG(), _beliefs() {};
+        MF() : DAIAlgFG(), _beliefs(), props(), maxdiff(0.0) {}
         // copy constructor
-        MF(const MF & x) : DAIAlgFG(x), _beliefs(x._beliefs) {};
+        MF( const MF& x ) : DAIAlgFG(x), _beliefs(x._beliefs), props(x.props), maxdiff(x.maxdiff) {}
         MF* clone() const { return new MF(*this); }
         // construct MF object from FactorGraph
-        MF(const FactorGraph & fg, const Properties &opts) : DAIAlgFG(fg, opts) {
-            assert( checkProperties() );
+        MF( const FactorGraph & fg, const PropertySet &opts ) : DAIAlgFG(fg), _beliefs(), props(), maxdiff(0.0) {
+            setProperties( opts );
             create();
         }
         // assignment operator
-        MF & operator=(const MF & x) {
-            if(this!=&x) {
-                DAIAlgFG::operator=(x);
+        MF& operator=( const MF &x ) {
+            if( this != &x ) {
+                DAIAlgFG::operator=( x );
                 _beliefs = x._beliefs;
+                props = x.props;
+                maxdiff = x.maxdiff;
             }
             return *this;
         }
@@ -68,7 +79,9 @@ class MF : public DAIAlgFG {
 
         void init( const VarSet &ns );
         void undoProbs( const VarSet &ns ) { FactorGraph::undoProbs(ns); init(ns); }
-        bool checkProperties();
+        void setProperties( const PropertySet &opts );
+        PropertySet getProperties() const;
+        double maxDiff() const { return maxdiff; }
 };
 
 
index 153b83a..f3cee73 100644 (file)
@@ -28,6 +28,7 @@
 #include <dai/factorgraph.h>
 #include <dai/daialg.h>
 #include <dai/enum.h>
+#include <dai/properties.h>
 
 
 namespace dai {
@@ -55,13 +56,18 @@ class MR : public DAIAlgFG {
         std::vector<double> Mag;
 
     public:
-        ENUM2(UpdateType,FULL,LINEAR)
-        ENUM3(InitType,RESPPROP,CLAMPING,EXACT)
+        struct Properties {
+            size_t verbose;
+            double tol;
+            ENUM2(UpdateType,FULL,LINEAR)
+            ENUM3(InitType,RESPPROP,CLAMPING,EXACT)
+            UpdateType updates;
+            InitType inits;
+        } props;
+        double maxdiff;
 
-        UpdateType Updates() const { return GetPropertyAs<UpdateType>("updates"); }
-        InitType Inits() const { return GetPropertyAs<InitType>("inits"); }
-
-        MR( const FactorGraph & fg, const Properties &opts );
+    public:
+        MR( const FactorGraph & fg, const PropertySet &opts );
         void init(size_t Nin, double *_w, double *_th);
         void makekindex();
         void read_files();
@@ -74,7 +80,7 @@ class MR : public DAIAlgFG {
         Factor belief( const VarSet &/*ns*/ ) const { assert( 0 == 1 ); }
         std::vector<Factor> beliefs() const;
         Complex logZ() const { return NAN; }
-        void init() { assert( checkProperties() ); }
+        void init() {}
         static const char *Name;
         std::string identify() const;
         double _tJ(size_t i, sub_nb A);
@@ -91,8 +97,9 @@ class MR : public DAIAlgFG {
         double sign(double a) { return (a >= 0) ? 1.0 : -1.0; }
         MR* clone() const { assert( 0 == 1 ); }
 
-        bool checkProperties();
-
+        void setProperties( const PropertySet &opts );
+        PropertySet getProperties() const;
+        double maxDiff() const { return maxdiff; }
 }; 
 
 
index 05401e3..1399ca9 100644 (file)
@@ -43,12 +43,12 @@ typedef std::pair<PropertyKey, PropertyValue> Property;
 std::ostream& operator<< (std::ostream & os, const Property & p);
 
 
-/// The Properties class represents a set of properties
-class Properties : public std::map<PropertyKey, PropertyValue> {
+/// The PropertySet class represents a set of properties
+class PropertySet : public std::map<PropertyKey, PropertyValue> {
     public:
         /// Gets a property
         const PropertyValue & Get(const PropertyKey &key) const { 
-            Properties::const_iterator x = find(key); 
+            PropertySet::const_iterator x = find(key); 
 #ifdef DAI_DEBUG            
             if( x == this->end() )
                 std::cerr << "Get cannot find property " << key << std::endl;
@@ -58,7 +58,7 @@ class Properties : public std::map<PropertyKey, PropertyValue> {
         }
 
         /// Sets a property 
-        Properties & Set(const PropertyKey &key, const PropertyValue &val) { this->operator[](key) = val; return *this; }
+        PropertySet & Set(const PropertyKey &key, const PropertyValue &val) { this->operator[](key) = val; return *this; }
 
         /// Gets a property, casted as ValueType
         template<typename ValueType>
@@ -88,17 +88,33 @@ class Properties : public std::map<PropertyKey, PropertyValue> {
             }
         }
 
-        /// Shorthand for (temporarily) adding properties, e.g. Properties p()("method","BP")("verbose",1)("tol",1e-9)
-        Properties operator()(const PropertyKey &key, const PropertyValue &val) const { Properties copy = *this; return copy.Set(key,val); }
+        /// Converts a property from string to ValueType, if necessary
+        template<typename ValueType>
+        ValueType getStringAs(const PropertyKey &key) const { 
+            PropertyValue val = Get(key);
+            if( val.type() == typeid(std::string) ) {
+                std::stringstream ss;
+                ss << GetAs<std::string>(key);
+                ValueType result;
+                ss >> result;
+                return result;
+            } else if( val.type() == typeid(ValueType) ) {
+                return boost::any_cast<ValueType>(val);
+            } else
+                assert( 0 == 1 );
+        }
+
+        /// Shorthand for (temporarily) adding properties, e.g. PropertySet p()("method","BP")("verbose",1)("tol",1e-9)
+        PropertySet operator()(const PropertyKey &key, const PropertyValue &val) const { PropertySet copy = *this; return copy.Set(key,val); }
 
         /// Check if a property with given key exists
-        bool hasKey(const PropertyKey &key) const { Properties::const_iterator x = find(key); return (x != this->end()); }
+        bool hasKey(const PropertyKey &key) const { PropertySet::const_iterator x = find(key); return (x != this->end()); }
 
-        /// Sends a Properties object to an output stream
-        friend std::ostream& operator<< (std::ostream & os, const Properties & ps);
+        /// Sends a PropertySet object to an output stream
+        friend std::ostream& operator<< (std::ostream & os, const PropertySet & ps);
 
-        /// Reads a Properties object from an input stream
-        friend std::istream& operator >> (std::istream& is, Properties & ps);
+        /// Reads a PropertySet object from an input stream
+        friend std::istream& operator >> (std::istream& is, PropertySet & ps);
 };
 
 
index 4d3e417..9b18a4c 100644 (file)
@@ -32,6 +32,7 @@
 #include <dai/clustergraph.h>
 #include <dai/weightedgraph.h>
 #include <dai/jtree.h>
+#include <dai/properties.h>
 #include <dai/enum.h>
 
 
@@ -84,11 +85,20 @@ class TreeEP : public JTree {
         std::map<size_t, TreeEPSubTree>  _Q;
 
     public:
-        ENUM2(TypeType,ORG,ALT)
-        TypeType Type() const { return GetPropertyAs<TypeType>("type"); }
-        
-        TreeEP() : JTree(), _Q() {};
-        TreeEP( const TreeEP& x ) : JTree(x), _Q(x._Q) {
+        struct Properties {
+            size_t verbose;
+            size_t maxiter;
+            double tol;
+            ENUM2(TypeType,ORG,ALT)
+            TypeType type;
+        } props;
+        double maxdiff;
+
+    public:
+        /// Default constructor
+        TreeEP() : JTree(), _Q(), props(), maxdiff() {};
+        /// Copy constructor
+        TreeEP( const TreeEP& x ) : JTree(x), _Q(x._Q), props(x.props), maxdiff(x.maxdiff) {
             for( size_t I = 0; I < nrFactors(); I++ )
                 if( offtree( I ) )
                     _Q[I].I() = &factor(I);
@@ -101,10 +111,12 @@ class TreeEP : public JTree {
                 for( size_t I = 0; I < nrFactors(); I++ )
                     if( offtree( I ) )
                         _Q[I].I() = &factor(I);
+                props = x.props;
+                maxdiff = x.maxdiff;
             }
             return *this;
         }
-        TreeEP( const FactorGraph &fg, const Properties &opts );
+        TreeEP( const FactorGraph &fg, const PropertySet &opts );
         void ConstructRG( const DEdgeVec &tree );
 
         static const char *Name;
@@ -117,7 +129,10 @@ class TreeEP : public JTree {
 
         void init( const VarSet &/*ns*/ ) { init(); }
         void undoProbs( const VarSet &ns ) { RegionGraph::undoProbs( ns ); init( ns ); }
-        bool checkProperties();
+
+        void setProperties( const PropertySet &opts );
+        PropertySet getProperties() const;
+        double maxDiff() const { return maxdiff; }
 };
 
 
index b8b8b24..cca6ec2 100644 (file)
@@ -21,6 +21,7 @@
 
 #include <string>
 #include <dai/alldai.h>
+#include <dai/properties.h>
 
 
 namespace dai {
@@ -29,37 +30,36 @@ namespace dai {
 using namespace std;
 
 
-InfAlg *newInfAlg( const string &name, const FactorGraph &fg, const Properties &opts ) {
+InfAlg *newInfAlg( const string &name, const FactorGraph &fg, const PropertySet &opts ) {
 #ifdef WITH_BP
     if( name == BP::Name ) 
         return new BP (fg, opts);
 #endif
 #ifdef WITH_MF
-    else if( name == MF::Name ) 
+    if( name == MF::Name ) 
         return new MF (fg, opts);
 #endif
 #ifdef WITH_HAK
-    else if( name == HAK::Name ) 
+    if( name == HAK::Name ) 
         return new HAK (fg, opts);
 #endif
 #ifdef WITH_LC
-    else if( name == LC::Name )
+    if( name == LC::Name )
         return new LC (fg, opts);
 #endif
 #ifdef WITH_TREEEP
-    else if( name == TreeEP::Name )
+    if( name == TreeEP::Name )
         return new TreeEP (fg, opts);
 #endif
 #ifdef WITH_JTREE
-    else if( name == JTree::Name )
+    if( name == JTree::Name )
         return new JTree (fg, opts);
 #endif
 #ifdef WITH_MR
-    else if( name == MR::Name )
+    if( name == MR::Name )
         return new MR (fg, opts);
 #endif
-    else
-        throw "Unknown inference algorithm";
+    throw "Unknown inference algorithm";
 }
 
 
index 79d751f..94680d6 100644 (file)
@@ -39,26 +39,29 @@ using namespace std;
 const char *BP::Name = "BP";
 
 
-bool BP::checkProperties() {
-    if( !HasProperty("updates") )
-        return false;
-    if( !HasProperty("tol") )
-        return false;
-    if (!HasProperty("maxiter") )
-        return false;
-    if (!HasProperty("verbose") )
-        return false;
-    if (!HasProperty("logdomain") )
-        return false;
+void BP::setProperties( const PropertySet &opts ) {
+    assert( opts.hasKey("tol") );
+    assert( opts.hasKey("maxiter") );
+    assert( opts.hasKey("verbose") );
+    assert( opts.hasKey("logdomain") );
+    assert( opts.hasKey("updates") );
     
-    ConvertPropertyTo<double>("tol");
-    ConvertPropertyTo<size_t>("maxiter");
-    ConvertPropertyTo<size_t>("verbose");
-    ConvertPropertyTo<UpdateType>("updates");
-    ConvertPropertyTo<bool>("logdomain");
-    logDomain = GetPropertyAs<bool>("logdomain");
-
-    return true;
+    props.tol = opts.getStringAs<double>("tol");
+    props.maxiter = opts.getStringAs<size_t>("maxiter");
+    props.verbose = opts.getStringAs<size_t>("verbose");
+    props.logdomain = opts.getStringAs<bool>("logdomain");
+    props.updates = opts.getStringAs<Properties::UpdateType>("updates");
+}
+
+
+PropertySet BP::getProperties() const {
+    PropertySet opts;
+    opts.Set( "tol", props.tol );
+    opts.Set( "maxiter", props.maxiter );
+    opts.Set( "verbose", props.verbose );
+    opts.Set( "logdomain", props.logdomain );
+    opts.Set( "updates", props.updates );
+    return opts;
 }
 
 
@@ -86,10 +89,9 @@ void BP::create() {
 
 
 void BP::init() {
-    assert( checkProperties() );
     for( size_t i = 0; i < nrVars(); ++i ) {
         foreach( const Neighbor &I, nbV(i) ) {
-            if( logDomain ) {
+            if( props.logdomain ) {
                 message( i, I.iter ).fill( 0.0 );
                 newMessage( i, I.iter ).fill( 0.0 );
             } else {
@@ -131,7 +133,7 @@ void BP::calcNewMessage( size_t i, size_t _I ) {
 */
     
     Prob prod( factor(I).p() );
-    if( logDomain ) 
+    if( props.logdomain ) 
         prod.takeLog();
 
     // Calculate product of incoming messages and factor I
@@ -142,10 +144,10 @@ void BP::calcNewMessage( size_t i, size_t _I ) {
             const ind_t & ind = index(j, _I);
 
             // prod_j will be the product of messages coming into j
-            Prob prod_j( var(j).states(), logDomain ? 0.0 : 1.0 ); 
+            Prob prod_j( var(j).states(), props.logdomain ? 0.0 : 1.0 ); 
             foreach( const Neighbor &J, nbV(j) )
                 if( J != I ) { // for all J in nb(j) \ I 
-                    if( logDomain )
+                    if( props.logdomain )
                         prod_j += message( j, J.iter );
                     else
                         prod_j *= message( j, J.iter );
@@ -153,13 +155,13 @@ void BP::calcNewMessage( size_t i, size_t _I ) {
 
             // multiply prod with prod_j
             for( size_t r = 0; r < prod.size(); ++r )
-                if( logDomain )
+                if( props.logdomain )
                     prod[r] += prod_j[ind[r]];
                 else
                     prod[r] *= prod_j[ind[r]];
         }
     }
-    if( logDomain ) {
+    if( props.logdomain ) {
         prod -= prod.maxVal();
         prod.takeExp();
     }
@@ -173,7 +175,7 @@ void BP::calcNewMessage( size_t i, size_t _I ) {
     marg.normalize( _normtype );
     
     // Store result
-    if( logDomain )
+    if( props.logdomain )
         newMessage(i,_I) = marg.log();
     else
         newMessage(i,_I) = marg;
@@ -183,9 +185,9 @@ void BP::calcNewMessage( size_t i, size_t _I ) {
 // BP::run does not check for NANs for performance reasons
 // Somehow NaNs do not often occur in BP...
 double BP::run() {
-    if( Verbose() >= 1 )
+    if( props.verbose >= 1 )
         cout << "Starting " << identify() << "...";
-    if( Verbose() >= 3)
+    if( props.verbose >= 3)
        cout << endl; 
 
     double tic = toc();
@@ -201,7 +203,7 @@ double BP::run() {
     size_t iter = 0;
     size_t nredges = nrEdges();
 
-    if( Updates() == UpdateType::SEQMAX ) {
+    if( props.updates == Properties::UpdateType::SEQMAX ) {
         // do the first pass
         for( size_t i = 0; i < nrVars(); ++i )
             foreach( const Neighbor &I, nbV(i) ) {
@@ -218,8 +220,8 @@ double BP::run() {
 
     // do several passes over the network until maximum number of iterations has
     // been reached or until the maximum belief difference is smaller than tolerance
-    for( iter=0; iter < MaxIter() && diffs.maxDiff() > Tol(); ++iter ) {
-        if( Updates() == UpdateType::SEQMAX ) {
+    for( iter=0; iter < props.maxiter && diffs.maxDiff() > props.tol; ++iter ) {
+        if( props.updates == Properties::UpdateType::SEQMAX ) {
             // Residuals-BP by Koller et al.
             for( size_t t = 0; t < nredges; ++t ) {
                 // update the message with the largest residual
@@ -243,7 +245,7 @@ double BP::run() {
                     }
                 }
             }
-        } else if( Updates() == UpdateType::PARALL ) {
+        } else if( props.updates == Properties::UpdateType::PARALL ) {
             // Parallel updates 
             for( size_t i = 0; i < nrVars(); ++i )
                 foreach( const Neighbor &I, nbV(i) )
@@ -254,7 +256,7 @@ double BP::run() {
                     message( i, I.iter ) = newMessage( i, I.iter );
         } else {
             // Sequential updates
-            if( Updates() == UpdateType::SEQRND )
+            if( props.updates == Properties::UpdateType::SEQRND )
                 random_shuffle( update_seq.begin(), update_seq.end() );
             
             foreach( const Edge &e, update_seq ) {
@@ -270,19 +272,20 @@ double BP::run() {
             old_beliefs[i] = nb;
         }
 
-        if( Verbose() >= 3 )
+        if( props.verbose >= 3 )
             cout << "BP::run:  maxdiff " << diffs.maxDiff() << " after " << iter+1 << " passes" << endl;
     }
 
-    updateMaxDiff( diffs.maxDiff() );
+    if( diffs.maxDiff() > maxdiff )
+        maxdiff = diffs.maxDiff();
 
-    if( Verbose() >= 1 ) {
-        if( diffs.maxDiff() > Tol() ) {
-            if( Verbose() == 1 )
+    if( props.verbose >= 1 ) {
+        if( diffs.maxDiff() > props.tol ) {
+            if( props.verbose == 1 )
                 cout << endl;
-                cout << "BP::run:  WARNING: not converged within " << MaxIter() << " passes (" << toc() - tic << " clocks)...final maxdiff:" << diffs.maxDiff() << endl;
+                cout << "BP::run:  WARNING: not converged within " << props.maxiter << " passes (" << toc() - tic << " clocks)...final maxdiff:" << diffs.maxDiff() << endl;
         } else {
-            if( Verbose() >= 3 )
+            if( props.verbose >= 3 )
                 cout << "BP::run:  ";
                 cout << "converged in " << iter << " passes (" << toc() - tic << " clocks)." << endl;
         }
@@ -293,13 +296,13 @@ double BP::run() {
 
 
 Factor BP::beliefV( size_t i ) const {
-    Prob prod( var(i).states(), logDomain ? 0.0 : 1.0 ); 
+    Prob prod( var(i).states(), props.logdomain ? 0.0 : 1.0 ); 
     foreach( const Neighbor &I, nbV(i) )
-        if( logDomain )
+        if( props.logdomain )
             prod += newMessage( i, I.iter );
         else
             prod *= newMessage( i, I.iter );
-    if( logDomain ) {
+    if( props.logdomain ) {
         prod -= prod.maxVal();
         prod.takeExp();
     }
@@ -340,7 +343,7 @@ Factor BP::belief( const VarSet &ns ) const {
 
 Factor BP::beliefF (size_t I) const {
     Prob prod( factor(I).p() );
-    if( logDomain )
+    if( props.logdomain )
         prod.takeLog();
 
     foreach( const Neighbor &j, nbF(I) ) {
@@ -349,10 +352,10 @@ Factor BP::beliefF (size_t I) const {
         const ind_t & ind = index(j, _I);
 
         // prod_j will be the product of messages coming into j
-        Prob prod_j( var(j).states(), logDomain ? 0.0 : 1.0 ); 
+        Prob prod_j( var(j).states(), props.logdomain ? 0.0 : 1.0 ); 
         foreach( const Neighbor &J, nbV(j) ) {
             if( J != I ) { // for all J in nb(j) \ I 
-                if( logDomain )
+                if( props.logdomain )
                     prod_j += newMessage( j, J.iter );
                 else
                     prod_j *= newMessage( j, J.iter );
@@ -361,14 +364,14 @@ Factor BP::beliefF (size_t I) const {
 
         // multiply prod with prod_j
         for( size_t r = 0; r < prod.size(); ++r ) {
-            if( logDomain )
+            if( props.logdomain )
                 prod[r] += prod_j[ind[r]];
             else
                 prod[r] *= prod_j[ind[r]];
         }
     }
 
-    if( logDomain ) {
+    if( props.logdomain ) {
         prod -= prod.maxVal();
         prod.takeExp();
     }
@@ -402,7 +405,7 @@ Complex BP::logZ() const {
 
 string BP::identify() const { 
     stringstream result (stringstream::out);
-    result << Name << GetProperties();
+    result << Name << getProperties();
     return result.str();
 }
 
@@ -411,7 +414,7 @@ void BP::init( const VarSet &ns ) {
     for( VarSet::const_iterator n = ns.begin(); n != ns.end(); ++n ) {
         size_t ni = findVar( *n );
         foreach( const Neighbor &I, nbV( ni ) )
-            message( ni, I.iter ).fill( logDomain ? 0.0 : 1.0 );
+            message( ni, I.iter ).fill( props.logdomain ? 0.0 : 1.0 );
     }
 }
 
index a688f36..7453f06 100644 (file)
@@ -48,8 +48,6 @@ Factor calcMarginal( const InfAlg & obj, const VarSet & ns, bool reInit ) {
             clamped->clamp( *n, s(*n) );
         
         // run DAIAlg, calc logZ, store in Pns
-        if( clamped->Verbose() >= 2 )
-            cout << s << ": ";
         if( reInit )
             clamped->init();
         clamped->run();
@@ -102,9 +100,6 @@ 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++ ) {
-            if( obj.Verbose() >= 2 )
-                cout << j << "/" << N-1 << " (" << j_val << "/" << vns[j].states() << "): ";
-
             // save unclamped factors connected to ns
             clamped->saveProbs( ns );
             
index 094d3fa..b4b6f0b 100644 (file)
@@ -34,30 +34,35 @@ using namespace std;
 const char *HAK::Name = "HAK";
 
 
-bool HAK::checkProperties() {
-    if( !HasProperty("tol") )
-        return false;
-    if (!HasProperty("maxiter") )
-        return false;
-    if (!HasProperty("verbose") )
-        return false;
-    if( !HasProperty("doubleloop") )
-        return false;
-    if( !HasProperty("clusters") )
-        return false;
+void HAK::setProperties( const PropertySet &opts ) {
+    assert( opts.hasKey("tol") );
+    assert( opts.hasKey("maxiter") );
+    assert( opts.hasKey("verbose") );
+    assert( opts.hasKey("doubleloop") );
+    assert( opts.hasKey("clusters") );
     
-    ConvertPropertyTo<double>("tol");
-    ConvertPropertyTo<size_t>("maxiter");
-    ConvertPropertyTo<size_t>("verbose");
-    ConvertPropertyTo<bool>("doubleloop");
-    ConvertPropertyTo<ClustersType>("clusters");
-
-    if( HasProperty("loopdepth") )
-        ConvertPropertyTo<size_t>("loopdepth");
-    else if( Clusters() == ClustersType::LOOP )
-        return false;
-
-    return true;
+    props.tol = opts.getStringAs<double>("tol");
+    props.maxiter = opts.getStringAs<size_t>("maxiter");
+    props.verbose = opts.getStringAs<size_t>("verbose");
+    props.doubleloop = opts.getStringAs<bool>("doubleloop");
+    props.clusters = opts.getStringAs<Properties::ClustersType>("clusters");
+
+    if( opts.hasKey("loopdepth") )
+        props.loopdepth = opts.getStringAs<size_t>("loopdepth");
+    else
+        assert( props.clusters != Properties::ClustersType::LOOP );
+}
+
+
+PropertySet HAK::getProperties() const {
+    PropertySet opts;
+    opts.Set( "tol", props.tol );
+    opts.Set( "maxiter", props.maxiter );
+    opts.Set( "verbose", props.verbose );
+    opts.Set( "doubleloop", props.doubleloop );
+    opts.Set( "clusters", props.clusters );
+    opts.Set( "loopdepth", props.loopdepth );
+    return opts;
 }
 
 
@@ -92,8 +97,8 @@ void HAK::constructMessages() {
 }
 
 
-HAK::HAK(const RegionGraph & rg, const Properties &opts) : DAIAlgRG(rg, opts) {
-    assert( checkProperties() );
+HAK::HAK(const RegionGraph & rg, const PropertySet &opts ) : DAIAlgRG(rg) {
+    setProperties( opts );
 
     constructMessages();
 }
@@ -111,26 +116,26 @@ void HAK::findLoopClusters( const FactorGraph & fg, std::set<VarSet> &allcl, Var
 }
 
 
-HAK::HAK(const FactorGraph & fg, const Properties &opts) : DAIAlgRG(opts) {
-    assert( checkProperties() );
+HAK::HAK(const FactorGraph & fg, const PropertySet &opts) : DAIAlgRG(), props(), maxdiff(0.0) {
+    setProperties( opts );
 
     vector<VarSet> cl;
-    if( Clusters() == ClustersType::MIN ) {
+    if( props.clusters == Properties::ClustersType::MIN ) {
         cl = fg.Cliques();
-    } else if( Clusters() == ClustersType::DELTA ) {
+    } else if( props.clusters == Properties::ClustersType::DELTA ) {
         for( size_t i = 0; i < fg.nrVars(); i++ )
             cl.push_back(fg.Delta(i)); 
-    } else if( Clusters() == ClustersType::LOOP ) {
+    } else if( props.clusters == Properties::ClustersType::LOOP ) {
         cl = fg.Cliques();
         set<VarSet> scl;
         for( size_t i0 = 0; i0 < fg.nrVars(); i0++ ) {
             VarSet i0d = fg.delta(i0);
-            if( LoopDepth() > 1 )
-                findLoopClusters( fg, scl, fg.var(i0), fg.var(i0), LoopDepth() - 1, fg.delta(i0) );
+            if( props.loopdepth > 1 )
+                findLoopClusters( fg, scl, fg.var(i0), fg.var(i0), props.loopdepth - 1, fg.delta(i0) );
         }
         for( set<VarSet>::const_iterator c = scl.begin(); c != scl.end(); c++ )
             cl.push_back(*c);
-        if( Verbose() >= 3 ) {
+        if( props.verbose >= 3 ) {
             cout << "HAK uses the following clusters: " << endl;
             for( vector<VarSet>::const_iterator cli = cl.begin(); cli != cl.end(); cli++ )
                 cout << *cli << endl;
@@ -142,14 +147,14 @@ HAK::HAK(const FactorGraph & fg, const Properties &opts) : DAIAlgRG(opts) {
     RegionGraph::operator=(rg);
     constructMessages();
 
-    if( Verbose() >= 3 )
+    if( props.verbose >= 3 )
         cout << "HAK regiongraph: " << *this << endl;
 }
 
 
 string HAK::identify() const { 
     stringstream result (stringstream::out);
-    result << Name << GetProperties();
+    result << Name << getProperties();
     return result.str();
 }
 
@@ -172,8 +177,6 @@ void HAK::init( const VarSet &ns ) {
 
 
 void HAK::init() {
-    assert( checkProperties() );
-
     for( vector<Factor>::iterator alpha = _Qa.begin(); alpha != _Qa.end(); alpha++ )
         alpha->fill( 1.0 / alpha->states() );
 
@@ -190,9 +193,9 @@ void HAK::init() {
 
 
 double HAK::doGBP() {
-    if( Verbose() >= 1 )
+    if( props.verbose >= 1 )
         cout << "Starting " << identify() << "...";
-    if( Verbose() >= 3)
+    if( props.verbose >= 3)
         cout << endl;
 
     double tic = toc();
@@ -213,7 +216,7 @@ double HAK::doGBP() {
     size_t iter = 0;
     // do several passes over the network until maximum number of iterations has
     // been reached or until the maximum belief difference is smaller than tolerance
-    for( iter = 0; iter < MaxIter() && diffs.maxDiff() > Tol(); iter++ ) {
+    for( iter = 0; iter < props.maxiter && diffs.maxDiff() > props.tol; iter++ ) {
         for( size_t beta = 0; beta < nrIRs(); beta++ ) {
             foreach( const Neighbor &alpha, nbIR(beta) ) {
                 size_t _beta = alpha.dual;
@@ -260,19 +263,20 @@ double HAK::doGBP() {
             old_beliefs[i] = new_belief;
         }
 
-        if( Verbose() >= 3 )
+        if( props.verbose >= 3 )
             cout << "HAK::doGBP:  maxdiff " << diffs.maxDiff() << " after " << iter+1 << " passes" << endl;
     }
 
-    updateMaxDiff( diffs.maxDiff() );
+    if( diffs.maxDiff() > maxdiff )
+        maxdiff = diffs.maxDiff();
 
-    if( Verbose() >= 1 ) {
-        if( diffs.maxDiff() > Tol() ) {
-            if( Verbose() == 1 )
+    if( props.verbose >= 1 ) {
+        if( diffs.maxDiff() > props.tol ) {
+            if( props.verbose == 1 )
                 cout << endl;
-            cout << "HAK::doGBP:  WARNING: not converged within " << MaxIter() << " passes (" << toc() - tic << " clocks)...final maxdiff:" << diffs.maxDiff() << endl;
+            cout << "HAK::doGBP:  WARNING: not converged within " << props.maxiter << " passes (" << toc() - tic << " clocks)...final maxdiff:" << diffs.maxDiff() << endl;
         } else {
-            if( Verbose() >= 2 )
+            if( props.verbose >= 2 )
                 cout << "HAK::doGBP:  ";
             cout << "converged in " << iter << " passes (" << toc() - tic << " clocks)." << endl;
         }
@@ -283,9 +287,9 @@ double HAK::doGBP() {
 
 
 double HAK::doDoubleLoop() {
-    if( Verbose() >= 1 )
+    if( props.verbose >= 1 )
         cout << "Starting " << identify() << "...";
-    if( Verbose() >= 3)
+    if( props.verbose >= 3)
         cout << endl;
 
     double tic = toc();
@@ -310,14 +314,14 @@ double HAK::doDoubleLoop() {
     // Differences in single node beliefs
     Diffs diffs(nrVars(), 1.0);
 
-    size_t  outer_maxiter   = MaxIter();
-    double  outer_tol       = Tol();
-    size_t  outer_verbose   = Verbose();
-    double  org_maxdiff     = MaxDiff();
+    size_t  outer_maxiter   = props.maxiter;
+    double  outer_tol       = props.tol;
+    size_t  outer_verbose   = props.verbose;
+    double  org_maxdiff     = maxdiff;
 
     // Set parameters for inner loop
-    MaxIter( 5 );
-    Verbose( outer_verbose ? outer_verbose - 1 : 0 );
+    props.maxiter = 5;
+    props.verbose = outer_verbose ? outer_verbose - 1 : 0;
 
     size_t outer_iter = 0;
     for( outer_iter = 0; outer_iter < outer_maxiter && diffs.maxDiff() > outer_tol; outer_iter++ ) {
@@ -339,16 +343,17 @@ double HAK::doDoubleLoop() {
             old_beliefs[i] = new_belief;
         }
 
-        if( Verbose() >= 3 )
+        if( props.verbose >= 3 )
             cout << "HAK::doDoubleLoop:  maxdiff " << diffs.maxDiff() << " after " << outer_iter+1 << " passes" << endl;
     }
 
     // restore _maxiter, _verbose and _maxdiff
-    MaxIter( outer_maxiter );
-    Verbose( outer_verbose );
-    MaxDiff( org_maxdiff );
+    props.maxiter = outer_maxiter;
+    props.verbose = outer_verbose;
+    maxdiff = org_maxdiff;
 
-    updateMaxDiff( diffs.maxDiff() );
+    if( diffs.maxDiff() > maxdiff )
+        maxdiff = diffs.maxDiff();
 
     // Restore original outer regions
     ORs = org_ORs;
@@ -357,13 +362,13 @@ double HAK::doDoubleLoop() {
     for( size_t beta = 0; beta < nrIRs(); ++beta )
         IR(beta).c() = org_IR_cs[beta];
 
-    if( Verbose() >= 1 ) {
-        if( diffs.maxDiff() > Tol() ) {
-            if( Verbose() == 1 )
+    if( props.verbose >= 1 ) {
+        if( diffs.maxDiff() > props.tol ) {
+            if( props.verbose == 1 )
                 cout << endl;
                 cout << "HAK::doDoubleLoop:  WARNING: not converged within " << outer_maxiter << " passes (" << toc() - tic << " clocks)...final maxdiff:" << diffs.maxDiff() << endl;
             } else {
-                if( Verbose() >= 3 )
+                if( props.verbose >= 3 )
                     cout << "HAK::doDoubleLoop:  ";
                 cout << "converged in " << outer_iter << " passes (" << toc() - tic << " clocks)." << endl;
             }
@@ -374,7 +379,7 @@ double HAK::doDoubleLoop() {
 
 
 double HAK::run() {
-    if( DoubleLoop() )
+    if( props.doubleloop )
         return doDoubleLoop();
     else
         return doGBP();
index c7652e1..39c7cfb 100644 (file)
@@ -32,21 +32,25 @@ using namespace std;
 const char *JTree::Name = "JTREE";
 
 
-bool JTree::checkProperties() {
-    if (!HasProperty("verbose") )
-        return false;
-    if( !HasProperty("updates") )
-        return false;
+void JTree::setProperties( const PropertySet &opts ) {
+    assert( opts.hasKey("verbose") );
+    assert( opts.hasKey("updates") );
     
-    ConvertPropertyTo<size_t>("verbose");
-    ConvertPropertyTo<UpdateType>("updates");
+    props.verbose = opts.getStringAs<size_t>("verbose");
+    props.updates = opts.getStringAs<Properties::UpdateType>("updates");
+}
+
 
-    return true;
+PropertySet JTree::getProperties() const {
+    PropertySet opts;
+    opts.Set( "verbose", props.verbose );
+    opts.Set( "updates", props.updates );
+    return opts;
 }
 
 
-JTree::JTree( const FactorGraph &fg, const Properties &opts, bool automatic ) : DAIAlgRG(fg, opts), _RTree(), _Qa(), _Qb(), _mes(), _logZ() {
-    assert( checkProperties() );
+JTree::JTree( const FactorGraph &fg, const PropertySet &opts, bool automatic ) : DAIAlgRG(fg), _RTree(), _Qa(), _Qb(), _mes(), _logZ(), props() {
+    setProperties( opts );
 
     if( automatic ) {
         // Copy VarSets of factors
@@ -56,16 +60,16 @@ JTree::JTree( const FactorGraph &fg, const Properties &opts, bool automatic ) :
             cl.push_back( factor(I).vars() );
         ClusterGraph _cg( cl );
 
-        if( Verbose() >= 3 )
+        if( props.verbose >= 3 )
             cout << "Initial clusters: " << _cg << endl;
 
         // Retain only maximal clusters
         _cg.eraseNonMaximal();
-        if( Verbose() >= 3 )
+        if( props.verbose >= 3 )
             cout << "Maximal clusters: " << _cg << endl;
 
         vector<VarSet> ElimVec = _cg.VarElim_MinFill().eraseNonMaximal().toVector();
-        if( Verbose() >= 3 )
+        if( props.verbose >= 3 )
             cout << "VarElim_MinFill result: " << ElimVec << endl;
 
         GenerateJT( ElimVec );
@@ -145,7 +149,7 @@ void JTree::GenerateJT( const std::vector<VarSet> &Cliques ) {
     // Check counting numbers
     Check_Counting_Numbers();
 
-    if( Verbose() >= 3 ) {
+    if( props.verbose >= 3 ) {
         cout << "Resulting regiongraph: " << *this << endl;
     }
 }
@@ -153,7 +157,7 @@ void JTree::GenerateJT( const std::vector<VarSet> &Cliques ) {
 
 string JTree::identify() const {
     stringstream result (stringstream::out);
-    result << Name << GetProperties();
+    result << Name << getProperties();
     return result.str();
 }
 
@@ -284,9 +288,9 @@ void JTree::runShaferShenoy() {
 
 
 double JTree::run() {
-    if( Updates() == UpdateType::HUGIN )
+    if( props.updates == Properties::UpdateType::HUGIN )
         runHUGIN();
-    else if( Updates() == UpdateType::SHSH )
+    else if( props.updates == Properties::UpdateType::SHSH )
         runShaferShenoy();
     return 0.0;
 }
index 57c84d5..2e795d4 100644 (file)
@@ -39,37 +39,43 @@ using namespace std;
 const char *LC::Name = "LC";
 
 
-bool LC::checkProperties() {
-    if( !HasProperty("cavity") )
-        return false;
-    if( !HasProperty("updates") )
-        return false;
-    if( !HasProperty("tol") )
-        return false;
-    if (!HasProperty("maxiter") )
-        return false;
-    if (!HasProperty("verbose") )
-        return false;
-
-    ConvertPropertyTo<CavityType>("cavity");
-    ConvertPropertyTo<UpdateType>("updates");
-    ConvertPropertyTo<double>("tol");
-    ConvertPropertyTo<size_t>("maxiter");
-    ConvertPropertyTo<size_t>("verbose");
-
-    if (HasProperty("cavainame") )
-        ConvertPropertyTo<string>("cavainame");
-    if (HasProperty("cavaiopts") )
-        ConvertPropertyTo<Properties>("cavaiopts");
-    if( HasProperty("reinit") )
-        ConvertPropertyTo<bool>("reinit");
+void LC::setProperties( const PropertySet &opts ) {
+    assert( opts.hasKey("tol") );
+    assert( opts.hasKey("maxiter") );
+    assert( opts.hasKey("verbose") );
+    assert( opts.hasKey("cavity") );
+    assert( opts.hasKey("updates") );
     
-    return true;
+    props.tol = opts.getStringAs<double>("tol");
+    props.maxiter = opts.getStringAs<size_t>("maxiter");
+    props.verbose = opts.getStringAs<size_t>("verbose");
+    props.cavity = opts.getStringAs<Properties::CavityType>("cavity");
+    props.updates = opts.getStringAs<Properties::UpdateType>("updates");
+    if( opts.hasKey("cavainame") )
+        props.cavainame = opts.getStringAs<string>("cavainame");
+    if( opts.hasKey("cavaiopts") )
+        props.cavaiopts = opts.getStringAs<PropertySet>("cavaiopts");
+    if( opts.hasKey("reinit") )
+        props.reinit = opts.getStringAs<bool>("reinit");
 }
 
 
-LC::LC(const FactorGraph & fg, const Properties &opts) : DAIAlgFG(fg, opts) {
-    assert( checkProperties() );
+PropertySet LC::getProperties() const {
+    PropertySet opts;
+    opts.Set( "tol", props.tol );
+    opts.Set( "maxiter", props.maxiter );
+    opts.Set( "verbose", props.verbose );
+    opts.Set( "cavity", props.cavity );
+    opts.Set( "updates", props.updates );
+    opts.Set( "cavainame", props.cavainame );
+    opts.Set( "cavaiopts", props.cavaiopts );
+    opts.Set( "reinit", props.reinit );
+    return opts;
+}
+
+
+LC::LC( const FactorGraph & fg, const PropertySet &opts ) : DAIAlgFG(fg), _pancakes(), _cavitydists(), _phis(), _beliefs(), props(), maxdiff(0.0) {
+    setProperties( opts );
 
     // create pancakes
     _pancakes.resize(nrVars());
@@ -95,7 +101,7 @@ LC::LC(const FactorGraph & fg, const Properties &opts) : DAIAlgFG(fg, opts) {
 
 string LC::identify() const { 
     stringstream result (stringstream::out);
-    result << Name << GetProperties();
+    result << Name << getProperties();
     return result.str();
 }
 
@@ -105,29 +111,29 @@ void LC::CalcBelief (size_t i) {
 }
 
 
-double LC::CalcCavityDist (size_t i, const std::string &name, const Properties &opts) {
+double LC::CalcCavityDist (size_t i, const std::string &name, const PropertySet &opts) {
     Factor Bi;
     double maxdiff = 0;
 
-    if( Verbose() >= 2 )
+    if( props.verbose >= 2 )
         cout << "Initing cavity " << var(i) << "(" << delta(i).size() << " vars, " << delta(i).states() << " states)" << endl;
 
-    if( Cavity() == CavityType::UNIFORM )
+    if( props.cavity == Properties::CavityType::UNIFORM )
         Bi = Factor(delta(i));
     else {
         InfAlg *cav = newInfAlg( name, *this, opts );
         cav->makeCavity( i );
 
-        if( Cavity() == CavityType::FULL )
-            Bi = calcMarginal( *cav, cav->delta(i), reInit() );
-        else if( Cavity() == CavityType::PAIR )
-            Bi = calcMarginal2ndO( *cav, cav->delta(i), reInit() );
-        else if( Cavity() == CavityType::PAIR2 ) {
-            vector<Factor> pairbeliefs = calcPairBeliefsNew( *cav, cav->delta(i), reInit() );
+        if( props.cavity == Properties::CavityType::FULL )
+            Bi = calcMarginal( *cav, cav->delta(i), props.reinit );
+        else if( props.cavity == Properties::CavityType::PAIR )
+            Bi = calcMarginal2ndO( *cav, cav->delta(i), props.reinit );
+        else if( props.cavity == Properties::CavityType::PAIR2 ) {
+            vector<Factor> pairbeliefs = calcPairBeliefsNew( *cav, cav->delta(i), props.reinit );
             for( size_t ij = 0; ij < pairbeliefs.size(); ij++ )
                 Bi *= pairbeliefs[ij];
-        } else if( Cavity() == CavityType::PAIRINT ) {
-            Bi = calcMarginal( *cav, cav->delta(i), reInit() );
+        } else if( props.cavity == Properties::CavityType::PAIRINT ) {
+            Bi = calcMarginal( *cav, cav->delta(i), props.reinit );
             
             // Set interactions of order > 2 to zero
             size_t N = delta(i).size();
@@ -138,8 +144,8 @@ double LC::CalcCavityDist (size_t i, const std::string &name, const Properties &
             x2x::w2logp (N, p);
 //            x2x::logpnorm (N, p);
             x2x::logp2p (N, p);
-        } else if( Cavity() == CavityType::PAIRCUM ) {
-            Bi = calcMarginal( *cav, cav->delta(i), reInit() );
+        } else if( props.cavity == Properties::CavityType::PAIRCUM ) {
+            Bi = calcMarginal( *cav, cav->delta(i), props.reinit );
             
             // Set cumulants of order > 2 to zero
             size_t N = delta(i).size();
@@ -150,7 +156,7 @@ double LC::CalcCavityDist (size_t i, const std::string &name, const Properties &
             x2x::c2m (N, p, N);
             x2x::m2p (N, p);
         }
-        maxdiff = cav->MaxDiff();
+        maxdiff = cav->maxDiff();
         delete cav;
     }
     Bi.normalize( _normtype );
@@ -160,18 +166,18 @@ double LC::CalcCavityDist (size_t i, const std::string &name, const Properties &
 }
 
 
-double LC::InitCavityDists (const std::string &name, const Properties &opts) {
+double LC::InitCavityDists( const std::string &name, const PropertySet &opts ) {
     double tic = toc();
 
-    if( Verbose() >= 1 ) {
+    if( props.verbose >= 1 ) {
         cout << "LC::InitCavityDists:  ";
-        if( Cavity() == CavityType::UNIFORM )
+        if( props.cavity == Properties::CavityType::UNIFORM )
             cout << "Using uniform initial cavity distributions" << endl;
-        else if( Cavity() == CavityType::FULL )
+        else if( props.cavity == Properties::CavityType::FULL )
             cout << "Using full " << name << opts << "...";
-        else if( Cavity() == CavityType::PAIR )
+        else if( props.cavity == Properties::CavityType::PAIR )
             cout << "Using pairwise " << name << opts << "...";
-        else if( Cavity() == CavityType::PAIR2 )
+        else if( props.cavity == Properties::CavityType::PAIR2 )
             cout << "Using pairwise(new) " << name << opts << "...";
     }
 
@@ -183,7 +189,7 @@ double LC::InitCavityDists (const std::string &name, const Properties &opts) {
     }
     init();
 
-    if( Verbose() >= 1 ) {
+    if( props.verbose >= 1 ) {
         cout << "used " << toc() - tic << " clocks." << endl;
     }
 
@@ -192,7 +198,7 @@ double LC::InitCavityDists (const std::string &name, const Properties &opts) {
 
 
 long LC::SetCavityDists( std::vector<Factor> &Q ) {
-    if( Verbose() >= 1 ) 
+    if( props.verbose >= 1 ) 
         cout << "LC::SetCavityDists:  Setting initial cavity distributions" << endl;
     if( Q.size() != nrVars() )
         return -1;
@@ -210,7 +216,7 @@ long LC::SetCavityDists( std::vector<Factor> &Q ) {
 void LC::init() {
     for( size_t i = 0; i < nrVars(); ++i )
         foreach( const Neighbor &I, nbV(i) )
-            if( Updates() == UpdateType::SEQRND )
+            if( props.updates == Properties::UpdateType::SEQRND )
                 _phis[i][I.iter].randomize();
             else
                 _phis[i][I.iter].fill(1.0);
@@ -219,7 +225,7 @@ void LC::init() {
         
         foreach( const Neighbor &I, nbV(i) ) {
             _pancakes[i] *= factor(I);
-            if( Updates() == UpdateType::SEQRND )
+            if( props.updates == Properties::UpdateType::SEQRND )
               _pancakes[i] *= _phis[i][I.iter];
         }
         
@@ -260,15 +266,17 @@ Factor LC::NewPancake (size_t i, size_t _I, bool & hasNaNs) {
 
 
 double LC::run() {
-    if( Verbose() >= 1 )
+    if( props.verbose >= 1 )
         cout << "Starting " << identify() << "...";
-    if( Verbose() >= 2 )
+    if( props.verbose >= 2 )
         cout << endl;
 
     double tic = toc();
     Diffs diffs(nrVars(), 1.0);
 
-    updateMaxDiff( InitCavityDists(GetPropertyAs<string>("cavainame"), GetPropertyAs<Properties>("cavaiopts")) );
+    double md = InitCavityDists( props.cavainame, props.cavaiopts );
+    if( md > maxdiff )
+        maxdiff = md;
 
     vector<Factor> old_beliefs;
     for(size_t i=0; i < nrVars(); i++ )
@@ -296,9 +304,9 @@ double LC::run() {
 
     // do several passes over the network until maximum number of iterations has
     // been reached or until the maximum belief difference is smaller than tolerance
-    for( iter=0; iter < MaxIter() && diffs.maxDiff() > Tol(); iter++ ) {
+    for( iter=0; iter < props.maxiter && diffs.maxDiff() > props.tol; iter++ ) {
         // Sequential updates
-        if( Updates() == UpdateType::SEQRND )
+        if( props.updates == Properties::UpdateType::SEQRND )
             random_shuffle( update_seq.begin(), update_seq.end() );
         
         for( size_t t=0; t < nredges; t++ ) {
@@ -316,19 +324,20 @@ double LC::run() {
             old_beliefs[i] = belief(i);
         }
 
-        if( Verbose() >= 3 )
+        if( props.verbose >= 3 )
             cout << "LC::run:  maxdiff " << diffs.maxDiff() << " after " << iter+1 << " passes" << endl;
     }
 
-    updateMaxDiff( diffs.maxDiff() );
+    if( diffs.maxDiff() > maxdiff )
+        maxdiff = diffs.maxDiff();
 
-    if( Verbose() >= 1 ) {
-        if( diffs.maxDiff() > Tol() ) {
-            if( Verbose() == 1 )
+    if( props.verbose >= 1 ) {
+        if( diffs.maxDiff() > props.tol ) {
+            if( props.verbose == 1 )
                 cout << endl;
-                cout << "LC::run:  WARNING: not converged within " << MaxIter() << " passes (" << toc() - tic << " clocks)...final maxdiff:" << diffs.maxDiff() << endl;
+                cout << "LC::run:  WARNING: not converged within " << props.maxiter << " passes (" << toc() - tic << " clocks)...final maxdiff:" << diffs.maxDiff() << endl;
         } else {
-            if( Verbose() >= 2 )
+            if( props.verbose >= 2 )
                 cout << "LC::run:  ";
                 cout << "converged in " << iter << " passes (" << toc() - tic << " clocks)." << endl;
         }
index 1ffc360..6da2bd4 100644 (file)
@@ -37,19 +37,23 @@ using namespace std;
 const char *MF::Name = "MF";
 
 
-bool MF::checkProperties() {
-    if( !HasProperty("tol") )
-        return false;
-    if (!HasProperty("maxiter") )
-        return false;
-    if (!HasProperty("verbose") )
-        return false;
-    
-    ConvertPropertyTo<double>("tol");
-    ConvertPropertyTo<size_t>("maxiter");
-    ConvertPropertyTo<size_t>("verbose");
+void MF::setProperties( const PropertySet &opts ) {
+    assert( opts.hasKey("tol") );
+    assert( opts.hasKey("maxiter") );
+    assert( opts.hasKey("verbose") );
+
+    props.tol = opts.getStringAs<double>("tol");
+    props.maxiter = opts.getStringAs<size_t>("maxiter");
+    props.verbose = opts.getStringAs<size_t>("verbose");
+}
 
-    return true;
+
+PropertySet MF::getProperties() const {
+    PropertySet opts;
+    opts.Set( "tol", props.tol );
+    opts.Set( "maxiter", props.maxiter );
+    opts.Set( "verbose", props.verbose );
+    return opts;
 }
 
 
@@ -66,14 +70,12 @@ void MF::create() {
 
 string MF::identify() const { 
     stringstream result (stringstream::out);
-    result << Name << GetProperties();
+    result << Name << getProperties();
     return result.str();
 }
 
 
 void MF::init() {
-    assert( checkProperties() );
-
     for( vector<Factor>::iterator qi = _beliefs.begin(); qi != _beliefs.end(); qi++ )
         qi->fill(1.0);
 }
@@ -82,14 +84,14 @@ void MF::init() {
 double MF::run() {
     double tic = toc();
 
-    if( Verbose() >= 1 )
+    if( props.verbose >= 1 )
         cout << "Starting " << identify() << "...";
 
     size_t pass_size = _beliefs.size();
     Diffs diffs(pass_size * 3, 1.0);
 
     size_t t=0;
-    for( t=0; t < (MaxIter()*pass_size) && diffs.maxDiff() > Tol(); t++ ) {
+    for( t=0; t < (props.maxiter*pass_size) && diffs.maxDiff() > props.tol; t++ ) {
         // choose random Var i
         size_t i = (size_t) (nrVars() * rnd_uniform());
 
@@ -119,15 +121,16 @@ double MF::run() {
         _beliefs[i] = jan;
     }
 
-    updateMaxDiff( diffs.maxDiff() );
+    if( diffs.maxDiff() > maxdiff )
+        maxdiff = diffs.maxDiff();
 
-    if( Verbose() >= 1 ) {
-        if( diffs.maxDiff() > Tol() ) {
-            if( Verbose() == 1 )
+    if( props.verbose >= 1 ) {
+        if( diffs.maxDiff() > props.tol ) {
+            if( props.verbose == 1 )
                 cout << endl;
-            cout << "MF::run:  WARNING: not converged within " << MaxIter() << " passes (" << toc() - tic << " clocks)...final maxdiff:" << diffs.maxDiff() << endl;
+            cout << "MF::run:  WARNING: not converged within " << props.maxiter << " passes (" << toc() - tic << " clocks)...final maxdiff:" << diffs.maxDiff() << endl;
         } else {
-            if( Verbose() >= 2 )
+            if( props.verbose >= 2 )
                 cout << "MF::run:  ";
             cout << "converged in " << t / pass_size << " passes (" << toc() - tic << " clocks)." << endl;
         }
index 5a3a7c8..eb9ab83 100644 (file)
@@ -39,22 +39,26 @@ using namespace std;
 const char *MR::Name = "MR";
 
 
-bool MR::checkProperties() {
-    if( !HasProperty("updates") )
-        return false;
-    if( !HasProperty("inits") )
-        return false;
-    if( !HasProperty("verbose") )
-        return false;
-    if( !HasProperty("tol") )
-        return false;
+void MR::setProperties( const PropertySet &opts ) {
+    assert( opts.hasKey("tol") );
+    assert( opts.hasKey("verbose") );
+    assert( opts.hasKey("updates") );
+    assert( opts.hasKey("inits") );
     
-    ConvertPropertyTo<UpdateType>("updates");
-    ConvertPropertyTo<InitType>("inits");
-    ConvertPropertyTo<size_t>("verbose");
-    ConvertPropertyTo<double>("tol");
+    props.tol = opts.getStringAs<double>("tol");
+    props.verbose = opts.getStringAs<size_t>("verbose");
+    props.updates = opts.getStringAs<Properties::UpdateType>("updates");
+    props.inits = opts.getStringAs<Properties::InitType>("inits");
+}
+
 
-    return true;
+PropertySet MR::getProperties() const {
+    PropertySet opts;
+    opts.Set( "tol", props.tol );
+    opts.Set( "verbose", props.verbose );
+    opts.Set( "updates", props.updates );
+    opts.Set( "inits", props.inits );
+    return opts;
 }
 
 
@@ -199,9 +203,9 @@ double MR::init_cor_resp() {
                         }
                     }
                 }
-            } while((md > Tol())&&(runx<runs)); // Precision condition reached -> BP and RP finished
+            } while((md > props.tol)&&(runx<runs)); // Precision condition reached -> BP and RP finished
             if(runx==runs)
-                if( Verbose() >= 2 )
+                if( props.verbose >= 2 )
                     cout << "init_cor_resp: Convergence not reached (md=" << md << ")..." << endl;
             if(md > maxdev)
                 maxdev = md;
@@ -409,7 +413,7 @@ void MR::solvemcav() {
                 assert( nb[j][_i] == i );
 
                 double newM = 0.0;
-                if( Updates() == UpdateType::FULL ) {
+                if( props.updates == Properties::UpdateType::FULL ) {
                     // find indices in nb[j] that do not correspond with i
                     sub_nb _nbj_min_i(con[j]);
                     _nbj_min_i -= kindex[i][_j];
@@ -429,7 +433,7 @@ void MR::solvemcav() {
                         numer += tJ[i][_k] * cors[i][_j][_k] * (tanh(theta[i]) * sum_even + sum_odd);
                     }
                     newM -= numer / denom;
-                } else if( Updates() == UpdateType::LINEAR ) {
+                } else if( props.updates == Properties::UpdateType::LINEAR ) {
                     newM = T(j,_i);
                     for(size_t _l=0; _l<con[i]; _l++) if( _l != _j )
                         newM -= Omega(i,_j,_l) * tJ[i][_l] * cors[i][_j][_l];
@@ -449,12 +453,13 @@ void MR::solvemcav() {
                 M[i][_j] = newM;
             }
         }
-    } while((maxdev>Tol())&&(run<maxruns));
+    } while((maxdev>props.tol)&&(run<maxruns));
 
-    updateMaxDiff( maxdev );
+    if( maxdev > maxdiff )
+        maxdiff = maxdev;
 
     if(run==maxruns){
-        if( Verbose() >= 1 )
+        if( props.verbose >= 1 )
             cout << "solve_mcav: Convergence not reached (maxdev=" << maxdev << ")..." << endl;
     }
 }
@@ -462,7 +467,7 @@ void MR::solvemcav() {
  
 void MR::solveM() { 
     for(size_t i=0; i<N; i++) {
-        if( Updates() == UpdateType::FULL ) {
+        if( props.updates == Properties::UpdateType::FULL ) {
             // find indices in nb[i]
             sub_nb _nbi(con[i]);
 
@@ -472,7 +477,7 @@ void MR::solveM() {
 
             Mag[i] = (tanh(theta[i]) * sum_even + sum_odd) / (sum_even + tanh(theta[i]) * sum_odd);
 
-        } else if( Updates() == UpdateType::LINEAR ) {
+        } else if( props.updates == Properties::UpdateType::LINEAR ) {
             sub_nb empty(con[i]);
             empty.clear();
             Mag[i] = T(i,empty);
@@ -490,12 +495,12 @@ void MR::solveM() {
 void MR::init_cor() {
     for( size_t i = 0; i < nrVars(); i++ ) {
         vector<Factor> pairq;
-        if( Inits() == InitType::CLAMPING ) {
-            BP bpcav(*this, Properties()("updates",string("SEQMAX"))("tol", string("1e-9"))("maxiter", string("1000UL"))("verbose", string("0UL"))("logdomain", string("0")));
+        if( props.inits == Properties::InitType::CLAMPING ) {
+            BP bpcav(*this, PropertySet()("updates",string("SEQMAX"))("tol", string("1e-9"))("maxiter", string("1000UL"))("verbose", string("0UL"))("logdomain", string("0")));
             bpcav.makeCavity( i );
             pairq = calcPairBeliefs( bpcav, delta(i), false );
-        } else if( Inits() == InitType::EXACT ) {
-            JTree jtcav(*this, Properties()("updates",string("HUGIN"))("verbose", string("0UL")) );
+        } else if( props.inits == Properties::InitType::EXACT ) {
+            JTree jtcav(*this, PropertySet()("updates",string("HUGIN"))("verbose", 0UL) );
             jtcav.makeCavity( i );
             pairq = calcPairBeliefs( jtcav, delta(i), false );
         }
@@ -517,14 +522,14 @@ void MR::init_cor() {
 
 string MR::identify() const { 
     stringstream result (stringstream::out);
-    result << Name << GetProperties();
+    result << Name << getProperties();
     return result.str();
 }
 
 
 double MR::run() {
     if( supported ) {
-        if( Verbose() >= 1 )
+        if( props.verbose >= 1 )
             cout << "Starting " << identify() << "...";
 
         double tic = toc();
@@ -545,11 +550,13 @@ double MR::run() {
         for(size_t i=0; i<N; i++)
           kindex[i].resize(kmax);
 
-        if( Inits() == InitType::RESPPROP )
-            updateMaxDiff( init_cor_resp() );
-        else if( Inits() == InitType::EXACT )
+        if( props.inits == Properties::InitType::RESPPROP ) {
+            double md = init_cor_resp();
+            if( md > maxdiff )
+                maxdiff = md;
+        } else if( props.inits == Properties::InitType::EXACT )
             init_cor(); // FIXME no MaxDiff() calculation
-        else if( Inits() == InitType::CLAMPING )
+        else if( props.inits == Properties::InitType::CLAMPING )
             init_cor(); // FIXME no MaxDiff() calculation
 
         solvemcav();
@@ -557,7 +564,7 @@ double MR::run() {
         Mag.resize(N);
         solveM();
 
-        if( Verbose() >= 1 )
+        if( props.verbose >= 1 )
             cout << "MR needed " << toc() - tic << " clocks." << endl;
 
         return 0.0;
@@ -601,7 +608,9 @@ vector<Factor> MR::beliefs() const {
 
 
 
-MR::MR( const FactorGraph &fg, const Properties &opts ) : DAIAlgFG(fg, opts), supported(true) {
+MR::MR( const FactorGraph &fg, const PropertySet &opts ) : DAIAlgFG(fg), supported(true), maxdiff(0.0) {
+    setProperties( opts );
+
     // check whether all vars in fg are binary
     // check whether connectivity is <= kmax
     for( size_t i = 0; i < fg.nrVars(); i++ )
index 49860fd..2b131b3 100644 (file)
@@ -38,35 +38,35 @@ std::ostream& operator<< (std::ostream & os, const Property & p) {
         os << boost::any_cast<double>(p.second);
     else if( p.second.type() == typeid(bool) )
         os << boost::any_cast<bool>(p.second);
-    else if( p.second.type() == typeid(Properties) )
-        os << boost::any_cast<Properties>(p.second);
+    else if( p.second.type() == typeid(PropertySet) )
+        os << boost::any_cast<PropertySet>(p.second);
 #ifdef WITH_BP
-    else if( p.second.type() == typeid(BP::UpdateType) )
-        os << boost::any_cast<BP::UpdateType>(p.second);
+    else if( p.second.type() == typeid(BP::Properties::UpdateType) )
+        os << boost::any_cast<BP::Properties::UpdateType>(p.second);
 #endif
 #ifdef WITH_HAK
-    else if( p.second.type() == typeid(HAK::ClustersType) )
-        os << boost::any_cast<HAK::ClustersType>(p.second);
+    else if( p.second.type() == typeid(HAK::Properties::ClustersType) )
+        os << boost::any_cast<HAK::Properties::ClustersType>(p.second);
 #endif
 #ifdef WITH_JTREE
-    else if( p.second.type() == typeid(JTree::UpdateType) )
-        os << boost::any_cast<JTree::UpdateType>(p.second);
+    else if( p.second.type() == typeid(JTree::Properties::UpdateType) )
+        os << boost::any_cast<JTree::Properties::UpdateType>(p.second);
 #endif
 #ifdef WITH_MR
-    else if( p.second.type() == typeid(MR::UpdateType) )
-        os << boost::any_cast<MR::UpdateType>(p.second);
-    else if( p.second.type() == typeid(MR::InitType) )
-        os << boost::any_cast<MR::InitType>(p.second);
+    else if( p.second.type() == typeid(MR::Properties::UpdateType) )
+        os << boost::any_cast<MR::Properties::UpdateType>(p.second);
+    else if( p.second.type() == typeid(MR::Properties::InitType) )
+        os << boost::any_cast<MR::Properties::InitType>(p.second);
 #endif
 #ifdef WITH_TREEEP
-    else if( p.second.type() == typeid(TreeEP::TypeType) )
-        os << boost::any_cast<TreeEP::TypeType>(p.second);
+    else if( p.second.type() == typeid(TreeEP::Properties::TypeType) )
+        os << boost::any_cast<TreeEP::Properties::TypeType>(p.second);
 #endif
 #ifdef WITH_LC
-    else if( p.second.type() == typeid(LC::CavityType) )
-        os << boost::any_cast<LC::CavityType>(p.second);
-    else if( p.second.type() == typeid(LC::UpdateType) )
-        os << boost::any_cast<LC::UpdateType>(p.second);
+    else if( p.second.type() == typeid(LC::Properties::CavityType) )
+        os << boost::any_cast<LC::Properties::CavityType>(p.second);
+    else if( p.second.type() == typeid(LC::Properties::UpdateType) )
+        os << boost::any_cast<LC::Properties::UpdateType>(p.second);
 #endif
     else
         throw "Unknown property type";
@@ -74,10 +74,10 @@ std::ostream& operator<< (std::ostream & os, const Property & p) {
 }
 
 
-/// Sends a Properties object to an output stream
-std::ostream& operator<< (std::ostream & os, const Properties & ps) {
+/// Sends a PropertySet object to an output stream
+std::ostream& operator<< (std::ostream & os, const PropertySet & ps) {
     os << "[";
-    for( Properties::const_iterator p = ps.begin(); p != ps.end(); p++ ) {
+    for( PropertySet::const_iterator p = ps.begin(); p != ps.end(); p++ ) {
         if( p != ps.begin() )
             os << ",";
         os << (Property)*p;
@@ -87,9 +87,9 @@ std::ostream& operator<< (std::ostream & os, const Properties & ps) {
 }
 
 
-/// Reads a Properties object from an input stream, storing values as strings
-std::istream& operator >> (std::istream& is, Properties & ps) {
-    ps = Properties();
+/// Reads a PropertySet object from an input stream, storing values as strings
+std::istream& operator >> (std::istream& is, PropertySet & ps) {
+    ps = PropertySet();
 
     std::string s;
     is >> s;
index d5c4614..9ce7354 100644 (file)
@@ -37,22 +37,26 @@ using namespace std;
 const char *TreeEP::Name = "TREEEP";
 
 
-bool TreeEP::checkProperties() {
-    if( !HasProperty("type") )
-        return false;
-    if( !HasProperty("tol") )
-        return false;
-    if (!HasProperty("maxiter") )
-        return false;
-    if (!HasProperty("verbose") )
-        return false;
+void TreeEP::setProperties( const PropertySet &opts ) {
+    assert( opts.hasKey("tol") );
+    assert( opts.hasKey("maxiter") );
+    assert( opts.hasKey("verbose") );
+    assert( opts.hasKey("type") );
     
-    ConvertPropertyTo<TypeType>("type");
-    ConvertPropertyTo<double>("tol");
-    ConvertPropertyTo<size_t>("maxiter");
-    ConvertPropertyTo<size_t>("verbose");
+    props.tol = opts.getStringAs<double>("tol");
+    props.maxiter = opts.getStringAs<size_t>("maxiter");
+    props.verbose = opts.getStringAs<size_t>("verbose");
+    props.type = opts.getStringAs<Properties::TypeType>("type");
+}
+
 
-    return true;
+PropertySet TreeEP::getProperties() const {
+    PropertySet opts;
+    opts.Set( "tol", props.tol );
+    opts.Set( "maxiter", props.maxiter );
+    opts.Set( "verbose", props.verbose );
+    opts.Set( "type", props.type );
+    return opts;
 }
 
 
@@ -182,15 +186,15 @@ double TreeEPSubTree::logZ( const std::vector<Factor> &Qa, const std::vector<Fac
 }
 
 
-TreeEP::TreeEP( const FactorGraph &fg, const Properties &opts ) : JTree(fg, opts("updates",string("HUGIN")), false) {
-    assert( checkProperties() );
+TreeEP::TreeEP( const FactorGraph &fg, const PropertySet &opts ) : JTree(fg, opts("updates",string("HUGIN")), false), props(), maxdiff(0.0) {
+    setProperties( opts );
 
     assert( fg.G.isConnected() );
 
     if( opts.hasKey("tree") ) {
         ConstructRG( opts.GetAs<DEdgeVec>("tree") );
     } else {
-        if( Type() == TypeType::ORG ) {
+        if( props.type == Properties::TypeType::ORG ) {
             // construct weighted graph with as weights a crude estimate of the
             // mutual information between the nodes
             WeightedGraph<double> wg;
@@ -225,7 +229,7 @@ TreeEP::TreeEP( const FactorGraph &fg, const Properties &opts ) : JTree(fg, opts
 //            for( DEdgeVec::const_iterator e = MST.begin(); e != MST.end(); e++ )
 //                cout << *e << endl; 
 //            ConstructRG( MST );
-        } else if( Type() == TypeType::ALT ) {
+        } else if( props.type == Properties::TypeType::ALT ) {
             // construct weighted graph with as weights an upper bound on the
             // effective interaction strength between pairs of nodes
             WeightedGraph<double> wg;
@@ -375,7 +379,7 @@ void TreeEP::ConstructRG( const DEdgeVec &tree ) {
             break;
         }
 
-    if( Verbose() >= 3 ) {
+    if( props.verbose >= 3 ) {
         cout << "Resulting regiongraph: " << *this << endl;
     }
 }
@@ -383,14 +387,12 @@ void TreeEP::ConstructRG( const DEdgeVec &tree ) {
 
 string TreeEP::identify() const { 
     stringstream result (stringstream::out);
-    result << Name << GetProperties();
+    result << Name << getProperties();
     return result.str();
 }
 
 
 void TreeEP::init() {
-    assert( checkProperties() );
-
     runHUGIN();
 
     // Init factor approximations
@@ -401,9 +403,9 @@ void TreeEP::init() {
 
 
 double TreeEP::run() {
-    if( Verbose() >= 1 )
+    if( props.verbose >= 1 )
         cout << "Starting " << identify() << "...";
-    if( Verbose() >= 3)
+    if( props.verbose >= 3)
         cout << endl;
 
     double tic = toc();
@@ -418,7 +420,7 @@ double TreeEP::run() {
     
     // do several passes over the network until maximum number of iterations has
     // been reached or until the maximum belief difference is smaller than tolerance
-    for( iter=0; iter < MaxIter() && diffs.maxDiff() > Tol(); iter++ ) {
+    for( iter=0; iter < props.maxiter && diffs.maxDiff() > props.tol; iter++ ) {
         for( size_t I = 0; I < nrFactors(); I++ )
             if( offtree(I) ) {  
                 _Q[I].InvertAndMultiply( _Qa, _Qb );
@@ -433,19 +435,20 @@ double TreeEP::run() {
             old_beliefs[i] = nb;
         }
 
-        if( Verbose() >= 3 )
+        if( props.verbose >= 3 )
             cout << "TreeEP::run:  maxdiff " << diffs.maxDiff() << " after " << iter+1 << " passes" << endl;
     }
 
-    updateMaxDiff( diffs.maxDiff() );
+    if( diffs.maxDiff() > maxdiff )
+        maxdiff = diffs.maxDiff();
 
-    if( Verbose() >= 1 ) {
-        if( diffs.maxDiff() > Tol() ) {
-            if( Verbose() == 1 )
+    if( props.verbose >= 1 ) {
+        if( diffs.maxDiff() > props.tol ) {
+            if( props.verbose == 1 )
                 cout << endl;
-            cout << "TreeEP::run:  WARNING: not converged within " << MaxIter() << " passes (" << toc() - tic << " clocks)...final maxdiff:" << diffs.maxDiff() << endl;
+            cout << "TreeEP::run:  WARNING: not converged within " << props.maxiter << " passes (" << toc() - tic << " clocks)...final maxdiff:" << diffs.maxDiff() << endl;
         } else {
-            if( Verbose() >= 3 )
+            if( props.verbose >= 3 )
                 cout << "TreeEP::run:  ";
             cout << "converged in " << iter << " passes (" << toc() - tic << " clocks)." << endl;
         }
index 007e7f3..02ca982 100644 (file)
@@ -47,7 +47,7 @@ class TestAI {
         double          maxdiff;
         double          time;
 
-        TestAI( const FactorGraph &fg, const string &_name, const Properties &opts ) : obj(NULL), name(_name), err(), q(), logZ(0.0), maxdiff(0.0), time(0) {
+        TestAI( const FactorGraph &fg, const string &_name, const PropertySet &opts ) : obj(NULL), name(_name), err(), q(), logZ(0.0), maxdiff(0.0), time(0) {
             double tic = toc();
             obj = newInfAlg( name, fg, opts );
             time += toc() - tic;
@@ -105,7 +105,7 @@ class TestAI {
                 obj->run();
                 time += toc() - tic;
                 logZ = real(obj->logZ());
-                maxdiff = obj->MaxDiff();
+                maxdiff = obj->maxDiff();
                 q = allBeliefs();
             };
         }
@@ -134,14 +134,14 @@ class TestAI {
 };
 
 
-pair<string, Properties> parseMethod( const string &_s, const map<string,string> & aliases ) {
+pair<string, PropertySet> parseMethod( const string &_s, const map<string,string> & aliases ) {
     string s = _s;
     if( aliases.find(_s) != aliases.end() )
         s = aliases.find(_s)->second;
 
-    pair<string, Properties> result;
+    pair<string, PropertySet> result;
     string & name = result.first;
-    Properties & opts = result.second;
+    PropertySet & opts = result.second;
 
     string::size_type pos = s.find_first_of('[');
     name = s.substr( 0, pos );
@@ -262,7 +262,7 @@ int main( int argc, char *argv[] ) {
             cout << "MAXDIFF" << endl;
 
             for( size_t m = 0; m < methods.size(); m++ ) {
-                pair<string, Properties> meth = parseMethod( methods[m], Aliases );
+                pair<string, PropertySet> meth = parseMethod( methods[m], Aliases );
 
                 if( vm.count("tol") )
                     meth.second.Set("tol",tol);