[Frederik Eaton] Added Fractional Belief Propagation
authorJoris Mooij <joris.mooij@tuebingen.mpg.de>
Mon, 21 Dec 2009 10:34:26 +0000 (11:34 +0100)
committerJoris Mooij <joris.mooij@tuebingen.mpg.de>
Mon, 21 Dec 2009 10:34:26 +0000 (11:34 +0100)
15 files changed:
ChangeLog
Makefile
Makefile.CYGWIN
Makefile.LINUX
Makefile.MACOSX
Makefile.WINDOWS
README
doxygen.conf
include/dai/alldai.h
include/dai/bp.h
include/dai/doc.h
include/dai/fbp.h [new file with mode: 0644]
src/alldai.cpp
src/fbp.cpp [new file with mode: 0644]
tests/aliases.conf

index 705c736..5761e2a 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,4 @@
+* [Frederik Eaton] Added Fractional Belief Propagation
 * Removed obsolete/deprecated stuff
 
 
index a93f4c3..999f254 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -56,6 +56,10 @@ ifdef WITH_BP
   CCFLAGS:=$(CCFLAGS) -DDAI_WITH_BP
   OBJECTS:=$(OBJECTS) bp$(OE)
 endif
+ifdef WITH_FBP
+  CCFLAGS:=$(CCFLAGS) -DDAI_WITH_FBP
+  OBJECTS:=$(OBJECTS) fbp$(OE)
+endif
 ifdef WITH_MF
   CCFLAGS:=$(CCFLAGS) -DDAI_WITH_MF
   OBJECTS:=$(OBJECTS) mf$(OE)
@@ -136,6 +140,9 @@ exactinf$(OE) : $(SRC)/exactinf.cpp $(INC)/exactinf.h $(HEADERS)
 bp$(OE) : $(SRC)/bp.cpp $(INC)/bp.h $(HEADERS)
        $(CC) -c $(SRC)/bp.cpp
 
+fbp$(OE) : $(SRC)/fbp.cpp $(INC)/fbp.h $(HEADERS)
+       $(CC) -c $(SRC)/fbp.cpp
+
 bp_dual$(OE) : $(SRC)/bp_dual.cpp $(INC)/bp_dual.h $(HEADERS)
        $(CC) -c $(SRC)/bp_dual.cpp
 
