Cleaned up error handling by introducing the DAI_THROWE macro.
[libdai.git] / include / dai / daialg.h
1 /* Copyright (C) 2006-2008 Joris Mooij [joris dot mooij at tuebingen dot mpg dot de]
2 Radboud University Nijmegen, The Netherlands /
3 Max Planck Institute for Biological Cybernetics, Germany
4
5 This file is part of libDAI.
6
7 libDAI is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
11
12 libDAI is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with libDAI; if not, write to the Free Software
19 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20 */
21
22
23 /// \file
24 /// \brief Defines abstract base class InfAlg, its descendants DAIAlg<T>, the specializations DAIAlgFG and DAIAlgRG and some generic inference methods.
25 /// \todo Improve documentation
26
27
28 #ifndef __defined_libdai_daialg_h
29 #define __defined_libdai_daialg_h
30
31
32 #include <string>
33 #include <iostream>
34 #include <vector>
35 #include <dai/factorgraph.h>
36 #include <dai/regiongraph.h>
37
38
39 namespace dai {
40
41
42 /// InfAlg is an abstract base class, defining the common interface of all inference algorithms in libDAI.
43 /** \todo General marginalization functions like calcMarginal now copy a complete InfAlg object. Instead,
44 * it would make more sense that they construct a new object without copying the FactorGraph or RegionGraph.
45 * Or they can simply be made methods of the general InfAlg class.
46 * \idea Use a PropertySet as output of an InfAlg, instead of functions like maxDiff() and Iterations().
47 */
48 class InfAlg {
49 public:
50 /// Virtual desctructor (needed because this class contains virtual functions)
51 virtual ~InfAlg() {}
52
53 public:
54 /// Returns a pointer to a new, cloned copy of *this (i.e., virtual copy constructor)
55 virtual InfAlg* clone() const = 0;
56
57 /// Identifies itself for logging purposes
58 virtual std::string identify() const = 0;
59
60 /// Returns the "belief" (i.e., approximate marginal probability distribution) of a variable
61 virtual Factor belief( const Var &n ) const = 0;
62
63 /// Returns the "belief" (i.e., approximate marginal probability distribution) of a set of variables
64 virtual Factor belief( const VarSet &n ) const = 0;
65
66 /// Returns marginal for a variable.
67 /** Sometimes preferred to belief() for performance reasons.
68 * Faster implementations exist in e.g. BP.
69 */
70 virtual Factor beliefV( size_t i ) const { return belief( fg().var(i) ); }
71
72 /// Returns marginal for a factor.
73 /** Sometimes preferred to belief() for performance reasons.
74 * Faster implementations exist in e.g. BP.
75 */
76 virtual Factor beliefF( size_t I ) const { return belief( fg().factor(I).vars() ); }
77
78 /// Returns all "beliefs" (i.e., approximate marginal probability distribution) calculated by the algorithm
79 virtual std::vector<Factor> beliefs() const = 0;
80
81 /// Returns the logarithm of the (approximated) partition sum (normalizing constant of the factor graph)
82 virtual Real logZ() const = 0;
83
84 /// Initializes all data structures of the approximate inference algorithm
85 /** This method should be called at least once before run() is called
86 */
87 virtual void init() = 0;
88
89 /// Initializes all data structures corresponding to some set of variables
90 /** This method can be used to do a partial initialization after a part of the factor graph has changed.
91 * Instead of initializing all data structures, it only initializes those involving the variables in ns.
92 */
93 virtual void init( const VarSet &ns ) = 0;
94
95 /// Runs the approximate inference algorithm
96 /* Before run() is called the first time, init() should be called.
97 * If run() returns successfully, the results can be queried using the methods belief(), beliefs() and logZ().
98 */
99 virtual double run() = 0;
100
101 /// Clamp variable with index i to value x (i.e. multiply with a Kronecker delta \f$\delta_{x_i, x}\f$)
102 /** If backup == true, make a backup of all factors that are changed
103 */
104 virtual void clamp( size_t i, size_t x, bool backup = false ) = 0;
105
106 // OBSOLETE
107 /// Only for backwards compatibility (to be removed soon)
108 virtual void clamp( const Var &v, size_t x, bool backup = false ) = 0;
109
110 /// Set all factors interacting with var(i) to 1
111 virtual void makeCavity( size_t i, bool backup = false ) = 0;
112
113 /// Return maximum difference between single node beliefs in the last pass
114 /// \throw Exception if not implemented/supported
115 virtual double maxDiff() const = 0;
116
117 /// Return number of passes over the factorgraph
118 /// \throw Exception if not implemented/supported
119 virtual size_t Iterations() const = 0;
120
121
122 /// Get reference to underlying FactorGraph
123 virtual FactorGraph &fg() = 0;
124
125 /// Get const reference to underlying FactorGraph
126 virtual const FactorGraph &fg() const = 0;
127
128 /// Save factor I
129 virtual void backupFactor( size_t I ) = 0;
130 /// Save Factors involving ns
131 virtual void backupFactors( const VarSet &ns ) = 0;
132
133 /// Restore factor I
134 virtual void restoreFactor( size_t I ) = 0;
135 /// Restore Factors involving ns
136 virtual void restoreFactors( const VarSet &ns ) = 0;
137 };
138
139
140 /// Combines an InfAlg and a graphical model, e.g., a FactorGraph or RegionGraph
141 /** \tparam GRM Should be castable to FactorGraph
142 * \todo A DAIAlg should not inherit from a FactorGraph or RegionGraph, but should
143 * store a reference to the graphical model object. This prevents needless copying
144 * of (possibly large) data structures. Disadvantage: the caller must not change
145 * the graphical model between calls to the inference algorithm (maybe a smart_ptr
146 * or some locking mechanism would help here?).
147 */
148 template <class GRM>
149 class DAIAlg : public InfAlg, public GRM {
150 public:
151 /// Default constructor
152 DAIAlg() : InfAlg(), GRM() {}
153
154 /// Construct from GRM
155 DAIAlg( const GRM &grm ) : InfAlg(), GRM(grm) {}
156
157 /// Save factor I
158 void backupFactor( size_t I ) { GRM::backupFactor( I ); }
159 /// Save Factors involving ns
160 void backupFactors( const VarSet &ns ) { GRM::backupFactors( ns ); }
161
162 /// Restore factor I
163 void restoreFactor( size_t I ) { GRM::restoreFactor( I ); }
164 /// Restore Factors involving ns
165 void restoreFactors( const VarSet &ns ) { GRM::restoreFactors( ns ); }
166
167 /// Clamp variable with index i to value x (i.e. multiply with a Kronecker delta \f$\delta_{x_i, x}\f$)
168 void clamp( size_t i, size_t x, bool backup = false ) { GRM::clamp( i, x, backup ); }
169
170 // OBSOLETE
171 /// Only for backwards compatibility (to be removed soon)
172 void clamp( const Var &v, size_t x, bool backup = false ) {
173 GRM::clamp( v, x, backup );
174 std::cerr << "Warning: this DAIAlg<...>::clamp(const Var&,...) interface is obsolete!" << std::endl;
175 }
176
177 /// Set all factors interacting with var(i) to 1
178 void makeCavity( size_t i, bool backup = false ) { GRM::makeCavity( i, backup ); }
179
180 /// Get reference to underlying FactorGraph
181 FactorGraph &fg() { return (FactorGraph &)(*this); }
182
183 /// Get const reference to underlying FactorGraph
184 const FactorGraph &fg() const { return (const FactorGraph &)(*this); }
185 };
186
187
188 /// Base class for inference algorithms that operate on a FactorGraph
189 typedef DAIAlg<FactorGraph> DAIAlgFG;
190
191 /// Base class for inference algorithms that operate on a RegionGraph
192 typedef DAIAlg<RegionGraph> DAIAlgRG;
193
194
195 Factor calcMarginal( const InfAlg & obj, const VarSet & ns, bool reInit );
196 std::vector<Factor> calcPairBeliefs( const InfAlg & obj, const VarSet& ns, bool reInit );
197 std::vector<Factor> calcPairBeliefsNew( const InfAlg & obj, const VarSet& ns, bool reInit );
198 Factor calcMarginal2ndO( const InfAlg & obj, const VarSet& ns, bool reInit );
199
200
201 } // end of namespace dai
202
203
204 #endif