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 [frederik at ofb dot net]
12 /// \brief Defines class BBP, which implements Back-Belief-Propagation
15 #ifndef ___defined_libdai_bbp_h
16 #define ___defined_libdai_bbp_h
23 #include <dai/daialg.h>
24 #include <dai/factorgraph.h>
26 #include <dai/bp_dual.h>
32 /// Enumeration of several cost functions that can be used with BBP
33 /** \note This class is meant as a base class for BBPCostFunction, which provides additional functionality.
35 DAI_ENUM(BBPCostFunctionBase
,CFN_GIBBS_B
,CFN_GIBBS_B2
,CFN_GIBBS_EXP
,CFN_GIBBS_B_FACTOR
,CFN_GIBBS_B2_FACTOR
,CFN_GIBBS_EXP_FACTOR
,CFN_VAR_ENT
,CFN_FACTOR_ENT
,CFN_BETHE_ENT
);
38 /// Predefined cost functions that can be used with BBP
39 class BBPCostFunction
: public BBPCostFunctionBase
{
41 /// Returns whether this cost function depends on having a Gibbs state
42 bool needGibbsState() const;
44 /// Evaluates cost function in state \a stateP using the information in inference algorithm \a ia
45 Real
evaluate( const InfAlg
&ia
, const std::vector
<size_t> *stateP
) const;
47 /// Assignment operator
48 BBPCostFunction
& operator=( const BBPCostFunctionBase
&x
) {
50 (BBPCostFunctionBase
)*this = x
;
57 /// Implements BBP (Back-Belief-Propagation) [\ref EaG09]
58 /** \author Frederik Eaton
62 /// \name Input variables
64 /// Stores a BP_dual helper object
66 /// Pointer to the factor graph
67 const FactorGraph
*_fg
;
68 /// Pointer to the approximate inference algorithm (currently, only BP objects are supported)
72 /// \name Output variables
74 /// Variable factor adjoints
75 std::vector
<Prob
> _adj_psi_V
;
77 std::vector
<Prob
> _adj_psi_F
;
78 /// Variable->factor message adjoints (indexed [i][_I])
79 std::vector
<std::vector
<Prob
> > _adj_n
;
80 /// Factor->variable message adjoints (indexed [i][_I])
81 std::vector
<std::vector
<Prob
> > _adj_m
;
82 /// Normalized variable belief adjoints
83 std::vector
<Prob
> _adj_b_V
;
84 /// Normalized factor belief adjoints
85 std::vector
<Prob
> _adj_b_F
;
88 /// \name Internal state variables
90 /// Initial variable factor adjoints
91 std::vector
<Prob
> _init_adj_psi_V
;
92 /// Initial factor adjoints
93 std::vector
<Prob
> _init_adj_psi_F
;
95 /// Unnormalized variable->factor message adjoint (indexed [i][_I])
96 std::vector
<std::vector
<Prob
> > _adj_n_unnorm
;
97 /// Unnormalized factor->variable message adjoint (indexed [i][_I])
98 std::vector
<std::vector
<Prob
> > _adj_m_unnorm
;
99 /// Updated normalized variable->factor message adjoint (indexed [i][_I])
100 std::vector
<std::vector
<Prob
> > _new_adj_n
;
101 /// Updated normalized factor->variable message adjoint (indexed [i][_I])
102 std::vector
<std::vector
<Prob
> > _new_adj_m
;
103 /// Unnormalized variable belief adjoints
104 std::vector
<Prob
> _adj_b_V_unnorm
;
105 /// Unnormalized factor belief adjoints
106 std::vector
<Prob
> _adj_b_F_unnorm
;
108 /// _T[i][_I] (see eqn. (41) in [\ref EaG09])
109 std::vector
<std::vector
<Prob
> > _T
;
110 /// _U[I][_i] (see eqn. (42) in [\ref EaG09])
111 std::vector
<std::vector
<Prob
> > _U
;
112 /// _S[i][_I][_j] (see eqn. (43) in [\ref EaG09])
113 std::vector
<std::vector
<std::vector
<Prob
> > > _S
;
114 /// _R[I][_i][_J] (see eqn. (44) in [\ref EaG09])
115 std::vector
<std::vector
<std::vector
<Prob
> > > _R
;
117 /// Number of iterations done
121 /// \name Index cache management (for performance)
124 typedef std::vector
<size_t> _ind_t
;
125 /// Cached indices (indexed [i][_I])
126 std::vector
<std::vector
<_ind_t
> > _indices
;
127 /// Prepares index cache _indices
130 void RegenerateInds();
131 /// Returns an index from the cache
132 const _ind_t
& _index(size_t i
, size_t _I
) const { return _indices
[i
][_I
]; }
135 /// \name Initialization helper functions
137 /// Calculate T values; see eqn. (41) in [\ref EaG09]
139 /// Calculate U values; see eqn. (42) in [\ref EaG09]
141 /// Calculate S values; see eqn. (43) in [\ref EaG09]
143 /// Calculate R values; see eqn. (44) in [\ref EaG09]
145 /// Calculate _adj_b_V_unnorm and _adj_b_F_unnorm from _adj_b_V and _adj_b_F
146 void RegenerateInputs();
147 /// Initialise members for factor adjoints
148 /** \pre RegenerateInputs() should be called first
150 void RegeneratePsiAdjoints();
151 /// Initialise members for message adjoints for parallel algorithm
152 /** \pre RegenerateInputs() should be called first
154 void RegenerateParMessageAdjoints();
155 /// Initialise members for message adjoints for sequential algorithm
156 /** Same as RegenerateMessageAdjoints, but calls sendSeqMsgN rather
157 * than updating _adj_n (and friends) which are unused in the sequential algorithm.
158 * \pre RegenerateInputs() should be called first
160 void RegenerateSeqMessageAdjoints();
161 /// Called by \a init, recalculates intermediate values
165 /// \name Accessors/mutators
167 /// Returns reference to T value; see eqn. (41) in [\ref EaG09]
168 Prob
& T(size_t i
, size_t _I
) { return _T
[i
][_I
]; }
169 /// Returns constant reference to T value; see eqn. (41) in [\ref EaG09]
170 const Prob
& T(size_t i
, size_t _I
) const { return _T
[i
][_I
]; }
171 /// Returns reference to U value; see eqn. (42) in [\ref EaG09]
172 Prob
& U(size_t I
, size_t _i
) { return _U
[I
][_i
]; }
173 /// Returns constant reference to U value; see eqn. (42) in [\ref EaG09]
174 const Prob
& U(size_t I
, size_t _i
) const { return _U
[I
][_i
]; }
175 /// Returns reference to S value; see eqn. (43) in [\ref EaG09]
176 Prob
& S(size_t i
, size_t _I
, size_t _j
) { return _S
[i
][_I
][_j
]; }
177 /// Returns constant reference to S value; see eqn. (43) in [\ref EaG09]
178 const Prob
& S(size_t i
, size_t _I
, size_t _j
) const { return _S
[i
][_I
][_j
]; }
179 /// Returns reference to R value; see eqn. (44) in [\ref EaG09]
180 Prob
& R(size_t I
, size_t _i
, size_t _J
) { return _R
[I
][_i
][_J
]; }
181 /// Returns constant reference to R value; see eqn. (44) in [\ref EaG09]
182 const Prob
& R(size_t I
, size_t _i
, size_t _J
) const { return _R
[I
][_i
][_J
]; }
184 /// Returns reference to variable->factor message adjoint
185 Prob
& adj_n(size_t i
, size_t _I
) { return _adj_n
[i
][_I
]; }
186 /// Returns constant reference to variable->factor message adjoint
187 const Prob
& adj_n(size_t i
, size_t _I
) const { return _adj_n
[i
][_I
]; }
188 /// Returns reference to factor->variable message adjoint
189 Prob
& adj_m(size_t i
, size_t _I
) { return _adj_m
[i
][_I
]; }
190 /// Returns constant reference to factor->variable message adjoint
191 const Prob
& adj_m(size_t i
, size_t _I
) const { return _adj_m
[i
][_I
]; }
194 /// \name Parallel algorithm
196 /// Calculates new variable->factor message adjoint
197 /** Increases variable factor adjoint according to eqn. (27) in [\ref EaG09] and
198 * calculates the new variable->factor message adjoint according to eqn. (29) in [\ref EaG09].
200 void calcNewN( size_t i
, size_t _I
);
201 /// Calculates new factor->variable message adjoint
202 /** Increases factor adjoint according to eqn. (28) in [\ref EaG09] and
203 * calculates the new factor->variable message adjoint according to the r.h.s. of eqn. (30) in [\ref EaG09].
205 void calcNewM( size_t i
, size_t _I
);
206 /// Calculates unnormalized variable->factor message adjoint from the normalized one
207 void calcUnnormMsgN( size_t i
, size_t _I
);
208 /// Calculates unnormalized factor->variable message adjoint from the normalized one
209 void calcUnnormMsgM( size_t i
, size_t _I
);
210 /// Updates (un)normalized variable->factor message adjoints
211 void upMsgN( size_t i
, size_t _I
);
212 /// Updates (un)normalized factor->variable message adjoints
213 void upMsgM( size_t i
, size_t _I
);
214 /// Do one parallel update of all message adjoints
218 /// \name Sequential algorithm
220 /// Helper function for sendSeqMsgM(): increases factor->variable message adjoint by \a p and calculates the corresponding unnormalized adjoint
221 void incrSeqMsgM( size_t i
, size_t _I
, const Prob
& p
);
222 // DISABLED BECAUSE IT IS BUGGY:
223 // void updateSeqMsgM( size_t i, size_t _I );
224 /// Sets normalized factor->variable message adjoint and calculates the corresponding unnormalized adjoint
225 void setSeqMsgM( size_t i
, size_t _I
, const Prob
&p
);
226 /// Implements routine Send-n in Figure 5 in [\ref EaG09]
227 void sendSeqMsgN( size_t i
, size_t _I
, const Prob
&f
);
228 /// Implements routine Send-m in Figure 5 in [\ref EaG09]
229 void sendSeqMsgM( size_t i
, size_t _I
);
232 /// Computes the adjoint of the unnormed probability vector from the normalizer and the adjoint of the normalized probability vector
233 /** \see eqn. (13) in [\ref EaG09]
235 Prob
unnormAdjoint( const Prob
&w
, Real Z_w
, const Prob
&adj_w
);
237 /// Calculates averaged L1 norm of unnormalized message adjoints
239 /// Calculates averaged L1 norms of current and new normalized message adjoints
240 void getMsgMags( Real
&s
, Real
&new_s
);
241 /// Returns indices and magnitude of the largest normalized factor->variable message adjoint
242 void getArgmaxMsgM( size_t &i
, size_t &_I
, Real
&mag
);
243 /// Returns magnitude of the largest (in L1-norm) normalized factor->variable message adjoint
246 /// Calculates sum of L1 norms of all normalized factor->variable message adjoints
248 /// Calculates sum of L1 norms of all updated normalized factor->variable message adjoints
249 Real
getTotalNewMsgM();
250 /// Calculates sum of L1 norms of all normalized variable->factor message adjoints
253 /// Returns a vector of Probs (filled with zeroes) with state spaces corresponding to the factors in the factor graph \a fg
254 std::vector
<Prob
> getZeroAdjF( const FactorGraph
&fg
);
255 /// Returns a vector of Probs (filled with zeroes) with state spaces corresponding to the variables in the factor graph \a fg
256 std::vector
<Prob
> getZeroAdjV( const FactorGraph
&fg
);
259 /// \name Constructors/destructors
261 /// Construct BBP object from a InfAlg \a ia and a PropertySet \a opts
262 /** \param ia should be a BP object or something compatible
263 * \param opts Parameters @see Properties
265 BBP( const InfAlg
*ia
, const PropertySet
&opts
) : _bp_dual(ia
), _fg(&(ia
->fg())), _ia(ia
) {
270 /// \name Initialization
272 /// Initializes from given belief adjoints \a adj_b_V, \a adj_b_F and initial factor adjoints \a adj_psi_V, \a adj_psi_F
273 void init( const std::vector
<Prob
> &adj_b_V
, const std::vector
<Prob
> &adj_b_F
, const std::vector
<Prob
> &adj_psi_V
, const std::vector
<Prob
> &adj_psi_F
) {
276 _init_adj_psi_V
= adj_psi_V
;
277 _init_adj_psi_F
= adj_psi_F
;
281 /// Initializes from given belief adjoints \a adj_b_V and \a adj_b_F (setting initial factor adjoints to zero)
282 void init( const std::vector
<Prob
> &adj_b_V
, const std::vector
<Prob
> &adj_b_F
) {
283 init( adj_b_V
, adj_b_F
, getZeroAdjV(*_fg
), getZeroAdjF(*_fg
) );
286 /// Initializes variable belief adjoints \a adj_b_V (and sets factor belief adjoints and initial factor adjoints to zero)
287 void init_V( const std::vector
<Prob
> &adj_b_V
) {
288 init( adj_b_V
, getZeroAdjF(*_fg
) );
291 /// Initializes factor belief adjoints \a adj_b_F (and sets variable belief adjoints and initial factor adjoints to zero)
292 void init_F( const std::vector
<Prob
> &adj_b_F
) {
293 init( getZeroAdjV(*_fg
), adj_b_F
);
296 /// Initializes with adjoints calculated from cost function \a cfn, and state \a stateP
297 /** Uses the internal pointer to an inference algorithm in combination with the cost function and state for initialization.
298 * \param cfn Cost function used for initialization;
299 * \param stateP is a Gibbs state and can be NULL; it will be initialised using a Gibbs run.
301 void initCostFnAdj( const BBPCostFunction
&cfn
, const std::vector
<size_t> *stateP
);
304 /// \name BBP Algorithm
306 /// Perform iterative updates until change is less than given tolerance
310 /// \name Query results
312 /// Returns reference to variable factor adjoint
313 Prob
& adj_psi_V(size_t i
) { return _adj_psi_V
[i
]; }
314 /// Returns constant reference to variable factor adjoint
315 const Prob
& adj_psi_V(size_t i
) const { return _adj_psi_V
[i
]; }
316 /// Returns reference to factor adjoint
317 Prob
& adj_psi_F(size_t I
) { return _adj_psi_F
[I
]; }
318 /// Returns constant reference to factor adjoint
319 const Prob
& adj_psi_F(size_t I
) const { return _adj_psi_F
[I
]; }
320 /// Returns reference to variable belief adjoint
321 Prob
& adj_b_V(size_t i
) { return _adj_b_V
[i
]; }
322 /// Returns constant reference to variable belief adjoint
323 const Prob
& adj_b_V(size_t i
) const { return _adj_b_V
[i
]; }
324 /// Returns reference to factor belief adjoint
325 Prob
& adj_b_F(size_t I
) { return _adj_b_F
[I
]; }
326 /// Returns constant reference to factor belief adjoint
327 const Prob
& adj_b_F(size_t I
) const { return _adj_b_F
[I
]; }
328 /// Return number of iterations done so far
329 size_t Iterations() { return _iters
; }
333 /// Parameters for BBP
334 /* PROPERTIES(props,BBP) {
335 /// \brief Enumeration of possible update schedules
336 /// - SEQ_FIX fixed sequential updates
337 /// - SEQ_MAX maximum residual updates (inspired by [\ref EMK06])
338 /// - SEQ_BP_REV schedule used by BP, but reversed
339 /// - SEQ_BP_FWD schedule used by BP
340 /// - PAR parallel updates
341 DAI_ENUM(UpdateType,SEQ_FIX,SEQ_MAX,SEQ_BP_REV,SEQ_BP_FWD,PAR);
343 /// Verbosity (amount of output sent to stderr)
346 /// Maximum number of iterations
349 /// Tolerance for convergence test
350 /// \note Not used for updates = SEQ_BP_REV, SEQ_BP_FWD
353 /// Damping constant (0 for none); damping = 1 - lambda where lambda is the damping constant used in [\ref EaG09]
359 // DISABLED BECAUSE IT IS BUGGY:
360 // bool clean_updates;
363 /* {{{ GENERATED CODE: DO NOT EDIT. Created by
364 ./scripts/regenerate-properties include/dai/bbp.h src/bbp.cpp
367 /// Enumeration of possible update schedules
368 /** The following update schedules are defined:
369 * - SEQ_FIX fixed sequential updates
370 * - SEQ_MAX maximum residual updates (inspired by [\ref EMK06])
371 * - SEQ_BP_REV schedule used by BP, but reversed
372 * - SEQ_BP_FWD schedule used by BP
373 * - PAR parallel updates
375 DAI_ENUM(UpdateType
,SEQ_FIX
,SEQ_MAX
,SEQ_BP_REV
,SEQ_BP_FWD
,PAR
);
376 /// Verbosity (amount of output sent to stderr)
378 /// Maximum number of iterations
380 /// Tolerance for convergence test
381 /** \note Not used for updates = SEQ_BP_REV, SEQ_BP_FWD
384 /// Damping constant (0 for none); damping = 1 - lambda where lambda is the damping constant used in [\ref EaG09]
389 /// Set members from PropertySet
390 /** \throw UNKNOWN_PROPERTY_TYPE if a Property key is not recognized
391 * \throw NOT_ALL_PROPERTIES_SPECIFIED if an expected Property is missing
393 void set(const PropertySet
&opts
);
394 /// Get members into PropertySet
395 PropertySet
get() const;
396 /// Convert to a string which can be parsed as a PropertySet
397 std::string
toString() const;
399 /* }}} END OF GENERATED CODE */
403 /// Function to verify the validity of adjoints computed by BBP using numerical differentiation.
404 /** Factors containing a variable are multiplied by small adjustments to verify accuracy of calculated variable factor adjoints.
405 * \param bp BP object;
406 * \param state Global state of all variables;
407 * \param bbp_props BBP parameters;
408 * \param cfn Cost function to be used;
409 * \param h Size of perturbation.
412 Real
numericBBPTest( const InfAlg
&bp
, const std::vector
<size_t> *state
, const PropertySet
&bbp_props
, const BBPCostFunction
&cfn
, Real h
);
415 } // end of namespace dai