b5e1a2b9e0d384b764352d4865c635a361b610ca
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) 2009 Frederik Eaton
8 * Copyright (C) 2009 Joris Mooij [joris dot mooij at libdai dot org]
15 #define DAI_FBP_FAST 1
24 const char *FBP::Name
= "FBP";
27 string
FBP::identify() const {
28 return string(Name
) + printProperties();
32 // This code has been copied from bp.cpp, except where comments indicate FBP-specific behaviour
33 Real
FBP::logZ() const {
35 for( size_t I
= 0; I
< nrFactors(); I
++ ) {
36 sum
+= (beliefF(I
) * factor(I
).log(true)).sum(); // FBP
37 sum
+= Weight(I
) * beliefF(I
).entropy(); // FBP
39 for( size_t i
= 0; i
< nrVars(); ++i
) {
41 foreach( const Neighbor
&I
, nbV(i
) )
43 sum
+= (1.0 - c_i
) * beliefV(i
).entropy(); // FBP
49 // This code has been copied from bp.cpp, except where comments indicate FBP-specific behaviour
50 Prob
FBP::calcIncomingMessageProduct( size_t I
, bool without_i
, size_t i
) const {
51 Real c_I
= Weight(I
); // FBP: c_I
53 Factor
Fprod( factor(I
) );
54 Prob
&prod
= Fprod
.p();
56 if( props
.logdomain
) {
60 prod
^= (1.0 / c_I
); // FBP
62 // Calculate product of incoming messages and factor I
63 foreach( const Neighbor
&j
, nbF(I
) )
64 if( !(without_i
&& (j
== i
)) ) {
65 // prod_j will be the product of messages coming into j
66 // FBP: corresponds to messages n_jI
67 Prob
prod_j( var(j
).states(), props
.logdomain
? 0.0 : 1.0 );
68 foreach( const Neighbor
&J
, nbV(j
) )
69 if( J
!= I
) { // for all J in nb(j) \ I
71 prod_j
+= message( j
, J
.iter
);
73 prod_j
*= message( j
, J
.iter
);
75 // FBP: multiply by m_Ij^(1-1/c_I)
77 prod_j
+= newMessage( j
, J
.iter
) * (1.0 - 1.0 / c_I
);
79 prod_j
*= newMessage( j
, J
.iter
) ^ (1.0 - 1.0 / c_I
);
82 // multiply prod with prod_j
84 // UNOPTIMIZED (SIMPLE TO READ, BUT SLOW) VERSION
86 Fprod
+= Factor( var(j
), prod_j
);
88 Fprod
*= Factor( var(j
), prod_j
);
92 // ind is the precalculated IndexFor(j,I) i.e. to x_I == k corresponds x_j == ind[k]
93 const ind_t
&ind
= index(j
, _I
);
95 for( size_t r
= 0; r
< prod
.size(); ++r
)
97 prod
[r
] += prod_j
[ind
[r
]];
99 prod
[r
] *= prod_j
[ind
[r
]];
106 // This code has been copied from bp.cpp, except where comments indicate FBP-specific behaviour
107 void FBP::calcNewMessage( size_t i
, size_t _I
) {
108 // calculate updated message I->i
109 size_t I
= nbV(i
,_I
);
111 Real c_I
= Weight(I
); // FBP: c_I
113 Factor
Fprod( factor(I
) );
114 Prob
&prod
= Fprod
.p();
115 prod
= calcIncomingMessageProduct( I
, true, i
);
117 if( props
.logdomain
) {
122 // Marginalize onto i
124 if( !DAI_FBP_FAST
) {
125 // UNOPTIMIZED (SIMPLE TO READ, BUT SLOW) VERSION
126 if( props
.inference
== Properties::InfType::SUMPROD
)
127 marg
= Fprod
.marginal( var(i
) ).p();
129 marg
= Fprod
.maxMarginal( var(i
) ).p();
132 marg
= Prob( var(i
).states(), 0.0 );
133 // ind is the precalculated IndexFor(i,I) i.e. to x_I == k corresponds x_i == ind[k]
134 const ind_t ind
= index(i
,_I
);
135 if( props
.inference
== Properties::InfType::SUMPROD
)
136 for( size_t r
= 0; r
< prod
.size(); ++r
)
137 marg
[ind
[r
]] += prod
[r
];
139 for( size_t r
= 0; r
< prod
.size(); ++r
)
140 if( prod
[r
] > marg
[ind
[r
]] )
141 marg
[ind
[r
]] = prod
[r
];
149 if( props
.logdomain
)
150 newMessage(i
,_I
) = marg
.log();
152 newMessage(i
,_I
) = marg
;
154 // Update the residual if necessary
155 if( props
.updates
== Properties::UpdateType::SEQMAX
)
156 updateResidual( i
, _I
, dist( newMessage( i
, _I
), message( i
, _I
), Prob::DISTLINF
) );
160 void FBP::construct() {
162 _weight
.resize( nrFactors(), 1.0 );
166 } // end of namespace dai