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
14 #define DAI_FBP_FAST 1
23 const char *FBP::Name
= "FBP";
26 string
FBP::identify() const {
27 return string(Name
) + printProperties();
31 /* This code has been copied from bp.cpp, except where comments indicate FBP-specific behaviour */
32 void FBP::calcNewMessage( size_t i
, size_t _I
) {
33 // calculate updated message I->i
36 Real scale
= scaleF(I
); // FBP: c_I
38 Factor
Fprod( factor(I
) );
39 Prob
&prod
= Fprod
.p();
40 if( props
.logdomain
) {
42 prod
*= (1/scale
); // FBP
44 prod
^= (1/scale
); // FBP
46 // Calculate product of incoming messages and factor I
47 foreach( const Neighbor
&j
, nbF(I
) )
48 if( j
!= i
) { // for all j in I \ i
50 // prod_j will be the product of messages coming into j
51 Prob
prod_j( var(j
).states(), props
.logdomain
? 0.0 : 1.0 );
52 foreach( const Neighbor
&J
, nbV(j
) )
53 if( J
!= I
) { // for all J in nb(j) \ I
55 prod_j
+= message( j
, J
.iter
);
57 prod_j
*= message( j
, J
.iter
);
62 // FBP: now multiply by m_Ij^(1-1/c_I)
64 prod_j
+= message( j
, _I
)*(1-1/scale
);
66 prod_j
*= message( j
, _I
)^(1-1/scale
);
68 // multiply prod with prod_j
70 /* UNOPTIMIZED (SIMPLE TO READ, BUT SLOW) VERSION */
72 Fprod
+= Factor( var(j
), prod_j
);
74 Fprod
*= Factor( var(j
), prod_j
);
76 /* OPTIMIZED VERSION */
77 // ind is the precalculated IndexFor(j,I) i.e. to x_I == k corresponds x_j == ind[k]
78 const ind_t
&ind
= index(j
, _I
);
79 for( size_t r
= 0; r
< prod
.size(); ++r
)
81 prod
[r
] += prod_j
[ind
[r
]];
83 prod
[r
] *= prod_j
[ind
[r
]];
87 if( props
.logdomain
) {
95 /* UNOPTIMIZED (SIMPLE TO READ, BUT SLOW) VERSION */
96 if( props
.inference
== Properties::InfType::SUMPROD
)
97 marg
= Fprod
.marginal( var(i
) ).p();
99 marg
= Fprod
.maxMarginal( var(i
) ).p();
101 /* OPTIMIZED VERSION */
102 marg
= Prob( var(i
).states(), 0.0 );
103 // ind is the precalculated IndexFor(i,I) i.e. to x_I == k corresponds x_i == ind[k]
104 const ind_t ind
= index(i
,_I
);
105 if( props
.inference
== Properties::InfType::SUMPROD
)
106 for( size_t r
= 0; r
< prod
.size(); ++r
)
107 marg
[ind
[r
]] += prod
[r
];
109 for( size_t r
= 0; r
< prod
.size(); ++r
)
110 if( prod
[r
] > marg
[ind
[r
]] )
111 marg
[ind
[r
]] = prod
[r
];
119 if( props
.logdomain
)
120 newMessage(i
,_I
) = marg
.log();
122 newMessage(i
,_I
) = marg
;
124 // Update the residual if necessary
125 if( props
.updates
== Properties::UpdateType::SEQMAX
)
126 updateResidual( i
, _I
, dist( newMessage( i
, _I
), message( i
, _I
), Prob::DISTLINF
) );
130 /* This code has been copied from bp.cpp, except where comments indicate FBP-specific behaviour */
131 void FBP::calcBeliefF( size_t I
, Prob
&p
) const {
132 Real scale
= scaleF(I
); // FBP: c_I
134 Factor
Fprod( factor(I
) );
135 Prob
&prod
= Fprod
.p();
137 if( props
.logdomain
) {
139 prod
/= scale
; // FBP
141 prod
^= (1/scale
); // FBP
143 foreach( const Neighbor
&j
, nbF(I
) ) {
144 // prod_j will be the product of messages coming into j
145 // FBP: corresponds to messages n_jI
146 Prob
prod_j( var(j
).states(), props
.logdomain
? 0.0 : 1.0 );
147 foreach( const Neighbor
&J
, nbV(j
) )
148 if( J
!= I
) { // for all J in nb(j) \ I
149 if( props
.logdomain
)
150 prod_j
+= newMessage( j
, J
.iter
);
152 prod_j
*= newMessage( j
, J
.iter
);
157 // FBP: now multiply by m_Ij^(1-1/c_I)
158 if( props
.logdomain
)
159 prod_j
+= newMessage( j
, _I
)*(1-1/scale
);
161 prod_j
*= newMessage( j
, _I
)^(1-1/scale
);
163 // multiply prod with prod_j
164 if( !DAI_FBP_FAST
) {
165 /* UNOPTIMIZED (SIMPLE TO READ, BUT SLOW) VERSION */
166 if( props
.logdomain
)
167 Fprod
+= Factor( var(j
), prod_j
);
169 Fprod
*= Factor( var(j
), prod_j
);
171 /* OPTIMIZED VERSION */
173 // ind is the precalculated IndexFor(j,I) i.e. to x_I == k corresponds x_j == ind[k]
174 const ind_t
& ind
= index(j
, _I
);
176 for( size_t r
= 0; r
< prod
.size(); ++r
) {
177 if( props
.logdomain
)
178 prod
[r
] += prod_j
[ind
[r
]];
180 prod
[r
] *= prod_j
[ind
[r
]];
189 void FBP::construct() {
191 constructScaleParams();
195 } // end of namespace dai