Improved documentation of factor.h, ...
[libdai.git] / src / mf.cpp
index 7fe6958..ae92182 100644 (file)
@@ -1,6 +1,7 @@
-/*  Copyright (C) 2006-2008  Joris Mooij  [j dot mooij at science dot ru dot nl]
-    Radboud University Nijmegen, The Netherlands
-    
+/*  Copyright (C) 2006-2008  Joris Mooij  [joris dot mooij at tuebingen dot mpg dot de]
+    Radboud University Nijmegen, The Netherlands /
+    Max Planck Institute for Biological Cybernetics, Germany
+
     This file is part of libDAI.
 
     libDAI is free software; you can redistribute it and/or modify
     This file is part of libDAI.
 
     libDAI is free software; you can redistribute it and/or modify
@@ -24,7 +25,6 @@
 #include <map>
 #include <set>
 #include <dai/mf.h>
 #include <map>
 #include <set>
 #include <dai/mf.h>
-#include <dai/diffs.h>
 #include <dai/util.h>
 
 
 #include <dai/util.h>
 
 
@@ -37,61 +37,75 @@ using namespace std;
 const char *MF::Name = "MF";
 
 
 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") );
+
+    props.tol = opts.getStringAs<double>("tol");
+    props.maxiter = opts.getStringAs<size_t>("maxiter");
+    if( opts.hasKey("verbose") )
+        props.verbose = opts.getStringAs<size_t>("verbose");
+    else
+        props.verbose = 0U;
+    if( opts.hasKey("damping") )
+        props.damping = opts.getStringAs<double>("damping");
+    else
+        props.damping = 0.0;
+}
+
 
 
-    return true;
+PropertySet MF::getProperties() const {
+    PropertySet opts;
+    opts.Set( "tol", props.tol );
+    opts.Set( "maxiter", props.maxiter );
+    opts.Set( "verbose", props.verbose );
+    opts.Set( "damping", props.damping );
+    return opts;
 }
 
 
 }
 
 
-void MF::Regenerate() {
-//    DAIAlgFG::Regenerate();
+string MF::printProperties() const {
+    stringstream s( stringstream::out );
+    s << "[";
+    s << "tol=" << props.tol << ",";
+    s << "maxiter=" << props.maxiter << ",";
+    s << "verbose=" << props.verbose << ",";
+    s << "damping=" << props.damping << "]";
+    return s.str();
+}
 
 
-    // clear beliefs
-    _beliefs.clear();
-    _beliefs.reserve( nrVars() );
 
 
+void MF::construct() {
     // create beliefs
     // create beliefs
+    _beliefs.clear();
+    _beliefs.reserve( nrVars() );
     for( size_t i = 0; i < nrVars(); ++i )
     for( size_t i = 0; i < nrVars(); ++i )
-        _beliefs.push_back(Factor(var(i)));
+        _beliefs.push_back( Factor( var(i) ) );
 }
 
 
 string MF::identify() const { 
 }
 
 
 string MF::identify() const { 
-    stringstream result (stringstream::out);
-    result << Name << GetProperties();
-    return result.str();
+    return string(Name) + printProperties();
 }
 
 
 void MF::init() {
 }
 
 
 void MF::init() {
-    assert( checkProperties() );
-
     for( vector<Factor>::iterator qi = _beliefs.begin(); qi != _beliefs.end(); qi++ )
         qi->fill(1.0);
 }
 
 
 double MF::run() {
     for( vector<Factor>::iterator qi = _beliefs.begin(); qi != _beliefs.end(); qi++ )
         qi->fill(1.0);
 }
 
 
 double MF::run() {
-    clock_t tic = toc();
+    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;
         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.max() > 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());
 
         // choose random Var i
         size_t i = (size_t) (nrVars() * rnd_uniform());
 
@@ -102,47 +116,51 @@ double MF::run() {
             foreach( const Neighbor &j, nbF(I) ) // for all j in I \ i
                 if( j != i )
                     henk *= _beliefs[j];
             foreach( const Neighbor &j, nbF(I) ) // for all j in I \ i
                 if( j != i )
                     henk *= _beliefs[j];
-            piet = factor(I).log0();
+            piet = factor(I).log(true);
             piet *= henk;
             piet *= henk;
-            piet = piet.part_sum(var(i));
+            piet = piet.marginal(var(i), false);
             piet = piet.exp();
             jan *= piet; 
         }
 
             piet = piet.exp();
             jan *= piet; 
         }
 
-        jan.normalize( _normtype );
+        jan.normalize();
 
         if( jan.hasNaNs() ) {
 
         if( jan.hasNaNs() ) {
-            cout << "MF::run():  ERROR: jan has NaNs!" << endl;
-            return NAN;
+            cout << Name << "::run():  ERROR: jan has NaNs!" << endl;
+            return 1.0;
         }
 
         }
 
+        if( props.damping != 0.0 )
+            jan = (jan^(1.0 - props.damping)) * (_beliefs[i]^props.damping);
         diffs.push( dist( jan, _beliefs[i], Prob::DISTLINF ) );
 
         _beliefs[i] = jan;
     }
 
         diffs.push( dist( jan, _beliefs[i], Prob::DISTLINF ) );
 
         _beliefs[i] = jan;
     }
 
-    updateMaxDiff( diffs.max() );
+    _iters = t / pass_size;
+    if( diffs.maxDiff() > _maxdiff )
+        _maxdiff = diffs.maxDiff();
 
 
-    if( Verbose() >= 1 ) {
-        if( diffs.max() > Tol() ) {
-            if( Verbose() == 1 )
+    if( props.verbose >= 1 ) {
+        if( diffs.maxDiff() > props.tol ) {
+            if( props.verbose == 1 )
                 cout << endl;
                 cout << endl;
-            cout << "MF::run:  WARNING: not converged within " << MaxIter() << " passes (" << toc() - tic << " clocks)...final maxdiff:" << diffs.max() << endl;
+            cout << Name << "::run:  WARNING: not converged within " << props.maxiter << " passes (" << toc() - tic << " seconds)...final maxdiff:" << diffs.maxDiff() << endl;
         } else {
         } else {
-            if( Verbose() >= 2 )
-                cout << "MF::run:  ";
-            cout << "converged in " << t / pass_size << " passes (" << toc() - tic << " clocks)." << endl;
+            if( props.verbose >= 2 )
+                cout << Name << "::run:  ";
+            cout << "converged in " << t / pass_size << " passes (" << toc() - tic << " seconds)." << endl;
         }
     }
 
         }
     }
 
-    return diffs.max();
+    return diffs.maxDiff();
 }
 
 
 }
 
 
-Factor MF::beliefV (size_t i) const {
+Factor MF::beliefV( size_t i ) const {
     Factor piet;
     piet = _beliefs[i];
     Factor piet;
     piet = _beliefs[i];
-    piet.normalize( Prob::NORMPROB );
+    piet.normalize();
     return(piet);
 }
 
     return(piet);
 }
 
@@ -170,8 +188,8 @@ vector<Factor> MF::beliefs() const {
 }
 
 
 }
 
 
-Complex MF::logZ() const {
-    Complex sum = 0.0;
+Real MF::logZ() const {
+    Real sum = 0.0;
     
     for(size_t i=0; i < nrVars(); i++ )
         sum -= beliefV(i).entropy();
     
     for(size_t i=0; i < nrVars(); i++ )
         sum -= beliefV(i).entropy();
@@ -179,11 +197,11 @@ Complex MF::logZ() const {
         Factor henk;
         foreach( const Neighbor &j, nbF(I) )  // for all j in I
             henk *= _beliefs[j];
         Factor henk;
         foreach( const Neighbor &j, nbF(I) )  // for all j in I
             henk *= _beliefs[j];
-        henk.normalize( Prob::NORMPROB );
+        henk.normalize();
         Factor piet;
         Factor piet;
-        piet = factor(I).log0();
+        piet = factor(I).log(true);
         piet *= henk;
         piet *= henk;
-        sum -= Complex( piet.totalSum() );
+        sum -= piet.totalSum();
     }
 
     return -sum;
     }
 
     return -sum;
@@ -192,7 +210,7 @@ Complex MF::logZ() const {
 
 void MF::init( const VarSet &ns ) {
     for( size_t i = 0; i < nrVars(); i++ ) {
 
 void MF::init( const VarSet &ns ) {
     for( size_t i = 0; i < nrVars(); i++ ) {
-        if( ns && var(i) )
+        if( ns.contains(var(i) ) )
             _beliefs[i].fill( 1.0 );
     }
 }
             _beliefs[i].fill( 1.0 );
     }
 }