1 /* This file is part of libDAI - http://www.libdai.org/
3 * libDAI is licensed under the terms of the GNU General Public License version
4 * 2, or (at your option) any later version. libDAI is distributed without any
5 * warranty. See the file COPYING for more details.
7 * Copyright (C) 2006-2009 Joris Mooij [joris dot mooij at libdai dot org]
8 * Copyright (C) 2006-2007 Radboud University Nijmegen, The Netherlands
26 const char *MF::Name
= "MF";
29 void MF::setProperties( const PropertySet
&opts
) {
30 DAI_ASSERT( opts
.hasKey("tol") );
31 DAI_ASSERT( opts
.hasKey("maxiter") );
33 props
.tol
= opts
.getStringAs
<Real
>("tol");
34 props
.maxiter
= opts
.getStringAs
<size_t>("maxiter");
35 if( opts
.hasKey("verbose") )
36 props
.verbose
= opts
.getStringAs
<size_t>("verbose");
39 if( opts
.hasKey("damping") )
40 props
.damping
= opts
.getStringAs
<Real
>("damping");
46 PropertySet
MF::getProperties() const {
48 opts
.Set( "tol", props
.tol
);
49 opts
.Set( "maxiter", props
.maxiter
);
50 opts
.Set( "verbose", props
.verbose
);
51 opts
.Set( "damping", props
.damping
);
56 string
MF::printProperties() const {
57 stringstream
s( stringstream::out
);
59 s
<< "tol=" << props
.tol
<< ",";
60 s
<< "maxiter=" << props
.maxiter
<< ",";
61 s
<< "verbose=" << props
.verbose
<< ",";
62 s
<< "damping=" << props
.damping
<< "]";
67 void MF::construct() {
70 _beliefs
.reserve( nrVars() );
71 for( size_t i
= 0; i
< nrVars(); ++i
)
72 _beliefs
.push_back( Factor( var(i
) ) );
76 string
MF::identify() const {
77 return string(Name
) + printProperties();
82 for( vector
<Factor
>::iterator qi
= _beliefs
.begin(); qi
!= _beliefs
.end(); qi
++ )
87 Factor
MF::calcNewBelief( size_t i
) {
89 foreach( const Neighbor
&I
, nbV(i
) ) {
91 foreach( const Neighbor
&j
, nbF(I
) ) // for all j in I \ i
94 Factor piet
= factor(I
).log(true);
96 piet
= piet
.marginal(var(i
), false);
106 if( props
.verbose
>= 1 )
107 cerr
<< "Starting " << identify() << "...";
111 vector
<size_t> update_seq
;
112 update_seq
.reserve( nrVars() );
113 for( size_t i
= 0; i
< nrVars(); i
++ )
114 update_seq
.push_back( i
);
116 // do several passes over the network until maximum number of iterations has
117 // been reached or until the maximum belief difference is smaller than tolerance
118 Real maxDiff
= INFINITY
;
119 for( _iters
= 0; _iters
< props
.maxiter
&& maxDiff
> props
.tol
; _iters
++ ) {
120 random_shuffle( update_seq
.begin(), update_seq
.end() );
123 foreach( const size_t &i
, update_seq
) {
124 Factor nb
= calcNewBelief( i
);
127 cerr
<< Name
<< "::run(): ERROR: new belief of variable " << var(i
) << " has NaNs!" << endl
;
131 if( props
.damping
!= 0.0 )
132 nb
= (nb
^(1.0 - props
.damping
)) * (_beliefs
[i
]^props
.damping
);
134 maxDiff
= std::max( maxDiff
, dist( nb
, _beliefs
[i
], Prob::DISTLINF
) );
138 if( props
.verbose
>= 3 )
139 cerr
<< Name
<< "::run: maxdiff " << maxDiff
<< " after " << _iters
+1 << " passes" << endl
;
142 if( maxDiff
> _maxdiff
)
145 if( props
.verbose
>= 1 ) {
146 if( maxDiff
> props
.tol
) {
147 if( props
.verbose
== 1 )
149 cerr
<< Name
<< "::run: WARNING: not converged within " << props
.maxiter
<< " passes (" << toc() - tic
<< " seconds)...final maxdiff:" << maxDiff
<< endl
;
151 if( props
.verbose
>= 3 )
152 cerr
<< Name
<< "::run: ";
153 cerr
<< "converged in " << _iters
<< " passes (" << toc() - tic
<< " seconds)." << endl
;
161 Factor
MF::beliefV( size_t i
) const {
162 return _beliefs
[i
].normalized();
166 Factor
MF::belief (const VarSet
&ns
) const {
169 else if( ns
.size() == 1 )
170 return beliefV( findVar( *(ns
.begin()) ) );
172 DAI_THROW(BELIEF_NOT_AVAILABLE
);
178 vector
<Factor
> MF::beliefs() const {
179 vector
<Factor
> result
;
180 for( size_t i
= 0; i
< nrVars(); i
++ )
181 result
.push_back( beliefV(i
) );
186 Real
MF::logZ() const {
189 for( size_t i
= 0; i
< nrVars(); i
++ )
190 s
-= beliefV(i
).entropy();
191 for( size_t I
= 0; I
< nrFactors(); I
++ ) {
193 foreach( const Neighbor
&j
, nbF(I
) ) // for all j in I
197 piet
= factor(I
).log(true);
206 void MF::init( const VarSet
&ns
) {
207 for( size_t i
= 0; i
< nrVars(); i
++ ) {
208 if( ns
.contains(var(i
) ) )
209 _beliefs
[i
].fill( 1.0 );
214 } // end of namespace dai