@@ -299,7 +306,7 @@ endif
 
 doc : $(INC)/*.h $(SRC)/*.cpp examples/*.cpp doxygen.conf
        doxygen doxygen.conf
-       DAI_VERSION=$(DAI_VERSION) DAI_DATE=$(DAI_DATE) scripts/makeREADME
+       DAI_VERSION=$(DAI_VERSION) DAI_DATE=$(DAI_DATE) scripts/makeREADME
 
 TAGS:
        etags src/*.cpp include/dai/*.h tests/*.cpp utils/*.cpp
index 47ec495..0fc6d3a 100644 (file)
@@ -18,6 +18,7 @@
 # COMPILATION AND BUILD FLAGS
 # Enable/disable various approximate inference methods
 WITH_BP=true
+WITH_FBP=true
 WITH_MF=true
 WITH_HAK=true
 WITH_LC=true
index 11bab16..0f47e48 100644 (file)
@@ -18,6 +18,7 @@
 # COMPILATION AND BUILD FLAGS
 # Enable/disable various approximate inference methods
 WITH_BP=true
+WITH_FBP=true
 WITH_MF=true
 WITH_HAK=true
 WITH_LC=true
index 2fb813d..7859ade 100644 (file)
@@ -18,6 +18,7 @@
 # COMPILATION AND BUILD FLAGS
 # Enable/disable various approximate inference methods
 WITH_BP=true
+WITH_FBP=true
 WITH_MF=true
 WITH_HAK=true
 WITH_LC=true
index 778f995..8bea63b 100644 (file)
@@ -19,6 +19,7 @@
 # COMPILATION AND BUILD FLAGS
 # Enable/disable various approximate inference methods
 WITH_BP=true
+WITH_FBP=true
 WITH_MF=true
 WITH_HAK=true
 WITH_LC=true
diff --git a/README b/README
index 81e977c..6640c28 100644 (file)
--- a/README
+++ b/README
@@ -73,6 +73,7 @@ Currently, libDAI supports the following (approximate) inference methods:
   • Exact inference by junction-tree methods;
   • Mean Field;
   • Loopy Belief Propagation [KFL01];
+  • Fractional Belief Propagation [WiH03];
   • Tree Expectation Propagation [MiQ04];
   • Generalized Belief Propagation [YFW05];
   • Double-loop GBP [HAK03];
index f8018d6..0eaeccf 100644 (file)
@@ -1253,6 +1253,7 @@ INCLUDE_FILE_PATTERNS  =
 # instead of the = operator.
 
 PREDEFINED             = DAI_WITH_BP \
+                         DAI_WITH_FBP \
                          DAI_WITH_MF \
                          DAI_WITH_HAK \
                          DAI_WITH_LC \
index ca96326..19f00f0 100644 (file)
@@ -26,6 +26,9 @@
 #ifdef DAI_WITH_BP
     #include <dai/bp.h>
 #endif
+#ifdef DAI_WITH_FBP
+    #include <dai/fbp.h>
+#endif
 #ifdef DAI_WITH_MF
     #include <dai/mf.h>
 #endif
@@ -82,6 +85,9 @@ static const char* DAINames[] = {
 #ifdef DAI_WITH_BP
     BP::Name,
 #endif
+#ifdef DAI_WITH_FBP
+    FBP::Name,
+#endif
 #ifdef DAI_WITH_MF
     MF::Name,
 #endif
index ea872e5..3bae74d 100644 (file)
@@ -37,9 +37,9 @@ namespace dai {
  *
  *  The messages \f$m_{I\to i}(x_i)\f$ are passed from factors \f$I\f$ to variables \f$i\f$. 
  *  In case of the sum-product algorith, the update equation is: 
- *    \f[ m_{I\to i}(x_i) \propto \sum_{x_{I\setminus\{i\}}} f_I(x_I) \prod_{j\in N_I\setminus\{i\}} \prod_{J\in N_j\setminus\{I\}} m_{J\to j}\f]
+ *    \f[ m_{I\to i}(x_i) \propto \sum_{x_{N_I\setminus\{i\}}} f_I(x_I) \prod_{j\in N_I\setminus\{i\}} \prod_{J\in N_j\setminus\{I\}} m_{J\to j}\f]
  *  and in case of the max-product algorithm:
- *    \f[ m_{I\to i}(x_i) \propto \max_{x_{I\setminus\{i\}}} f_I(x_I) \prod_{j\in N_I\setminus\{i\}} \prod_{J\in N_j\setminus\{I\}} m_{J\to j}\f]
+ *    \f[ m_{I\to i}(x_i) \propto \max_{x_{N_I\setminus\{i\}}} f_I(x_I) \prod_{j\in N_I\setminus\{i\}} \prod_{J\in N_j\setminus\{I\}} m_{J\to j}\f]
  *  In order to improve convergence, the updates can be damped. For improved numerical stability,
  *  the updates can be done in the log-domain alternatively.
  *
@@ -59,7 +59,7 @@ namespace dai {
  *  enabled by defining DAI_BP_FAST as false in the source file.
  */
 class BP : public DAIAlgFG {
-    private:
+    protected:
         /// Type used for index cache
         typedef std::vector<size_t> ind_t;
         /// Type used for storing edge properties
@@ -212,7 +212,7 @@ class BP : public DAIAlgFG {
         void clearSentMessages() { _sentMessages.clear(); }
     //@}
 
-    private:
+    protected:
         /// Returns constant reference to message from the \a _I 'th neighbor of variable \a i to variable \a i
         const Prob & message(size_t i, size_t _I) const { return _edges[i][_I].message; }
         /// Returns reference to message from the \a _I 'th neighbor of variable \a i to variable \a i
@@ -231,7 +231,7 @@ class BP : public DAIAlgFG {
         Real & residual(size_t i, size_t _I) { return _edges[i][_I].residual; }
 
         /// Calculate the updated message from the \a _I 'th neighbor of variable \a i to variable \a i
-        void calcNewMessage( size_t i, size_t _I );
+        virtual void calcNewMessage( size_t i, size_t _I );
         /// Replace the "old" message from the \a _I 'th neighbor of variable \a i to variable \a i by the "new" (updated) message
         void updateMessage( size_t i, size_t _I );
         /// Set the residual (difference between new and old message) for the edge between variable \a i and its \a _I 'th neighbor to \a r
@@ -241,10 +241,10 @@ class BP : public DAIAlgFG {
         /// Calculates unnormalized belief of variable \a i
         void calcBeliefV( size_t i, Prob &p ) const;
         /// Calculates unnormalized belief of factor \a I
-        void calcBeliefF( size_t I, Prob &p ) const;
+        virtual void calcBeliefF( size_t I, Prob &p ) const;
 
         /// Helper function for constructors
-        void construct();
+        virtual void construct();
 };
 
 
index 9ffc0a2..9d6084c 100644 (file)
@@ -85,6 +85,7 @@
  *  - Exact inference by junction-tree methods;
  *  - Mean Field;
  *  - Loopy Belief Propagation [\ref KFL01];
+ *  - Fractional Belief Propagation [\ref WiH03];
  *  - Tree Expectation Propagation [\ref MiQ04];
  *  - Generalized Belief Propagation [\ref YFW05];
  *  - Double-loop GBP [\ref HAK03];
  *  "Residual Belief Propagation: Informed Scheduling for Asynchronous Message Passing",
  *  <em>Proceedings of the 22nd Annual Conference on Uncertainty in Artificial Intelligence (UAI-06)</em>
  *  http://uai.sis.pitt.edu/papers/06/UAI2006_0091.pdf
+ *
+ *  \anchor WiH03 \ref WiH03
+ *  W. Wiegerinck and T. Heskes (2003):
+ *  "Fractional Belief Propagation",
+ *  <em>Advances in Neural Information Processing Systems</em> (NIPS) 15, pp. 438-445.
+ *  http://books.nips.cc/papers/files/nips15/LT16.pdf
+ *
+ *  \anchor Min05 \ref Min05
+ *  T. Minka (2005):
+ *  "Divergence measures and message passing",
+ *  <em>MicroSoft Research Technical Report</em> MSR-TR-2005-173,
+ *  http://research.microsoft.com/en-us/um/people/minka/papers/message-passing/minka-divergence.pdf
  */
 
 
diff --git a/include/dai/fbp.h b/include/dai/fbp.h
new file mode 100644 (file)
index 0000000..7730cc2
--- /dev/null
@@ -0,0 +1,161 @@
+/*  This file is part of libDAI - http://www.libdai.org/
+ *
+ *  libDAI is licensed under the terms of the GNU General Public License version
+ *  2, or (at your option) any later version. libDAI is distributed without any
+ *  warranty. See the file COPYING for more details.
+ *
+ *  Copyright (C) 2009 Frederik Eaton
+ */
+
+
+/// \file
+/// \brief Defines class FBP, which implements Fractional Belief Propagation
+
+
+#ifndef __defined_libdai_fbp_h
+#define __defined_libdai_fbp_h
+
+
+#include <string>
+#include <dai/daialg.h>
+#include <dai/factorgraph.h>
+#include <dai/properties.h>
+#include <dai/enum.h>
+#include <dai/bp.h>
+
+
+namespace dai {
+
+
+/// Approximate inference algorithm "Fractional Belief Propagation" [\ref WiH03]
+/** The Fractional Belief Propagation algorithm is like Belief
+ *  Propagation, but associates each factor with a scale parameter
+ *  which controls the divergence measure being minimized. Standard
+ *  Belief Propagation corresponds to the case of FBP where each scale
+ *  parameter is 1. When cast as an EP algorithm, BP (and EP) minimize
+ *  the inclusive KL-divergence, i.e. \f$\min_q KL(p||q)\f$ (note that the
+ *  Bethe free energy is typically derived from \f$ KL(q||p) \f$). If each
+ *  factor \a I has scale parameter \f$ c_I \f$, then FBP minimizes the
+ *  alpha-divergence with \f$ \alpha=1/c_I \f$ for that factor, which also
+ *  corresponds to Power EP [\ref Min05].
+ *
+ *  The messages \f$m_{I\to i}(x_i)\f$ are passed from factors \f$I\f$ to variables \f$i\f$. 
+ *  The update equation is given by:
+ *    \f[ m_{I\to i}(x_i) \propto \left( \sum_{x_{N_I\setminus\{i\}}} f_I(x_I)^{1/c_I} \prod_{j\in N_I\setminus\{i\}} m_{I\to j}^{1-1/c_I}\right)^{c_I} \prod_{J\in N_j\setminus\{I\}} m_{J\to j} \f]
+ *  After convergence, the variable beliefs are calculated by:
+ *    \f[ b_i(x_i) \propto \prod_{I\in N_i} m_{I\to i} \f]
+ *  and the factor beliefs are calculated by:
+ *    \f[ b_I(x_I) \propto f_I(x_I)^{1/c_I} \prod_{j \in N_I} m_{I\to j}^{1-1/c_I} \prod_{J\in N_j\setminus\{I\}} m_{J\to j} \f]
+ *
+ *  \todo Implement logZ
+ *  \todo Why are the _scale_var necessary?
+ *  \todo Add nice way to set scale parameters
+ *
+ *  \author Frederik Eaton
+ */
+class FBP : public BP {
+    protected:
+        /// Factor scale parameters (indexed by factor ID)
+        std::vector<Real> _scale_factor;
+        /// Variable scale parameters (indexed by variable ID)
+        /** \note Equal to sum of scale parameters of neighboring factors
+         */
+        std::vector<Real> _scale_var;
+
+    public:
+        /// Name of this inference algorithm
+        static const char *Name;
+
+    public:
+    /// \name Constructors/destructors
+    //@{
+        /// Default constructor
+        FBP() : BP(), _scale_factor(), _scale_var() {}
+
+        /// Construct from FactorGraph \a fg and PropertySet \a opts
+        /** \param opts Parameters @see BP::Properties
+         */
+        FBP( const FactorGraph &fg, const PropertySet &opts ) : BP(fg, opts), _scale_factor(), _scale_var() {
+            setProperties( opts );
+            construct();
+        }
+    //@}
+
+    /// \name General InfAlg interface
+    //@{
+        virtual FBP* clone() const { return new FBP(*this); }
+        virtual std::string identify() const;
+    //@}
+
+    /// \name FBP accessors/mutators for scale parameters
+    //@{
+        /// Returns scale parameter of the \a I 'th factor
+        Real scaleF( size_t I ) const { return _scale_factor[I]; }
+
+        /// Returns constant reference to vector of all factor scale parameters
+        const std::vector<Real>& scaleFs() const { return _scale_factor; }
+
+        /// Returns scale parameter of the \a i 'th variable
+        Real scaleV( size_t i ) const { return _scale_var[i]; }
+
+        /// Returns constant reference to vector of all variable scale parameters
+        const std::vector<Real>& scaleVs() const { return _scale_var; }
+
+        /// Sets the scale parameter of the \a I 'th factor to \a c
+        void setScaleF( size_t I, Real c ) {
+            _scale_factor[I] = c;
+            foreach( const Neighbor &i, nbF(I) )
+                recalcScaleV(i);
+        }
+
+        /// Sets the scale parameters of all factors simultaenously
+        /** \note Faster than calling setScaleF(size_t,Real) for each factor
+         */
+        void setScaleFs( const std::vector<Real> &c ) {
+            _scale_factor = c;
+            recalcScaleVs();
+        }
+
+        /// Recalculates all variable scale parameters
+        /** \note For each variable, its scale parameter is set to 
+         *  the sum of the scale parameters of its neighboring factors.
+         */
+        void recalcScaleVs() {
+            for( size_t i = 0; i < nrVars(); i++ )
+                recalcScaleV(i);
+        }
+
+        /// Recalculates the scale parameter of the \a i 'th variable
+        /** \note The scale parameter is set to the sum of the scale parameters of its neighboring factors.
+         */
+        void recalcScaleV( size_t i ) {
+            // Set _scale_var[i] to the sum of its neighbors
+            Real c_i = 0.0;
+            foreach( const Neighbor &I, nbV(i) )
+                c_i += scaleF(I);
+            _scale_var[i] = c_i;
+        }
+
+    protected:
+        // Calculate the updated message from the \a _I 'th neighbor of variable \a i to variable \a i
+        virtual void calcNewMessage( size_t i, size_t _I );
+
+        // Calculates unnormalized belief of factor \a I
+        virtual void calcBeliefF( size_t I, Prob &p ) const;
+
+        // Helper function for constructors
+        virtual void construct();
+
+        /// (Re)constructs the scale parameters data structures
+        void constructScaleParams() {
+            _scale_factor.resize( nrFactors(), 1.0 );
+            _scale_var.resize( nrVars() );
+            recalcScaleVs();
+        }
+};
+
+
+} // end of namespace dai
+
+
+#endif
index fe12e3a..d6688d6 100644 (file)
@@ -28,6 +28,10 @@ InfAlg *newInfAlg( const std::string &name, const FactorGraph &fg, const Propert
     if( name == BP::Name )
         return new BP (fg, opts);
 #endif
+#ifdef DAI_WITH_FBP
+    if( name == FBP::Name )
+        return new FBP (fg, opts);
+#endif
 #ifdef DAI_WITH_MF
     if( name == MF::Name )
         return new MF (fg, opts);
diff --git a/src/fbp.cpp b/src/fbp.cpp
new file mode 100644 (file)
index 0000000..056cbfa
--- /dev/null
@@ -0,0 +1,195 @@
+/*  This file is part of libDAI - http://www.libdai.org/
+ *
+ *  libDAI is licensed under the terms of the GNU General Public License version
+ *  2, or (at your option) any later version. libDAI is distributed without any
+ *  warranty. See the file COPYING for more details.
+ *
+ *  Copyright (C) 2009 Frederik Eaton
+ */
+
+
+#include <dai/fbp.h>
+
+
+#define DAI_FBP_FAST 1
+
+
+namespace dai {
+
+
+using namespace std;
+
+
+const char *FBP::Name = "FBP";
+
+
+string FBP::identify() const {
+    return string(Name) + printProperties();
+}
+
+
+/* This code has been copied from bp.cpp, except where comments indicate FBP-specific behaviour */
+void FBP::calcNewMessage( size_t i, size_t _I ) {
+    // calculate updated message I->i
+    size_t I = nbV(i,_I);
+
+    Real scale = scaleF(I); // FBP: c_I
+
+    Factor Fprod( factor(I) );
+    Prob &prod = Fprod.p();
+    if( props.logdomain ) {
+        prod.takeLog();
+        prod *= (1/scale); // FBP
+    } else
+        prod ^= (1/scale); // FBP
+    
+    // Calculate product of incoming messages and factor I
+    foreach( const Neighbor &j, nbF(I) )
+        if( j != i ) { // for all j in I \ i
+            // FBP: same as n_jI
+            // prod_j will be the product of messages coming into j
+            Prob prod_j( var(j).states(), props.logdomain ? 0.0 : 1.0 );
+            foreach( const Neighbor &J, nbV(j) )
+                if( J != I ) { // for all J in nb(j) \ I
+                    if( props.logdomain )
+                        prod_j += message( j, J.iter );
+                    else
+                        prod_j *= message( j, J.iter );
+                }
+
+
+            size_t _I = j.dual;
+            // FBP: now multiply by m_Ij^(1-1/c_I)
+            if(props.logdomain)
+                prod_j += message( j, _I)*(1-1/scale);
+            else
+                prod_j *= message( j, _I)^(1-1/scale);
+
+            // multiply prod with prod_j
+            if( !DAI_FBP_FAST ) {
+                /* UNOPTIMIZED (SIMPLE TO READ, BUT SLOW) VERSION */
+                if( props.logdomain )
+                    Fprod += Factor( var(j), prod_j );
+                else
+                    Fprod *= Factor( var(j), prod_j );
+            } else {
+                /* OPTIMIZED VERSION */
+                // ind is the precalculated IndexFor(j,I) i.e. to x_I == k corresponds x_j == ind[k]
+                const ind_t &ind = index(j, _I);
+                for( size_t r = 0; r < prod.size(); ++r )
+                    if( props.logdomain )
+                        prod[r] += prod_j[ind[r]];
+                    else
+                        prod[r] *= prod_j[ind[r]];
+            }
+        }
+
+    if( props.logdomain ) {
+        prod -= prod.max();
+        prod.takeExp();
+    }
+
+    // Marginalize onto i
+    Prob marg;
+    if( !DAI_FBP_FAST ) {
+        /* UNOPTIMIZED (SIMPLE TO READ, BUT SLOW) VERSION */
+        if( props.inference == Properties::InfType::SUMPROD )
+            marg = Fprod.marginal( var(i) ).p();
+        else
+            marg = Fprod.maxMarginal( var(i) ).p();
+    } else {
+        /* OPTIMIZED VERSION */
+        marg = Prob( var(i).states(), 0.0 );
+        // ind is the precalculated IndexFor(i,I) i.e. to x_I == k corresponds x_i == ind[k]
+        const ind_t ind = index(i,_I);
+        if( props.inference == Properties::InfType::SUMPROD )
+            for( size_t r = 0; r < prod.size(); ++r )
+                marg[ind[r]] += prod[r];
+        else
+            for( size_t r = 0; r < prod.size(); ++r )
+                if( prod[r] > marg[ind[r]] )
+                    marg[ind[r]] = prod[r];
+        marg.normalize();
+    }
+
+    // FBP
+    marg ^= scale;
+
+    // Store result
+    if( props.logdomain )
+        newMessage(i,_I) = marg.log();
+    else
+        newMessage(i,_I) = marg;
+
+    // Update the residual if necessary
+    if( props.updates == Properties::UpdateType::SEQMAX )
+        updateResidual( i, _I , dist( newMessage( i, _I ), message( i, _I ), Prob::DISTLINF ) );
+}
+
+
+/* This code has been copied from bp.cpp, except where comments indicate FBP-specific behaviour */
+void FBP::calcBeliefF( size_t I, Prob &p ) const {
+    Real scale = scaleF(I); // FBP: c_I
+
+    Factor Fprod( factor(I) );
+    Prob &prod = Fprod.p();
+    
+    if( props.logdomain ) {
+        prod.takeLog();
+        prod /= scale; // FBP
+    } else
+        prod ^= (1/scale); // FBP
+
+    foreach( const Neighbor &j, nbF(I) ) {
+        // prod_j will be the product of messages coming into j
+        // FBP: corresponds to messages n_jI
+        Prob prod_j( var(j).states(), props.logdomain ? 0.0 : 1.0 );
+        foreach( const Neighbor &J, nbV(j) )
+            if( J != I ) { // for all J in nb(j) \ I
+                if( props.logdomain )
+                    prod_j += newMessage( j, J.iter );
+                else
+                    prod_j *= newMessage( j, J.iter );
+            }
+
+        size_t _I = j.dual;
+
+        // FBP: now multiply by m_Ij^(1-1/c_I)
+        if( props.logdomain )
+            prod_j += newMessage( j, _I)*(1-1/scale);
+        else
+            prod_j *= newMessage( j, _I)^(1-1/scale);
+
+        // multiply prod with prod_j
+        if( !DAI_FBP_FAST ) {
+            /* UNOPTIMIZED (SIMPLE TO READ, BUT SLOW) VERSION */
+            if( props.logdomain )
+                Fprod += Factor( var(j), prod_j );
+            else
+                Fprod *= Factor( var(j), prod_j );
+        } else {
+            /* OPTIMIZED VERSION */
+            size_t _I = j.dual;
+            // ind is the precalculated IndexFor(j,I) i.e. to x_I == k corresponds x_j == ind[k]
+            const ind_t & ind = index(j, _I);
+
+            for( size_t r = 0; r < prod.size(); ++r ) {
+                if( props.logdomain )
+                    prod[r] += prod_j[ind[r]];
+                else
+                    prod[r] *= prod_j[ind[r]];
+            }
+        }
+    }
+
+    p = prod;
+}
+    
+
+void FBP::construct() {
+    BP::construct();
+    constructScaleParams();
+}
+
+
+} // end of namespace dai
index 0c4d526..3ee5681 100644 (file)
@@ -22,6 +22,10 @@ MP_SEQRND_LOG:                  BP[updates=SEQRND,tol=1e-9,maxiter=10000,logdoma
 MP_SEQMAX_LOG:                  BP[updates=SEQMAX,tol=1e-9,maxiter=10000,logdomain=1,inference=MAXPROD]
 MP_PARALL_LOG:                  BP[updates=PARALL,tol=1e-9,maxiter=10000,logdomain=1,inference=MAXPROD]
 
+# --- FBP ---------------------
+
+FBP:                            FBP[updates=SEQFIX,tol=1e-9,maxiter=10000,logdomain=0]
+
 # --- JTREE -------------------
 
 JTREE_HUGIN:                    JTREE[updates=HUGIN,verbose=0]