Partial adoption of contributions by Giuseppe:
authorJoris Mooij <jorism@marvin.jorismooij.nl>
Mon, 25 Aug 2008 21:03:30 +0000 (23:03 +0200)
committerJoris Mooij <jorism@marvin.jorismooij.nl>
Mon, 25 Aug 2008 21:03:30 +0000 (23:03 +0200)
* removed "using namespace std;" from header files - bad practice
* moved header files in include/dai and sources in src
* changed #ifndefs in headers to GNU style
* added extra warning checks (-W -Wextra) and fixed resulting warnings

88 files changed:
Makefile
alldai.cpp [deleted file]
alldai.h [deleted file]
bipgraph.h [deleted file]
bp.cpp [deleted file]
bp.h [deleted file]
clustergraph.cpp [deleted file]
clustergraph.h [deleted file]
daialg.cpp [deleted file]
daialg.h [deleted file]
diffs.h [deleted file]
doxygen.conf
enum.h [deleted file]
example.cpp
factor.h [deleted file]
factorgraph.cpp [deleted file]
factorgraph.h [deleted file]
hak.cpp [deleted file]
hak.h [deleted file]
include/dai/alldai.h [new file with mode: 0644]
include/dai/bipgraph.h [new file with mode: 0644]
include/dai/bp.h [new file with mode: 0644]
include/dai/clustergraph.h [new file with mode: 0644]
include/dai/daialg.h [new file with mode: 0644]
include/dai/diffs.h [new file with mode: 0644]
include/dai/enum.h [new file with mode: 0644]
include/dai/factor.h [new file with mode: 0644]
include/dai/factorgraph.h [new file with mode: 0644]
include/dai/hak.h [new file with mode: 0644]
include/dai/index.h [new file with mode: 0644]
include/dai/jtree.h [new file with mode: 0644]
include/dai/lc.h [new file with mode: 0644]
include/dai/mf.h [new file with mode: 0644]
include/dai/mr.h [new file with mode: 0644]
include/dai/prob.h [new file with mode: 0644]
include/dai/properties.h [new file with mode: 0644]
include/dai/regiongraph.h [new file with mode: 0644]
include/dai/treeep.h [new file with mode: 0644]
include/dai/util.h [new file with mode: 0644]
include/dai/var.h [new file with mode: 0644]
include/dai/varset.h [new file with mode: 0644]
include/dai/weightedgraph.h [new file with mode: 0644]
include/dai/x2x.h [new file with mode: 0644]
index.h [deleted file]
jtree.cpp [deleted file]
jtree.h [deleted file]
lc.cpp [deleted file]
lc.h [deleted file]
mf.cpp [deleted file]
mf.h [deleted file]
mr.cpp [deleted file]
mr.h [deleted file]
prob.h [deleted file]
properties.cpp [deleted file]
properties.h [deleted file]
regiongraph.cpp [deleted file]
regiongraph.h [deleted file]
src/alldai.cpp [new file with mode: 0644]
src/bp.cpp [new file with mode: 0644]
src/clustergraph.cpp [new file with mode: 0644]
src/daialg.cpp [new file with mode: 0644]
src/factorgraph.cpp [new file with mode: 0644]
src/hak.cpp [new file with mode: 0644]
src/jtree.cpp [new file with mode: 0644]
src/lc.cpp [new file with mode: 0644]
src/mf.cpp [new file with mode: 0644]
src/mr.cpp [new file with mode: 0644]
src/properties.cpp [new file with mode: 0644]
src/regiongraph.cpp [new file with mode: 0644]
src/treeep.cpp [new file with mode: 0644]
src/util.cpp [new file with mode: 0644]
src/weightedgraph.cpp [new file with mode: 0644]
src/x2x.cpp [new file with mode: 0644]
tests/test.cpp
treeep.cpp [deleted file]
treeep.h [deleted file]
util.cpp [deleted file]
util.h [deleted file]
utils/createfg.cpp
utils/fg2dot.cpp
utils/fginfo.cpp
utils/remove_short_loops.cpp
var.h [deleted file]
varset.h [deleted file]
weightedgraph.cpp [deleted file]
weightedgraph.h [deleted file]
x2x.cpp [deleted file]
x2x.h [deleted file]

index 72fc05a..f68a0f6 100644 (file)
--- a/Makefile
+++ b/Makefile
 #   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 
 
+# Directories
+INC = include/dai
+SRC = src
+LIB = lib
+
 # We use the BOOST Program Options library
 BOOSTFLAGS = -lboost_program_options
 
@@ -25,7 +30,7 @@ BOOSTFLAGS = -lboost_program_options
 CC = g++
 
 # Flags for the C++ compiler
-CCFLAGS = -Wall -fpic -g -DDEBUG -I. -I$(HOME)/include -O3 #-static #-pg #-DVERBOSE
+CCFLAGS = -Wall -W -Wextra -fpic -g -DDEBUG -I./include -Llib -O3 #-static #-pg #-DVERBOSE
 
 # To enable the Matlab interface, define WITH_MATLAB = yes
 WITH_MATLAB = 
@@ -39,10 +44,10 @@ endif
 # Replace the following with the extension of compiled MEX files on this platform, e.g. .mexglx for x86
 MEXEXT = .mexglx
 
-HEADERS = bipgraph.h diffs.h index.h var.h factor.h varset.h prob.h daialg.h properties.h alldai.h enum.h x2x.h
+HEADERS = $(INC)/bipgraph.h $(INC)/diffs.h $(INC)/index.h $(INC)/var.h $(INC)/factor.h $(INC)/varset.h $(INC)/prob.h $(INC)/daialg.h $(INC)/properties.h $(INC)/alldai.h $(INC)/enum.h $(INC)/x2x.h
 
 # target matlabs is disabled by default since it only compiles with a very recent MatLab version
-TARGETS = tests utils libdai.a example testregression
+TARGETS = tests utils $(LIB)/libdai.a example testregression
 ifdef WITH_MATLAB
 TARGETS := $(TARGETS) matlabs
 endif
@@ -51,8 +56,8 @@ all : $(TARGETS)
 
 matlabs : matlab/dai.$(MEXEXT) matlab/dai_readfg.$(MEXEXT) matlab/dai_writefg.$(MEXEXT) matlab/dai_removeshortloops.$(MEXEXT) matlab/dai_potstrength.$(MEXEXT)
 
-libdai.a : daialg.o alldai.o bp.o clustergraph.o factorgraph.o hak.o jtree.o lc.o mf.o mr.o properties.o regiongraph.o util.o treeep.o weightedgraph.o x2x.o
-       ar rcs libdai.a daialg.o alldai.o bp.o clustergraph.o factorgraph.o hak.o jtree.o lc.o mf.o mr.o properties.o regiongraph.o util.o treeep.o weightedgraph.o x2x.o
+$(LIB)/libdai.a : daialg.o alldai.o bp.o clustergraph.o factorgraph.o hak.o jtree.o lc.o mf.o mr.o properties.o regiongraph.o util.o treeep.o weightedgraph.o x2x.o
+       ar rcs $(LIB)/libdai.a daialg.o alldai.o bp.o clustergraph.o factorgraph.o hak.o jtree.o lc.o mf.o mr.o properties.o regiongraph.o util.o treeep.o weightedgraph.o x2x.o
 
 tests : tests/test
 
@@ -62,73 +67,73 @@ testregression : tests/test
        echo Testing...this can take a while...
        cd tests; ./testregression; cd ..
 
-doc : *.h *.cpp doxygen.conf
+doc : $(INC)/*.h $(SRC)/*.cpp doxygen.conf
        doxygen doxygen.conf
 
 clean :
-       rm *.o *.$(MEXEXT) example matlab/*.$(MEXEXT) matlab/*.o tests/test utils/fg2dot utils/createfg utils/remove_short_loops utils/fginfo libdai.a; echo
+       rm *.o *.$(MEXEXT) example matlab/*.$(MEXEXT) matlab/*.o tests/test utils/fg2dot utils/createfg utils/remove_short_loops utils/fginfo $(LIB)/libdai.a; echo
        rm -R doc; echo
 
 
-daialg.o : daialg.cpp $(HEADERS)
-       $(CC) $(CCFLAGS) -c daialg.cpp
+daialg.o : $(SRC)/daialg.cpp $(HEADERS)
+       $(CC) $(CCFLAGS) -c $(SRC)/daialg.cpp
 
-bp.o : bp.cpp bp.h $(HEADERS)
-       $(CC) $(CCFLAGS) -c bp.cpp
+bp.o : $(SRC)/bp.cpp $(INC)/bp.h $(HEADERS)
+       $(CC) $(CCFLAGS) -c $(SRC)/bp.cpp
 
-lc.o : lc.cpp lc.h $(HEADERS)
-       $(CC) $(CCFLAGS) -c lc.cpp
+lc.o : $(SRC)/lc.cpp $(INC)/lc.h $(HEADERS)
+       $(CC) $(CCFLAGS) -c $(SRC)/lc.cpp
 
-mf.o : mf.cpp mf.h $(HEADERS)
-       $(CC) $(CCFLAGS) -c mf.cpp
+mf.o : $(SRC)/mf.cpp $(INC)/mf.h $(HEADERS)
+       $(CC) $(CCFLAGS) -c $(SRC)/mf.cpp
 
-factorgraph.o : factorgraph.cpp factorgraph.h $(HEADERS)
-       $(CC) $(CCFLAGS) -c factorgraph.cpp
+factorgraph.o : $(SRC)/factorgraph.cpp $(INC)/factorgraph.h $(HEADERS)
+       $(CC) $(CCFLAGS) -c $(SRC)/factorgraph.cpp
 
-util.o : util.cpp util.h $(HEADERS)
-       $(CC) $(CCFLAGS) -c util.cpp
+util.o : $(SRC)/util.cpp $(INC)/util.h $(HEADERS)
+       $(CC) $(CCFLAGS) -c $(SRC)/util.cpp
 
-regiongraph.o : regiongraph.cpp regiongraph.h $(HEADERS)
-       $(CC) $(CCFLAGS) -c regiongraph.cpp
+regiongraph.o : $(SRC)/regiongraph.cpp $(INC)/regiongraph.h $(HEADERS)
+       $(CC) $(CCFLAGS) -c $(SRC)/regiongraph.cpp
 
-hak.o : hak.cpp hak.h $(HEADERS) regiongraph.h
-       $(CC) $(CCFLAGS) -c hak.cpp
+hak.o : $(SRC)/hak.cpp $(INC)/hak.h $(HEADERS) $(INC)/regiongraph.h
+       $(CC) $(CCFLAGS) -c $(SRC)/hak.cpp
 
-clustergraph.o : clustergraph.cpp clustergraph.h $(HEADERS)
-       $(CC) $(CCFLAGS) -c clustergraph.cpp
+clustergraph.o : $(SRC)/clustergraph.cpp $(INC)/clustergraph.h $(HEADERS)
+       $(CC) $(CCFLAGS) -c $(SRC)/clustergraph.cpp
 
-jtree.o : jtree.cpp jtree.h $(HEADERS) weightedgraph.h clustergraph.h regiongraph.h
-       $(CC) $(CCFLAGS) -c jtree.cpp
+jtree.o : $(SRC)/jtree.cpp $(INC)/jtree.h $(HEADERS) $(INC)/weightedgraph.h $(INC)/clustergraph.h $(INC)/regiongraph.h
+       $(CC) $(CCFLAGS) -c $(SRC)/jtree.cpp
 
-treeep.o : treeep.cpp treeep.h $(HEADERS) weightedgraph.h clustergraph.h regiongraph.h jtree.h
-       $(CC) $(CCFLAGS) -c treeep.cpp
+treeep.o : $(SRC)/treeep.cpp $(INC)/treeep.h $(HEADERS) $(INC)/weightedgraph.h $(INC)/clustergraph.h $(INC)/regiongraph.h $(INC)/jtree.h
+       $(CC) $(CCFLAGS) -c $(SRC)/treeep.cpp
 
-weightedgraph.o : weightedgraph.cpp weightedgraph.h $(HEADERS)
-       $(CC) $(CCFLAGS) -c weightedgraph.cpp
+weightedgraph.o : $(SRC)/weightedgraph.cpp $(INC)/weightedgraph.h $(HEADERS)
+       $(CC) $(CCFLAGS) -c $(SRC)/weightedgraph.cpp
 
-mr.o : mr.cpp mr.h $(HEADERS)
-       $(CC) $(CCFLAGS) -c mr.cpp
+mr.o : $(SRC)/mr.cpp $(INC)/mr.h $(HEADERS)
+       $(CC) $(CCFLAGS) -c $(SRC)/mr.cpp
 
-properties.o : properties.cpp $(HEADERS)
-       $(CC) $(CCFLAGS) -c properties.cpp
+properties.o : $(SRC)/properties.cpp $(HEADERS)
+       $(CC) $(CCFLAGS) -c $(SRC)/properties.cpp
 
-alldai.o : alldai.cpp $(HEADERS)
-       $(CC) $(CCFLAGS) -c alldai.cpp
+alldai.o : $(SRC)/alldai.cpp $(HEADERS)
+       $(CC) $(CCFLAGS) -c $(SRC)/alldai.cpp
 
-x2x.o : x2x.cpp $(HEADERS)
-       $(CC) $(CCFLAGS) -c x2x.cpp
+x2x.o : $(SRC)/x2x.cpp $(HEADERS)
+       $(CC) $(CCFLAGS) -c $(SRC)/x2x.cpp
 
 # EXAMPLE
 ##########
 
-example : example.cpp $(HEADERS) libdai.a
-       $(CC) $(CCFLAGS) -o example example.cpp -L. libdai.a
+example : $(SRC)/example.cpp $(HEADERS) $(LIB)/libdai.a
+       $(CC) $(CCFLAGS) -o example $(SRC)/example.cpp -ldai
 
 # TESTS
 ########
 
-tests/test : tests/test.cpp $(HEADERS) libdai.a
-       $(CC) $(CCFLAGS) -o tests/test tests/test.cpp -L. -ldai $(BOOSTFLAGS)
+tests/test : tests/test.cpp $(HEADERS) lib/libdai.a
+       $(CC) $(CCFLAGS) -o tests/test tests/test.cpp -ldai $(BOOSTFLAGS)
 
 
 # MATLAB INTERFACE
diff --git a/alldai.cpp b/alldai.cpp
deleted file mode 100644 (file)
index 10fa8a5..0000000
+++ /dev/null
@@ -1,48 +0,0 @@
-/*  Copyright (C) 2006-2008  Joris Mooij  [j dot mooij at science dot ru dot nl]
-    Radboud University Nijmegen, The Netherlands
-    
-    This file is part of libDAI.
-
-    libDAI is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    libDAI is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with libDAI; if not, write to the Free Software
-    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-
-#include "alldai.h"
-
-
-namespace dai {
-
-
-InfAlg *newInfAlg( const string &name, const FactorGraph &fg, const Properties &opts ) {
-    if( name == BP::Name ) 
-        return new BP (fg, opts);
-    else if( name == MF::Name ) 
-        return new MF (fg, opts);
-    else if( name == HAK::Name ) 
-        return new HAK (fg, opts);
-    else if( name == LC::Name )
-        return new LC (fg, opts);
-    else if( name == TreeEP::Name )
-        return new TreeEP (fg, opts);
-    else if( name == MR::Name )
-        return new MR (fg, opts);
-    else if( name == JTree::Name )
-        return new JTree (fg, opts);
-    else
-        throw "Unknown inference algorithm";
-}
-
-
-}
diff --git a/alldai.h b/alldai.h
deleted file mode 100644 (file)
index ea7d750..0000000
--- a/alldai.h
+++ /dev/null
@@ -1,51 +0,0 @@
-/*  Copyright (C) 2006-2008  Joris Mooij  [j dot mooij at science dot ru dot nl]
-    Radboud University Nijmegen, The Netherlands
-    
-    This file is part of libDAI.
-
-    libDAI is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    libDAI is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with libDAI; if not, write to the Free Software
-    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-
-#ifndef __ALLDAI_H__
-#define __ALLDAI_H__
-
-
-#include "daialg.h"
-#include "bp.h"
-#include "lc.h"
-#include "hak.h"
-#include "mf.h"
-#include "jtree.h"
-#include "treeep.h"
-#include "mr.h"
-
-
-namespace dai {
-
-
-/// newInfAlg constructs a new approximate inference algorithm named name for the
-/// FactorGraph fg with optionts opts and returns a pointer to the new object.
-/// The caller needs to delete it (maybe some sort of smart_ptr might be useful here).
-InfAlg *newInfAlg( const string &name, const FactorGraph &fg, const Properties &opts );
-
-
-/// AINames contains the names of all approximate inference algorithms
-static const char* DAINames[] = {BP::Name, MF::Name, HAK::Name, LC::Name, TreeEP::Name, MR::Name, JTree::Name};
-
-}
-
-
-#endif
diff --git a/bipgraph.h b/bipgraph.h
deleted file mode 100644 (file)
index b0c0e1a..0000000
+++ /dev/null
@@ -1,163 +0,0 @@
-/*  Copyright (C) 2006-2008  Joris Mooij  [j dot mooij at science dot ru dot nl]
-    Radboud University Nijmegen, The Netherlands
-    
-    This file is part of libDAI.
-
-    libDAI is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    libDAI is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with libDAI; if not, write to the Free Software
-    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-
-#ifndef __BIPGRAPH_H__
-#define __BIPGRAPH_H__
-
-
-#include <vector>
-#include <algorithm>
-#include <boost/numeric/ublas/vector_sparse.hpp>
-
-
-namespace dai {
-
-
-/// A BipartiteGraph represents a graph with two types of nodes
-template <class T1, class T2> class BipartiteGraph {
-    public:
-        typedef std::pair<size_t,size_t>    _edge_t;
-        typedef std::vector<size_t>         _nb_t;
-        typedef _nb_t::const_iterator       _nb_cit;
-        
-
-    private:
-        /// Vertices of first type
-        std::vector<T1>                     _V1;
-
-        /// Vertices of second type
-        std::vector<T2>                     _V2;
-        
-        /// Edges, which are pairs (v1,v2) with v1 in _V1 and v2 in _V2
-        std::vector<_edge_t>                _E12;
-
-        /// Conversion matrix that computes which index of _E12 corresponds to a vertex index pair (v1,v2)
-        std::vector<boost::numeric::ublas::mapped_vector<size_t> > _E12ind;
-
-        /// Neighbour indices of vertices of first type
-        std::vector<_nb_t>                  _nb1;
-
-        /// Neighbour indices of vertices of second type
-        std::vector<_nb_t>                  _nb2;
-
-
-    public:
-        /// Default constructor
-        BipartiteGraph<T1,T2> () {};
-
-        /// Copy constructor
-        BipartiteGraph<T1,T2> ( const BipartiteGraph<T1,T2> & x ) : _V1(x._V1), _V2(x._V2), _E12(x._E12), _E12ind(x._E12ind), _nb1(x._nb1), _nb2(x._nb2) {};
-
-        /// Assignment operator
-        BipartiteGraph<T1,T2> & operator=(const BipartiteGraph<T1,T2> & x) {
-            if( this != &x ) {
-                _V1 =       x._V1;
-                _V2 =       x._V2;
-                _E12 =      x._E12;
-                _E12ind =   x._E12ind;
-                _nb1 =      x._nb1;
-                _nb2 =      x._nb2;
-            }
-            return *this;
-        }
-        
-        /// Provides read access to node of first type
-        const T1 & V1( size_t i1 ) const { return _V1[i1]; }
-        /// Provides full access to node of first type
-        T1 & V1( size_t i1 ) { return _V1[i1]; }
-        /// Provides read access to all nodes of first type
-        const std::vector<T1> & V1s() const { return _V1; }
-        /// Provides full access to all nodes of first type
-        std::vector<T1> & V1s() { return _V1; }
-
-        /// Provides read access to node of second type
-        const T2 & V2( size_t i2 ) const { return _V2[i2]; }
-        /// Provides full access to node of second type
-        T2 & V2( size_t i2 ) { return _V2[i2]; }
-        /// Provides read access to all nodes of second type
-        const std::vector<T2> & V2s() const { return _V2; }
-        /// Provides full access to all nodes of second type
-        std::vector<T2> & V2s() { return _V2; }
-
-        /// Provides read access to edge
-        const _edge_t & edge(size_t ind) const { return _E12[ind]; }
-        /// Provides full access to edge
-        _edge_t & edge(size_t ind) { return _E12[ind]; }
-        /// Provides read access to all edges
-        const std::vector<_edge_t> & edges() const { return _E12; }
-        /// Provides full access to all edges
-        std::vector<_edge_t> & edges() { return _E12; }
-        /// Returns number of edges
-        size_t nr_edges() const { return _E12.size(); }
-
-        /// Provides read access to neighbours of node of first type
-        const _nb_t & nb1( size_t i1 ) const { return _nb1[i1]; }
-        /// Provides full access to neighbours of node of first type
-        _nb_t & nb1( size_t i1 ) { return _nb1[i1]; }
-
-        /// Provides read access to neighbours of node of second type
-        const _nb_t & nb2( size_t i2 ) const { return _nb2[i2]; }
-        /// Provides full access to neighbours of node of second type
-        _nb_t & nb2( size_t i2 ) { return _nb2[i2]; }
-
-        /// Converts the pair of indices (i1,i2) to the corresponding edge index
-        size_t VV2E( const size_t i1, const size_t i2 ) const { return _E12ind[i1](i2); }
-
-
-        /// Regenerates internal structures (_E12ind, _nb1 and _nb2) based upon _V1, _V2 and _E12
-        void Regenerate() {
-            // Calculate _nb1 and _nb2
-
-            // Start with empty vectors
-            _nb1.clear();
-            _nb1.resize(_V1.size());
-            // Start with empty vectors
-            _nb2.clear();
-            _nb2.resize(_V2.size());
-            // Each edge yields a neighbour pair
-            for( std::vector<_edge_t>::const_iterator e = _E12.begin(); e != _E12.end(); e++ ) {
-                _nb1[e->first].push_back(e->second);
-                _nb2[e->second].push_back(e->first);
-            }
-            // Remove duplicates from _nb1
-            for( size_t i1 = 0; i1 < _V1.size(); i1++ ) {
-                _nb_t::iterator new_end = unique(_nb1[i1].begin(), _nb1[i1].end());
-                _nb1[i1].erase( new_end, _nb1[i1].end() );
-            }
-            // Remove duplicates from _nb2
-            for( size_t i2 = 0; i2 < _V2.size(); i2++ ) {
-                _nb_t::iterator new_end = unique(_nb2[i2].begin(), _nb2[i2].end());
-                _nb2[i2].erase( new_end, _nb2[i2].end() );
-            }
-
-            // Calculate _E12ind
-            _E12ind = std::vector<boost::numeric::ublas::mapped_vector<size_t> >(_V1.size(), boost::numeric::ublas::mapped_vector<size_t>(_V2.size()) );            
-            for( size_t k = 0; k < _E12.size(); k++ )
-                _E12ind[_E12[k].first](_E12[k].second) = k;
-                    
-        }
-};
-
-
-}
-
-
-#endif
diff --git a/bp.cpp b/bp.cpp
deleted file mode 100644 (file)
index 4a5419b..0000000
--- a/bp.cpp
+++ /dev/null
@@ -1,352 +0,0 @@
-/*  Copyright (C) 2006-2008  Joris Mooij  [j dot mooij at science dot ru dot nl]
-    Radboud University Nijmegen, The Netherlands
-    
-    This file is part of libDAI.
-
-    libDAI is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    libDAI is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with libDAI; if not, write to the Free Software
-    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-
-#include <iostream>
-#include <sstream>
-#include <map>
-#include <set>
-#include <algorithm>
-#include "bp.h"
-#include "diffs.h"
-#include "util.h"
-#include "properties.h"
-
-
-namespace dai {
-
-
-using namespace std;
-
-
-const char *BP::Name = "BP";
-
-
-bool BP::checkProperties() {
-    if( !HasProperty("updates") )
-        return false;
-    if( !HasProperty("tol") )
-        return false;
-    if (!HasProperty("maxiter") )
-        return false;
-    if (!HasProperty("verbose") )
-        return false;
-    
-    ConvertPropertyTo<double>("tol");
-    ConvertPropertyTo<size_t>("maxiter");
-    ConvertPropertyTo<size_t>("verbose");
-    ConvertPropertyTo<UpdateType>("updates");
-
-    return true;
-}
-
-
-void BP::Regenerate() {
-    DAIAlgFG::Regenerate();
-    
-    // clear messages
-    _messages.clear();
-    _messages.reserve(nr_edges());
-
-    // clear indices
-    _indices.clear();
-    _indices.reserve(nr_edges());
-
-    // create messages and indices
-    for( vector<_edge_t>::const_iterator iI=edges().begin(); iI!=edges().end(); iI++ ) {
-        _messages.push_back( Prob( var(iI->first).states() ) );
-
-        vector<size_t> ind( factor(iI->second).stateSpace(), 0 );
-        Index i (var(iI->first), factor(iI->second).vars() );
-        for( size_t j = 0; i >= 0; ++i,++j )
-            ind[j] = i; 
-        _indices.push_back( ind );
-    }
-
-    // create new_messages
-    _newmessages = _messages;
-}
-
-
-void BP::init() {
-    assert( checkProperties() );
-    for( vector<Prob>::iterator mij = _messages.begin(); mij != _messages.end(); mij++ )
-        mij->fill(1.0 / mij->size());
-    _newmessages = _messages;
-}
-
-
-void BP::calcNewMessage (size_t iI) {
-    // calculate updated message I->i
-    size_t i = edge(iI).first;
-    size_t I = edge(iI).second;
-
-/*  UNOPTIMIZED (SIMPLE TO READ, BUT SLOW) VERSION
-
-    Factor prod( factor( I ) );
-    for( _nb_cit j = nb2(I).begin(); j != nb2(I).end(); j++ )
-        if( *j != i ) {     // for all j in I \ i
-            for( _nb_cit J = nb1(*j).begin(); J != nb1(*j).end(); J++ ) 
-                if( *J != I ) {     // for all J in nb(j) \ I 
-                    prod *= Factor( *j, message(*j,*J) );
-    Factor marg = prod.marginal(var(i));
-*/
-    
-    Prob prod( factor(I).p() );
-
-    // Calculate product of incoming messages and factor I
-    for( _nb_cit j = nb2(I).begin(); j != nb2(I).end(); j++ )
-        if( *j != i ) {     // for all j in I \ i
-            // ind is the precalculated Index(j,I) i.e. to x_I == k corresponds x_j == ind[k]
-            _ind_t* ind = &(index(*j,I));
-
-            // prod_j will be the product of messages coming into j
-            Prob prod_j( var(*j).states() ); 
-            for( _nb_cit J = nb1(*j).begin(); J != nb1(*j).end(); J++ ) 
-                if( *J != I )   // for all J in nb(j) \ I 
-                    prod_j *= message(*j,*J);
-
-            // multiply prod with prod_j
-            for( size_t r = 0; r < prod.size(); r++ )
-                prod[r] *= prod_j[(*ind)[r]];
-        }
-
-    // Marginalize onto i
-    Prob marg( var(i).states(), 0.0 );
-    // ind is the precalculated Index(i,I) i.e. to x_I == k corresponds x_i == ind[k]
-    _ind_t* ind = &(index(i,I));
-    for( size_t r = 0; r < prod.size(); r++ )
-        marg[(*ind)[r]] += prod[r];
-    marg.normalize( _normtype );
-    
-    // Store result
-    _newmessages[iI] = marg;
-}
-
-
-// BP::run does not check for NANs for performance reasons
-// Somehow NaNs do not often occur in BP...
-double BP::run() {
-    if( Verbose() >= 1 )
-        cout << "Starting " << identify() << "...";
-    if( Verbose() >= 3)
-       cout << endl; 
-
-    clock_t tic = toc();
-    Diffs diffs(nrVars(), 1.0);
-    
-    vector<size_t> edge_seq;
-    vector<double> residuals;
-
-    vector<Factor> old_beliefs;
-    old_beliefs.reserve( nrVars() );
-    for( size_t i = 0; i < nrVars(); i++ )
-        old_beliefs.push_back(belief1(i));
-
-    size_t iter = 0;
-
-    if( Updates() == UpdateType::SEQMAX ) {
-        // do the first pass
-        for(size_t iI = 0; iI < nr_edges(); iI++ ) 
-            calcNewMessage(iI);
-
-        // calculate initial residuals
-        residuals.reserve(nr_edges());
-        for( size_t iI = 0; iI < nr_edges(); iI++ )
-            residuals.push_back( dist( _newmessages[iI], _messages[iI], Prob::DISTLINF ) );
-    } else {
-        edge_seq.reserve( nr_edges() );
-        for( size_t i = 0; i < nr_edges(); i++ )
-            edge_seq.push_back( i );
-    }
-
-    // do several passes over the network until maximum number of iterations has
-    // been reached or until the maximum belief difference is smaller than tolerance
-    for( iter=0; iter < MaxIter() && diffs.max() > Tol(); iter++ ) {
-        if( Updates() == UpdateType::SEQMAX ) {
-            // Residuals-BP by Koller et al.
-            for( size_t t = 0; t < nr_edges(); t++ ) {
-                // update the message with the largest residual
-                size_t iI = max_element(residuals.begin(), residuals.end()) - residuals.begin();
-                _messages[iI] = _newmessages[iI];
-                residuals[iI] = 0;
-
-                // I->i has been updated, which means that residuals for all
-                // J->j with J in nb[i]\I and j in nb[J]\i have to be updated
-                size_t i = edge(iI).first;
-                size_t I = edge(iI).second;
-                for( _nb_cit J = nb1(i).begin(); J != nb1(i).end(); J++ ) 
-                    if( *J != I )
-                        for( _nb_cit j = nb2(*J).begin(); j != nb2(*J).end(); j++ )
-                            if( *j != i ) {
-                                size_t jJ = VV2E(*j,*J);
-                                calcNewMessage(jJ);
-                                residuals[jJ] = dist( _newmessages[jJ], _messages[jJ], Prob::DISTLINF );
-                            }
-            }
-        } else if( Updates() == UpdateType::PARALL ) {
-            // Parallel updates 
-            for( size_t t = 0; t < nr_edges(); t++ )
-                calcNewMessage(t);
-
-            for( size_t t = 0; t < nr_edges(); t++ )
-                _messages[t] = _newmessages[t];
-        } else {
-            // Sequential updates
-            if( Updates() == UpdateType::SEQRND )
-                random_shuffle( edge_seq.begin(), edge_seq.end() );
-            
-            for( size_t t = 0; t < nr_edges(); t++ ) {
-                size_t k = edge_seq[t];
-                calcNewMessage(k);
-                _messages[k] = _newmessages[k];
-            }
-        }
-
-        // calculate new beliefs and compare with old ones
-        for( size_t i = 0; i < nrVars(); i++ ) {
-            Factor nb( belief1(i) );
-            diffs.push( dist( nb, old_beliefs[i], Prob::DISTLINF ) );
-            old_beliefs[i] = nb;
-        }
-
-        if( Verbose() >= 3 )
-            cout << "BP::run:  maxdiff " << diffs.max() << " after " << iter+1 << " passes" << endl;
-    }
-
-    updateMaxDiff( diffs.max() );
-
-    if( Verbose() >= 1 ) {
-        if( diffs.max() > Tol() ) {
-            if( Verbose() == 1 )
-                cout << endl;
-                cout << "BP::run:  WARNING: not converged within " << MaxIter() << " passes (" << toc() - tic << " clocks)...final maxdiff:" << diffs.max() << endl;
-        } else {
-            if( Verbose() >= 3 )
-                cout << "BP::run:  ";
-                cout << "converged in " << iter << " passes (" << toc() - tic << " clocks)." << endl;
-        }
-    }
-
-    return diffs.max();
-}
-
-
-Factor BP::belief1( size_t i ) const {
-    Prob prod( var(i).states() ); 
-    for( _nb_cit I = nb1(i).begin(); I != nb1(i).end(); I++ ) 
-        prod *= newMessage(i,*I);
-
-    prod.normalize( Prob::NORMPROB );
-    return( Factor( var(i), prod ) );
-}
-
-
-Factor BP::belief (const Var &n) const {
-    return( belief1( findVar( n ) ) );
-}
-
-
-vector<Factor> BP::beliefs() const {
-    vector<Factor> result;
-    for( size_t i = 0; i < nrVars(); i++ )
-        result.push_back( belief1(i) );
-    for( size_t I = 0; I < nrFactors(); I++ )
-        result.push_back( belief2(I) );
-    return result;
-}
-
-
-Factor BP::belief( const VarSet &ns ) const {
-    if( ns.size() == 1 )
-        return belief( *(ns.begin()) );
-    else {
-        size_t I;
-        for( I = 0; I < nrFactors(); I++ )
-            if( factor(I).vars() >> ns )
-                break;
-        assert( I != nrFactors() );
-        return belief2(I).marginal(ns);
-    }
-}
-
-
-Factor BP::belief2 (size_t I) const {
-    Prob prod( factor(I).p() );
-
-    for( _nb_cit j = nb2(I).begin(); j != nb2(I).end(); j++ ) {
-        // ind is the precalculated Index(j,I) i.e. to x_I == k corresponds x_j == ind[k]
-        const _ind_t *ind = &(index(*j, I));
-
-        // prod_j will be the product of messages coming into j
-        Prob prod_j( var(*j).states() ); 
-        for( _nb_cit J = nb1(*j).begin(); J != nb1(*j).end(); J++ ) 
-            if( *J != I )   // for all J in nb(j) \ I 
-                prod_j *= newMessage(*j,*J);
-
-        // multiply prod with prod_j
-        for( size_t r = 0; r < prod.size(); r++ )
-            prod[r] *= prod_j[(*ind)[r]];
-    }
-
-    Factor result( factor(I).vars(), prod );
-    result.normalize( Prob::NORMPROB );
-    
-    return( result );
-
-/*  UNOPTIMIZED VERSION
-    Factor prod( factor(I) );
-    for( _nb_cit i = nb2(I).begin(); i != nb2(I).end(); i++ ) {
-        for( _nb_cit J = nb1(*i).begin(); J != nb1(*i).end(); J++ )
-            if( *J != I )
-                prod *= Factor( var(*i), newMessage(*i,*J)) );
-    }
-    return prod.normalize( Prob::NORMPROB );*/
-}
-
-
-Complex BP::logZ() const {
-    Complex sum = 0.0;
-    for(size_t i = 0; i < nrVars(); i++ )
-        sum += Complex(1.0 - nb1(i).size()) * belief1(i).entropy();
-    for( size_t I = 0; I < nrFactors(); I++ )
-        sum -= KL_dist( belief2(I), factor(I) );
-    return sum;
-}
-
-
-string BP::identify() const { 
-    stringstream result (stringstream::out);
-    result << Name << GetProperties();
-    return result.str();
-}
-
-
-void BP::init( const VarSet &ns ) {
-    for( VarSet::const_iterator n = ns.begin(); n != ns.end(); n++ ) {
-        size_t ni = findVar( *n );
-        for( _nb_cit I = nb1(ni).begin(); I != nb1(ni).end(); I++ )
-            message(ni,*I).fill( 1.0 );
-    }
-}
-
-
-}
diff --git a/bp.h b/bp.h
deleted file mode 100644 (file)
index e8bf564..0000000
--- a/bp.h
+++ /dev/null
@@ -1,99 +0,0 @@
-/*  Copyright (C) 2006-2008  Joris Mooij  [j dot mooij at science dot ru dot nl]
-    Radboud University Nijmegen, The Netherlands
-    
-    This file is part of libDAI.
-
-    libDAI is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    libDAI is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with libDAI; if not, write to the Free Software
-    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-
-#ifndef __BP_H__
-#define __BP_H__
-
-
-#include "daialg.h"
-#include "factorgraph.h"
-#include "enum.h"
-
-
-namespace dai {
-
-
-using namespace std;
-
-
-class BP : public DAIAlgFG {
-    protected:
-        typedef vector<size_t>  _ind_t;
-
-        vector<_ind_t>          _indices;
-        vector<Prob>            _messages, _newmessages;
-
-    public:
-        ENUM4(UpdateType,SEQFIX,SEQRND,SEQMAX,PARALL)
-        UpdateType Updates() const { return GetPropertyAs<UpdateType>("updates"); }
-
-        // default constructor
-        BP() : DAIAlgFG() {};
-        // copy constructor
-        BP(const BP & x) : DAIAlgFG(x), _indices(x._indices), _messages(x._messages), _newmessages(x._newmessages) {};
-        BP* clone() const { return new BP(*this); }
-        // construct BP object from FactorGraph
-        BP(const FactorGraph & fg, const Properties &opts) : DAIAlgFG(fg, opts) {
-            assert( checkProperties() );
-            Regenerate();
-        }
-        // assignment operator
-        BP & operator=(const BP & x) {
-            if(this!=&x) {
-                DAIAlgFG::operator=(x);
-                _messages = x._messages;
-                _newmessages = x._newmessages;
-                _indices = x._indices;
-            }
-            return *this;
-        }
-        
-        static const char *Name;
-
-        Prob & message(size_t i1, size_t i2) { return( _messages[VV2E(i1,i2)] ); }  
-        const Prob & message(size_t i1, size_t i2) const { return( _messages[VV2E(i1,i2)] ); }  
-        Prob & newMessage(size_t i1, size_t i2) { return( _newmessages[VV2E(i1,i2)] ); }    
-        const Prob & newMessage(size_t i1, size_t i2) const { return( _newmessages[VV2E(i1,i2)] ); }    
-        _ind_t & index(size_t i1, size_t i2) { return( _indices[VV2E(i1,i2)] ); }
-        const _ind_t & index(size_t i1, size_t i2) const { return( _indices[VV2E(i1,i2)] ); }
-
-        string identify() const;
-        void Regenerate();
-        void init();
-        void calcNewMessage(size_t iI);
-        double run();
-        Factor belief1 (size_t i) const;
-        Factor belief2 (size_t I) const;
-        Factor belief (const Var &n) const;
-        Factor belief (const VarSet &n) const;
-        vector<Factor> beliefs() const;
-        Complex logZ() const;
-
-        void init( const VarSet &ns );
-        void undoProbs( const VarSet &ns ) { FactorGraph::undoProbs(ns); init(ns); }
-        bool checkProperties();
-};
-
-
-}
-
-
-#endif
diff --git a/clustergraph.cpp b/clustergraph.cpp
deleted file mode 100644 (file)
index 3a33a11..0000000
+++ /dev/null
@@ -1,122 +0,0 @@
-/*  Copyright (C) 2006-2008  Joris Mooij  [j dot mooij at science dot ru dot nl]
-    Radboud University Nijmegen, The Netherlands
-    
-    This file is part of libDAI.
-
-    libDAI is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    libDAI is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with libDAI; if not, write to the Free Software
-    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-
-#include <set>
-#include <vector>
-#include <iostream>
-#include "varset.h"
-#include "clustergraph.h"
-
-
-namespace dai {
-
-
-using namespace std;
-
-
-ClusterGraph ClusterGraph::VarElim( const vector<Var> & ElimSeq ) const {
-    const long verbose = 0;
-
-    // Make a copy
-    ClusterGraph _Cl(*this);
-
-    ClusterGraph result;
-    _Cl.eraseNonMaximal();
-    
-    // Do variable elimination
-    for( vector<Var>::const_iterator n = ElimSeq.begin(); n != ElimSeq.end(); n++ ) {
-        assert( _Cl.vars() && *n );
-
-        if( verbose >= 1 )
-            cout << "Cost of eliminating " << *n << ": " << _Cl.eliminationCost( *n ) << " new edges" << endl;
-        
-        result.insert( _Cl.Delta(*n) );
-
-        if( verbose >= 1 )
-            cout << "_Cl = " << _Cl << endl;
-
-        if( verbose >= 1 )
-            cout << "After inserting " << _Cl.delta(*n) << ", _Cl = ";
-        _Cl.insert( _Cl.delta(*n) );
-        if( verbose >= 1 )
-            cout << _Cl << endl;
-
-        if( verbose >= 1 )
-            cout << "After erasing clusters that contain " << *n <<  ", _Cl = ";
-        _Cl.eraseSubsuming( *n );
-        if( verbose >= 1 )
-            cout << _Cl << endl;
-
-        if( verbose >= 1 )
-            cout << "After erasing nonmaximal clusters, _Cl = ";
-        _Cl.eraseNonMaximal();
-        if( verbose >= 1 )
-            cout << _Cl << endl;
-    }
-
-    return result;
-}
-
-
-ClusterGraph ClusterGraph::VarElim_MinFill() const {
-    const long verbose = 0;
-
-    // Make a copy
-    ClusterGraph _Cl(*this);
-    VarSet _vars( vars() );
-
-    ClusterGraph result;
-    _Cl.eraseNonMaximal();
-    
-    // Do variable elimination
-    while( !_vars.empty() ) {
-        if( verbose >= 1 )
-            cout << "Var  Eliminiation cost" << endl;
-        VarSet::iterator lowest = _vars.end();
-        size_t lowest_cost = -1UL;
-        for( VarSet::const_iterator n = _vars.begin(); n != _vars.end(); n++ ) {
-            size_t cost = _Cl.eliminationCost( *n );
-            if( verbose >= 1 )
-                cout << *n << "  " << cost << endl;
-            if( lowest == _vars.end() || lowest_cost > cost ) {
-                lowest = n;
-                lowest_cost = cost;
-            }
-        }
-        Var n = *lowest;
-
-        if( verbose >= 1 )
-            cout << "Lowest: " << n << " (" << lowest_cost << ")" << endl;
-
-        result.insert( _Cl.Delta(n) );
-
-        _Cl.insert( _Cl.delta(n) );
-        _Cl.eraseSubsuming( n );
-        _Cl.eraseNonMaximal();
-        _vars /= n;
-
-    }
-
-    return result;
-}
-
-
-}
diff --git a/clustergraph.h b/clustergraph.h
deleted file mode 100644 (file)
index e187caa..0000000
+++ /dev/null
@@ -1,184 +0,0 @@
-/*  Copyright (C) 2006-2008  Joris Mooij  [j dot mooij at science dot ru dot nl]
-    Radboud University Nijmegen, The Netherlands
-    
-    This file is part of libDAI.
-
-    libDAI is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    libDAI is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with libDAI; if not, write to the Free Software
-    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-
-#ifndef __CLUSTERGRAPH_H__
-#define __CLUSTERGRAPH_H__
-
-
-#include <set>
-#include <vector>
-#include "varset.h"
-
-
-namespace dai {
-
-
-using namespace std;
-
-
-/// A ClusterGraph is a hypergraph with VarSets as nodes.
-/// It is implemented as a set<VarSet> in which the adjacency
-/// relationship is computed realtime. It may be better to
-/// implement it as a bipartitegraph, though. The additional
-/// functionality compared to a simple set<VarSet> is
-/// finding maximal clusters, finding cliques, etc...
-class ClusterGraph : public set<VarSet> {
-    public:
-        /// Default constructor
-        ClusterGraph() : set<VarSet>() {}
-
-        /// Construct from vector<VarSet>
-        ClusterGraph( const vector<VarSet> & cls ) {
-            insert( cls.begin(), cls.end() );
-        }
-        
-        /// Copy constructor
-        ClusterGraph(const ClusterGraph &x) : set<VarSet>(x) {}
-
-        /// Assignment operator
-        ClusterGraph& operator=( const ClusterGraph &x ) {
-            if( this != &x ) {
-                set<VarSet>::operator=( x );
-            }
-            return *this;
-        }
-
-        /// Returns true if ns is a maximal member of *this under inclusion (VarSet::operator<<)
-        bool isMaximal( const VarSet &ns ) const {
-            if( count( ns ) ) {
-                // ns is a member
-                bool maximal = true;
-                for( const_iterator x = begin(); x != end() && maximal; x++ )
-                    if( (ns << *x) && (ns != *x) )
-                        maximal = false;
-                return maximal;
-            } else
-                return false;
-        }
-
-        /// Erase all VarSets that are not maximal
-        ClusterGraph& eraseNonMaximal() {
-            for( iterator x = begin(); x != end(); )
-                if( !isMaximal(*x) )
-                    erase(x++);
-                else
-                    x++;
-            return *this;
-        }
-
-        /// Return union of all members
-        VarSet vars() const {
-            VarSet result;
-            for( iterator x = begin(); x != end(); x++ )
-                result |= *x;
-            return result;
-        }
-
-        /// Returns true if n1 and n2 are adjacent, i.e.\ by
-        /// definition, are both contained in some cluster in *this
-        bool adj( const Var& n1, const Var& n2 ) {
-            bool result = false;
-            for( iterator x = begin(); (x != end()) && (!result); x++ )
-                if( (*x && n1) && (*x && n2) )
-                    result = true;
-            return result;
-        }
-        
-        /// Returns union of clusters that contain n, minus n
-        VarSet Delta( const Var& n ) const {
-            VarSet result;
-            for( iterator x = begin(); x != end(); x++ )
-                if( (*x && n) )
-                    result |= *x;
-            return result;
-        }
-
-        /// Returns union of clusters that contain n, minus n
-        VarSet delta( const Var& n ) const {
-            return Delta( n ) / n;
-        }
-        
-        /// Erases all members that contain n
-        ClusterGraph& eraseSubsuming( const Var& n ) {
-            for( iterator x = begin(); x != end(); )
-                if( (*x && n) )
-                    erase(x++);
-                else
-                    x++;
-            return *this;
-        }
-        
-        /// Send to output stream
-        friend std::ostream & operator << ( std::ostream & os, const ClusterGraph & cl ) {
-            os << "{";
-            ClusterGraph::const_iterator x = cl.begin();
-            if( x != cl.end() )
-                os << *(x++);
-            for( ; x != cl.end(); x++ )
-                os << ", " << *x;
-            os << "}";
-            return os;
-        }
-
-        /// Convert to vector<VarSet>
-        vector<VarSet> toVector() const {
-            vector<VarSet> result;
-            result.reserve( size() );
-            for( const_iterator x = begin(); x != end(); x++ )
-                result.push_back( *x );
-            return result;
-        }
-
-        /// Calculate cost of eliminating variable n
-        /// using as a measure "number of added edges in the adjacency graph"
-        /// where the adjacency graph has the variables as its nodes and
-        /// connects nodes i1 and i2 iff i1 and i2 occur in some common factor I
-        size_t eliminationCost( const Var& n ) {
-            VarSet d_n = delta( n );
-            size_t cost = 0;
-
-            // for each unordered pair {i1,i2} adjacent to n
-            for( VarSet::const_iterator i1 = d_n.begin(); i1 != d_n.end(); i1++ ) {
-                VarSet d_i1 = delta( *i1 );
-                for( VarSet::const_iterator i2 = i1; (++i2) != d_n.end(); ) {
-                    // if i1 and i2 are not adjacent, eliminating n would make them adjacent
-                    if( !adj(*i1, *i2) )
-                        cost++;
-                }
-            }
-            return cost;
-        }
-
-        /// Perform Variable Elimination without Probs, i.e. only keeping track of
-        /// the interactions that are created along the way.
-        /// Input:  a set of outer clusters and an elimination sequence
-        /// Output: a set of elimination "cliques"
-        ClusterGraph VarElim( const vector<Var> &ElimSeq ) const;
-
-        /// As Taylan does it
-        ClusterGraph VarElim_MinFill() const;
-};
-
-
-}
-
-
-#endif
diff --git a/daialg.cpp b/daialg.cpp
deleted file mode 100644 (file)
index c4c3d92..0000000
+++ /dev/null
@@ -1,230 +0,0 @@
-/*  Copyright (C) 2006-2008  Joris Mooij  [j dot mooij at science dot ru dot nl]
-    Radboud University Nijmegen, The Netherlands
-    
-    This file is part of libDAI.
-
-    libDAI is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    libDAI is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with libDAI; if not, write to the Free Software
-    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-
-#include "daialg.h"
-
-
-namespace dai {
-
-
-/// Calculate the marginal of obj on ns by clamping 
-/// all variables in ns and calculating logZ for each joined state
-Factor calcMarginal( const InfAlg & obj, const VarSet & ns, bool reInit ) {
-    Factor Pns (ns);
-    
-    multind mi( ns );
-
-    InfAlg *clamped = obj.clone();
-    if( !reInit )
-        clamped->init();
-
-    Complex logZ0;
-    for( size_t j = 0; j < mi.max(); j++ ) {
-        // save unclamped factors connected to ns
-        clamped->saveProbs( ns );
-
-        // set clamping Factors to delta functions
-        vector<size_t> vi = mi.vi( j );
-        size_t k = 0;
-        for( VarSet::const_iterator n = ns.begin(); n != ns.end(); n++, k++ )
-            clamped->clamp( *n, vi[k] );
-        
-        // run DAIAlg, calc logZ, store in Pns
-        if( clamped->Verbose() >= 2 )
-            cout << j << ": ";
-        if( reInit )
-            clamped->init();
-        clamped->run();
-
-        Complex Z;
-        if( j == 0 ) {
-            logZ0 = clamped->logZ();
-            Z = 1.0;
-        } else {
-            // subtract logZ0 to avoid very large numbers
-            Z = exp(clamped->logZ() - logZ0);
-            if( fabs(imag(Z)) > 1e-5 )
-                cout << "Marginal:: WARNING: complex Z (" << Z << ")" << endl;
-        }
-
-        Pns[j] = real(Z);
-        
-        // restore clamped factors
-        clamped->undoProbs( ns );
-    }
-
-    delete clamped;
-
-    return( Pns.normalized(Prob::NORMPROB) );
-}
-
-
-vector<Factor> calcPairBeliefs( const InfAlg & obj, const VarSet& ns, bool reInit ) {
-    // convert ns to vector<VarSet>
-    size_t N = ns.size();
-    vector<Var> vns;
-    vns.reserve( N );
-    for( VarSet::const_iterator n = ns.begin(); n != ns.end(); n++ )
-        vns.push_back( *n );
-
-    vector<Factor> pairbeliefs;
-    pairbeliefs.reserve( N * N );
-    for( size_t j = 0; j < N; j++ )
-        for( size_t k = 0; k < N; k++ )
-            if( j == k )
-                pairbeliefs.push_back(Factor());
-            else
-                pairbeliefs.push_back(Factor(vns[j] | vns[k]));
-
-    InfAlg *clamped = obj.clone();
-    if( !reInit )
-        clamped->init();
-
-    Complex logZ0;
-    for( size_t j = 0; j < N; j++ ) {
-        // clamp Var j to its possible values
-        for( size_t j_val = 0; j_val < vns[j].states(); j_val++ ) {
-            if( obj.Verbose() >= 2 )
-                cout << j << "/" << N-1 << " (" << j_val << "/" << vns[j].states() << "): ";
-
-            // save unclamped factors connected to ns
-            clamped->saveProbs( ns );
-            
-            clamped->clamp( vns[j], j_val );
-            if( reInit )
-                clamped->init();
-            clamped->run();
-
-            //if( j == 0 )
-            //  logZ0 = obj.logZ();
-            double Z_xj = 1.0;
-            if( j == 0 && j_val == 0 ) {
-                logZ0 = clamped->logZ();
-            } else {
-                // subtract logZ0 to avoid very large numbers
-                Complex Z = exp(clamped->logZ() - logZ0);
-                if( fabs(imag(Z)) > 1e-5 )
-                    cout << "calcPairBelief::  Warning: complex Z: " << Z << endl;
-                Z_xj = real(Z);
-            }
-
-            for( size_t k = 0; k < N; k++ ) 
-                if( k != j ) {
-                    Factor b_k = clamped->belief(vns[k]);
-                    for( size_t k_val = 0; k_val < vns[k].states(); k_val++ ) 
-                        if( vns[j].label() < vns[k].label() )
-                            pairbeliefs[j * N + k][j_val + (k_val * vns[j].states())] = Z_xj * b_k[k_val];
-                        else
-                            pairbeliefs[j * N + k][k_val + (j_val * vns[k].states())] = Z_xj * b_k[k_val];
-                }
-
-            // restore clamped factors
-            clamped->undoProbs( ns );
-        }
-    }
-    
-    delete clamped;
-
-    // Calculate result by taking the geometric average
-    vector<Factor> result;
-    result.reserve( N * (N - 1) / 2 );
-    for( size_t j = 0; j < N; j++ )
-        for( size_t k = j+1; k < N; k++ )
-            result.push_back( (pairbeliefs[j * N + k] * pairbeliefs[k * N + j]) ^ 0.5 );
-
-    return result;
-}
-
-
-Factor calcMarginal2ndO( const InfAlg & obj, const VarSet& ns, bool reInit ) {
-    // returns a a probability distribution whose 1st order interactions
-    // are unspecified, whose 2nd order interactions approximate those of 
-    // the marginal on ns, and whose higher order interactions are absent.
-
-    vector<Factor> pairbeliefs = calcPairBeliefs( obj, ns, reInit );
-
-    Factor Pns (ns);
-    for( size_t ij = 0; ij < pairbeliefs.size(); ij++ )
-        Pns *= pairbeliefs[ij];
-    
-    return( Pns.normalized(Prob::NORMPROB) );
-}
-
-
-vector<Factor> calcPairBeliefsNew( const InfAlg & obj, const VarSet& ns, bool reInit ) {
-    vector<Factor> result;
-    result.reserve( ns.size() * (ns.size() - 1) / 2 );
-
-    InfAlg *clamped = obj.clone();
-    if( !reInit )
-        clamped->init();
-
-    Complex logZ0;
-    VarSet::const_iterator nj = ns.begin();
-    for( long j = 0; j < (long)ns.size() - 1; j++, nj++ ) {
-        size_t k = 0;
-        for( VarSet::const_iterator nk = nj; (++nk) != ns.end(); k++ ) {
-            Factor pairbelief( *nj | *nk );
-
-            // clamp Vars j and k to their possible values
-            for( size_t j_val = 0; j_val < nj->states(); j_val++ ) 
-                for( size_t k_val = 0; k_val < nk->states(); k_val++ ) {
-                    // save unclamped factors connected to ns
-                    clamped->saveProbs( ns );
-            
-                    clamped->clamp( *nj, j_val );
-                    clamped->clamp( *nk, k_val );
-                    if( reInit )
-                        clamped->init();
-                    clamped->run();
-
-                    double Z_xj = 1.0;
-                    if( j_val == 0 && k_val == 0 ) {
-                        logZ0 = clamped->logZ();
-                    } else {
-                        // subtract logZ0 to avoid very large numbers
-                        Complex Z = exp(clamped->logZ() - logZ0);
-                        if( fabs(imag(Z)) > 1e-5 )
-                            cout << "calcPairBelief::  Warning: complex Z: " << Z << endl;
-                        Z_xj = real(Z);
-                    }
-
-                    // we assume that j.label() < k.label()
-                    // i.e. we make an assumption here about the indexing
-                    pairbelief[j_val + (k_val * nj->states())] = Z_xj;
-
-                    // restore clamped factors
-                    clamped->undoProbs( ns );
-                }
-        
-            result.push_back( pairbelief );
-        }
-    }
-    
-    delete clamped;
-
-    assert( result.size() == (ns.size() * (ns.size() - 1) / 2) );
-
-    return result;
-}
-
-
-}
diff --git a/daialg.h b/daialg.h
deleted file mode 100644 (file)
index 5a1eeb1..0000000
--- a/daialg.h
+++ /dev/null
@@ -1,290 +0,0 @@
-/*  Copyright (C) 2006-2008  Joris Mooij  [j dot mooij at science dot ru dot nl]
-    Radboud University Nijmegen, The Netherlands
-    
-    This file is part of libDAI.
-
-    libDAI is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    libDAI is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with libDAI; if not, write to the Free Software
-    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-
-#ifndef __DAIALG_H__
-#define __DAIALG_H__
-
-
-#include <string>
-#include <iostream>
-#include <vector>
-#include "factorgraph.h"
-#include "regiongraph.h"
-#include "properties.h"
-
-
-namespace dai {
-
-
-/// The InfAlg class is the common denominator of the various approximate inference algorithms.
-/// A InfAlg object represents a discrete factorized probability distribution over multiple variables 
-/// together with an inference algorithm.
-class InfAlg {
-    private:
-        /// Properties of the algorithm (replaces _tol, _maxiter, _verbose)
-        Properties              _properties;
-
-        /// Maximum difference encountered so far
-        double                  _maxdiff;
-
-
-    public:
-        /// Default constructor
-        InfAlg() : _properties(), _maxdiff(0.0) {}
-        
-        /// Constructor with options
-        InfAlg( const Properties &opts ) : _properties(opts), _maxdiff(0.0) {}
-        
-        /// Copy constructor
-        InfAlg( const InfAlg & x ) : _properties(x._properties), _maxdiff(x._maxdiff) {}
-
-        /// Clone (virtual copy constructor)
-        virtual InfAlg* clone() const = 0;
-
-        /// Assignment operator
-        InfAlg & operator=( const InfAlg & x ) {
-            if( this != &x ) {
-                _properties = x._properties;
-                _maxdiff    = x._maxdiff;
-            }
-            return *this;
-        }
-        
-        /// Virtual desctructor
-        // (this is needed because this class contains virtual functions)
-        virtual ~InfAlg() {}
-        
-        /// Returns true if a property with the given key is present
-        bool HasProperty(const PropertyKey &key) const { return _properties.hasKey(key); }
-
-        /// Gets a property
-        const PropertyValue & GetProperty(const PropertyKey &key) const { return _properties.Get(key); }
-        /// Gets a property, casted as ValueType
-        template<typename ValueType>
-        ValueType GetPropertyAs(const PropertyKey &key) const { return _properties.GetAs<ValueType>(key); }
-
-        /// Sets a property 
-        void SetProperty(const PropertyKey &key, const PropertyValue &val) { _properties[key] = val; }
-
-        /// Converts a property from string to ValueType, if necessary
-        template<typename ValueType>
-        void ConvertPropertyTo(const PropertyKey &key) { _properties.ConvertTo<ValueType>(key); }
-
-        /// Gets all properties
-        const Properties & GetProperties() const { return _properties; }
-
-        /// Sets properties
-        void SetProperties(const Properties &p) { _properties = p; }
-
-        /// Sets tolerance
-        void Tol( double tol ) { SetProperty("tol", tol); }
-        /// Gets tolerance
-        double Tol() const { return GetPropertyAs<double>("tol"); }
-
-        /// Sets maximum number of iterations
-        void MaxIter( size_t maxiter ) { SetProperty("maxiter", maxiter); }
-        /// Gets maximum number of iterations
-        size_t MaxIter() const { return GetPropertyAs<size_t>("maxiter"); }
-
-        /// Sets verbosity
-        void Verbose( size_t verbose ) { SetProperty("verbose", verbose); }
-        /// Gets verbosity
-        size_t Verbose() const { return GetPropertyAs<size_t>("verbose"); }
-
-        /// Sets maximum difference encountered so far
-        void MaxDiff( double maxdiff ) { _maxdiff = maxdiff; }
-        /// Gets maximum difference encountered so far
-        double MaxDiff() const { return _maxdiff; }
-        /// Updates maximum difference encountered so far
-        void updateMaxDiff( double maxdiff ) { if( maxdiff > _maxdiff ) _maxdiff = maxdiff; }
-        /// Sets maximum difference encountered so far to zero
-        void clearMaxDiff() { _maxdiff = 0.0; }
-
-        /// Identifies itself for logging purposes
-        virtual std::string identify() const = 0;
-
-        /// Get single node belief
-        virtual Factor belief( const Var &n ) const = 0;
-
-        /// Get general belief
-        virtual Factor belief( const VarSet &n ) const = 0;
-
-        /// Get all beliefs
-        virtual vector<Factor> beliefs() const = 0;
-
-        /// Get log partition sum
-        virtual Complex logZ() const = 0;
-
-        /// Clear messages and beliefs
-        virtual void init() = 0;
-
-        /// The actual approximate inference algorithm
-        virtual double run() = 0;
-
-        /// Save factor I
-        virtual void saveProb( size_t I ) = 0;
-        /// Save Factors involving ns
-        virtual void saveProbs( const VarSet &ns ) = 0;
-
-        /// Restore factor I
-        virtual void undoProb( size_t I ) = 0;
-        /// Restore Factors involving ns
-        virtual void undoProbs( const VarSet &ns ) = 0;
-
-        /// Clamp variable n to value i (i.e. multiply with a Kronecker delta \f$\delta_{x_n, i}\f$)
-        virtual void clamp( const Var & n, size_t i ) = 0;
-
-        /// Return all variables that interact with n
-        virtual VarSet delta( const Var & n ) const = 0;
-
-        /// Set all factors interacting with n to 1
-        virtual void makeCavity( const Var & n ) = 0;
-
-        /// Set factor I to 1
-        virtual void makeFactorCavity( size_t I ) = 0;
-
-        /// Get index of variable n
-        virtual size_t findVar( const Var & n ) const = 0;
-
-        /// Get index of first factor involving ns
-        virtual size_t findFactor( const VarSet &ns ) const = 0;
-
-        /// Get number of variables
-        virtual size_t nrVars() const = 0;
-
-        /// Get number of factors
-        virtual size_t nrFactors() const = 0;
-
-        /// Get const reference to variable i
-        virtual const Var & var(size_t i) const = 0;
-
-        /// Get reference to variable i
-        virtual Var & var(size_t i) = 0;
-
-        /// Get const reference to factor I
-        virtual const Factor & factor( size_t I ) const = 0;
-
-        /// Get reference to factor I
-        virtual Factor & factor( size_t I ) = 0;
-
-        /// Factor I has been updated
-        virtual void updatedFactor( size_t I ) = 0;
-
-        /// Checks whether all necessary properties have been set
-        /// and casts string-valued properties to other values if necessary
-        virtual bool checkProperties() = 0;
-};
-
-
-template <class T>
-class DAIAlg : public InfAlg, public T {
-    public:
-        /// Default constructor
-        DAIAlg() : InfAlg(), T() {}
-        
-        /// Construct DAIAlg with empty T but using the specified properties
-        DAIAlg( const Properties &opts ) : InfAlg( opts ), T() {}
-
-        /// Construct DAIAlg using the specified properties
-        DAIAlg( const T & t, const Properties &opts ) : InfAlg( opts ), T(t) {}
-        
-        /// Copy constructor
-        DAIAlg( const DAIAlg & x ) : InfAlg(x), T(x) {}
-
-        /// Save factor I (using T::saveProb)
-        void saveProb( size_t I ) { T::saveProb( I ); }
-        /// Save Factors involving ns (using T::saveProbs)
-        void saveProbs( const VarSet &ns ) { T::saveProbs( ns ); }
-
-        /// Restore factor I (using T::undoProb)
-        void undoProb( size_t I ) { T::undoProb( I ); }
-        /// Restore Factors involving ns (using T::undoProbs)
-        void undoProbs( const VarSet &ns ) { T::undoProbs( ns ); }
-
-        /// Clamp variable n to value i (i.e. multiply with a Kronecker delta \f$\delta_{x_n, i}\f$) (using T::clamp)
-        void clamp( const Var & n, size_t i ) { T::clamp( n, i ); }
-
-        /// Return all variables that interact with n (using T::delta)
-        VarSet delta( const Var & n ) const { return T::delta(n); }
-
-        /// Set all factors interacting with n to 1 (using T::makeCavity)
-        void makeCavity( const Var & n ) { T::makeCavity(n); }
-
-        /// Set factor I to 1 (using T::makeFactorCavity)
-        void makeFactorCavity( size_t I ) { T::makeFactorCavity(I); }
-
-        /// Get index of variable n (using T::findVar)
-        size_t findVar( const Var & n ) const { return T::findVar(n); }
-
-        /// Get index of first factor involving ns (using T::findFactor)
-        size_t findFactor( const VarSet &ns ) const { return T::findFactor(ns); }
-
-        /// Get number of variables (using T::nrFactors)
-        size_t nrVars() const { return T::nrVars(); }
-
-        /// Get number of factors (using T::nrFactors)
-        size_t nrFactors() const { return T::nrFactors(); }
-
-        /// Get const reference to variable i (using T::var)
-        const Var & var(size_t i) const { return T::var(i); }
-
-        /// Get reference to variable i (using T::var)
-        Var & var(size_t i) { return T::var(i); }
-
-        /// Get const reference to factor I (using T::factor)
-        const Factor & factor( size_t I ) const { return T::factor(I); }
-
-        /// Get reference to factor I (using T::factor)
-        Factor & factor( size_t I ) { return T::factor(I); }
-
-        /// Factor I has been updated (using T::updatedFactor)
-        void updatedFactor( size_t I ) { T::updatedFactor(I); }
-};
-
-
-typedef DAIAlg<FactorGraph> DAIAlgFG;
-typedef DAIAlg<RegionGraph> DAIAlgRG;
-
-
-/// Calculate the marginal of obj on ns by clamping 
-/// all variables in ns and calculating logZ for each joined state
-Factor calcMarginal( const InfAlg & obj, const VarSet & ns, bool reInit );
-
-
-/// Calculate beliefs of all pairs in ns (by clamping
-/// nodes in ns and calculating logZ and the beliefs for each state)
-vector<Factor> calcPairBeliefs( const InfAlg & obj, const VarSet& ns, bool reInit );
-
-
-/// Calculate beliefs of all pairs in ns (by clamping
-/// pairs in ns and calculating logZ for each joined state)
-vector<Factor> calcPairBeliefsNew( const InfAlg & obj, const VarSet& ns, bool reInit );
-
-
-/// Calculate 2nd order interactions of the marginal of obj on ns
-Factor calcMarginal2ndO( const InfAlg & obj, const VarSet& ns, bool reInit );
-
-
-}
-
-
-#endif
diff --git a/diffs.h b/diffs.h
deleted file mode 100644 (file)
index 406ced1..0000000
--- a/diffs.h
+++ /dev/null
@@ -1,78 +0,0 @@
-/*  Copyright (C) 2006-2008  Joris Mooij  [j dot mooij at science dot ru dot nl]
-    Radboud University Nijmegen, The Netherlands
-    
-    This file is part of libDAI.
-
-    libDAI is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    libDAI is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with libDAI; if not, write to the Free Software
-    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-
-#ifndef __DIFFS_H__
-#define __DIFFS_H__
-
-
-#include <vector>
-
-
-namespace dai {
-
-
-using namespace std;
-
-
-class Diffs : public vector<double> {
-    private:
-        size_t _maxsize;
-        double _def;
-        vector<double>::iterator _pos;
-        vector<double>::iterator _maxpos;
-    public:
-        Diffs(long maxsize, double def) : vector<double>(), _maxsize(maxsize), _def(def) { 
-            this->reserve(_maxsize); 
-            _pos = begin(); 
-            _maxpos = begin(); 
-        };
-        double max() { 
-            if( size() < _maxsize )
-                return _def;
-            else
-                return( *_maxpos ); 
-        }
-        void push(double x) {
-            if( size() < _maxsize ) {
-                push_back(x);
-                _pos = end();
-                _maxpos = max_element(begin(),end());
-            }
-            else {
-                if( _pos == end() )
-                    _pos = begin();
-                if( _maxpos == _pos ) {
-                    *_pos++ = x; 
-                    _maxpos = max_element(begin(),end());
-                } else {
-                    if( x > *_maxpos )
-                        _maxpos = _pos;
-                    *_pos++ = x;
-                }
-            }
-        }
-};
-
-
-}
-
-
-#endif
index a968bed..9cef1fb 100644 (file)
@@ -450,7 +450,7 @@ WARN_LOGFILE           =
 # directories like "/usr/src/myproject". Separate the files or directories 
 # with spaces.
 
-INPUT                  = 
+INPUT                  = src include/dai 
 
 # If the value of the INPUT tag contains directories, you can use the 
 # FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp 
diff --git a/enum.h b/enum.h
deleted file mode 100644 (file)
index d3975d5..0000000
--- a/enum.h
+++ /dev/null
@@ -1,272 +0,0 @@
-/*  Copyright (C) 2006-2008  Joris Mooij  [j dot mooij at science dot ru dot nl]
-    Radboud University Nijmegen, The Netherlands
-    
-    This file is part of libDAI.
-
-    libDAI is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    libDAI is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with libDAI; if not, write to the Free Software
-    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-
-#ifndef __ENUM_H
-#define __ENUM_H
-
-
-#include <cstring>
-#include <iostream>
-
-
-namespace dai {
-
-
-// C++ enums are too limited for my purposes. This defines wrapper classes
-// that provide much more functionality than a simple enum. The only
-// disadvantage is that one wrapper class needs to be written for each
-// number of values an enum can take... a better solution is needed.
-
-
-#define ENUM2(x,a,b) class x {\
-    public:\
-        enum value {a, b};\
-\
-        x() : v(a) {}\
-\
-        x(value w) : v(w) {}\
-\
-        x(char const *w) {\
-           static char const* labels[] = {#a, #b};\
-           size_t i = 0;\
-           for( ; i < sizeof(labels) / sizeof(char const *); i++ )\
-               if( strcmp( w, labels[i] ) == 0 ) {\
-                   v = (value)i;\
-                   break;\
-               }\
-           if( i == sizeof(labels) / sizeof(char const *) )\
-               throw "Unknown " #x " value";\
-        }\
-\
-        operator value () const { return v; }\
-\
-        operator size_t () const { return (size_t)v; }\
-\
-        operator char const* () const {\
-           static char const* labels[] = {#a, #b};\
-           return labels[v];\
-        }\
-\
-        friend std::istream& operator >> (std::istream& is, x& y) {\
-            std::string s;\
-            is >> s;\
-            y = x(s.c_str());\
-            return is;\
-        }\
-\
-        friend std::ostream& operator << (std::ostream& os, const x& y) {\
-            os << (const char *)y;\
-            return os;\
-        }\
-\
-    private:\
-        value v;\
-};
-
-
-#define ENUM3(x,a,b,c) class x {\
-    public:\
-        enum value {a, b, c};\
-\
-        x() : v(a) {}\
-\
-        x(value w) : v(w) {}\
-\
-        x(char const *w) {\
-           static char const* labels[] = {#a, #b, #c};\
-           size_t i = 0;\
-           for( ; i < sizeof(labels) / sizeof(char const *); i++ )\
-               if( strcmp( w, labels[i] ) == 0 ) {\
-                   v = (value)i;\
-                   break;\
-               }\
-           if( i == sizeof(labels) / sizeof(char const *) )\
-               throw "Unknown " #x " value";\
-        }\
-\
-        operator value () const { return v; }\
-\
-        operator size_t () const { return (size_t)v; }\
-\
-        operator char const* () const {\
-           static char const* labels[] = {#a, #b, #c};\
-           return labels[v];\
-        }\
-\
-        friend std::istream& operator >> (std::istream& is, x& y) {\
-            std::string s;\
-            is >> s;\
-            y = x(s.c_str());\
-            return is;\
-        }\
-\
-        friend std::ostream& operator << (std::ostream& os, const x& y) {\
-            os << (const char *)y;\
-            return os;\
-        }\
-\
-    private:\
-        value v;\
-};
-
-
-#define ENUM4(x,a,b,c,d) class x {\
-    public:\
-        enum value {a, b, c, d};\
-\
-        x() : v(a) {}\
-\
-        x(value w) : v(w) {}\
-\
-        x(char const *w) {\
-           static char const* labels[] = {#a, #b, #c, #d};\
-           size_t i = 0;\
-           for( ; i < sizeof(labels) / sizeof(char const *); i++ )\
-               if( strcmp( w, labels[i] ) == 0 ) {\
-                   v = (value)i;\
-                   break;\
-               }\
-           if( i == sizeof(labels) / sizeof(char const *) )\
-               throw "Unknown " #x " value";\
-        }\
-\
-        operator value () const { return v; }\
-\
-        operator size_t () const { return (size_t)v; }\
-\
-        operator char const* () const {\
-           static char const* labels[] = {#a, #b, #c, #d};\
-           return labels[v];\
-        }\
-\
-        friend std::istream& operator >> (std::istream& is, x& y) {\
-            std::string s;\
-            is >> s;\
-            y = x(s.c_str());\
-            return is;\
-        }\
-\
-        friend std::ostream& operator << (std::ostream& os, const x& y) {\
-            os << (const char *)y;\
-            return os;\
-        }\
-\
-    private:\
-        value v;\
-};
-
-
-#define ENUM5(x,a,b,c,d,e) class x {\
-    public:\
-        enum value {a, b, c, d, e};\
-\
-        x() : v(a) {}\
-\
-        x(value w) : v(w) {}\
-\
-        x(char const *w) {\
-           static char const* labels[] = {#a, #b, #c, #d, #e};\
-           size_t i = 0;\
-           for( ; i < sizeof(labels) / sizeof(char const *); i++ )\
-               if( strcmp( w, labels[i] ) == 0 ) {\
-                   v = (value)i;\
-                   break;\
-               }\
-           if( i == sizeof(labels) / sizeof(char const *) )\
-               throw "Unknown " #x " value";\
-        }\
-\
-        operator value () const { return v; }\
-\
-        operator size_t () const { return (size_t)v; }\
-\
-        operator char const* () const {\
-           static char const* labels[] = {#a, #b, #c, #d, #e};\
-           return labels[v];\
-        }\
-\
-        friend std::istream& operator >> (std::istream& is, x& y) {\
-            std::string s;\
-            is >> s;\
-            y = x(s.c_str());\
-            return is;\
-        }\
-\
-        friend std::ostream& operator << (std::ostream& os, const x& y) {\
-            os << (const char *)y;\
-            return os;\
-        }\
-\
-    private:\
-        value v;\
-};
-
-
-#define ENUM6(x,a,b,c,d,e,f) class x {\
-    public:\
-        enum value {a, b, c, d, e, f};\
-\
-        x() : v(a) {}\
-\
-        x(value w) : v(w) {}\
-\
-        x(char const *w) {\
-           static char const* labels[] = {#a, #b, #c, #d, #e, #f};\
-           size_t i = 0;\
-           for( ; i < sizeof(labels) / sizeof(char const *); i++ )\
-               if( strcmp( w, labels[i] ) == 0 ) {\
-                   v = (value)i;\
-                   break;\
-               }\
-           if( i == sizeof(labels) / sizeof(char const *) )\
-               throw "Unknown " #x " value";\
-        }\
-\
-        operator value () const { return v; }\
-\
-        operator size_t () const { return (size_t)v; }\
-\
-        operator char const* () const {\
-           static char const* labels[] = {#a, #b, #c, #d, #e, #f};\
-           return labels[v];\
-        }\
-\
-        friend std::istream& operator >> (std::istream& is, x& y) {\
-            std::string s;\
-            is >> s;\
-            y = x(s.c_str());\
-            return is;\
-        }\
-\
-        friend std::ostream& operator << (std::ostream& os, const x& y) {\
-            os << (const char *)y;\
-            return os;\
-        }\
-\
-    private:\
-        value v;\
-};
-
-
-}
-
-
-#endif
index 531a677..27c244d 100644 (file)
@@ -20,7 +20,7 @@
 
 
 #include <iostream>
-#include "alldai.h"
+#include <dai/alldai.h>
 
 
 using namespace dai;
diff --git a/factor.h b/factor.h
deleted file mode 100644 (file)
index 04ff6c9..0000000
--- a/factor.h
+++ /dev/null
@@ -1,365 +0,0 @@
-/*  Copyright (C) 2006-2008  Joris Mooij  [j dot mooij at science dot ru dot nl]
-    Radboud University Nijmegen, The Netherlands
-    
-    This file is part of libDAI.
-
-    libDAI is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    libDAI is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with libDAI; if not, write to the Free Software
-    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-
-#ifndef __FACTOR_H__
-#define __FACTOR_H__
-
-
-#include <iostream>
-#include <cmath>
-#include "prob.h"
-#include "varset.h"
-#include "index.h"
-
-
-namespace dai {
-
-
-template<typename T> class      TFactor;
-typedef TFactor<Real>           Factor;
-typedef TFactor<Complex>        CFactor;
-
-
-// predefine friends
-template<typename T> Real           dist( const TFactor<T> & x, const TFactor<T> & y, Prob::DistType dt );
-template<typename T> Complex        KL_dist( const TFactor<T> & p, const TFactor<T> & q );
-template<typename T> std::ostream&  operator<< (std::ostream& os, const TFactor<T>& P);
-
-        
-// T should be castable from and to double and to complex
-template <typename T> class TFactor {
-    protected:
-        VarSet      _vs;
-        TProb<T>    _p;
-
-    public:
-        // Default constructor
-        TFactor () : _vs(), _p(1,1.0) {}
-        
-        // Construct Factor from VarSet
-        TFactor( const VarSet& ns ) : _vs(ns), _p(_vs.stateSpace()) {}
-        
-        // Construct Factor from VarSet and initial value
-        TFactor( const VarSet& ns, Real p ) : _vs(ns), _p(_vs.stateSpace(),p) {}
-        
-        // Construct Factor from VarSet and initial array
-        TFactor( const VarSet& ns, const Real* p ) : _vs(ns), _p(_vs.stateSpace(),p) {}
-
-        // Construct Factor from VarSet and TProb<T>
-        TFactor( const VarSet& ns, const TProb<T> p ) : _vs(ns), _p(p) {
-#ifdef DEBUG
-            assert( _vs.stateSpace() == _p.size() );
-#endif
-        }
-        
-        // Construct Factor from Var
-        TFactor( const Var& n ) : _vs(n), _p(n.states()) {}
-
-        // Copy constructor
-        TFactor( const TFactor<T> &x ) : _vs(x._vs), _p(x._p) {}
-        
-        // Assignment operator
-        TFactor<T> & operator= (const TFactor<T> &x) {
-            if( this != &x ) {
-                _vs = x._vs;
-                _p  = x._p;
-            }
-            return *this;
-        }
-
-        const TProb<T> & p() const { return _p; }
-        TProb<T> & p() { return _p; }
-        const VarSet & vars() const { return _vs; }
-        size_t stateSpace() const { 
-#ifdef DEBUG
-            assert( _vs.stateSpace() == _p.size() );
-#endif
-            return _p.size();
-        }
-
-        T operator[] (size_t i) const { return _p[i]; }
-        T& operator[] (size_t i) { return _p[i]; }
-        TFactor<T> & fill (T p)
-            { _p.fill( p ); return(*this); }
-        TFactor<T> & randomize ()
-            { _p.randomize(); return(*this); }
-        TFactor<T> operator* (T x) const {
-            Factor result = *this;
-            result.p() *= x;
-            return result;
-        }
-        TFactor<T>& operator*= (T x) {
-            _p *= x;
-            return *this;
-        }
-        TFactor<T> operator/ (T x) const {
-            Factor result = *this;
-            result.p() /= x;
-            return result;
-        }
-        TFactor<T>& operator/= (T x) {
-            _p /= x;
-            return *this;
-        }
-        TFactor<T> operator* (const TFactor<T>& Q) const;
-        TFactor<T>& operator*= (const TFactor<T>& Q) { return( *this = (*this * Q) ); }
-        TFactor<T> operator+ (const TFactor<T>& Q) const {
-#ifdef DEBUG
-            assert( Q._vs == _vs );
-#endif
-            TFactor<T> sum(*this); 
-            sum._p += Q._p; 
-            return sum; 
-        }
-        TFactor<T> operator- (const TFactor<T>& Q) const {
-#ifdef DEBUG
-            assert( Q._vs == _vs );
-#endif
-            TFactor<T> sum(*this); 
-            sum._p -= Q._p; 
-            return sum; 
-        }
-        TFactor<T>& operator+= (const TFactor<T>& Q) { 
-#ifdef DEBUG
-            assert( Q._vs == _vs );
-#endif
-            _p += Q._p;
-            return *this;
-        }
-        TFactor<T>& operator-= (const TFactor<T>& Q) { 
-#ifdef DEBUG
-            assert( Q._vs == _vs );
-#endif
-            _p -= Q._p;
-            return *this;
-        }
-
-        TFactor<T> operator^ (Real a) const { TFactor<T> x; x._vs = _vs; x._p = _p^a; return x; }
-        TFactor<T>& operator^= (Real a) { _p ^= a; return *this; }
-
-        TFactor<T>& makeZero( Real epsilon ) {
-            _p.makeZero( epsilon );
-            return *this;
-        }
-            
-        TFactor<T> inverse() const { 
-            TFactor<T> inv; 
-            inv._vs = _vs; 
-            inv._p = _p.inverse(true);  // FIXME
-            return inv; 
-        }
-
-        TFactor<T> divided_by( const TFactor<T>& denom ) const { 
-#ifdef DEBUG
-            assert( denom._vs == _vs );
-#endif
-            TFactor<T> quot(*this); 
-            quot._p /= denom._p; 
-            return quot; 
-        }
-
-        TFactor<T>& divide( const TFactor<T>& denom ) {
-#ifdef DEBUG
-            assert( denom._vs == _vs );
-#endif
-            _p /= denom._p;
-            return *this;
-        }
-
-        TFactor<T> exp() const { 
-            TFactor<T> e; 
-            e._vs = _vs; 
-            e._p = _p.exp(); 
-            return e; 
-        }
-
-        TFactor<T> log() const {
-            TFactor<T> l; 
-            l._vs = _vs; 
-            l._p = _p.log(); 
-            return l; 
-        }
-
-        TFactor<T> log0() const {
-            TFactor<T> l0; 
-            l0._vs = _vs; 
-            l0._p = _p.log0(); 
-            return l0; 
-        }
-
-        CFactor clog0() const {
-            CFactor l0; 
-            l0._vs = _vs; 
-            l0._p = _p.clog0(); 
-            return l0; 
-        }
-
-        T normalize( typename Prob::NormType norm ) { return _p.normalize( norm ); }
-        TFactor<T> normalized( typename Prob::NormType norm ) const { 
-            TFactor<T> result;
-            result._vs = _vs;
-            result._p = _p.normalized( norm );
-            return result;
-        }
-
-        // returns slice of this factor where the subset ns is in state ns_state
-        Factor slice( const VarSet & ns, size_t ns_state ) const {
-            assert( ns << _vs );
-            VarSet nsrem = _vs / ns;
-            Factor result( nsrem, 0.0 );
-            
-            // OPTIMIZE ME
-            Index i_ns (ns, _vs);
-            Index i_nsrem (nsrem, _vs);
-            for( size_t i = 0; i < stateSpace(); i++, ++i_ns, ++i_nsrem )
-                if( (size_t)i_ns == ns_state )
-                    result._p[i_nsrem] = _p[i];
-
-            return result;
-        }
-
-        // returns unnormalized marginal
-        TFactor<T> part_sum(const VarSet & ns) const;
-        // returns normalized marginal
-        TFactor<T> marginal(const VarSet & ns) const { return part_sum(ns).normalized( Prob::NORMPROB ); }
-
-        bool hasNaNs() const { return _p.hasNaNs(); }
-        bool hasNegatives() const { return _p.hasNegatives(); }
-        T totalSum() const { return _p.totalSum(); }
-        T maxAbs() const { return _p.maxAbs(); }
-        T max() const { return _p.max(); }
-        Complex entropy() const { return _p.entropy(); }
-        T strength( const Var &i, const Var &j ) const;
-
-        friend Real dist( const TFactor<T> & x, const TFactor<T> & y, Prob::DistType dt ) {
-            if( x._vs.empty() || y._vs.empty() )
-                return -1;
-            else {
-#ifdef DEBUG
-                assert( x._vs == y._vs );
-#endif
-                return dist( x._p, y._p, dt );
-            }
-        }
-        friend Complex KL_dist <> (const TFactor<T> & p, const TFactor<T> & q);
-        template<class U> friend std::ostream& operator<< (std::ostream& os, const TFactor<U>& P);
-};
-
-
-template<typename T> TFactor<T> TFactor<T>::part_sum(const VarSet & ns) const {
-#ifdef DEBUG
-    assert( ns << _vs );
-#endif
-
-    TFactor<T> res( ns, 0.0 );
-
-    Index i_res( ns, _vs );
-    for( size_t i = 0; i < _p.size(); i++, ++i_res )
-        res._p[i_res] += _p[i];
-
-    return res;
-}
-
-
-template<typename T> std::ostream& operator<< (std::ostream& os, const TFactor<T>& P) {
-    os << "(" << P.vars() << " <";
-    for( size_t i = 0; i < P._p.size(); i++ )
-        os << P._p[i] << " ";
-    os << ">)";
-    return os;
-}
-
-
-template<typename T> TFactor<T> TFactor<T>::operator* (const TFactor<T>& Q) const {
-    TFactor<T> prod( _vs | Q._vs, 0.0 );
-
-    Index i1(_vs, prod._vs);
-    Index i2(Q._vs, prod._vs);
-
-    for( size_t i = 0; i < prod._p.size(); i++, ++i1, ++i2 )
-        prod._p[i] += _p[i1] * Q._p[i2];
-
-    return prod;
-}
-
-
-template<typename T> Complex KL_dist(const TFactor<T> & P, const TFactor<T> & Q) {
-    if( P._vs.empty() || Q._vs.empty() )
-        return -1;
-    else {
-#ifdef DEBUG
-        assert( P._vs == Q._vs );
-#endif
-        return KL_dist( P._p, Q._p );
-    }
-}
-
-
-// calculate N(psi, i, j)
-template<typename T> T TFactor<T>::strength( const Var &i, const Var &j ) const {
-#ifdef DEBUG
-    assert( _vs && i );
-    assert( _vs && j );
-    assert( i != j );
-#endif
-    VarSet ij = i | j;
-
-    T max = 0.0;
-    for( size_t alpha1 = 0; alpha1 < i.states(); alpha1++ )
-        for( size_t alpha2 = 0; alpha2 < i.states(); alpha2++ )
-            if( alpha2 != alpha1 )
-                for( size_t beta1 = 0; beta1 < j.states(); beta1++ ) 
-                    for( size_t beta2 = 0; beta2 < j.states(); beta2++ )
-                        if( beta2 != beta1 ) {
-                            size_t as = 1, bs = 1;
-                            if( i < j )
-                                bs = i.states();
-                            else
-                                as = j.states();
-                            T f1 = slice( ij, alpha1 * as + beta1 * bs ).p().divide( slice( ij, alpha2 * as + beta1 * bs ).p() ).max();
-                            T f2 = slice( ij, alpha2 * as + beta2 * bs ).p().divide( slice( ij, alpha1 * as + beta2 * bs ).p() ).max();
-                            T f = f1 * f2;
-                            if( f > max )
-                                max = f;
-                        }
-    
-    return std::tanh( 0.25 * std::log( max ) );
-}
-
-
-template<typename T> TFactor<T> RemoveFirstOrderInteractions( const TFactor<T> & psi ) {
-    TFactor<T> result = psi;
-
-    VarSet vars = psi.vars();
-    for( size_t iter = 0; iter < 100; iter++ ) {
-        for( VarSet::const_iterator n = vars.begin(); n != vars.end(); n++ )
-            result = result * result.part_sum(*n).inverse();
-        result.normalize( Prob::NORMPROB );
-    }
-
-    return result;
-}
-
-
-}
-
-
-#endif
diff --git a/factorgraph.cpp b/factorgraph.cpp
deleted file mode 100644 (file)
index 14fd2fe..0000000
+++ /dev/null
@@ -1,630 +0,0 @@
-/*  Copyright (C) 2006-2008  Joris Mooij  [j dot mooij at science dot ru dot nl]
-    Radboud University Nijmegen, The Netherlands
-    
-    This file is part of libDAI.
-
-    libDAI is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    libDAI is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with libDAI; if not, write to the Free Software
-    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-
-#include <iostream>
-#include <iterator>
-#include <map>
-#include <set>
-#include <fstream>
-#include <string>
-#include <algorithm>
-#include <functional>
-#include <tr1/unordered_map>
-#include "factorgraph.h"
-
-
-namespace dai {
-
-
-using namespace std;
-
-
-FactorGraph::FactorGraph( const vector<Factor> &P ) : BipartiteGraph<Var,Factor>(), _undoProbs(), _normtype(Prob::NORMPROB) {
-    // add factors, obtain variables
-    set<Var> _vars;
-    V2s().reserve( P.size() );
-    size_t nrEdges = 0;
-    for( vector<Factor>::const_iterator p2 = P.begin(); p2 != P.end(); p2++ ) {
-        V2s().push_back( *p2 );
-       copy( p2->vars().begin(), p2->vars().end(), inserter( _vars, _vars.begin() ) );
-       nrEdges += p2->vars().size();
-    }
-
-    // add _vars
-    V1s().reserve( _vars.size() );
-    for( set<Var>::const_iterator p1 = _vars.begin(); p1 != _vars.end(); p1++ )
-        V1s().push_back( *p1 );
-    
-    // create graph structure
-    createGraph( nrEdges );
-}
-
-
-/// Part of constructors (creates edges, neighbours and adjacency matrix)
-void FactorGraph::createGraph( size_t nrEdges ) {
-    // create a mapping for indices
-    std::tr1::unordered_map<size_t, size_t> hashmap;
-    
-    for( size_t i = 0; i < vars().size(); i++ )        
-       hashmap[vars()[i].label()] = i;
-    
-    // create edges
-    edges().reserve( nrEdges );
-    for( size_t i2 = 0; i2 < nrFactors(); i2++ ) {
-        const VarSet& ns = factor(i2).vars();
-        for( VarSet::const_iterator q = ns.begin(); q != ns.end(); q++ )
-            edges().push_back(_edge_t(hashmap[q->label()], i2));               
-    }
-
-    // calc neighbours and adjacency matrix
-    Regenerate();
-}
-
-
-/*FactorGraph& FactorGraph::addFactor( const Factor &I ) {
-    // add Factor
-    _V2.push_back( I );
-
-    // add new vars in Factor
-    for( VarSet::const_iterator i = I.vars().begin(); i != I.vars().end(); i++ ) {
-        size_t i_ind = find(vars().begin(), vars().end(), *i) - vars().begin();
-        if( i_ind == vars().size() )
-            _V1.push_back( *i );
-        _E12.push_back( _edge_t( i_ind, nrFactors() - 1 ) );
-    }
-
-    Regenerate();
-    return(*this);
-}*/
-
-
-ostream& operator << (ostream& os, const FactorGraph& fg) {
-    os << fg.nrFactors() << endl;
-
-    for( size_t I = 0; I < fg.nrFactors(); I++ ) {
-        os << endl;
-        os << fg.factor(I).vars().size() << endl;
-        for( VarSet::const_iterator i = fg.factor(I).vars().begin(); i != fg.factor(I).vars().end(); i++ )
-            os << i->label() << " ";
-        os << endl;
-        for( VarSet::const_iterator i = fg.factor(I).vars().begin(); i != fg.factor(I).vars().end(); i++ )
-            os << i->states() << " ";
-        os << endl;
-        size_t nr_nonzeros = 0;
-        for( size_t k = 0; k < fg.factor(I).stateSpace(); k++ )
-            if( fg.factor(I)[k] != 0.0 )
-                nr_nonzeros++;
-        os << nr_nonzeros << endl;
-        for( size_t k = 0; k < fg.factor(I).stateSpace(); k++ )
-            if( fg.factor(I)[k] != 0.0 ) {
-                char buf[20];
-                sprintf(buf,"%18.14g", fg.factor(I)[k]);
-                os << k << " " << buf << endl;
-            }
-    }
-
-    return(os);
-}
-
-
-istream& operator >> (istream& is, FactorGraph& fg) {
-    long verbose = 0;
-
-    try {
-        vector<Factor> factors;
-        size_t nr_f;
-        string line;
-        
-        while( (is.peek()) == '#' )
-            getline(is,line);
-        is >> nr_f;
-        if( is.fail() )
-            throw "ReadFromFile: unable to read number of Factors";
-        if( verbose >= 2 )
-            cout << "Reading " << nr_f << " factors..." << endl;
-
-        getline (is,line);
-        if( is.fail() )
-            throw "ReadFromFile: empty line expected";
-
-        for( size_t I = 0; I < nr_f; I++ ) {
-            if( verbose >= 3 )
-                cout << "Reading factor " << I << "..." << endl;
-            size_t nr_members;
-            while( (is.peek()) == '#' )
-                getline(is,line);
-            is >> nr_members;
-            if( verbose >= 3 )
-                cout << "  nr_members: " << nr_members << endl;
-
-            vector<long> labels;
-            for( size_t mi = 0; mi < nr_members; mi++ ) {
-                long mi_label;
-                while( (is.peek()) == '#' )
-                    getline(is,line);
-                is >> mi_label;
-                labels.push_back(mi_label);
-            }
-            if( verbose >= 3 ) {
-                cout << "  labels: ";
-                copy (labels.begin(), labels.end(), ostream_iterator<int>(cout, " "));
-                cout << endl;
-            }
-
-            vector<size_t> dims;
-            for( size_t mi = 0; mi < nr_members; mi++ ) {
-                size_t mi_dim;
-                while( (is.peek()) == '#' )
-                    getline(is,line);
-                is >> mi_dim;
-                dims.push_back(mi_dim);
-            }
-            if( verbose >= 3 ) {
-                cout << "  dimensions: ";
-                copy (dims.begin(), dims.end(), ostream_iterator<int>(cout, " "));
-                cout << endl;
-            }
-
-            // add the Factor
-            VarSet I_vars;
-            for( size_t mi = 0; mi < nr_members; mi++ )
-                I_vars.insert( Var(labels[mi], dims[mi]) );
-            factors.push_back(Factor(I_vars,0.0));
-            
-            // calculate permutation sigma (internally, members are sorted)
-            vector<long> sigma(nr_members,0);
-            VarSet::iterator j = I_vars.begin();
-            for( size_t mi = 0; mi < nr_members; mi++,j++ ) {
-                long search_for = j->label();
-                vector<long>::iterator j_loc = find(labels.begin(),labels.end(),search_for);
-                sigma[mi] = j_loc - labels.begin();
-            }
-            if( verbose >= 3 ) {
-                cout << "  sigma: ";
-                copy( sigma.begin(), sigma.end(), ostream_iterator<int>(cout," "));
-                cout << endl;
-            }
-
-            // calculate multindices
-            vector<size_t> sdims(nr_members,0);
-            for( size_t k = 0; k < nr_members; k++ ) {
-                sdims[k] = dims[sigma[k]];
-            }
-            multind mi(dims);
-            multind smi(sdims);
-            if( verbose >= 3 ) {
-                cout << "  mi.max(): " << mi.max() << endl;
-                cout << "       ";
-                for( size_t k=0; k < nr_members; k++ ) 
-                    cout << labels[k] << " ";
-                cout << "   ";
-                for( size_t k=0; k < nr_members; k++ ) 
-                    cout << labels[sigma[k]] << " ";
-                cout << endl;
-            }
-            
-            // read values
-            size_t nr_nonzeros;
-            while( (is.peek()) == '#' )
-                getline(is,line);
-            is >> nr_nonzeros;
-            if( verbose >= 3 ) 
-                cout << "  nonzeroes: " << nr_nonzeros << endl;
-            for( size_t k = 0; k < nr_nonzeros; k++ ) {
-                size_t li;
-                double val;
-                while( (is.peek()) == '#' )
-                    getline(is,line);
-                is >> li;
-                while( (is.peek()) == '#' )
-                    getline(is,line);
-                is >> val;
-
-                vector<size_t> vi = mi.vi(li);
-                vector<size_t> svi(vi.size(),0);
-                for( size_t k = 0; k < vi.size(); k++ )
-                    svi[k] = vi[sigma[k]];
-                size_t sli = smi.li(svi);
-                if( verbose >= 3 ) {
-                    cout << "    " << li << ": ";
-                    copy( vi.begin(), vi.end(), ostream_iterator<size_t>(cout," "));
-                    cout << "-> ";
-                    copy( svi.begin(), svi.end(), ostream_iterator<size_t>(cout," "));
-                    cout << ": " << sli << endl;
-                }
-                factors.back()[sli] = val;
-            }
-        }
-
-        if( verbose >= 3 ) {
-            cout << "factors:" << endl;
-            copy(factors.begin(), factors.end(), ostream_iterator<Factor>(cout,"\n"));
-        }
-
-        fg = FactorGraph(factors);
-    } catch (char *e) {
-        cout << e << endl;
-    }
-
-    return is;
-}
-
-
-VarSet FactorGraph::delta(const Var & n) const {
-    // calculate Markov Blanket
-    size_t i = findVar( n );
-
-    VarSet del;
-    for( _nb_cit I = nb1(i).begin(); I != nb1(i).end(); I++ )
-        for( _nb_cit j = nb2(*I).begin(); j != nb2(*I).end(); j++ )
-            if( *j != i )
-                del |= var(*j);
-
-    return del;
-}
-
-
-VarSet FactorGraph::Delta(const Var & n) const {
-    return( delta(n) | n );
-}
-
-
-void FactorGraph::makeFactorCavity(size_t I) {
-    // fill Factor I with ones
-    factor(I).fill(1.0);
-}
-
-
-void FactorGraph::makeCavity(const Var & n) {
-    // fills all Factors that include Var n with ones
-    size_t i = findVar( n );
-
-    for( _nb_cit I = nb1(i).begin(); I != nb1(i).end(); I++ )
-        factor(*I).fill(1.0);
-}
-
-
-bool FactorGraph::hasNegatives() const {
-    bool result = false;
-    for( size_t I = 0; I < nrFactors() && !result; I++ )
-        if( factor(I).hasNegatives() )
-           result = true;
-    return result;
-}
-
-/*FactorGraph & FactorGraph::DeleteFactor(size_t I) {
-    // Go through all edges
-    for( vector<_edge_t>::iterator edge = _E12.begin(); edge != _E12.end(); edge++ )
-        if( edge->second >= I ) {
-            if( edge->second == I )
-                edge->second = -1UL;
-            else 
-                (edge->second)--;
-        }
-    // Remove all edges containing I
-    for( vector<_edge_t>::iterator edge = _E12.begin(); edge != _E12.end(); edge++ )
-        if( edge->second == -1UL )
-            edge = _E12.erase( edge );
-//  vector<_edge_t>::iterator new_end = _E12.remove_if( _E12.begin(), _E12.end(), compose1( bind2nd(equal_to<size_t>(), -1), select2nd<_edge_t>() ) );
-//  _E12.erase( new_end, _E12.end() );
-
-    // Erase the factor
-    _V2.erase( _V2.begin() + I );
-    
-    Regenerate();
-
-    return *this;
-}
-
-
-FactorGraph & FactorGraph::DeleteVar(size_t i) {
-    // Go through all edges
-    for( vector<_edge_t>::iterator edge = _E12.begin(); edge != _E12.end(); edge++ )
-        if( edge->first >= i ) {
-            if( edge->first == i )
-                edge->first = -1UL;
-            else 
-                (edge->first)--;
-        }
-    // Remove all edges containing i
-    for( vector<_edge_t>::iterator edge = _E12.begin(); edge != _E12.end(); edge++ )
-        if( edge->first == -1UL )
-            edge = _E12.erase( edge );
-                
-//  vector<_edge_t>::iterator new_end = _E12.remove_if( _E12.begin(), _E12.end(), compose1( bind2nd(equal_to<size_t>(), -1), select1st<_edge_t>() ) );
-//  _E12.erase( new_end, _E12.end() );
-
-    // Erase the variable
-    _V1.erase( _V1.begin() + i );
-    
-    Regenerate();
-
-    return *this;
-}*/
-
-
-long FactorGraph::ReadFromFile(const char *filename) {
-    ifstream infile;
-    infile.open (filename);
-    if (infile.is_open()) {
-        infile >> *this;
-        infile.close();
-        return 0;
-    } else {
-        cout << "ERROR OPENING FILE" << endl;
-        return 1;
-    }
-}
-
-
-long FactorGraph::WriteToFile(const char *filename) const {
-    ofstream outfile;
-    outfile.open (filename);
-    if (outfile.is_open()) {
-        try {
-            outfile << *this;
-        } catch (char *e) {
-            cout << e << endl;
-            return 1;
-        }
-        outfile.close();
-        return 0;
-    } else {
-        cout << "ERROR OPENING FILE" << endl;
-        return 1;
-    }
-}
-
-
-long FactorGraph::WriteToDotFile(const char *filename) const {
-    ofstream outfile;
-    outfile.open (filename);
-    if (outfile.is_open()) {
-        try {
-            outfile << "graph G {" << endl;
-            outfile << "graph[size=\"9,9\"];" << endl;
-            outfile << "node[shape=circle,width=0.4,fixedsize=true];" << endl;
-            for( size_t i = 0; i < nrVars(); i++ )
-                outfile << "\tx" << var(i).label() << ";" << endl;
-            outfile << "node[shape=box,style=filled,color=lightgrey,width=0.3,height=0.3,fixedsize=true];" << endl;
-            for( size_t I = 0; I < nrFactors(); I++ )
-                outfile << "\tp" << I << ";" << endl;
-            for( size_t iI = 0; iI < nr_edges(); iI++ )
-                outfile << "\tx" << var(edge(iI).first).label() << " -- p" << edge(iI).second << ";" << endl;
-            outfile << "}" << endl;
-        } catch (char *e) {
-            cout << e << endl;
-            return 1;
-        }
-        outfile.close();
-        return 0;
-    } else {
-        cout << "ERROR OPENING FILE" << endl;
-        return 1;
-    }
-}
-
-
-bool hasShortLoops( const vector<Factor> &P ) {
-    bool found = false;
-    vector<Factor>::const_iterator I, J;
-    for( I = P.begin(); I != P.end(); I++ ) {
-        J = I;
-        J++;
-        for( ; J != P.end(); J++ )
-            if( (I->vars() & J->vars()).size() >= 2 ) {
-                found = true;
-                break;
-            }
-        if( found )
-            break;
-    }
-    return found;
-}
-
-
-void RemoveShortLoops(vector<Factor> &P) {
-    bool found = true;
-    while( found ) {
-        found = false;
-        vector<Factor>::iterator I, J;
-        for( I = P.begin(); I != P.end(); I++ ) {
-            J = I;
-            J++;
-            for( ; J != P.end(); J++ )
-                if( (I->vars() & J->vars()).size() >= 2 ) {
-                    found = true;
-                    break;
-                }
-            if( found )
-                break;
-        }
-        if( found ) {
-            cout << "Merging factors " << I->vars() << " and " << J->vars() << endl;
-            *I *= *J;
-            P.erase(J);
-        }
-    }
-}
-
-
-Factor FactorGraph::ExactMarginal(const VarSet & x) const {
-    Factor P;
-    for( size_t I = 0; I < nrFactors(); I++ )
-        P *= factor(I);
-    return P.marginal(x);
-}
-
-
-Real FactorGraph::ExactlogZ() const {
-    Factor P;
-    for( size_t I = 0; I < nrFactors(); I++ )
-        P *= factor(I);
-    return std::log(P.totalSum());
-}
-
-
-vector<VarSet> FactorGraph::Cliques() const {
-    vector<VarSet> result;
-    
-    for( size_t I = 0; I < nrFactors(); I++ ) {
-        bool maximal = true;
-        for( size_t J = 0; (J < nrFactors()) && maximal; J++ )
-            if( (factor(J).vars() >> factor(I).vars()) && !(factor(J).vars() == factor(I).vars()) )
-                maximal = false;
-        
-        if( maximal )
-            result.push_back( factor(I).vars() );
-    }
-
-    return result;
-}
-
-
-void FactorGraph::clamp( const Var & n, size_t i ) {
-    assert( i <= n.states() );
-
-/*  if( do_surgery ) {
-        size_t ni = find( vars().begin(), vars().end(), n) - vars().begin();
-
-        if( ni != nrVars() ) {
-            for( _nb_cit I = nb1(ni).begin(); I != nb1(ni).end(); I++ ) {
-                if( factor(*I).size() == 1 )
-                    // Remove this single-variable factor
-    //              I = (_V2.erase(I))--;
-                    _E12.erase( _E12.begin() + VV2E(ni, *I) );
-                else {
-                    // Replace it by the slice
-                    Index ind_I_min_n( factor(*I), factor(*I) / n );
-                    Index ind_n( factor(*I), n );
-                    Factor slice_I( factor(*I) / n );
-                    for( size_t ind_I = 0; ind_I < factor(*I).stateSpace(); ++ind_I, ++ind_I_min_n, ++ind_n )
-                        if( ind_n == i )
-                            slice_I[ind_I_min_n] = factor(*I)[ind_I];
-                    factor(*I) = slice_I;
-
-                    // Remove the edge between n and I
-                    _E12.erase( _E12.begin() + VV2E(ni, *I) );
-                }
-            }
-
-            Regenerate();
-            
-            // remove all unconnected factors
-            for( size_t I = 0; I < nrFactors(); I++ )
-                if( nb2(I).size() == 0 )
-                    DeleteFactor(I--);
-
-            DeleteVar( ni );
-
-            // FIXME
-        }
-    } */
-
-    // The cheap solution (at least in terms of coding time) is to multiply every factor
-    // that contains the variable with a delta function
-
-    Factor delta_n_i(n,0.0);
-    delta_n_i[i] = 1.0;
-
-    // For all factors that contain n
-    for( size_t I = 0; I < nrFactors(); I++ ) 
-        if( factor(I).vars() && n )
-            // Multiply it with a delta function
-            factor(I) *= delta_n_i;
-
-    return;
-}
-
-
-void FactorGraph::saveProb( size_t I ) {
-    map<size_t,Prob>::iterator it = _undoProbs.find( I );
-    if( it != _undoProbs.end() )
-        cout << "FactorGraph::saveProb:  WARNING: _undoProbs[I] already defined!" << endl;
-    _undoProbs[I] = factor(I).p();
-}
-
-
-void FactorGraph::undoProb( size_t I ) {
-    map<size_t,Prob>::iterator it = _undoProbs.find( I );
-    if( it != _undoProbs.end() ) {
-        factor(I).p() = (*it).second;
-        _undoProbs.erase(it);
-    }
-}
-
-
-void FactorGraph::saveProbs( const VarSet &ns ) {
-    if( !_undoProbs.empty() )
-        cout << "FactorGraph::saveProbs:  WARNING: _undoProbs not empy!" << endl;
-    for( size_t I = 0; I < nrFactors(); I++ )
-        if( factor(I).vars() && ns )
-            _undoProbs[I] = factor(I).p();
-}
-
-
-void FactorGraph::undoProbs( const VarSet &ns ) {
-    for( map<size_t,Prob>::iterator uI = _undoProbs.begin(); uI != _undoProbs.end(); ) {
-        if( factor((*uI).first).vars() && ns ) {
-//          cout << "undoing " << factor((*uI).first).vars() << endl;
-//          cout << "from " << factor((*uI).first).p() << " to " << (*uI).second << endl;
-            factor((*uI).first).p() = (*uI).second;
-            _undoProbs.erase(uI++);
-        } else
-            uI++;
-    }
-}
-
-
-bool FactorGraph::isConnected() const {
-    if( nrVars() == 0 )
-        return false;
-    else {
-        Var n = var( 0 );
-
-        VarSet component = n;
-
-        VarSet remaining;
-        for( size_t i = 1; i < nrVars(); i++ )
-            remaining |= var(i);
-
-        bool found_new_vars = true;
-        while( found_new_vars ) {
-            VarSet new_vars;
-            for( VarSet::const_iterator m = remaining.begin(); m != remaining.end(); m++ )
-                if( delta(*m) && component )
-                    new_vars |= *m;
-
-            if( new_vars.empty() )
-                found_new_vars = false;
-            else 
-                found_new_vars = true;
-
-            component |= new_vars;
-            remaining /= new_vars;
-        };
-        return remaining.empty();
-    }
-}
-
-
-}
diff --git a/factorgraph.h b/factorgraph.h
deleted file mode 100644 (file)
index 7dada6e..0000000
+++ /dev/null
@@ -1,166 +0,0 @@
-/*  Copyright (C) 2006-2008  Joris Mooij  [j dot mooij at science dot ru dot nl]
-    Radboud University Nijmegen, The Netherlands
-    
-    This file is part of libDAI.
-
-    libDAI is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    libDAI is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with libDAI; if not, write to the Free Software
-    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-
-#ifndef __FACTORGRAPH_H__
-#define __FACTORGRAPH_H__
-
-
-#include <iostream>
-#include <map>
-#include "bipgraph.h"
-#include "factor.h"
-
-#include <tr1/unordered_map>
-
-
-namespace dai {
-
-
-using namespace std;
-
-
-bool hasShortLoops(const vector<Factor> &P);
-void RemoveShortLoops(vector<Factor> &P);
-
-class FactorGraph : public BipartiteGraph<Var,Factor> {
-    protected:
-        map<size_t,Prob>    _undoProbs;
-        Prob::NormType      _normtype;
-
-    public:
-        /// Default constructor
-        FactorGraph() : BipartiteGraph<Var,Factor>(), _undoProbs(), _normtype(Prob::NORMPROB) {};
-        /// Copy constructor
-        FactorGraph(const FactorGraph & x) : BipartiteGraph<Var,Factor>(x), _undoProbs(), _normtype(x._normtype) {};
-        /// Construct FactorGraph from vector of Factors
-        FactorGraph(const vector<Factor> &P);
-        // Construct a FactorGraph from given factor and variable iterators
-        template<typename FactorInputIterator, typename VarInputIterator>
-        FactorGraph(FactorInputIterator fact_begin, FactorInputIterator fact_end, VarInputIterator var_begin, VarInputIterator var_end, size_t nr_fact_hint = 0, size_t nr_var_hint = 0 );
-        
-        /// Assignment operator
-        FactorGraph & operator=(const FactorGraph & x) {
-            if(this!=&x) {
-                BipartiteGraph<Var,Factor>::operator=(x);
-                _undoProbs      = x._undoProbs;
-                _normtype       = x._normtype;
-            }
-            return *this;
-        }
-        virtual ~FactorGraph() {}
-
-        // aliases
-        Var & var(size_t i) { return V1(i); }
-        const Var & var(size_t i) const { return V1(i); }
-        const vector<Var> & vars() const { return V1s(); }
-        vector<Var> & vars() { return V1s(); }
-        size_t nrVars() const { return V1s().size(); }
-        Factor & factor(size_t I) { return V2(I); }
-        const Factor & factor(size_t I) const { return V2(I); }
-        const vector<Factor> & factors() const { return V2s(); }
-        vector<Factor> & factors() { return V2s(); }
-        size_t nrFactors() const { return V2s().size(); }
-
-        /// Provides read access to neighbours of variable
-        const _nb_t & nbV( size_t i1 ) const { return nb1(i1); }
-        /// Provides full access to neighbours of variable
-        _nb_t & nbV( size_t i1 ) { return nb1(i1); }
-        /// Provides read access to neighbours of factor
-        const _nb_t & nbF( size_t i2 ) const { return nb2(i2); }
-        /// Provides full access to neighbours of factor
-        _nb_t & nbF( size_t i2 ) { return nb2(i2); }
-
-        size_t findVar(const Var & n) const {
-            size_t i = find( vars().begin(), vars().end(), n ) - vars().begin();
-            assert( i != nrVars() );
-            return i;
-        }
-        size_t findFactor(const VarSet &ns) const {
-            size_t I;
-            for( I = 0; I < nrFactors(); I++ )
-                if( factor(I).vars() == ns )
-                    break;
-            assert( I != nrFactors() );
-            return I;
-        }
-
-        friend ostream& operator << (ostream& os, const FactorGraph& fg);
-        friend istream& operator >> (istream& is, FactorGraph& fg);
-
-        VarSet delta(const Var & n) const;
-        VarSet Delta(const Var & n) const;
-        virtual void makeFactorCavity(size_t I);
-        virtual void makeCavity(const Var & n);
-
-        long ReadFromFile(const char *filename);
-        long WriteToFile(const char *filename) const;
-        long WriteToDotFile(const char *filename) const;
-
-        Factor ExactMarginal(const VarSet & x) const;
-        Real ExactlogZ() const;
-
-        virtual void clamp( const Var & n, size_t i );
-        
-        bool hasNegatives() const;
-        Prob::NormType NormType() const { return _normtype; }
-        
-        vector<VarSet> Cliques() const;
-
-        virtual void undoProbs( const VarSet &ns );
-        void saveProbs( const VarSet &ns );
-        virtual void undoProb( size_t I );
-        void saveProb( size_t I );
-
-        bool isConnected() const;
-
-        virtual void updatedFactor( size_t I ) {};
-
-    private:
-        /// Part of constructors (creates edges, neighbours and adjacency matrix)
-        void createGraph( size_t nrEdges );
-};
-
-
-// assumes that the set of variables in [var_begin,var_end) is the union of the variables in the factors in [fact_begin, fact_end)
-template<typename FactorInputIterator, typename VarInputIterator>
-FactorGraph::FactorGraph(FactorInputIterator fact_begin, FactorInputIterator fact_end, VarInputIterator var_begin, VarInputIterator var_end, size_t nr_fact_hint, size_t nr_var_hint ) : BipartiteGraph<Var,Factor>(), _undoProbs(), _normtype(Prob::NORMPROB) {
-    // add factors
-    size_t nrEdges = 0;
-    V2s().reserve( nr_fact_hint );
-    for( FactorInputIterator p2 = fact_begin; p2 != fact_end; ++p2 ) {
-        V2s().push_back( *p2 );
-       nrEdges += p2->vars().size();
-    }
-    // add variables
-    V1s().reserve( nr_var_hint );
-    for( VarInputIterator p1 = var_begin; p1 != var_end; ++p1 )
-       V1s().push_back( *p1 );
-
-    // create graph structure
-    createGraph( nrEdges );
-}
-
-
-}
-
-
-#endif
diff --git a/hak.cpp b/hak.cpp
deleted file mode 100644 (file)
index dc57653..0000000
--- a/hak.cpp
+++ /dev/null
@@ -1,410 +0,0 @@
-/*  Copyright (C) 2006-2008  Joris Mooij  [j dot mooij at science dot ru dot nl]
-    Radboud University Nijmegen, The Netherlands
-    
-    This file is part of libDAI.
-
-    libDAI is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    libDAI is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with libDAI; if not, write to the Free Software
-    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-
-#include <map>
-#include "hak.h"
-#include "util.h"
-#include "diffs.h"
-
-
-namespace dai {
-
-
-const char *HAK::Name = "HAK";
-
-
-bool HAK::checkProperties() {
-    if( !HasProperty("tol") )
-        return false;
-    if (!HasProperty("maxiter") )
-        return false;
-    if (!HasProperty("verbose") )
-        return false;
-    if( !HasProperty("doubleloop") )
-        return false;
-    if( !HasProperty("clusters") )
-        return false;
-    
-    ConvertPropertyTo<double>("tol");
-    ConvertPropertyTo<size_t>("maxiter");
-    ConvertPropertyTo<size_t>("verbose");
-    ConvertPropertyTo<bool>("doubleloop");
-    ConvertPropertyTo<ClustersType>("clusters");
-
-    if( HasProperty("loopdepth") )
-        ConvertPropertyTo<size_t>("loopdepth");
-    else if( Clusters() == ClustersType::LOOP )
-        return false;
-
-    return true;
-}
-
-
-void HAK::constructMessages() {
-    // Create outer beliefs
-    _Qa.clear();
-    _Qa.reserve(nr_ORs());
-    for( size_t alpha = 0; alpha < nr_ORs(); alpha++ )
-        _Qa.push_back( Factor( OR(alpha).vars() ) );
-
-    // Create inner beliefs
-    _Qb.clear();
-    _Qb.reserve(nr_IRs());
-    for( size_t beta = 0; beta < nr_IRs(); beta++ )
-        _Qb.push_back( Factor( IR(beta) ) );
-    
-    // Create messages
-    _muab.clear();
-    _muab.reserve(nr_Redges());
-    _muba.clear();
-    _muba.reserve(nr_Redges());
-    for( vector<R_edge_t>::const_iterator ab = Redges().begin(); ab != Redges().end(); ab++ ) {
-        _muab.push_back( Factor( IR(ab->second) ) );
-        _muba.push_back( Factor( IR(ab->second) ) );
-    }
-}
-
-
-HAK::HAK(const RegionGraph & rg, const Properties &opts) : DAIAlgRG(rg, opts) {
-    assert( checkProperties() );
-
-    constructMessages();
-}
-
-
-void HAK::findLoopClusters( const FactorGraph & fg, set<VarSet> &allcl, VarSet newcl, const Var & root, size_t length, VarSet vars ) {
-    for( VarSet::const_iterator in = vars.begin(); in != vars.end(); in++ ) {
-        VarSet ind = fg.delta( *in );
-        if( (newcl.size()) >= 2 && (ind >> root) ) {
-            allcl.insert( newcl | *in );
-        }
-        else if( length > 1 )
-            findLoopClusters( fg, allcl, newcl | *in, root, length - 1, ind / newcl );
-    }
-}
-
-
-HAK::HAK(const FactorGraph & fg, const Properties &opts) : DAIAlgRG(opts) {
-    assert( checkProperties() );
-
-    vector<VarSet> cl;
-    if( Clusters() == ClustersType::MIN ) {
-        cl = fg.Cliques();
-    } else if( Clusters() == ClustersType::DELTA ) {
-        for( size_t i = 0; i < fg.nrVars(); i++ )
-            cl.push_back(fg.Delta(fg.var(i))); 
-    } else if( Clusters() == ClustersType::LOOP ) {
-        cl = fg.Cliques();
-        set<VarSet> scl;
-        for( vector<Var>::const_iterator i0 = fg.vars().begin(); i0 != fg.vars().end(); i0++ ) {
-            VarSet i0d = fg.delta(*i0);
-            if( LoopDepth() > 1 )
-                findLoopClusters( fg, scl, *i0, *i0, LoopDepth() - 1, fg.delta(*i0) );
-        }
-        for( set<VarSet>::const_iterator c = scl.begin(); c != scl.end(); c++ )
-            cl.push_back(*c);
-        if( Verbose() >= 3 ) {
-            cout << "HAK uses the following clusters: " << endl;
-            for( vector<VarSet>::const_iterator cli = cl.begin(); cli != cl.end(); cli++ )
-                cout << *cli << endl;
-        }
-    } else
-        throw "Invalid Clusters type";
-
-    RegionGraph rg(fg,cl);
-    RegionGraph::operator=(rg);
-    constructMessages();
-
-    if( Verbose() >= 3 )
-        cout << "HAK regiongraph: " << *this << endl;
-}
-
-
-string HAK::identify() const { 
-    stringstream result (stringstream::out);
-    result << Name << GetProperties();
-    return result.str();
-}
-
-
-void HAK::init( const VarSet &ns ) {
-    for( vector<Factor>::iterator alpha = _Qa.begin(); alpha != _Qa.end(); alpha++ )
-        if( alpha->vars() && ns )
-            alpha->fill( 1.0 / alpha->stateSpace() );
-
-    for( size_t beta = 0; beta < nr_IRs(); beta++ )
-        if( IR(beta) && ns ) {
-            _Qb[beta].fill( 1.0 / IR(beta).stateSpace() );
-            for( R_nb_cit alpha = nbIR(beta).begin(); alpha != nbIR(beta).end(); alpha++ ) {
-                muab(*alpha,beta).fill( 1.0 / IR(beta).stateSpace() );
-                muba(beta,*alpha).fill( 1.0 / IR(beta).stateSpace() );
-            }
-        }
-}
-
-
-void HAK::init() {
-    assert( checkProperties() );
-
-    for( vector<Factor>::iterator alpha = _Qa.begin(); alpha != _Qa.end(); alpha++ )
-        alpha->fill( 1.0 / alpha->stateSpace() );
-
-    for( vector<Factor>::iterator beta = _Qb.begin(); beta != _Qb.end(); beta++ )
-        beta->fill( 1.0 / beta->stateSpace() );
-
-    for( size_t ab = 0; ab < nr_Redges(); ab++ ) {
-        _muab[ab].fill( 1.0 / _muab[ab].stateSpace() );
-        _muba[ab].fill( 1.0 / _muba[ab].stateSpace() );
-    }
-}
-
-
-double HAK::doGBP() {
-    if( Verbose() >= 1 )
-        cout << "Starting " << identify() << "...";
-    if( Verbose() >= 3)
-        cout << endl;
-
-    clock_t tic = toc();
-
-    // Check whether counting numbers won't lead to problems
-    for( size_t beta = 0; beta < nr_IRs(); beta++ )
-        assert( nbIR(beta).size() + IR(beta).c() != 0.0 );
-
-    // Keep old beliefs to check convergence
-    vector<Factor> old_beliefs;
-    old_beliefs.reserve( nrVars() );
-    for( size_t i = 0; i < nrVars(); i++ )
-        old_beliefs.push_back( belief( var(i) ) );
-
-    // Differences in single node beliefs
-    Diffs diffs(nrVars(), 1.0);
-
-    size_t iter = 0;
-    // do several passes over the network until maximum number of iterations has
-    // been reached or until the maximum belief difference is smaller than tolerance
-    for( iter = 0; iter < MaxIter() && diffs.max() > Tol(); iter++ ) {
-        for( size_t beta = 0; beta < nr_IRs(); beta++ ) {
-            for( R_nb_cit alpha = nbIR(beta).begin(); alpha != nbIR(beta).end(); alpha++ )
-                muab(*alpha,beta) = _Qa[*alpha].marginal(IR(beta)).divided_by( muba(beta,*alpha) );
-
-            Factor Qb_new;
-            for( R_nb_cit alpha = nbIR(beta).begin(); alpha != nbIR(beta).end(); alpha++ )
-                Qb_new *= muab(*alpha,beta) ^ (1 / (nbIR(beta).size() + IR(beta).c()));
-            Qb_new.normalize( _normtype );
-            if( Qb_new.hasNaNs() ) {
-                cout << "HAK::doGBP:  Qb_new has NaNs!" << endl;
-                return NAN;
-            }
-//          _Qb[beta] = Qb_new.makeZero(1e-100);    // damping?
-            _Qb[beta] = Qb_new;
-
-            for( R_nb_cit alpha = nbIR(beta).begin(); alpha != nbIR(beta).end(); alpha++ ) {
-                muba(beta,*alpha) = _Qb[beta].divided_by( muab(*alpha,beta) );
-
-                Factor Qa_new = OR(*alpha);
-                for( R_nb_cit gamma = nbOR(*alpha).begin(); gamma != nbOR(*alpha).end(); gamma++ )
-                    Qa_new *= muba(*gamma,*alpha);
-                Qa_new ^= (1.0 / OR(*alpha).c());
-                Qa_new.normalize( _normtype );
-                if( Qa_new.hasNaNs() ) {
-                    cout << "HAK::doGBP:  Qa_new has NaNs!" << endl;
-                    return NAN;
-                }
-//              _Qa[*alpha] = Qa_new.makeZero(1e-100); // damping?
-                _Qa[*alpha] = Qa_new;
-            }
-        }
-
-        // Calculate new single variable beliefs and compare with old ones
-        for( size_t i = 0; i < nrVars(); i++ ) {
-            Factor new_belief = belief( var( i ) );
-            diffs.push( dist( new_belief, old_beliefs[i], Prob::DISTLINF ) );
-            old_beliefs[i] = new_belief;
-        }
-
-        if( Verbose() >= 3 )
-            cout << "HAK::doGBP:  maxdiff " << diffs.max() << " after " << iter+1 << " passes" << endl;
-    }
-
-    updateMaxDiff( diffs.max() );
-
-    if( Verbose() >= 1 ) {
-        if( diffs.max() > Tol() ) {
-            if( Verbose() == 1 )
-                cout << endl;
-            cout << "HAK::doGBP:  WARNING: not converged within " << MaxIter() << " passes (" << toc() - tic << " clocks)...final maxdiff:" << diffs.max() << endl;
-        } else {
-            if( Verbose() >= 2 )
-                cout << "HAK::doGBP:  ";
-            cout << "converged in " << iter << " passes (" << toc() - tic << " clocks)." << endl;
-        }
-    }
-
-    return diffs.max();
-}
-
-
-double HAK::doDoubleLoop() {
-    if( Verbose() >= 1 )
-        cout << "Starting " << identify() << "...";
-    if( Verbose() >= 3)
-        cout << endl;
-
-    clock_t tic = toc();
-
-    // Save original outer regions
-    vector<FRegion> org_ORs = ORs();
-
-    // Save original inner counting numbers and set negative counting numbers to zero
-    vector<double> org_IR_cs( nr_IRs(), 0.0 );
-    for( size_t beta = 0; beta < nr_IRs(); beta++ ) {
-        org_IR_cs[beta] = IR(beta).c();
-        if( IR(beta).c() < 0.0 )
-            IR(beta).c() = 0.0;
-    }
-
-    // Keep old beliefs to check convergence
-    vector<Factor> old_beliefs;
-    old_beliefs.reserve( nrVars() );
-    for( size_t i = 0; i < nrVars(); i++ )
-        old_beliefs.push_back( belief( var(i) ) );
-
-    // Differences in single node beliefs
-    Diffs diffs(nrVars(), 1.0);
-
-    size_t   outer_maxiter   = MaxIter();
-    double  outer_tol       = Tol();
-    size_t   outer_verbose   = Verbose();
-    double  org_maxdiff     = MaxDiff();
-
-    // Set parameters for inner loop
-    MaxIter( 5 );
-    Verbose( outer_verbose ? outer_verbose - 1 : 0 );
-
-    size_t outer_iter = 0;
-    for( outer_iter = 0; outer_iter < outer_maxiter && diffs.max() > outer_tol; outer_iter++ ) {
-        // Calculate new outer regions
-        for( size_t alpha = 0; alpha < nr_ORs(); alpha++ ) {
-            OR(alpha) = org_ORs[alpha];
-            for( R_nb_cit beta = nbOR(alpha).begin(); beta != nbOR(alpha).end(); beta++ )
-                OR(alpha) *= _Qb[*beta] ^ ((IR(*beta).c() - org_IR_cs[*beta]) / nbIR(*beta).size());
-        }
-
-        // Inner loop
-        if( isnan( doGBP() ) )
-            return NAN;
-
-        // Calculate new single variable beliefs and compare with old ones
-        for( size_t i = 0; i < nrVars(); i++ ) {
-            Factor new_belief = belief( var( i ) );
-            diffs.push( dist( new_belief, old_beliefs[i], Prob::DISTLINF ) );
-            old_beliefs[i] = new_belief;
-        }
-
-        if( Verbose() >= 3 )
-            cout << "HAK::doDoubleLoop:  maxdiff " << diffs.max() << " after " << outer_iter+1 << " passes" << endl;
-    }
-
-    // restore _maxiter, _verbose and _maxdiff
-    MaxIter( outer_maxiter );
-    Verbose( outer_verbose );
-    MaxDiff( org_maxdiff );
-
-    updateMaxDiff( diffs.max() );
-
-    // Restore original outer regions
-    ORs() = org_ORs;
-
-    // Restore original inner counting numbers
-    for( size_t beta = 0; beta < nr_IRs(); beta++ )
-        IR(beta).c() = org_IR_cs[beta];
-
-    if( Verbose() >= 1 ) {
-        if( diffs.max() > Tol() ) {
-            if( Verbose() == 1 )
-                cout << endl;
-                cout << "HAK::doDoubleLoop:  WARNING: not converged within " << outer_maxiter << " passes (" << toc() - tic << " clocks)...final maxdiff:" << diffs.max() << endl;
-            } else {
-                if( Verbose() >= 3 )
-                    cout << "HAK::doDoubleLoop:  ";
-                cout << "converged in " << outer_iter << " passes (" << toc() - tic << " clocks)." << endl;
-            }
-        }
-
-    return diffs.max();
-}
-
-
-double HAK::run() {
-    if( DoubleLoop() )
-        return doDoubleLoop();
-    else
-        return doGBP();
-}
-
-
-Factor HAK::belief( const VarSet &ns ) const {
-    vector<Factor>::const_iterator beta;
-    for( beta = _Qb.begin(); beta != _Qb.end(); beta++ )
-        if( beta->vars() >> ns )
-            break;
-    if( beta != _Qb.end() )
-        return( beta->marginal(ns) );
-    else {
-        vector<Factor>::const_iterator alpha;
-        for( alpha = _Qa.begin(); alpha != _Qa.end(); alpha++ )
-            if( alpha->vars() >> ns )
-                break;
-        assert( alpha != _Qa.end() );
-        return( alpha->marginal(ns) );
-    }
-}
-
-
-Factor HAK::belief( const Var &n ) const {
-    return belief( (VarSet)n );
-}
-
-
-vector<Factor> HAK::beliefs() const {
-    vector<Factor> result;
-    for( size_t beta = 0; beta < nr_IRs(); beta++ )
-        result.push_back( Qb(beta) );
-    for( size_t alpha = 0; alpha < nr_ORs(); alpha++ )
-        result.push_back( Qa(alpha) );
-    return result;
-}
-
-
-Complex HAK::logZ() const {
-    Complex sum = 0.0;
-    for( size_t beta = 0; beta < nr_IRs(); beta++ )
-        sum += Complex(IR(beta).c()) * Qb(beta).entropy();
-    for( size_t alpha = 0; alpha < nr_ORs(); alpha++ ) {
-        sum += Complex(OR(alpha).c()) * Qa(alpha).entropy();
-        sum += (OR(alpha).log0() * Qa(alpha)).totalSum();
-    }
-    return sum;
-}
-
-
-}
diff --git a/hak.h b/hak.h
deleted file mode 100644 (file)
index 62deefa..0000000
--- a/hak.h
+++ /dev/null
@@ -1,109 +0,0 @@
-/*  Copyright (C) 2006-2008  Joris Mooij  [j dot mooij at science dot ru dot nl]
-    Radboud University Nijmegen, The Netherlands
-    
-    This file is part of libDAI.
-
-    libDAI is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    libDAI is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with libDAI; if not, write to the Free Software
-    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-
-#ifndef __HAK_H__
-#define __HAK_H__
-
-
-#include "daialg.h"
-#include "regiongraph.h"
-#include "enum.h"
-
-
-namespace dai {
-
-
-using namespace std;
-
-
-/// HAK provides an implementation of the single and double-loop algorithms by Heskes, Albers and Kappen
-class HAK : public DAIAlgRG {
-    protected:
-        vector<Factor>          _Qa;
-        vector<Factor>          _Qb;
-        vector<Factor>          _muab;
-        vector<Factor>          _muba;
-        
-    public:
-        /// Default constructor
-        HAK() : DAIAlgRG() {};
-
-        /// Copy constructor
-        HAK(const HAK & x) : DAIAlgRG(x), _Qa(x._Qa), _Qb(x._Qb), _muab(x._muab), _muba(x._muba) {};
-
-        /// Clone function
-        HAK* clone() const { return new HAK(*this); }
-        
-        /// Construct from RegionGraph
-        HAK(const RegionGraph & rg, const Properties &opts);
-
-        /// Construct from RactorGraph using "clusters" option
-        HAK(const FactorGraph & fg, const Properties &opts);
-
-        /// Assignment operator
-        HAK & operator=(const HAK & x) {
-            if( this != &x ) {
-                DAIAlgRG::operator=(x);
-                _Qa         = x._Qa;
-                _Qb         = x._Qb;
-                _muab       = x._muab;
-                _muba       = x._muba;
-            }
-            return *this;
-        }
-        
-        static const char *Name;
-
-        ENUM3(ClustersType,MIN,DELTA,LOOP)
-        ClustersType Clusters() const { return GetPropertyAs<ClustersType>("clusters"); }
-        bool DoubleLoop() { return GetPropertyAs<bool>("doubleloop"); }
-        size_t LoopDepth() { return GetPropertyAs<size_t>("loopdepth"); }
-
-        Factor & muab( size_t alpha, size_t beta ) { return _muab[ORIR2E(alpha,beta)]; }
-        Factor & muba( size_t beta, size_t alpha ) { return _muba[ORIR2E(alpha,beta)]; }
-        const Factor& Qa( size_t alpha ) const { return _Qa[alpha]; };
-        const Factor& Qb( size_t beta ) const { return _Qb[beta]; };
-
-//      void Regenerate();
-        double doGBP();
-        double doDoubleLoop();
-        double run();
-        void init();
-        string identify() const;
-        Factor belief( const Var &n ) const;
-        Factor belief( const VarSet &ns ) const;
-        vector<Factor> beliefs() const;
-        Complex logZ () const;
-
-        void init( const VarSet &ns );
-        void undoProbs( const VarSet &ns ) { RegionGraph::undoProbs( ns ); init( ns ); }
-        bool checkProperties();
-
-    private:
-        void constructMessages();
-        void findLoopClusters( const FactorGraph &fg, set<VarSet> &allcl, VarSet newcl, const Var & root, size_t length, VarSet vars );
-};
-
-
-}
-
-
-#endif
diff --git a/include/dai/alldai.h b/include/dai/alldai.h
new file mode 100644 (file)
index 0000000..111a9b6
--- /dev/null
@@ -0,0 +1,53 @@
+/*  Copyright (C) 2006-2008  Joris Mooij  [j dot mooij at science dot ru dot nl]
+    Radboud University Nijmegen, The Netherlands
+    
+    This file is part of libDAI.
+
+    libDAI is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    libDAI is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with libDAI; if not, write to the Free Software
+    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+
+#ifndef __defined_libdai_alldai_h
+#define __defined_libdai_alldai_h
+
+
+#include <string>
+#include <dai/daialg.h>
+#include <dai/bp.h>
+#include <dai/lc.h>
+#include <dai/hak.h>
+#include <dai/mf.h>
+#include <dai/jtree.h>
+#include <dai/treeep.h>
+#include <dai/mr.h>
+
+
+namespace dai {
+
+
+/// newInfAlg constructs a new approximate inference algorithm named name for the
+/// FactorGraph fg with optionts opts and returns a pointer to the new object.
+/// The caller needs to delete it (maybe some sort of smart_ptr might be useful here).
+InfAlg *newInfAlg( const std::string &name, const FactorGraph &fg, const Properties &opts );
+
+
+/// AINames contains the names of all approximate inference algorithms
+static const char* DAINames[] = {BP::Name, MF::Name, HAK::Name, LC::Name, TreeEP::Name, MR::Name, JTree::Name};
+
+
+} // end of namespace dai
+
+
+#endif
diff --git a/include/dai/bipgraph.h b/include/dai/bipgraph.h
new file mode 100644 (file)
index 0000000..d7decba
--- /dev/null
@@ -0,0 +1,163 @@
+/*  Copyright (C) 2006-2008  Joris Mooij  [j dot mooij at science dot ru dot nl]
+    Radboud University Nijmegen, The Netherlands
+    
+    This file is part of libDAI.
+
+    libDAI is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    libDAI is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with libDAI; if not, write to the Free Software
+    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+
+#ifndef __defined_libdai_bipgraph_h
+#define __defined_libdai_bipgraph_h
+
+
+#include <vector>
+#include <algorithm>
+#include <boost/numeric/ublas/vector_sparse.hpp>
+
+
+namespace dai {
+
+
+/// A BipartiteGraph represents a graph with two types of nodes
+template <class T1, class T2> class BipartiteGraph {
+    public:
+        typedef std::pair<size_t,size_t>    _edge_t;
+        typedef std::vector<size_t>         _nb_t;
+        typedef _nb_t::const_iterator       _nb_cit;
+        
+
+    private:
+        /// Vertices of first type
+        std::vector<T1>                     _V1;
+
+        /// Vertices of second type
+        std::vector<T2>                     _V2;
+        
+        /// Edges, which are pairs (v1,v2) with v1 in _V1 and v2 in _V2
+        std::vector<_edge_t>                _E12;
+
+        /// Conversion matrix that computes which index of _E12 corresponds to a vertex index pair (v1,v2)
+        std::vector<boost::numeric::ublas::mapped_vector<size_t> > _E12ind;
+
+        /// Neighbour indices of vertices of first type
+        std::vector<_nb_t>                  _nb1;
+
+        /// Neighbour indices of vertices of second type
+        std::vector<_nb_t>                  _nb2;
+
+
+    public:
+        /// Default constructor
+        BipartiteGraph<T1,T2> () {};
+
+        /// Copy constructor
+        BipartiteGraph<T1,T2> ( const BipartiteGraph<T1,T2> & x ) : _V1(x._V1), _V2(x._V2), _E12(x._E12), _E12ind(x._E12ind), _nb1(x._nb1), _nb2(x._nb2) {};
+
+        /// Assignment operator
+        BipartiteGraph<T1,T2> & operator=(const BipartiteGraph<T1,T2> & x) {
+            if( this != &x ) {
+                _V1 =       x._V1;
+                _V2 =       x._V2;
+                _E12 =      x._E12;
+                _E12ind =   x._E12ind;
+                _nb1 =      x._nb1;
+                _nb2 =      x._nb2;
+            }
+            return *this;
+        }
+        
+        /// Provides read access to node of first type
+        const T1 & V1( size_t i1 ) const { return _V1[i1]; }
+        /// Provides full access to node of first type
+        T1 & V1( size_t i1 ) { return _V1[i1]; }
+        /// Provides read access to all nodes of first type
+        const std::vector<T1> & V1s() const { return _V1; }
+        /// Provides full access to all nodes of first type
+        std::vector<T1> & V1s() { return _V1; }
+
+        /// Provides read access to node of second type
+        const T2 & V2( size_t i2 ) const { return _V2[i2]; }
+        /// Provides full access to node of second type
+        T2 & V2( size_t i2 ) { return _V2[i2]; }
+        /// Provides read access to all nodes of second type
+        const std::vector<T2> & V2s() const { return _V2; }
+        /// Provides full access to all nodes of second type
+        std::vector<T2> & V2s() { return _V2; }
+
+        /// Provides read access to edge
+        const _edge_t & edge(size_t ind) const { return _E12[ind]; }
+        /// Provides full access to edge
+        _edge_t & edge(size_t ind) { return _E12[ind]; }
+        /// Provides read access to all edges
+        const std::vector<_edge_t> & edges() const { return _E12; }
+        /// Provides full access to all edges
+        std::vector<_edge_t> & edges() { return _E12; }
+        /// Returns number of edges
+        size_t nr_edges() const { return _E12.size(); }
+
+        /// Provides read access to neighbours of node of first type
+        const _nb_t & nb1( size_t i1 ) const { return _nb1[i1]; }
+        /// Provides full access to neighbours of node of first type
+        _nb_t & nb1( size_t i1 ) { return _nb1[i1]; }
+
+        /// Provides read access to neighbours of node of second type
+        const _nb_t & nb2( size_t i2 ) const { return _nb2[i2]; }
+        /// Provides full access to neighbours of node of second type
+        _nb_t & nb2( size_t i2 ) { return _nb2[i2]; }
+
+        /// Converts the pair of indices (i1,i2) to the corresponding edge index
+        size_t VV2E( const size_t i1, const size_t i2 ) const { return _E12ind[i1](i2); }
+
+
+        /// Regenerates internal structures (_E12ind, _nb1 and _nb2) based upon _V1, _V2 and _E12
+        void Regenerate() {
+            // Calculate _nb1 and _nb2
+
+            // Start with empty vectors
+            _nb1.clear();
+            _nb1.resize(_V1.size());
+            // Start with empty vectors
+            _nb2.clear();
+            _nb2.resize(_V2.size());
+            // Each edge yields a neighbour pair
+            for( std::vector<_edge_t>::const_iterator e = _E12.begin(); e != _E12.end(); e++ ) {
+                _nb1[e->first].push_back(e->second);
+                _nb2[e->second].push_back(e->first);
+            }
+            // Remove duplicates from _nb1
+            for( size_t i1 = 0; i1 < _V1.size(); i1++ ) {
+                _nb_t::iterator new_end = unique(_nb1[i1].begin(), _nb1[i1].end());
+                _nb1[i1].erase( new_end, _nb1[i1].end() );
+            }
+            // Remove duplicates from _nb2
+            for( size_t i2 = 0; i2 < _V2.size(); i2++ ) {
+                _nb_t::iterator new_end = unique(_nb2[i2].begin(), _nb2[i2].end());
+                _nb2[i2].erase( new_end, _nb2[i2].end() );
+            }
+
+            // Calculate _E12ind
+            _E12ind = std::vector<boost::numeric::ublas::mapped_vector<size_t> >(_V1.size(), boost::numeric::ublas::mapped_vector<size_t>(_V2.size()) );            
+            for( size_t k = 0; k < _E12.size(); k++ )
+                _E12ind[_E12[k].first](_E12[k].second) = k;
+                    
+        }
+};
+
+
+} // end of namespace dai
+
+
+#endif
diff --git a/include/dai/bp.h b/include/dai/bp.h
new file mode 100644 (file)
index 0000000..7b66aef
--- /dev/null
@@ -0,0 +1,97 @@
+/*  Copyright (C) 2006-2008  Joris Mooij  [j dot mooij at science dot ru dot nl]
+    Radboud University Nijmegen, The Netherlands
+    
+    This file is part of libDAI.
+
+    libDAI is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    libDAI is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with libDAI; if not, write to the Free Software
+    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+
+#ifndef __defined_libdai_bp_h
+#define __defined_libdai_bp_h
+
+
+#include <string>
+#include <dai/daialg.h>
+#include <dai/factorgraph.h>
+#include <dai/enum.h>
+
+
+namespace dai {
+
+
+class BP : public DAIAlgFG {
+    protected:
+        typedef std::vector<size_t>  _ind_t;
+
+        std::vector<_ind_t>          _indices;
+        std::vector<Prob>            _messages, _newmessages;
+
+    public:
+        ENUM4(UpdateType,SEQFIX,SEQRND,SEQMAX,PARALL)
+        UpdateType Updates() const { return GetPropertyAs<UpdateType>("updates"); }
+
+        // default constructor
+        BP() : DAIAlgFG() {};
+        // copy constructor
+        BP(const BP & x) : DAIAlgFG(x), _indices(x._indices), _messages(x._messages), _newmessages(x._newmessages) {};
+        BP* clone() const { return new BP(*this); }
+        // construct BP object from FactorGraph
+        BP(const FactorGraph & fg, const Properties &opts) : DAIAlgFG(fg, opts) {
+            assert( checkProperties() );
+            Regenerate();
+        }
+        // assignment operator
+        BP & operator=(const BP & x) {
+            if(this!=&x) {
+                DAIAlgFG::operator=(x);
+                _messages = x._messages;
+                _newmessages = x._newmessages;
+                _indices = x._indices;
+            }
+            return *this;
+        }
+
+        static const char *Name;
+
+        Prob & message(size_t i1, size_t i2) { return( _messages[VV2E(i1,i2)] ); }  
+        const Prob & message(size_t i1, size_t i2) const { return( _messages[VV2E(i1,i2)] ); }  
+        Prob & newMessage(size_t i1, size_t i2) { return( _newmessages[VV2E(i1,i2)] ); }    
+        const Prob & newMessage(size_t i1, size_t i2) const { return( _newmessages[VV2E(i1,i2)] ); }    
+        _ind_t & index(size_t i1, size_t i2) { return( _indices[VV2E(i1,i2)] ); }
+        const _ind_t & index(size_t i1, size_t i2) const { return( _indices[VV2E(i1,i2)] ); }
+
+        std::string identify() const;
+        void Regenerate();
+        void init();
+        void calcNewMessage(size_t iI);
+        double run();
+        Factor belief1 (size_t i) const;
+        Factor belief2 (size_t I) const;
+        Factor belief (const Var &n) const;
+        Factor belief (const VarSet &n) const;
+        std::vector<Factor> beliefs() const;
+        Complex logZ() const;
+
+        void init( const VarSet &ns );
+        void undoProbs( const VarSet &ns ) { FactorGraph::undoProbs(ns); init(ns); }
+        bool checkProperties();
+};
+
+
+} // end of namespace dai
+
+
+#endif
diff --git a/include/dai/clustergraph.h b/include/dai/clustergraph.h
new file mode 100644 (file)
index 0000000..faa7755
--- /dev/null
@@ -0,0 +1,181 @@
+/*  Copyright (C) 2006-2008  Joris Mooij  [j dot mooij at science dot ru dot nl]
+    Radboud University Nijmegen, The Netherlands
+    
+    This file is part of libDAI.
+
+    libDAI is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    libDAI is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with libDAI; if not, write to the Free Software
+    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+
+#ifndef __defined_libdai_clustergraph_h
+#define __defined_libdai_clustergraph_h
+
+
+#include <set>
+#include <vector>
+#include <dai/varset.h>
+
+
+namespace dai {
+
+
+/// A ClusterGraph is a hypergraph with VarSets as nodes.
+/// It is implemented as a set<VarSet> in which the adjacency
+/// relationship is computed realtime. It may be better to
+/// implement it as a bipartitegraph, though. The additional
+/// functionality compared to a simple set<VarSet> is
+/// finding maximal clusters, finding cliques, etc...
+class ClusterGraph : public std::set<VarSet> {
+    public:
+        /// Default constructor
+        ClusterGraph() : std::set<VarSet>() {}
+
+        /// Construct from vector<VarSet>
+        ClusterGraph( const std::vector<VarSet> & cls ) {
+            insert( cls.begin(), cls.end() );
+        }
+        
+        /// Copy constructor
+        ClusterGraph(const ClusterGraph &x) : std::set<VarSet>(x) {}
+
+        /// Assignment operator
+        ClusterGraph& operator=( const ClusterGraph &x ) {
+            if( this != &x ) {
+                std::set<VarSet>::operator=( x );
+            }
+            return *this;
+        }
+
+        /// Returns true if ns is a maximal member of *this under inclusion (VarSet::operator<<)
+        bool isMaximal( const VarSet &ns ) const {
+            if( count( ns ) ) {
+                // ns is a member
+                bool maximal = true;
+                for( const_iterator x = begin(); x != end() && maximal; x++ )
+                    if( (ns << *x) && (ns != *x) )
+                        maximal = false;
+                return maximal;
+            } else
+                return false;
+        }
+
+        /// Erase all VarSets that are not maximal
+        ClusterGraph& eraseNonMaximal() {
+            for( iterator x = begin(); x != end(); )
+                if( !isMaximal(*x) )
+                    erase(x++);
+                else
+                    x++;
+            return *this;
+        }
+
+        /// Return union of all members
+        VarSet vars() const {
+            VarSet result;
+            for( iterator x = begin(); x != end(); x++ )
+                result |= *x;
+            return result;
+        }
+
+        /// Returns true if n1 and n2 are adjacent, i.e.\ by
+        /// definition, are both contained in some cluster in *this
+        bool adj( const Var& n1, const Var& n2 ) {
+            bool result = false;
+            for( iterator x = begin(); (x != end()) && (!result); x++ )
+                if( (*x && n1) && (*x && n2) )
+                    result = true;
+            return result;
+        }
+        
+        /// Returns union of clusters that contain n, minus n
+        VarSet Delta( const Var& n ) const {
+            VarSet result;
+            for( iterator x = begin(); x != end(); x++ )
+                if( (*x && n) )
+                    result |= *x;
+            return result;
+        }
+
+        /// Returns union of clusters that contain n, minus n
+        VarSet delta( const Var& n ) const {
+            return Delta( n ) / n;
+        }
+        
+        /// Erases all members that contain n
+        ClusterGraph& eraseSubsuming( const Var& n ) {
+            for( iterator x = begin(); x != end(); )
+                if( (*x && n) )
+                    erase(x++);
+                else
+                    x++;
+            return *this;
+        }
+        
+        /// Send to output stream
+        friend std::ostream & operator << ( std::ostream & os, const ClusterGraph & cl ) {
+            os << "{";
+            ClusterGraph::const_iterator x = cl.begin();
+            if( x != cl.end() )
+                os << *(x++);
+            for( ; x != cl.end(); x++ )
+                os << ", " << *x;
+            os << "}";
+            return os;
+        }
+
+        /// Convert to vector<VarSet>
+        std::vector<VarSet> toVector() const {
+            std::vector<VarSet> result;
+            result.reserve( size() );
+            for( const_iterator x = begin(); x != end(); x++ )
+                result.push_back( *x );
+            return result;
+        }
+
+        /// Calculate cost of eliminating variable n
+        /// using as a measure "number of added edges in the adjacency graph"
+        /// where the adjacency graph has the variables as its nodes and
+        /// connects nodes i1 and i2 iff i1 and i2 occur in some common factor I
+        size_t eliminationCost( const Var& n ) {
+            VarSet d_n = delta( n );
+            size_t cost = 0;
+
+            // for each unordered pair {i1,i2} adjacent to n
+            for( VarSet::const_iterator i1 = d_n.begin(); i1 != d_n.end(); i1++ ) {
+                VarSet d_i1 = delta( *i1 );
+                for( VarSet::const_iterator i2 = i1; (++i2) != d_n.end(); ) {
+                    // if i1 and i2 are not adjacent, eliminating n would make them adjacent
+                    if( !adj(*i1, *i2) )
+                        cost++;
+                }
+            }
+            return cost;
+        }
+
+        /// Perform Variable Elimination without Probs, i.e. only keeping track of
+        /// the interactions that are created along the way.
+        /// Input:  a set of outer clusters and an elimination sequence
+        /// Output: a set of elimination "cliques"
+        ClusterGraph VarElim( const std::vector<Var> &ElimSeq ) const;
+
+        /// As Taylan does it
+        ClusterGraph VarElim_MinFill() const;
+};
+
+
+} // end of namespace dai
+
+
+#endif
diff --git a/include/dai/daialg.h b/include/dai/daialg.h
new file mode 100644 (file)
index 0000000..46cce56
--- /dev/null
@@ -0,0 +1,290 @@
+/*  Copyright (C) 2006-2008  Joris Mooij  [j dot mooij at science dot ru dot nl]
+    Radboud University Nijmegen, The Netherlands
+    
+    This file is part of libDAI.
+
+    libDAI is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    libDAI is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with libDAI; if not, write to the Free Software
+    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+
+#ifndef __defined_libdai_daialg_h
+#define __defined_libdai_daialg_h
+
+
+#include <string>
+#include <iostream>
+#include <vector>
+#include <dai/factorgraph.h>
+#include <dai/regiongraph.h>
+#include <dai/properties.h>
+
+
+namespace dai {
+
+
+/// The InfAlg class is the common denominator of the various approximate inference algorithms.
+/// A InfAlg object represents a discrete factorized probability distribution over multiple variables 
+/// together with an inference algorithm.
+class InfAlg {
+    private:
+        /// Properties of the algorithm (replaces _tol, _maxiter, _verbose)
+        Properties              _properties;
+
+        /// Maximum difference encountered so far
+        double                  _maxdiff;
+
+
+    public:
+        /// Default constructor
+        InfAlg() : _properties(), _maxdiff(0.0) {}
+        
+        /// Constructor with options
+        InfAlg( const Properties &opts ) : _properties(opts), _maxdiff(0.0) {}
+        
+        /// Copy constructor
+        InfAlg( const InfAlg & x ) : _properties(x._properties), _maxdiff(x._maxdiff) {}
+
+        /// Clone (virtual copy constructor)
+        virtual InfAlg* clone() const = 0;
+
+        /// Assignment operator
+        InfAlg & operator=( const InfAlg & x ) {
+            if( this != &x ) {
+                _properties = x._properties;
+                _maxdiff    = x._maxdiff;
+            }
+            return *this;
+        }
+        
+        /// Virtual desctructor
+        // (this is needed because this class contains virtual functions)
+        virtual ~InfAlg() {}
+        
+        /// Returns true if a property with the given key is present
+        bool HasProperty(const PropertyKey &key) const { return _properties.hasKey(key); }
+
+        /// Gets a property
+        const PropertyValue & GetProperty(const PropertyKey &key) const { return _properties.Get(key); }
+        /// Gets a property, casted as ValueType
+        template<typename ValueType>
+        ValueType GetPropertyAs(const PropertyKey &key) const { return _properties.GetAs<ValueType>(key); }
+
+        /// Sets a property 
+        void SetProperty(const PropertyKey &key, const PropertyValue &val) { _properties[key] = val; }
+
+        /// Converts a property from string to ValueType, if necessary
+        template<typename ValueType>
+        void ConvertPropertyTo(const PropertyKey &key) { _properties.ConvertTo<ValueType>(key); }
+
+        /// Gets all properties
+        const Properties & GetProperties() const { return _properties; }
+
+        /// Sets properties
+        void SetProperties(const Properties &p) { _properties = p; }
+
+        /// Sets tolerance
+        void Tol( double tol ) { SetProperty("tol", tol); }
+        /// Gets tolerance
+        double Tol() const { return GetPropertyAs<double>("tol"); }
+
+        /// Sets maximum number of iterations
+        void MaxIter( size_t maxiter ) { SetProperty("maxiter", maxiter); }
+        /// Gets maximum number of iterations
+        size_t MaxIter() const { return GetPropertyAs<size_t>("maxiter"); }
+
+        /// Sets verbosity
+        void Verbose( size_t verbose ) { SetProperty("verbose", verbose); }
+        /// Gets verbosity
+        size_t Verbose() const { return GetPropertyAs<size_t>("verbose"); }
+
+        /// Sets maximum difference encountered so far
+        void MaxDiff( double maxdiff ) { _maxdiff = maxdiff; }
+        /// Gets maximum difference encountered so far
+        double MaxDiff() const { return _maxdiff; }
+        /// Updates maximum difference encountered so far
+        void updateMaxDiff( double maxdiff ) { if( maxdiff > _maxdiff ) _maxdiff = maxdiff; }
+        /// Sets maximum difference encountered so far to zero
+        void clearMaxDiff() { _maxdiff = 0.0; }
+
+        /// Identifies itself for logging purposes
+        virtual std::string identify() const = 0;
+
+        /// Get single node belief
+        virtual Factor belief( const Var &n ) const = 0;
+
+        /// Get general belief
+        virtual Factor belief( const VarSet &n ) const = 0;
+
+        /// Get all beliefs
+        virtual std::vector<Factor> beliefs() const = 0;
+
+        /// Get log partition sum
+        virtual Complex logZ() const = 0;
+
+        /// Clear messages and beliefs
+        virtual void init() = 0;
+
+        /// The actual approximate inference algorithm
+        virtual double run() = 0;
+
+        /// Save factor I
+        virtual void saveProb( size_t I ) = 0;
+        /// Save Factors involving ns
+        virtual void saveProbs( const VarSet &ns ) = 0;
+
+        /// Restore factor I
+        virtual void undoProb( size_t I ) = 0;
+        /// Restore Factors involving ns
+        virtual void undoProbs( const VarSet &ns ) = 0;
+
+        /// Clamp variable n to value i (i.e. multiply with a Kronecker delta \f$\delta_{x_n, i}\f$)
+        virtual void clamp( const Var & n, size_t i ) = 0;
+
+        /// Return all variables that interact with n
+        virtual VarSet delta( const Var & n ) const = 0;
+
+        /// Set all factors interacting with n to 1
+        virtual void makeCavity( const Var & n ) = 0;
+
+        /// Set factor I to 1
+        virtual void makeFactorCavity( size_t I ) = 0;
+
+        /// Get index of variable n
+        virtual size_t findVar( const Var & n ) const = 0;
+
+        /// Get index of first factor involving ns
+        virtual size_t findFactor( const VarSet &ns ) const = 0;
+
+        /// Get number of variables
+        virtual size_t nrVars() const = 0;
+
+        /// Get number of factors
+        virtual size_t nrFactors() const = 0;
+
+        /// Get const reference to variable i
+        virtual const Var & var(size_t i) const = 0;
+
+        /// Get reference to variable i
+        virtual Var & var(size_t i) = 0;
+
+        /// Get const reference to factor I
+        virtual const Factor & factor( size_t I ) const = 0;
+
+        /// Get reference to factor I
+        virtual Factor & factor( size_t I ) = 0;
+
+        /// Factor I has been updated
+        virtual void updatedFactor( size_t I ) = 0;
+
+        /// Checks whether all necessary properties have been set
+        /// and casts string-valued properties to other values if necessary
+        virtual bool checkProperties() = 0;
+};
+
+
+template <class T>
+class DAIAlg : public InfAlg, public T {
+    public:
+        /// Default constructor
+        DAIAlg() : InfAlg(), T() {}
+        
+        /// Construct DAIAlg with empty T but using the specified properties
+        DAIAlg( const Properties &opts ) : InfAlg( opts ), T() {}
+
+        /// Construct DAIAlg using the specified properties
+        DAIAlg( const T & t, const Properties &opts ) : InfAlg( opts ), T(t) {}
+        
+        /// Copy constructor
+        DAIAlg( const DAIAlg & x ) : InfAlg(x), T(x) {}
+
+        /// Save factor I (using T::saveProb)
+        void saveProb( size_t I ) { T::saveProb( I ); }
+        /// Save Factors involving ns (using T::saveProbs)
+        void saveProbs( const VarSet &ns ) { T::saveProbs( ns ); }
+
+        /// Restore factor I (using T::undoProb)
+        void undoProb( size_t I ) { T::undoProb( I ); }
+        /// Restore Factors involving ns (using T::undoProbs)
+        void undoProbs( const VarSet &ns ) { T::undoProbs( ns ); }
+
+        /// Clamp variable n to value i (i.e. multiply with a Kronecker delta \f$\delta_{x_n, i}\f$) (using T::clamp)
+        void clamp( const Var & n, size_t i ) { T::clamp( n, i ); }
+
+        /// Return all variables that interact with n (using T::delta)
+        VarSet delta( const Var & n ) const { return T::delta(n); }
+
+        /// Set all factors interacting with n to 1 (using T::makeCavity)
+        void makeCavity( const Var & n ) { T::makeCavity(n); }
+
+        /// Set factor I to 1 (using T::makeFactorCavity)
+        void makeFactorCavity( size_t I ) { T::makeFactorCavity(I); }
+
+        /// Get index of variable n (using T::findVar)
+        size_t findVar( const Var & n ) const { return T::findVar(n); }
+
+        /// Get index of first factor involving ns (using T::findFactor)
+        size_t findFactor( const VarSet &ns ) const { return T::findFactor(ns); }
+
+        /// Get number of variables (using T::nrFactors)
+        size_t nrVars() const { return T::nrVars(); }
+
+        /// Get number of factors (using T::nrFactors)
+        size_t nrFactors() const { return T::nrFactors(); }
+
+        /// Get const reference to variable i (using T::var)
+        const Var & var( size_t i ) const { return T::var(i); }
+
+        /// Get reference to variable i (using T::var)
+        Var & var(size_t i) { return T::var(i); }
+
+        /// Get const reference to factor I (using T::factor)
+        const Factor & factor( size_t I ) const { return T::factor(I); }
+
+        /// Get reference to factor I (using T::factor)
+        Factor & factor( size_t I ) { return T::factor(I); }
+
+        /// Factor I has been updated (using T::updatedFactor)
+        void updatedFactor( size_t I ) { T::updatedFactor(I); }
+};
+
+
+typedef DAIAlg<FactorGraph> DAIAlgFG;
+typedef DAIAlg<RegionGraph> DAIAlgRG;
+
+
+/// Calculate the marginal of obj on ns by clamping 
+/// all variables in ns and calculating logZ for each joined state
+Factor calcMarginal( const InfAlg & obj, const VarSet & ns, bool reInit );
+
+
+/// Calculate beliefs of all pairs in ns (by clamping
+/// nodes in ns and calculating logZ and the beliefs for each state)
+std::vector<Factor> calcPairBeliefs( const InfAlg & obj, const VarSet& ns, bool reInit );
+
+
+/// Calculate beliefs of all pairs in ns (by clamping
+/// pairs in ns and calculating logZ for each joined state)
+std::vector<Factor> calcPairBeliefsNew( const InfAlg & obj, const VarSet& ns, bool reInit );
+
+
+/// Calculate 2nd order interactions of the marginal of obj on ns
+Factor calcMarginal2ndO( const InfAlg & obj, const VarSet& ns, bool reInit );
+
+
+} // end of namespace dai
+
+
+#endif
diff --git a/include/dai/diffs.h b/include/dai/diffs.h
new file mode 100644 (file)
index 0000000..bf0657a
--- /dev/null
@@ -0,0 +1,75 @@
+/*  Copyright (C) 2006-2008  Joris Mooij  [j dot mooij at science dot ru dot nl]
+    Radboud University Nijmegen, The Netherlands
+    
+    This file is part of libDAI.
+
+    libDAI is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    libDAI is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with libDAI; if not, write to the Free Software
+    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+
+#ifndef __defined_libdai_diffs_h
+#define __defined_libdai_diffs_h
+
+
+#include <vector>
+
+
+namespace dai {
+
+
+class Diffs : public std::vector<double> {
+    private:
+        size_t _maxsize;
+        double _def;
+        std::vector<double>::iterator _pos;
+        std::vector<double>::iterator _maxpos;
+    public:
+        Diffs(long maxsize, double def) : std::vector<double>(), _maxsize(maxsize), _def(def) { 
+            this->reserve(_maxsize); 
+            _pos = begin(); 
+            _maxpos = begin(); 
+        };
+        double max() { 
+            if( size() < _maxsize )
+                return _def;
+            else
+                return( *_maxpos ); 
+        }
+        void push(double x) {
+            if( size() < _maxsize ) {
+                push_back(x);
+                _pos = end();
+                _maxpos = max_element(begin(),end());
+            }
+            else {
+                if( _pos == end() )
+                    _pos = begin();
+                if( _maxpos == _pos ) {
+                    *_pos++ = x; 
+                    _maxpos = max_element(begin(),end());
+                } else {
+                    if( x > *_maxpos )
+                        _maxpos = _pos;
+                    *_pos++ = x;
+                }
+            }
+        }
+};
+
+
+} // end of namespace dai
+
+
+#endif
diff --git a/include/dai/enum.h b/include/dai/enum.h
new file mode 100644 (file)
index 0000000..f2618f7
--- /dev/null
@@ -0,0 +1,272 @@
+/*  Copyright (C) 2006-2008  Joris Mooij  [j dot mooij at science dot ru dot nl]
+    Radboud University Nijmegen, The Netherlands
+    
+    This file is part of libDAI.
+
+    libDAI is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    libDAI is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with libDAI; if not, write to the Free Software
+    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+
+#ifndef __defined_libdai_enum_h
+#define __defined_libdai_enum_h
+
+
+#include <cstring>
+#include <iostream>
+
+
+namespace dai {
+
+
+// C++ enums are too limited for my purposes. This defines wrapper classes
+// that provide much more functionality than a simple enum. The only
+// disadvantage is that one wrapper class needs to be written for each
+// number of values an enum can take... a better solution is needed.
+
+
+#define ENUM2(x,a,b) class x {\
+    public:\
+        enum value {a, b};\
+\
+        x() : v(a) {}\
+\
+        x(value w) : v(w) {}\
+\
+        x(char const *w) {\
+           static char const* labels[] = {#a, #b};\
+           size_t i = 0;\
+           for( ; i < sizeof(labels) / sizeof(char const *); i++ )\
+               if( strcmp( w, labels[i] ) == 0 ) {\
+                   v = (value)i;\
+                   break;\
+               }\
+           if( i == sizeof(labels) / sizeof(char const *) )\
+               throw "Unknown " #x " value";\
+        }\
+\
+        operator value () const { return v; }\
+\
+        operator size_t () const { return (size_t)v; }\
+\
+        operator char const* () const {\
+           static char const* labels[] = {#a, #b};\
+           return labels[v];\
+        }\
+\
+        friend std::istream& operator >> (std::istream& is, x& y) {\
+            std::string s;\
+            is >> s;\
+            y = x(s.c_str());\
+            return is;\
+        }\
+\
+        friend std::ostream& operator << (std::ostream& os, const x& y) {\
+            os << (const char *)y;\
+            return os;\
+        }\
+\
+    private:\
+        value v;\
+};
+
+
+#define ENUM3(x,a,b,c) class x {\
+    public:\
+        enum value {a, b, c};\
+\
+        x() : v(a) {}\
+\
+        x(value w) : v(w) {}\
+\
+        x(char const *w) {\
+           static char const* labels[] = {#a, #b, #c};\
+           size_t i = 0;\
+           for( ; i < sizeof(labels) / sizeof(char const *); i++ )\
+               if( strcmp( w, labels[i] ) == 0 ) {\
+                   v = (value)i;\
+                   break;\
+               }\
+           if( i == sizeof(labels) / sizeof(char const *) )\
+               throw "Unknown " #x " value";\
+        }\
+\
+        operator value () const { return v; }\
+\
+        operator size_t () const { return (size_t)v; }\
+\
+        operator char const* () const {\
+           static char const* labels[] = {#a, #b, #c};\
+           return labels[v];\
+        }\
+\
+        friend std::istream& operator >> (std::istream& is, x& y) {\
+            std::string s;\
+            is >> s;\
+            y = x(s.c_str());\
+            return is;\
+        }\
+\
+        friend std::ostream& operator << (std::ostream& os, const x& y) {\
+            os << (const char *)y;\
+            return os;\
+        }\
+\
+    private:\
+        value v;\
+};
+
+
+#define ENUM4(x,a,b,c,d) class x {\
+    public:\
+        enum value {a, b, c, d};\
+\
+        x() : v(a) {}\
+\
+        x(value w) : v(w) {}\
+\
+        x(char const *w) {\
+           static char const* labels[] = {#a, #b, #c, #d};\
+           size_t i = 0;\
+           for( ; i < sizeof(labels) / sizeof(char const *); i++ )\
+               if( strcmp( w, labels[i] ) == 0 ) {\
+                   v = (value)i;\
+                   break;\
+               }\
+           if( i == sizeof(labels) / sizeof(char const *) )\
+               throw "Unknown " #x " value";\
+        }\
+\
+        operator value () const { return v; }\
+\
+        operator size_t () const { return (size_t)v; }\
+\
+        operator char const* () const {\
+           static char const* labels[] = {#a, #b, #c, #d};\
+           return labels[v];\
+        }\
+\
+        friend std::istream& operator >> (std::istream& is, x& y) {\
+            std::string s;\
+            is >> s;\
+            y = x(s.c_str());\
+            return is;\
+        }\
+\
+        friend std::ostream& operator << (std::ostream& os, const x& y) {\
+            os << (const char *)y;\
+            return os;\
+        }\
+\
+    private:\
+        value v;\
+};
+
+
+#define ENUM5(x,a,b,c,d,e) class x {\
+    public:\
+        enum value {a, b, c, d, e};\
+\
+        x() : v(a) {}\
+\
+        x(value w) : v(w) {}\
+\
+        x(char const *w) {\
+           static char const* labels[] = {#a, #b, #c, #d, #e};\
+           size_t i = 0;\
+           for( ; i < sizeof(labels) / sizeof(char const *); i++ )\
+               if( strcmp( w, labels[i] ) == 0 ) {\
+                   v = (value)i;\
+                   break;\
+               }\
+           if( i == sizeof(labels) / sizeof(char const *) )\
+               throw "Unknown " #x " value";\
+        }\
+\
+        operator value () const { return v; }\
+\
+        operator size_t () const { return (size_t)v; }\
+\
+        operator char const* () const {\
+           static char const* labels[] = {#a, #b, #c, #d, #e};\
+           return labels[v];\
+        }\
+\
+        friend std::istream& operator >> (std::istream& is, x& y) {\
+            std::string s;\
+            is >> s;\
+            y = x(s.c_str());\
+            return is;\
+        }\
+\
+        friend std::ostream& operator << (std::ostream& os, const x& y) {\
+            os << (const char *)y;\
+            return os;\
+        }\
+\
+    private:\
+        value v;\
+};
+
+
+#define ENUM6(x,a,b,c,d,e,f) class x {\
+    public:\
+        enum value {a, b, c, d, e, f};\
+\
+        x() : v(a) {}\
+\
+        x(value w) : v(w) {}\
+\
+        x(char const *w) {\
+           static char const* labels[] = {#a, #b, #c, #d, #e, #f};\
+           size_t i = 0;\
+           for( ; i < sizeof(labels) / sizeof(char const *); i++ )\
+               if( strcmp( w, labels[i] ) == 0 ) {\
+                   v = (value)i;\
+                   break;\
+               }\
+           if( i == sizeof(labels) / sizeof(char const *) )\
+               throw "Unknown " #x " value";\
+        }\
+\
+        operator value () const { return v; }\
+\
+        operator size_t () const { return (size_t)v; }\
+\
+        operator char const* () const {\
+           static char const* labels[] = {#a, #b, #c, #d, #e, #f};\
+           return labels[v];\
+        }\
+\
+        friend std::istream& operator >> (std::istream& is, x& y) {\
+            std::string s;\
+            is >> s;\
+            y = x(s.c_str());\
+            return is;\
+        }\
+\
+        friend std::ostream& operator << (std::ostream& os, const x& y) {\
+            os << (const char *)y;\
+            return os;\
+        }\
+\
+    private:\
+        value v;\
+};
+
+
+} // end of namespace dai
+
+
+#endif
diff --git a/include/dai/factor.h b/include/dai/factor.h
new file mode 100644 (file)
index 0000000..5978943
--- /dev/null
@@ -0,0 +1,365 @@
+/*  Copyright (C) 2006-2008  Joris Mooij  [j dot mooij at science dot ru dot nl]
+    Radboud University Nijmegen, The Netherlands
+    
+    This file is part of libDAI.
+
+    libDAI is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    libDAI is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with libDAI; if not, write to the Free Software
+    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+
+#ifndef __defined_libdai_factor_h
+#define __defined_libdai_factor_h
+
+
+#include <iostream>
+#include <cmath>
+#include <dai/prob.h>
+#include <dai/varset.h>
+#include <dai/index.h>
+
+
+namespace dai {
+
+
+template<typename T> class      TFactor;
+typedef TFactor<Real>           Factor;
+typedef TFactor<Complex>        CFactor;
+
+
+// predefine friends
+template<typename T> Real           dist( const TFactor<T> & x, const TFactor<T> & y, Prob::DistType dt );
+template<typename T> Complex        KL_dist( const TFactor<T> & p, const TFactor<T> & q );
+template<typename T> std::ostream&  operator<< (std::ostream& os, const TFactor<T>& P);
+
+        
+// T should be castable from and to double and to complex
+template <typename T> class TFactor {
+    protected:
+        VarSet      _vs;
+        TProb<T>    _p;
+
+    public:
+        // Default constructor
+        TFactor () : _vs(), _p(1,1.0) {}
+        
+        // Construct Factor from VarSet
+        TFactor( const VarSet& ns ) : _vs(ns), _p(_vs.stateSpace()) {}
+        
+        // Construct Factor from VarSet and initial value
+        TFactor( const VarSet& ns, Real p ) : _vs(ns), _p(_vs.stateSpace(),p) {}
+        
+        // Construct Factor from VarSet and initial array
+        TFactor( const VarSet& ns, const Real* p ) : _vs(ns), _p(_vs.stateSpace(),p) {}
+
+        // Construct Factor from VarSet and TProb<T>
+        TFactor( const VarSet& ns, const TProb<T> p ) : _vs(ns), _p(p) {
+#ifdef DEBUG
+            assert( _vs.stateSpace() == _p.size() );
+#endif
+        }
+        
+        // Construct Factor from Var
+        TFactor( const Var& n ) : _vs(n), _p(n.states()) {}
+
+        // Copy constructor
+        TFactor( const TFactor<T> &x ) : _vs(x._vs), _p(x._p) {}
+        
+        // Assignment operator
+        TFactor<T> & operator= (const TFactor<T> &x) {
+            if( this != &x ) {
+                _vs = x._vs;
+                _p  = x._p;
+            }
+            return *this;
+        }
+
+        const TProb<T> & p() const { return _p; }
+        TProb<T> & p() { return _p; }
+        const VarSet & vars() const { return _vs; }
+        size_t stateSpace() const { 
+#ifdef DEBUG
+            assert( _vs.stateSpace() == _p.size() );
+#endif
+            return _p.size();
+        }
+
+        T operator[] (size_t i) const { return _p[i]; }
+        T& operator[] (size_t i) { return _p[i]; }
+        TFactor<T> & fill (T p)
+            { _p.fill( p ); return(*this); }
+        TFactor<T> & randomize ()
+            { _p.randomize(); return(*this); }
+        TFactor<T> operator* (T x) const {
+            Factor result = *this;
+            result.p() *= x;
+            return result;
+        }
+        TFactor<T>& operator*= (T x) {
+            _p *= x;
+            return *this;
+        }
+        TFactor<T> operator/ (T x) const {
+            Factor result = *this;
+            result.p() /= x;
+            return result;
+        }
+        TFactor<T>& operator/= (T x) {
+            _p /= x;
+            return *this;
+        }
+        TFactor<T> operator* (const TFactor<T>& Q) const;
+        TFactor<T>& operator*= (const TFactor<T>& Q) { return( *this = (*this * Q) ); }
+        TFactor<T> operator+ (const TFactor<T>& Q) const {
+#ifdef DEBUG
+            assert( Q._vs == _vs );
+#endif
+            TFactor<T> sum(*this); 
+            sum._p += Q._p; 
+            return sum; 
+        }
+        TFactor<T> operator- (const TFactor<T>& Q) const {
+#ifdef DEBUG
+            assert( Q._vs == _vs );
+#endif
+            TFactor<T> sum(*this); 
+            sum._p -= Q._p; 
+            return sum; 
+        }
+        TFactor<T>& operator+= (const TFactor<T>& Q) { 
+#ifdef DEBUG
+            assert( Q._vs == _vs );
+#endif
+            _p += Q._p;
+            return *this;
+        }
+        TFactor<T>& operator-= (const TFactor<T>& Q) { 
+#ifdef DEBUG
+            assert( Q._vs == _vs );
+#endif
+            _p -= Q._p;
+            return *this;
+        }
+
+        TFactor<T> operator^ (Real a) const { TFactor<T> x; x._vs = _vs; x._p = _p^a; return x; }
+        TFactor<T>& operator^= (Real a) { _p ^= a; return *this; }
+
+        TFactor<T>& makeZero( Real epsilon ) {
+            _p.makeZero( epsilon );
+            return *this;
+        }
+            
+        TFactor<T> inverse() const { 
+            TFactor<T> inv; 
+            inv._vs = _vs; 
+            inv._p = _p.inverse(true);  // FIXME
+            return inv; 
+        }
+
+        TFactor<T> divided_by( const TFactor<T>& denom ) const { 
+#ifdef DEBUG
+            assert( denom._vs == _vs );
+#endif
+            TFactor<T> quot(*this); 
+            quot._p /= denom._p; 
+            return quot; 
+        }
+
+        TFactor<T>& divide( const TFactor<T>& denom ) {
+#ifdef DEBUG
+            assert( denom._vs == _vs );
+#endif
+            _p /= denom._p;
+            return *this;
+        }
+
+        TFactor<T> exp() const { 
+            TFactor<T> e; 
+            e._vs = _vs; 
+            e._p = _p.exp(); 
+            return e; 
+        }
+
+        TFactor<T> log() const {
+            TFactor<T> l; 
+            l._vs = _vs; 
+            l._p = _p.log(); 
+            return l; 
+        }
+
+        TFactor<T> log0() const {
+            TFactor<T> l0; 
+            l0._vs = _vs; 
+            l0._p = _p.log0(); 
+            return l0; 
+        }
+
+        CFactor clog0() const {
+            CFactor l0; 
+            l0._vs = _vs; 
+            l0._p = _p.clog0(); 
+            return l0; 
+        }
+
+        T normalize( typename Prob::NormType norm ) { return _p.normalize( norm ); }
+        TFactor<T> normalized( typename Prob::NormType norm ) const { 
+            TFactor<T> result;
+            result._vs = _vs;
+            result._p = _p.normalized( norm );
+            return result;
+        }
+
+        // returns slice of this factor where the subset ns is in state ns_state
+        Factor slice( const VarSet & ns, size_t ns_state ) const {
+            assert( ns << _vs );
+            VarSet nsrem = _vs / ns;
+            Factor result( nsrem, 0.0 );
+            
+            // OPTIMIZE ME
+            Index i_ns (ns, _vs);
+            Index i_nsrem (nsrem, _vs);
+            for( size_t i = 0; i < stateSpace(); i++, ++i_ns, ++i_nsrem )
+                if( (size_t)i_ns == ns_state )
+                    result._p[i_nsrem] = _p[i];
+
+            return result;
+        }
+
+        // returns unnormalized marginal
+        TFactor<T> part_sum(const VarSet & ns) const;
+        // returns normalized marginal
+        TFactor<T> marginal(const VarSet & ns) const { return part_sum(ns).normalized( Prob::NORMPROB ); }
+
+        bool hasNaNs() const { return _p.hasNaNs(); }
+        bool hasNegatives() const { return _p.hasNegatives(); }
+        T totalSum() const { return _p.totalSum(); }
+        T maxAbs() const { return _p.maxAbs(); }
+        T max() const { return _p.max(); }
+        Complex entropy() const { return _p.entropy(); }
+        T strength( const Var &i, const Var &j ) const;
+
+        friend Real dist( const TFactor<T> & x, const TFactor<T> & y, Prob::DistType dt ) {
+            if( x._vs.empty() || y._vs.empty() )
+                return -1;
+            else {
+#ifdef DEBUG
+                assert( x._vs == y._vs );
+#endif
+                return dist( x._p, y._p, dt );
+            }
+        }
+        friend Complex KL_dist <> (const TFactor<T> & p, const TFactor<T> & q);
+        template<class U> friend std::ostream& operator<< (std::ostream& os, const TFactor<U>& P);
+};
+
+
+template<typename T> TFactor<T> TFactor<T>::part_sum(const VarSet & ns) const {
+#ifdef DEBUG
+    assert( ns << _vs );
+#endif
+
+    TFactor<T> res( ns, 0.0 );
+
+    Index i_res( ns, _vs );
+    for( size_t i = 0; i < _p.size(); i++, ++i_res )
+        res._p[i_res] += _p[i];
+
+    return res;
+}
+
+
+template<typename T> std::ostream& operator<< (std::ostream& os, const TFactor<T>& P) {
+    os << "(" << P.vars() << " <";
+    for( size_t i = 0; i < P._p.size(); i++ )
+        os << P._p[i] << " ";
+    os << ">)";
+    return os;
+}
+
+
+template<typename T> TFactor<T> TFactor<T>::operator* (const TFactor<T>& Q) const {
+    TFactor<T> prod( _vs | Q._vs, 0.0 );
+
+    Index i1(_vs, prod._vs);
+    Index i2(Q._vs, prod._vs);
+
+    for( size_t i = 0; i < prod._p.size(); i++, ++i1, ++i2 )
+        prod._p[i] += _p[i1] * Q._p[i2];
+
+    return prod;
+}
+
+
+template<typename T> Complex KL_dist(const TFactor<T> & P, const TFactor<T> & Q) {
+    if( P._vs.empty() || Q._vs.empty() )
+        return -1;
+    else {
+#ifdef DEBUG
+        assert( P._vs == Q._vs );
+#endif
+        return KL_dist( P._p, Q._p );
+    }
+}
+
+
+// calculate N(psi, i, j)
+template<typename T> T TFactor<T>::strength( const Var &i, const Var &j ) const {
+#ifdef DEBUG
+    assert( _vs && i );
+    assert( _vs && j );
+    assert( i != j );
+#endif
+    VarSet ij = i | j;
+
+    T max = 0.0;
+    for( size_t alpha1 = 0; alpha1 < i.states(); alpha1++ )
+        for( size_t alpha2 = 0; alpha2 < i.states(); alpha2++ )
+            if( alpha2 != alpha1 )
+                for( size_t beta1 = 0; beta1 < j.states(); beta1++ ) 
+                    for( size_t beta2 = 0; beta2 < j.states(); beta2++ )
+                        if( beta2 != beta1 ) {
+                            size_t as = 1, bs = 1;
+                            if( i < j )
+                                bs = i.states();
+                            else
+                                as = j.states();
+                            T f1 = slice( ij, alpha1 * as + beta1 * bs ).p().divide( slice( ij, alpha2 * as + beta1 * bs ).p() ).max();
+                            T f2 = slice( ij, alpha2 * as + beta2 * bs ).p().divide( slice( ij, alpha1 * as + beta2 * bs ).p() ).max();
+                            T f = f1 * f2;
+                            if( f > max )
+                                max = f;
+                        }
+    
+    return std::tanh( 0.25 * std::log( max ) );
+}
+
+
+template<typename T> TFactor<T> RemoveFirstOrderInteractions( const TFactor<T> & psi ) {
+    TFactor<T> result = psi;
+
+    VarSet vars = psi.vars();
+    for( size_t iter = 0; iter < 100; iter++ ) {
+        for( VarSet::const_iterator n = vars.begin(); n != vars.end(); n++ )
+            result = result * result.part_sum(*n).inverse();
+        result.normalize( Prob::NORMPROB );
+    }
+
+    return result;
+}
+
+
+} // end of namespace dai
+
+
+#endif
diff --git a/include/dai/factorgraph.h b/include/dai/factorgraph.h
new file mode 100644 (file)
index 0000000..f68ea46
--- /dev/null
@@ -0,0 +1,163 @@
+/*  Copyright (C) 2006-2008  Joris Mooij  [j dot mooij at science dot ru dot nl]
+    Radboud University Nijmegen, The Netherlands
+    
+    This file is part of libDAI.
+
+    libDAI is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    libDAI is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with libDAI; if not, write to the Free Software
+    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+
+#ifndef __defined_libdai_factorgraph_h
+#define __defined_libdai_factorgraph_h
+
+
+#include <iostream>
+#include <map>
+#include <tr1/unordered_map>
+#include <dai/bipgraph.h>
+#include <dai/factor.h>
+
+
+namespace dai {
+
+
+bool hasShortLoops( const std::vector<Factor> &P );
+void RemoveShortLoops( std::vector<Factor> &P );
+
+
+class FactorGraph : public BipartiteGraph<Var,Factor> {
+    protected:
+        std::map<size_t,Prob>    _undoProbs;
+        Prob::NormType           _normtype;
+
+    public:
+        /// Default constructor
+        FactorGraph() : BipartiteGraph<Var,Factor>(), _undoProbs(), _normtype(Prob::NORMPROB) {};
+        /// Copy constructor
+        FactorGraph(const FactorGraph & x) : BipartiteGraph<Var,Factor>(x), _undoProbs(), _normtype(x._normtype) {};
+        /// Construct FactorGraph from vector of Factors
+        FactorGraph(const std::vector<Factor> &P);
+        // Construct a FactorGraph from given factor and variable iterators
+        template<typename FactorInputIterator, typename VarInputIterator>
+        FactorGraph(FactorInputIterator fact_begin, FactorInputIterator fact_end, VarInputIterator var_begin, VarInputIterator var_end, size_t nr_fact_hint = 0, size_t nr_var_hint = 0 );
+        
+        /// Assignment operator
+        FactorGraph & operator=(const FactorGraph & x) {
+            if(this!=&x) {
+                BipartiteGraph<Var,Factor>::operator=(x);
+                _undoProbs      = x._undoProbs;
+                _normtype       = x._normtype;
+            }
+            return *this;
+        }
+        virtual ~FactorGraph() {}
+
+        // aliases
+        Var & var(size_t i) { return V1(i); }
+        const Var & var(size_t i) const { return V1(i); }
+        const std::vector<Var> & vars() const { return V1s(); }
+        std::vector<Var> & vars() { return V1s(); }
+        size_t nrVars() const { return V1s().size(); }
+        Factor & factor(size_t I) { return V2(I); }
+        const Factor & factor(size_t I) const { return V2(I); }
+        const std::vector<Factor> & factors() const { return V2s(); }
+        std::vector<Factor> & factors() { return V2s(); }
+        size_t nrFactors() const { return V2s().size(); }
+
+        /// Provides read access to neighbours of variable
+        const _nb_t & nbV( size_t i1 ) const { return nb1(i1); }
+        /// Provides full access to neighbours of variable
+        _nb_t & nbV( size_t i1 ) { return nb1(i1); }
+        /// Provides read access to neighbours of factor
+        const _nb_t & nbF( size_t i2 ) const { return nb2(i2); }
+        /// Provides full access to neighbours of factor
+        _nb_t & nbF( size_t i2 ) { return nb2(i2); }
+
+        size_t findVar(const Var & n) const {
+            size_t i = find( vars().begin(), vars().end(), n ) - vars().begin();
+            assert( i != nrVars() );
+            return i;
+        }
+        size_t findFactor(const VarSet &ns) const {
+            size_t I;
+            for( I = 0; I < nrFactors(); I++ )
+                if( factor(I).vars() == ns )
+                    break;
+            assert( I != nrFactors() );
+            return I;
+        }
+
+        friend std::ostream& operator << (std::ostream& os, const FactorGraph& fg);
+        friend std::istream& operator >> (std::istream& is, FactorGraph& fg);
+
+        VarSet delta(const Var & n) const;
+        VarSet Delta(const Var & n) const;
+        virtual void makeFactorCavity(size_t I);
+        virtual void makeCavity(const Var & n);
+
+        long ReadFromFile(const char *filename);
+        long WriteToFile(const char *filename) const;
+        long WriteToDotFile(const char *filename) const;
+
+        Factor ExactMarginal(const VarSet & x) const;
+        Real ExactlogZ() const;
+
+        virtual void clamp( const Var & n, size_t i );
+        
+        bool hasNegatives() const;
+        Prob::NormType NormType() const { return _normtype; }
+        
+        std::vector<VarSet> Cliques() const;
+
+        virtual void undoProbs( const VarSet &ns );
+        void saveProbs( const VarSet &ns );
+        virtual void undoProb( size_t I );
+        void saveProb( size_t I );
+
+        bool isConnected() const;
+
+        virtual void updatedFactor( size_t /*I*/ ) {};
+
+    private:
+        /// Part of constructors (creates edges, neighbours and adjacency matrix)
+        void createGraph( size_t nrEdges );
+};
+
+
+// assumes that the set of variables in [var_begin,var_end) is the union of the variables in the factors in [fact_begin, fact_end)
+template<typename FactorInputIterator, typename VarInputIterator>
+FactorGraph::FactorGraph(FactorInputIterator fact_begin, FactorInputIterator fact_end, VarInputIterator var_begin, VarInputIterator var_end, size_t nr_fact_hint, size_t nr_var_hint ) : BipartiteGraph<Var,Factor>(), _undoProbs(), _normtype(Prob::NORMPROB) {
+    // add factors
+    size_t nrEdges = 0;
+    V2s().reserve( nr_fact_hint );
+    for( FactorInputIterator p2 = fact_begin; p2 != fact_end; ++p2 ) {
+        V2s().push_back( *p2 );
+       nrEdges += p2->vars().size();
+    }
+    // add variables
+    V1s().reserve( nr_var_hint );
+    for( VarInputIterator p1 = var_begin; p1 != var_end; ++p1 )
+       V1s().push_back( *p1 );
+
+    // create graph structure
+    createGraph( nrEdges );
+}
+
+
+} // end of namespace dai
+
+
+#endif
diff --git a/include/dai/hak.h b/include/dai/hak.h
new file mode 100644 (file)
index 0000000..fac40ba
--- /dev/null
@@ -0,0 +1,107 @@
+/*  Copyright (C) 2006-2008  Joris Mooij  [j dot mooij at science dot ru dot nl]
+    Radboud University Nijmegen, The Netherlands
+    
+    This file is part of libDAI.
+
+    libDAI is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    libDAI is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with libDAI; if not, write to the Free Software
+    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+
+#ifndef __defined_libdai_hak_h
+#define __defined_libdai_hak_h
+
+
+#include <string>
+#include <dai/daialg.h>
+#include <dai/regiongraph.h>
+#include <dai/enum.h>
+
+
+namespace dai {
+
+
+/// HAK provides an implementation of the single and double-loop algorithms by Heskes, Albers and Kappen
+class HAK : public DAIAlgRG {
+    protected:
+        std::vector<Factor>          _Qa;
+        std::vector<Factor>          _Qb;
+        std::vector<Factor>          _muab;
+        std::vector<Factor>          _muba;
+        
+    public:
+        /// Default constructor
+        HAK() : DAIAlgRG() {};
+
+        /// Copy constructor
+        HAK(const HAK & x) : DAIAlgRG(x), _Qa(x._Qa), _Qb(x._Qb), _muab(x._muab), _muba(x._muba) {};
+
+        /// Clone function
+        HAK* clone() const { return new HAK(*this); }
+        
+        /// Construct from RegionGraph
+        HAK(const RegionGraph & rg, const Properties &opts);
+
+        /// Construct from RactorGraph using "clusters" option
+        HAK(const FactorGraph & fg, const Properties &opts);
+
+        /// Assignment operator
+        HAK & operator=(const HAK & x) {
+            if( this != &x ) {
+                DAIAlgRG::operator=(x);
+                _Qa         = x._Qa;
+                _Qb         = x._Qb;
+                _muab       = x._muab;
+                _muba       = x._muba;
+            }
+            return *this;
+        }
+        
+        static const char *Name;
+
+        ENUM3(ClustersType,MIN,DELTA,LOOP)
+        ClustersType Clusters() const { return GetPropertyAs<ClustersType>("clusters"); }
+        bool DoubleLoop() { return GetPropertyAs<bool>("doubleloop"); }
+        size_t LoopDepth() { return GetPropertyAs<size_t>("loopdepth"); }
+
+        Factor & muab( size_t alpha, size_t beta ) { return _muab[ORIR2E(alpha,beta)]; }
+        Factor & muba( size_t beta, size_t alpha ) { return _muba[ORIR2E(alpha,beta)]; }
+        const Factor& Qa( size_t alpha ) const { return _Qa[alpha]; };
+        const Factor& Qb( size_t beta ) const { return _Qb[beta]; };
+
+//      void Regenerate();
+        double doGBP();
+        double doDoubleLoop();
+        double run();
+        void init();
+        std::string identify() const;
+        Factor belief( const Var &n ) const;
+        Factor belief( const VarSet &ns ) const;
+        std::vector<Factor> beliefs() const;
+        Complex logZ () const;
+
+        void init( const VarSet &ns );
+        void undoProbs( const VarSet &ns ) { RegionGraph::undoProbs( ns ); init( ns ); }
+        bool checkProperties();
+
+    private:
+        void constructMessages();
+        void findLoopClusters( const FactorGraph &fg, std::set<VarSet> &allcl, VarSet newcl, const Var & root, size_t length, VarSet vars );
+};
+
+
+} // end of namespace dai
+
+
+#endif
diff --git a/include/dai/index.h b/include/dai/index.h
new file mode 100644 (file)
index 0000000..7399c5c
--- /dev/null
@@ -0,0 +1,159 @@
+/*  Copyright (C) 2006-2008  Joris Mooij  [j dot mooij at science dot ru dot nl]
+    Radboud University Nijmegen, The Netherlands
+    
+    This file is part of libDAI.
+
+    libDAI is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    libDAI is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with libDAI; if not, write to the Free Software
+    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+
+#ifndef __defined_libdai_index_h
+#define __defined_libdai_index_h
+
+
+#include <vector>
+#include <dai/varset.h>
+
+
+namespace dai {
+
+
+/* Example:
+ *
+ * Index i ({s_j_1,s_j_2,...,s_j_m}, {s_1,...,s_N});    // j_k in {1,...,N}
+ * for( ; i>=0; ++i ) {
+ *      // loops over all states of (s_1,...,s_N)
+ *      // i is linear index of corresponding state of (s_j_1, ..., s_j_m)
+ * }
+ */
+
+
+class Index
+{
+private:
+    long _index;
+    std::vector<int> _count,_max,_sum;
+public:
+    Index () { _index=-1; };
+    Index (const VarSet& P, const VarSet& ns)
+    {
+        long sum=1;
+        VarSet::const_iterator j=ns.begin();
+        for(VarSet::const_iterator i=P.begin();i!=P.end();++i)
+        {
+            for(;j!=ns.end()&&j->label()<=i->label();++j)
+            {
+                _count.push_back(0);
+                _max.push_back(j->states());
+                _sum.push_back((i->label()==j->label())?sum:0);
+            };
+            sum*=i->states();
+        };
+        for(;j!=ns.end();++j)
+        {
+            _count.push_back(0);
+            _max.push_back(j->states());
+            _sum.push_back(0);
+        };
+        _index=0;
+    };
+    Index (const Index & ind) : _index(ind._index), _count(ind._count), _max(ind._max), _sum(ind._sum) {};
+    Index & operator=(const Index & ind) {
+        if(this!=&ind) {
+            _index = ind._index;
+            _count = ind._count;
+            _max = ind._max;
+            _sum = ind._sum;
+        }
+        return *this;
+    }
+    Index& clear ()
+    {
+        for(unsigned i=0;i!=_count.size();++i) _count[i]=0;
+        _index=0;
+        return(*this);
+    };
+    operator long () const { return(_index); };
+    Index& operator ++ ()
+    {
+        if(_index>=0)
+        {
+            unsigned i;
+            for(i=0;(i<_count.size())
+                    &&(_index+=_sum[i],++_count[i]==_max[i]);++i)
+            {
+                _index-=_sum[i]*_max[i];
+                _count[i]=0;
+            };
+            if(i==_count.size()) _index=-1;
+        };
+        return(*this);
+    };
+};
+
+
+class multind {
+    private:
+        std::vector<size_t> _dims;  // dimensions
+        std::vector<size_t> _pdims; // products of dimensions
+
+    public:
+        multind(const std::vector<size_t> di) {
+            _dims = di;
+            size_t prod = 1;
+            for( std::vector<size_t>::const_iterator i=di.begin(); i!=di.end(); i++ ) {
+                _pdims.push_back(prod);
+                prod = prod * (*i);
+            }
+            _pdims.push_back(prod);
+        }
+        multind(const VarSet& ns) {
+            _dims.reserve( ns.size() ); 
+            _pdims.reserve( ns.size() + 1 ); 
+            size_t prod = 1;
+            for( VarSet::const_iterator n = ns.begin(); n != ns.end(); n++ ) {
+                _pdims.push_back( prod );
+                prod *= n->states();
+                _dims.push_back( n->states() );
+            }
+            _pdims.push_back( prod );
+        }
+        std::vector<size_t> vi(size_t li) const {   // linear index to vector index
+            std::vector<size_t> v(_dims.size(),0);
+            assert(li < _pdims.back());
+            for( long j = v.size()-1; j >= 0; j-- ) {
+                size_t q = li / _pdims[j];
+                v[j] = q;
+                li = li - q * _pdims[j];
+            }
+            return v;
+        }
+        size_t li(const std::vector<size_t> vi) const { // linear index
+            size_t s = 0;
+            assert(vi.size() == _dims.size());
+            for( size_t j = 0; j < vi.size(); j++ ) 
+                s += vi[j] * _pdims[j];
+            return s;
+        }
+        size_t max() const { return( _pdims.back() ); };
+
+        // FIXME add an iterator, which increases a vector index just using addition
+};
+
+
+} // end of namespace dai
+
+
+#endif
diff --git a/include/dai/jtree.h b/include/dai/jtree.h
new file mode 100644 (file)
index 0000000..48b8b47
--- /dev/null
@@ -0,0 +1,99 @@
+/*  Copyright (C) 2006-2008  Joris Mooij  [j dot mooij at science dot ru dot nl]
+    Radboud University Nijmegen, The Netherlands
+    
+    This file is part of libDAI.
+
+    libDAI is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    libDAI is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with libDAI; if not, write to the Free Software
+    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+
+#ifndef __defined_libdai_jtree_h
+#define __defined_libdai_jtree_h
+
+
+#include <vector>
+#include <string>
+#include <dai/daialg.h>
+#include <dai/varset.h>
+#include <dai/regiongraph.h>
+#include <dai/factorgraph.h>
+#include <dai/clustergraph.h>
+#include <dai/weightedgraph.h>
+#include <dai/enum.h>
+
+
+namespace dai {
+
+
+class JTree : public DAIAlgRG {
+    protected:
+        DEdgeVec             _RTree;     // rooted tree
+        std::vector<Factor>  _Qa;
+        std::vector<Factor>  _Qb;
+        std::vector<Factor>  _mes;
+        double               _logZ;
+
+
+    public:
+        ENUM2(UpdateType,HUGIN,SHSH)
+        UpdateType Updates() const { return GetPropertyAs<UpdateType>("updates"); }
+
+        JTree() : DAIAlgRG(), _RTree(), _Qa(), _Qb(), _mes(), _logZ() {};
+        JTree( const JTree& x ) : DAIAlgRG(x), _RTree(x._RTree), _Qa(x._Qa), _Qb(x._Qb), _mes(x._mes), _logZ(x._logZ) {};
+        JTree* clone() const { return new JTree(*this); }
+        JTree & operator=( const JTree& x ) {
+            if( this != &x ) {
+                DAIAlgRG::operator=(x);
+                _RTree  = x._RTree;
+                _Qa     = x._Qa;
+                _Qb     = x._Qb;
+                _mes    = x._mes;
+                _logZ   = x._logZ;
+            }
+            return *this;
+        }
+        JTree( const FactorGraph &fg, const Properties &opts, bool automatic=true );
+        void GenerateJT( const std::vector<VarSet> &Cliques );
+
+        Factor & message(size_t i1, size_t i2) { return( _mes[ORIR2E(i1,i2)] ); }   
+        const Factor & message(size_t i1, size_t i2) const { return( _mes[ORIR2E(i1,i2)] ); }   
+
+        static const char *Name;
+        std::string identify() const;
+//      void Regenerate();
+        void init() {
+            assert( checkProperties() );
+        }
+        void runHUGIN();
+        void runShaferShenoy();
+        double run();
+        Factor belief( const Var &n ) const;
+        Factor belief( const VarSet &ns ) const;
+        std::vector<Factor> beliefs() const;
+        Complex logZ() const;
+
+        void init( const VarSet &/*ns*/ ) {}
+        void undoProbs( const VarSet &ns ) { RegionGraph::undoProbs( ns ); init( ns ); }
+
+        size_t findEfficientTree( const VarSet& ns, DEdgeVec &Tree, size_t PreviousRoot=(size_t)-1 ) const;
+        Factor calcMarginal( const VarSet& ns );
+        bool checkProperties();
+};
+
+
+} // end of namespace dai
+
+
+#endif
diff --git a/include/dai/lc.h b/include/dai/lc.h
new file mode 100644 (file)
index 0000000..b7d5fee
--- /dev/null
@@ -0,0 +1,111 @@
+/*  Copyright (C) 2006-2008  Joris Mooij  [j dot mooij at science dot ru dot nl]
+    Radboud University Nijmegen, The Netherlands
+
+    This file is part of libDAI.
+
+    libDAI is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    libDAI is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with libDAI; if not, write to the Free Software
+    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+
+#ifndef __defined_libdai_lc_h
+#define __defined_libdai_lc_h
+
+
+#include <string>
+#include <dai/daialg.h>
+#include <dai/enum.h>
+#include <dai/factorgraph.h>
+
+
+namespace dai {
+
+
+class LC : public DAIAlgFG {
+    protected:
+        typedef struct { size_t i; size_t I; } _iI_type;
+
+        std::vector<Factor>      _pancakes;      // used by all LC types (psi_I is stored in the pancake)
+        std::vector<Factor>      _cavitydists;   // used by all LC types to store the approximate cavity distribution
+        /// _phis[VV2E(i,I)] corresponds to \f$ \phi^{\setminus i}_I(x_{I \setminus i}) \f$
+        std::vector<Factor>      _phis;
+
+        /// Single variable beliefs
+        std::vector<Factor>      _beliefs;
+
+        /// For each pair (i,j) with j in delta(i), store i and the common factor I
+        std::vector<_iI_type>    _iI;
+
+    public:
+        ENUM6(CavityType,FULL,PAIR,PAIR2,PAIRINT,PAIRCUM,UNIFORM)
+        ENUM3(UpdateType,SEQFIX,SEQRND,NONE)
+
+        CavityType Cavity() const { return GetPropertyAs<CavityType>("cavity"); }
+        UpdateType Updates() const { return GetPropertyAs<UpdateType>("updates"); }
+        bool reInit() const { return GetPropertyAs<bool>("reinit"); }
+        
+        /// Default constructor
+        LC() : DAIAlgFG() {};
+        /// Copy constructor
+        LC(const LC & x) : DAIAlgFG(x), _pancakes(x._pancakes), _cavitydists(x._cavitydists), _phis(x._phis), _beliefs(x._beliefs), _iI(x._iI) {};
+        /// Clone function
+        LC* clone() const { return new LC(*this); }
+        /// Construct LC object from a FactorGraph and parameters
+        LC(const FactorGraph & fg, const Properties &opts);
+        /// Assignment operator
+        LC& operator=(const LC & x) {
+            if( this != &x ) {
+                DAIAlgFG::operator=(x);
+                _pancakes       = x._pancakes;
+                _cavitydists    = x._cavitydists;
+                _phis           = x._phis;
+                _beliefs        = x._beliefs;
+                _iI             = x._iI;
+            }
+            return *this;
+        }
+
+        static const char *Name;
+        double CalcCavityDist( size_t i, const std::string &name, const Properties &opts );
+        double InitCavityDists( const std::string &name, const Properties &opts );
+        long SetCavityDists( std::vector<Factor> &Q );
+
+        void init();
+        Factor NewPancake (size_t iI, bool & hasNaNs);
+        double run();
+
+        std::string identify() const;
+        Factor belief (const Var &n) const { return( _beliefs[findVar(n)] ); }
+        Factor belief (const VarSet &/*ns*/) const { assert( 0 == 1 ); }
+        std::vector<Factor> beliefs() const { return _beliefs; }
+        Complex logZ() const { return NAN; }
+        void CalcBelief (size_t i);
+        const Factor & belief (size_t i) const { return _beliefs[i]; };
+        const Factor & pancake (size_t i) const { return _pancakes[i]; };
+        const Factor & cavitydist (size_t i) const { return _cavitydists[i]; };
+        size_t nr_iI() const { return _iI.size(); };
+
+        void clamp( const Var &/*n*/, size_t /*i*/ ) { assert( 0 == 1 ); }
+        void undoProbs( const VarSet &/*ns*/ ) { assert( 0 == 1 ); }
+        void saveProbs( const VarSet &/*ns*/ ) { assert( 0 == 1 ); }
+        void makeFactorCavity(size_t /*I*/) { assert( 0 == 1 ); }
+        virtual void makeCavity(const Var & /*n*/) { assert( 0 == 1 ); }
+        bool checkProperties();
+};
+
+
+} // end of namespace dai
+
+
+#endif
diff --git a/include/dai/mf.h b/include/dai/mf.h
new file mode 100644 (file)
index 0000000..d44cf0e
--- /dev/null
@@ -0,0 +1,78 @@
+/*  Copyright (C) 2006-2008  Joris Mooij  [j dot mooij at science dot ru dot nl]
+    Radboud University Nijmegen, The Netherlands
+    
+    This file is part of libDAI.
+
+    libDAI is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    libDAI is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with libDAI; if not, write to the Free Software
+    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+
+#ifndef __defined_libdai_mf_h
+#define __defined_libdai_mf_h
+
+
+#include <string>
+#include <dai/daialg.h>
+#include <dai/factorgraph.h>
+
+
+namespace dai {
+
+
+class MF : public DAIAlgFG {
+    protected:
+        std::vector<Factor>  _beliefs;
+        
+    public:
+        // default constructor
+        MF() : DAIAlgFG(), _beliefs() {};
+        // copy constructor
+        MF(const MF & x) : DAIAlgFG(x), _beliefs(x._beliefs) {};
+        MF* clone() const { return new MF(*this); }
+        // construct MF object from FactorGraph
+        MF(const FactorGraph & fg, const Properties &opts) : DAIAlgFG(fg, opts) {
+            assert( checkProperties() );
+            Regenerate();
+        }
+        // assignment operator
+        MF & operator=(const MF & x) {
+            if(this!=&x) {
+                DAIAlgFG::operator=(x);
+                _beliefs = x._beliefs;
+            }
+            return *this;
+        }
+
+        static const char *Name;
+        std::string identify() const;
+        void Regenerate();
+        void init();
+        double run();
+        Factor belief1 (size_t i) const;
+        Factor belief (const Var &n) const;
+        Factor belief (const VarSet &ns) const;
+        std::vector<Factor> beliefs() const;
+        Complex logZ() const;
+
+        void init( const VarSet &ns );
+        void undoProbs( const VarSet &ns ) { FactorGraph::undoProbs(ns); init(ns); }
+        bool checkProperties();
+};
+
+
+} // end of namespace dai
+
+
+#endif
diff --git a/include/dai/mr.h b/include/dai/mr.h
new file mode 100644 (file)
index 0000000..707d4f6
--- /dev/null
@@ -0,0 +1,217 @@
+/*  Copyright (C) 2006-2008  Joris Mooij  [j dot mooij at science dot ru dot nl]
+    Radboud University Nijmegen, The Netherlands
+    
+    This file is part of libDAI.
+
+    libDAI is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    libDAI is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with libDAI; if not, write to the Free Software
+    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+
+#ifndef __defined_libdai_mr_h
+#define __defined_libdai_mr_h
+
+
+#include <vector>
+#include <string>
+#include <dai/factorgraph.h>
+#include <dai/daialg.h>
+#include <dai/enum.h>
+
+
+namespace dai {
+
+
+class sub_nb;
+
+
+class MR : public DAIAlgFG {
+    private:
+        bool supported;                                            // is the underlying factor graph supported?
+
+        std::vector<size_t>                             con;       // con[i] = connectivity of spin i
+        std::vector<std::vector<size_t> >               nb;        // nb[i] are the neighbours of spin i
+        std::vector<std::vector<double> >               tJ;        // tJ[i][_j] is the tanh of the interaction between spin i and its neighbour nb[i][_j]
+        std::vector<double>                             theta;     // theta[i] is the local field on spin i
+        std::vector<std::vector<double> >               M;         // M[i][_j] is M^{(i)}_j
+        std::vector<std::vector<size_t> >               kindex;    // the _j'th neighbour of spin i has spin i as its kindex[i][_j]'th neighbour
+        std::vector<std::vector<std::vector<double> > > cors;
+    
+        static const size_t kmax = 31;
+        
+        size_t N;
+
+        std::vector<double> Mag;
+
+    public:
+        ENUM2(UpdateType,FULL,LINEAR)
+        ENUM3(InitType,RESPPROP,CLAMPING,EXACT)
+
+        UpdateType Updates() const { return GetPropertyAs<UpdateType>("updates"); }
+        InitType Inits() const { return GetPropertyAs<InitType>("inits"); }
+
+        MR( const FactorGraph & fg, const Properties &opts );
+        void init(size_t _N, double *_w, double *_th);
+        void makekindex();
+        void read_files();
+        void init_cor();
+        double init_cor_resp();
+        void solvemcav();
+        void solveM();
+        double run();
+        Factor belief( const Var &n ) const;
+        Factor belief( const VarSet &/*ns*/ ) const { assert( 0 == 1 ); }
+        std::vector<Factor> beliefs() const;
+        Complex logZ() const { return NAN; }
+        void init() { assert( checkProperties() ); }
+        static const char *Name;
+        std::string identify() const;
+        double _tJ(size_t i, sub_nb A);
+
+        double Omega(size_t i, size_t _j, size_t _l);
+        double T(size_t i, sub_nb A);
+        double T(size_t i, size_t _j);
+        double Gamma(size_t i, size_t _j, size_t _l1, size_t _l2);
+        double Gamma(size_t i, size_t _l1, size_t _l2);
+
+        double appM(size_t i, sub_nb A);
+        void sum_subs(size_t j, sub_nb A, double *sum_even, double *sum_odd);
+
+        double sign(double a) { return (a >= 0) ? 1.0 : -1.0; }
+        MR* clone() const { assert( 0 == 1 ); }
+
+        bool checkProperties();
+
+}; 
+
+
+// represents a subset of nb[i] as a binary number
+// the elements of a subset should be thought of as indices in nb[i]
+class sub_nb {
+    private:
+        size_t s;
+        size_t bits;
+    
+    public:
+        // construct full subset containing nr_elmt elements
+        sub_nb(size_t nr_elmt) {
+#ifdef DEBUG
+            assert( nr_elmt < sizeof(size_t) / sizeof(char) * 8 );
+#endif
+            bits = nr_elmt;
+            s = (1U << bits) - 1;
+        }
+
+        // copy constructor
+        sub_nb( const sub_nb & x ) : s(x.s), bits(x.bits) {}
+
+        // assignment operator 
+        sub_nb & operator=( const sub_nb &x ) {
+            if( this != &x ) {
+                s = x.s;
+                bits = x.bits;
+            }
+            return *this;
+        }
+
+        // returns number of elements
+        size_t size() {
+            size_t size = 0;
+            for(size_t bit = 0; bit < bits; bit++)
+                if( s & (1U << bit) )
+                    size++;
+            return size;
+        }
+
+        // increases s by one (for enumeration in lexicographical order)
+        sub_nb operator++() { 
+            s++; 
+            if( s >= (1U << bits) )
+                s = 0;
+            return *this; 
+        }
+        
+        // return i'th element of this subset
+        size_t operator[](size_t i) { 
+            size_t bit;
+            for(bit = 0; bit < bits; bit++ )
+                if( s & (1U << bit) ) {
+                    if( i == 0 )
+                        break;
+                    else
+                        i--;
+                }
+#ifdef DEBUG
+            assert( bit < bits );
+#endif
+            return bit;
+        }
+
+        // add index _j to this subset
+        sub_nb &operator +=(size_t _j) {
+            s |= (1U << _j); 
+            return *this;
+        }
+
+        // return copy with index _j
+        sub_nb operator+(size_t _j) {
+            sub_nb x = *this;
+            x += _j;
+            return x;
+        }
+
+        // delete index _j from this subset
+        sub_nb &operator -=(size_t _j) {
+            s &= ~(1U << _j); 
+            return *this;
+        }
+
+        // return copy without index _j
+        sub_nb operator-(size_t _j) {
+            sub_nb x = *this;
+            x -= _j;
+            return x;
+        }
+
+        // empty this subset
+        sub_nb & clear() {
+            s = 0;
+            return *this;
+        }
+
+        // returns true if subset is empty
+        bool empty() { return (s == 0); }
+
+        // return 1 if _j is contained, 0 otherwise ("is element of")
+        size_t operator&(size_t _j) { return s & (1U << _j); }
+
+        friend std::ostream& operator<< (std::ostream& os, const sub_nb x) {
+            if( x.bits == 0 )
+                os << "empty";
+            else {
+                for(size_t bit = x.bits; bit > 0; bit-- )
+                    if( x.s & (1U << (bit-1)) )
+                        os << "1";
+                    else
+                        os << "0";
+            }
+            return os;
+        }
+};
+
+
+} // end of namespace dai
+
+
+#endif
diff --git a/include/dai/prob.h b/include/dai/prob.h
new file mode 100644 (file)
index 0000000..1291242
--- /dev/null
@@ -0,0 +1,481 @@
+/*  Copyright (C) 2006-2008  Joris Mooij  [j dot mooij at science dot ru dot nl]
+    Radboud University Nijmegen, The Netherlands
+    
+    This file is part of libDAI.
+
+    libDAI is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    libDAI is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with libDAI; if not, write to the Free Software
+    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+
+#ifndef __defined_libdai_prob_h
+#define __defined_libdai_prob_h
+
+
+#include <complex>
+#include <cmath>
+#include <vector>
+#include <iostream>
+#include <cassert>
+#include <dai/util.h>
+
+
+namespace dai {
+
+
+typedef double                  Real;
+typedef std::complex<double>    Complex;
+
+template<typename T> class      TProb;
+typedef TProb<Real>             Prob;
+typedef TProb<Complex>          CProb;
+
+
+/// TProb<T> implements a probability vector of type T.
+/// T should be castable from and to double and to complex.
+template <typename T> class TProb {
+    protected:
+        /// The entries
+        std::vector<T> _p;
+
+    private:
+        /// Calculate x times log(x), or 0 if x == 0
+        Complex xlogx( Real x ) const { return( x == 0.0 ? 0.0 : Complex(x) * std::log(Complex(x))); }
+
+    public:
+        /// NORMPROB means that the sum of all entries should be 1
+        /// NORMLINF means that the maximum absolute value of all entries should be 1
+        typedef enum { NORMPROB, NORMLINF } NormType;
+        /// DISTL1 is the L-1 distance (sum of absolute values of pointwise difference)
+        /// DISTLINF is the L-inf distance (maximum absolute value of pointwise difference)
+        /// DISTTV is the Total Variation distance
+        typedef enum { DISTL1, DISTLINF, DISTTV } DistType;
+        
+        /// Default constructor
+        TProb() : _p() {}
+        
+        /// Construct uniform distribution of given length
+        TProb( size_t n ) : _p(std::vector<T>(n, 1.0 / n)) {}
+        
+        /// Construct with given length and initial value
+        TProb( size_t n, Real p ) : _p(std::vector<T>(n,(T)p)) {}
+        
+        /// Construct with given length and initial array
+        TProb( size_t n, const Real* p ) {
+            // Reserve-push_back is faster than resize-copy
+            _p.reserve( n );
+            for( size_t i = 0; i < n; i++ ) 
+                _p.push_back( p[i] );
+        }
+        
+        /// Copy constructor
+        TProb( const TProb<T> & x ) : _p(x._p) {}
+        
+        /// Assignment operator
+        TProb<T> & operator=( const TProb<T> &x ) {
+            if( this != &x ) {
+                _p = x._p;
+            }
+            return *this;
+        }
+        
+        /// Provide read access to _p
+        const std::vector<T> & p() const { return _p; }
+
+        /// Provide full access to _p
+        std::vector<T> & p() { return _p; }
+        
+        /// Provide read access to ith element of _p
+        T operator[]( size_t i ) const { return _p[i]; }
+        
+        /// Provide full access to ith element of _p
+        T& operator[]( size_t i ) { return _p[i]; }
+
+        /// Set all elements to x
+        TProb<T> & fill(T x) { 
+            for( size_t i = 0; i < size(); i++ )
+                _p[i] = x;
+            return *this;
+        }
+
+        /// Set all elements to iid random numbers from uniform(0,1) distribution
+        TProb<T> & randomize() { 
+            for( size_t i = 0; i < size(); i++ )
+                _p[i] = rnd_uniform();
+            return *this;
+        }
+
+        /// Return size
+        size_t size() const {
+            return _p.size();
+        }
+
+        /// Make entries zero if (Real) absolute value smaller than epsilon
+        TProb<T>& makeZero (Real epsilon) {
+            for( size_t i = 0; i < size(); i++ )
+                if( fabs((Real)_p[i]) < epsilon )
+                    _p[i] = 0;
+            return *this;
+        }
+
+        /// Multiplication with T x
+        TProb<T>& operator*= (T x) {
+            for( size_t i = 0; i < size(); i++ )
+                _p[i] *= x;
+            return *this;
+        }
+
+        /// Return product of *this with T x
+        TProb<T> operator* (T x) const {
+            TProb<T> prod( *this );
+            prod *= x;
+            return prod;
+        }
+
+        /// Division by T x
+        TProb<T>& operator/= (T x) {
+#ifdef DEBUG
+            assert( x != 0.0 );
+#endif
+            for( size_t i = 0; i < size(); i++ )
+                _p[i] /= x;
+            return *this;
+        }
+
+        /// Return quotient of *this and T x
+        TProb<T> operator/ (T x) const {
+            TProb<T> prod( *this );
+            prod /= x;
+            return prod;
+        }
+
+        /// Pointwise multiplication with q
+        TProb<T>& operator*= (const TProb<T> & q) {
+#ifdef DEBUG
+            assert( size() == q.size() );
+#endif
+            for( size_t i = 0; i < size(); i++ )
+                _p[i] *= q[i];
+            return *this;
+        }
+        
+        /// Return product of *this with q
+        TProb<T> operator* (const TProb<T> & q) const {
+#ifdef DEBUG
+            assert( size() == q.size() );
+#endif
+            TProb<T> prod( *this );
+            prod *= q;
+            return prod;
+        }
+
+        /// Pointwise addition with q
+        TProb<T>& operator+= (const TProb<T> & q) {
+#ifdef DEBUG
+            assert( size() == q.size() );
+#endif
+            for( size_t i = 0; i < size(); i++ )
+                _p[i] += q[i];
+            return *this;
+        }
+        
+        /// Pointwise subtraction of q
+        TProb<T>& operator-= (const TProb<T> & q) {
+#ifdef DEBUG
+            assert( size() == q.size() );
+#endif
+            for( size_t i = 0; i < size(); i++ )
+                _p[i] -= q[i];
+            return *this;
+        }
+        
+        /// Return sum of *this and q
+        TProb<T> operator+ (const TProb<T> & q) const {
+#ifdef DEBUG
+            assert( size() == q.size() );
+#endif
+            TProb<T> sum( *this );
+            sum += q;
+            return sum;
+        }
+        
+        /// Return *this minus q
+        TProb<T> operator- (const TProb<T> & q) const {
+#ifdef DEBUG
+            assert( size() == q.size() );
+#endif
+            TProb<T> sum( *this );
+            sum -= q;
+            return sum;
+        }
+
+        /// Pointwise division by q
+        TProb<T>& operator/= (const TProb<T> & q) {
+#ifdef DEBUG
+            assert( size() == q.size() );
+#endif
+            for( size_t i = 0; i < size(); i++ ) {
+#ifdef DEBUG
+//              assert( q[i] != 0.0 );
+#endif
+                if( q[i] == 0.0 )       // FIXME
+                    _p[i] = 0.0;
+                else
+                    _p[i] /= q[i];
+            }
+            return *this;
+        }
+        
+        /// Pointwise division by q, division by zero yields infinity
+        TProb<T>& divide (const TProb<T> & q) {
+#ifdef DEBUG
+            assert( size() == q.size() );
+#endif
+            for( size_t i = 0; i < size(); i++ )
+                _p[i] /= q[i];
+            return *this;
+        }
+        
+        /// Return quotient of *this with q
+        TProb<T> operator/ (const TProb<T> & q) const {
+#ifdef DEBUG
+            assert( size() == q.size() );
+#endif
+            TProb<T> quot( *this );
+            quot /= q;
+            return quot;
+        }
+
+        /// Return pointwise inverse
+        TProb<T> inverse(bool zero = false) const {
+            TProb<T> inv;
+            inv._p.reserve( size() );
+            if( zero )
+                for( size_t i = 0; i < size(); i++ )
+                    inv._p.push_back( _p[i] == 0.0 ? 0.0 : 1.0 / _p[i] );
+            else
+                for( size_t i = 0; i < size(); i++ ) {
+#ifdef DEBUG
+                    assert( _p[i] != 0.0 );
+#endif
+                    inv._p.push_back( 1.0 / _p[i] );
+                }
+            return inv;
+        }
+
+        /// Return *this to the power of a (pointwise)
+        TProb<T>& operator^= (Real a) {
+            if( a != 1.0 ) {
+                for( size_t i = 0; i < size(); i++ )
+                    _p[i] = std::pow( _p[i], a );
+            }
+            return *this;
+        }
+
+        /// Pointwise power of a
+        TProb<T> operator^ (Real a) const {
+            TProb<T> power;
+            if( a != 1.0 ) {
+                power._p.reserve( size() );
+                for( size_t i = 0; i < size(); i++ )
+                    power._p.push_back( std::pow( _p[i], a ) );
+            } else
+                power = *this;
+            return power;
+        }
+
+        /// Pointwise exp
+        TProb<T> exp() const {
+            TProb<T> e;
+            e._p.reserve( size() );
+            for( size_t i = 0; i < size(); i++ )
+                e._p.push_back( std::exp( _p[i] ) );
+            return e;
+        }
+
+        /// Pointwise log
+        TProb<T> log() const {
+            TProb<T> l;
+            l._p.reserve( size() );
+            for( size_t i = 0; i < size(); i++ )
+                l._p.push_back( std::log( _p[i] ) );
+            return l;
+        }
+
+        /// Pointwise log (or 0 if == 0)
+        TProb<T> log0() const {
+            TProb<T> l0;
+            l0._p.reserve( size() );
+            for( size_t i = 0; i < size(); i++ )
+                l0._p.push_back( (_p[i] == 0.0) ? 0.0 : std::log( _p[i] ) );
+            return l0;
+        }
+
+        /// Pointwise (complex) log (or 0 if == 0)
+/*      CProb clog0() const {
+            CProb l0;
+            l0._p.reserve( size() );
+            for( size_t i = 0; i < size(); i++ )
+                l0._p.push_back( (_p[i] == 0.0) ? 0.0 : std::log( Complex( _p[i] ) ) );
+            return l0;
+        }*/
+
+        /// Return distance of p and q
+        friend Real dist( const TProb<T> & p, const TProb<T> & q, DistType dt ) {
+#ifdef DEBUG
+            assert( p.size() == q.size() );
+#endif
+            Real result = 0.0;
+            switch( dt ) {
+                case DISTL1:
+                    for( size_t i = 0; i < p.size(); i++ )
+                        result += fabs((Real)p[i] - (Real)q[i]);
+                    break;
+                    
+                case DISTLINF:
+                    for( size_t i = 0; i < p.size(); i++ ) {
+                        Real z = fabs((Real)p[i] - (Real)q[i]);
+                        if( z > result )
+                            result = z;
+                    }
+                    break;
+
+                case DISTTV:
+                    for( size_t i = 0; i < p.size(); i++ )
+                        result += fabs((Real)p[i] - (Real)q[i]);
+                    result *= 0.5;
+                    break;
+            }
+            return result;
+        }
+
+        /// Return (complex) Kullback-Leibler distance with q
+        friend Complex KL_dist( const TProb<T> & p, const TProb<T> & q ) {
+#ifdef DEBUG
+            assert( p.size() == q.size() );
+#endif
+            Complex result = 0.0;
+            for( size_t i = 0; i < p.size(); i++ ) {
+                if( (Real) p[i] != 0.0 ) {
+                    Complex p_i = p[i];
+                    Complex q_i = q[i];
+                    result += p_i * (std::log(p_i) - std::log(q_i));
+                }
+            }
+            return result;
+        }
+
+        /// Return sum of all entries
+        T totalSum() const {
+            T Z = 0.0;
+            for( size_t i = 0; i < size(); i++ )
+                Z += _p[i];
+            return Z;
+        }
+
+        /// Converts entries to Real and returns maximum absolute value
+        T maxAbs() const {
+            T Z = 0.0;
+            for( size_t i = 0; i < size(); i++ ) {
+                Real mag = fabs( (Real) _p[i] );
+                if( mag > Z )
+                    Z = mag;
+            }
+            return Z;
+        }
+
+        /// Returns maximum value
+        T max() const {
+            T Z = 0.0;
+            for( size_t i = 0; i < size(); i++ ) {
+                if( _p[i] > Z )
+                    Z = _p[i];
+            }
+            return Z;
+        }
+
+        /// Normalize, using the specified norm
+        T normalize( NormType norm ) {
+            T Z = 0.0;
+            if( norm == NORMPROB )
+                Z = totalSum();
+            else if( norm == NORMLINF )
+                Z = maxAbs();
+#ifdef DEBUG
+            assert( Z != 0.0 );
+#endif
+            T Zi = 1.0 / Z;
+            for( size_t i = 0; i < size(); i++ )
+               _p[i] *= Zi;
+            return Z;
+        }
+
+        /// Return normalized copy of *this, using the specified norm
+        TProb<T> normalized( NormType norm ) const {
+            T Z = 0.0;
+            if( norm == NORMPROB ) 
+                Z = totalSum();
+            else if( norm == NORMLINF )
+                Z = maxAbs();
+#ifdef DEBUG
+            assert( Z != 0.0 );
+#endif
+            Z = 1.0 / Z;
+            
+            TProb<T> result;
+            result._p.reserve( size() );
+            for( size_t i = 0; i < size(); i++ )
+                result._p.push_back( _p[i] * Z );
+            return result;
+        }
+    
+        /// Returns true if one or more entries are NaN
+        bool hasNaNs() const {
+            bool NaNs = false;
+            for( size_t i = 0; i < size() && !NaNs; i++ ) 
+                if( isnan( _p[i] ) )
+                    NaNs = true;
+            return NaNs;
+        }
+
+        /// Returns true if one or more entries are negative
+        bool hasNegatives() const {
+            bool Negatives = false;
+            for( size_t i = 0; i < size() && !Negatives; i++ ) 
+                if( _p[i] < 0.0 )
+                    Negatives = true;
+            return Negatives;
+        }
+
+        /// Returns (complex) entropy
+        Complex entropy() const {
+            Complex S = 0.0;
+            for( size_t i = 0; i < size(); i++ )
+                S -= xlogx(_p[i]);
+            return S;
+        }
+
+        friend std::ostream& operator<< (std::ostream& os, const TProb<T>& P) {
+            for( size_t i = 0; i < P.size(); i++ )
+                os << P._p[i] << " ";
+            os << std::endl;
+            return os;
+        }
+};
+
+
+} // end of namespace dai
+
+
+#endif
diff --git a/include/dai/properties.h b/include/dai/properties.h
new file mode 100644 (file)
index 0000000..f871d62
--- /dev/null
@@ -0,0 +1,108 @@
+/*  Copyright (C) 2006-2008  Joris Mooij  [j dot mooij at science dot ru dot nl]
+    Radboud University Nijmegen, The Netherlands
+    
+    This file is part of libDAI.
+
+    libDAI is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    libDAI is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with libDAI; if not, write to the Free Software
+    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+
+#ifndef __defined_libdai_properties_h
+#define __defined_libdai_properties_h
+
+
+#include <iostream>
+#include <sstream>
+#include <boost/any.hpp>
+#include <map>
+#include <cassert>
+#include <typeinfo>
+
+
+namespace dai {
+
+
+typedef std::string PropertyKey;
+typedef boost::any  PropertyValue;
+typedef std::pair<PropertyKey, PropertyValue> Property;
+
+
+/// Sends a Properties object to an output stream
+std::ostream& operator<< (std::ostream & os, const Property & p);
+
+
+/// The Properties class represents a set of properties
+class Properties : public std::map<PropertyKey, PropertyValue> {
+    public:
+        /// Gets a property
+        const PropertyValue & Get(const PropertyKey &key) const { 
+            Properties::const_iterator x = find(key); 
+#ifdef DEBUG            
+            if( x == this->end() )
+                std::cerr << "Get cannot find property " << key << std::endl;
+#endif
+            assert( x != this->end() ); 
+            return x->second; 
+        }
+
+        /// Sets a property 
+        Properties & Set(const PropertyKey &key, const PropertyValue &val) { this->operator[](key) = val; return *this; }
+
+        /// Gets a property, casted as ValueType
+        template<typename ValueType>
+        ValueType GetAs(const PropertyKey &key) const {
+            try {
+                return boost::any_cast<ValueType>(Get(key));
+            } catch( const boost::bad_any_cast & ) {
+                std::cerr << "Cannot cast property " << key << " to ";
+                std::cerr << typeid(ValueType).name() << std::endl;
+                return boost::any_cast<ValueType>(Get(key));
+            }
+        }
+
+        /// Converts a property from string to ValueType, if necessary
+        template<typename ValueType>
+        void ConvertTo(const PropertyKey &key) { 
+            PropertyValue val = Get(key);
+            if( val.type() != typeid(ValueType) ) {
+                assert( val.type() == typeid(std::string) );
+
+                std::stringstream ss;
+                ss << GetAs<std::string>(key);
+                ValueType result;
+                ss >> result;
+
+                Set(key, result);
+            }
+        }
+
+        /// Shorthand for (temporarily) adding properties, e.g. Properties p()("method","BP")("verbose",1)("tol",1e-9)
+        Properties operator()(const PropertyKey &key, const PropertyValue &val) const { Properties copy = *this; return copy.Set(key,val); }
+
+        /// Check if a property with given key exists
+        bool hasKey(const PropertyKey &key) const { Properties::const_iterator x = find(key); return (x != this->end()); }
+
+        /// Sends a Properties object to an output stream
+        friend std::ostream& operator<< (std::ostream & os, const Properties & ps);
+
+        /// Reads a Properties object from an input stream
+        friend std::istream& operator >> (std::istream& is, Properties & ps);
+};
+
+
+} // end of namespace dai
+
+
+#endif
diff --git a/include/dai/regiongraph.h b/include/dai/regiongraph.h
new file mode 100644 (file)
index 0000000..b7ab9e7
--- /dev/null
@@ -0,0 +1,231 @@
+/*  Copyright (C) 2006-2008  Joris Mooij  [j dot mooij at science dot ru dot nl]
+    Radboud University Nijmegen, The Netherlands
+    
+    This file is part of libDAI.
+
+    libDAI is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    libDAI is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with libDAI; if not, write to the Free Software
+    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+
+#ifndef __defined_libdai_regiongraph_h
+#define __defined_libdai_regiongraph_h
+
+
+#include <iostream>
+#include <dai/bipgraph.h>
+#include <dai/factorgraph.h>
+#include <dai/weightedgraph.h>
+
+
+namespace dai {
+
+
+/// A Region is a set of variables with a counting number
+class Region : public VarSet {
+    protected:
+        /// Counting number
+        double          _c;
+
+    public:
+        /// Default constructor
+        Region() : VarSet(), _c(1.0) {}
+
+        /// Construct Region from a VarSet and a counting number
+        Region(const VarSet & x, double c) : VarSet(x), _c(c) {}
+        
+        /// Copy constructor
+        Region(const Region & x) : VarSet(x), _c(x._c) {}
+
+        /// Assignment operator
+        Region & operator=(const Region & x) {
+            if( this != &x ) {
+                VarSet::operator=(x);
+                _c          = x._c;
+            }
+            return *this;
+        }
+
+        /// Provide read access to counting number
+        const double & c() const { return _c; }
+        /// Provide full access to counting number
+        double & c() { return _c; }
+};
+
+
+/// A FRegion is a factor with a counting number
+class FRegion : public Factor {
+    protected:
+        /// Counting number
+        double _c;
+
+    public:
+        /// Default constructor
+        FRegion() : Factor(), _c(1.0) {}
+
+        /// Constructs FRegion from a Factor and a counting number
+        FRegion( const Factor & x, double c ) : Factor(x), _c(c) {}
+        
+        /// Copy constructor
+        FRegion( const FRegion & x ) : Factor(x), _c(x._c) {}
+
+        /// Assignment operator
+        FRegion & operator=(const FRegion & x) {
+            if( this != &x ) {
+                Factor::operator=(x);
+                _c = x._c;
+            }
+            return *this;
+        }
+
+        /// Provide read access to counting number
+        const double & c() const { return _c; }
+        /// Provide full access to counting number
+        double & c() { return _c; }
+};
+
+
+typedef BipartiteGraph<FRegion,Region> BipRegGraph;
+
+
+/// A RegionGraph is a bipartite graph consisting of outer regions (type FRegion) and inner regions (type Region)
+class RegionGraph : public FactorGraph, BipRegGraph {
+    public:
+        typedef BipRegGraph::_nb_t      R_nb_t;
+        typedef R_nb_t::const_iterator  R_nb_cit;
+        typedef BipRegGraph::_edge_t    R_edge_t;
+
+        
+    protected:
+        /// Give back the OR index that corresponds to a factor index
+        typedef std::map<size_t,size_t>::const_iterator fac2OR_cit;
+        std::map<size_t,size_t>         _fac2OR;
+
+
+    public:
+        /// Default constructor
+        RegionGraph() : FactorGraph(), BipRegGraph(), _fac2OR() {}
+
+        /// Constructs a RegionGraph from a FactorGraph
+        RegionGraph(const FactorGraph & fg) : FactorGraph(fg), BipRegGraph(), _fac2OR() {}
+
+        /// Constructs a RegionGraph from a FactorGraph, a vector of outer regions, a vector of inner regions and a vector of edges
+        RegionGraph(const FactorGraph & fg, const std::vector<Region> & ors, const std::vector<Region> & irs, const std::vector<R_edge_t> & edges);
+        
+        /// Constructs a RegionGraph from a FactorGraph and a vector of outer VarSets (CVM style)
+        RegionGraph(const FactorGraph & fg, const std::vector<VarSet> & cl);
+
+        /// Copy constructor
+        RegionGraph(const RegionGraph & x) : FactorGraph(x), BipRegGraph(x), _fac2OR(x._fac2OR) {}
+
+        /// Assignment operator
+        RegionGraph & operator=(const RegionGraph & x) {
+            if( this != &x ) {
+                FactorGraph::operator=(x);
+                BipRegGraph::operator=(x);
+                _fac2OR = x._fac2OR;
+            }
+            return *this;
+        }
+
+        /// Provides read access to outer region
+        const FRegion & OR(long alpha) const { return BipRegGraph::V1(alpha); }
+        /// Provides access to outer region
+        FRegion & OR(long alpha) { return BipRegGraph::V1(alpha); }
+        /// Provides read access to all outer regions
+        const std::vector<FRegion> & ORs() const { return BipRegGraph::V1s(); }
+        /// Provides access to all outer regions
+        std::vector<FRegion> &ORs() { return BipRegGraph::V1s(); }
+        /// Returns number of outer regions
+        size_t nr_ORs() const { return BipRegGraph::V1s().size(); }
+
+        /// Provides read access to inner region
+        const Region & IR(long beta) const { return BipRegGraph::V2(beta); }
+        /// Provides access to inner region
+        Region & IR(long beta) { return BipRegGraph::V2(beta); }
+        /// Provides read access to all inner regions
+        const std::vector<Region> & IRs() const { return BipRegGraph::V2s(); }
+        /// Provides access to all inner regions
+        std::vector<Region> & IRs() { return BipRegGraph::V2s(); }
+        /// Returns number of inner regions
+        size_t nr_IRs() const { return BipRegGraph::V2s().size(); }
+
+        /// Provides read access to edge
+        const R_edge_t & Redge(size_t ind) const { return BipRegGraph::edge(ind); }
+        /// Provides full access to edge
+        R_edge_t & Redge(size_t ind) { return BipRegGraph::edge(ind); }
+        /// Provides read access to all edges
+        const std::vector<R_edge_t> & Redges() const { return BipRegGraph::edges(); }
+        /// Provides full access to all edges
+        std::vector<R_edge_t> & Redges() { return BipRegGraph::edges(); }
+        /// Returns number of edges
+        size_t nr_Redges() const { return BipRegGraph::edges().size(); }
+
+        /// Provides read access to neighbours of outer region
+        const R_nb_t & nbOR( size_t i1 ) const { return BipRegGraph::nb1(i1); }
+        /// Provides full access to neighbours of outer region
+        R_nb_t & nbOR( size_t i1 ) { return BipRegGraph::nb1(i1); }
+
+        /// Provides read access to neighbours of inner region
+        const R_nb_t & nbIR( size_t i2 ) const { return BipRegGraph::nb2(i2); }
+        /// Provides full access to neighbours of inner region
+        R_nb_t & nbIR( size_t i2 ) { return BipRegGraph::nb2(i2); }
+
+        /// Converts the pair of outer/inner region indices (i1,i2) to the corresponding edge index
+        size_t ORIR2E( const size_t i1, const size_t i2 ) const { return BipRegGraph::VV2E(i1, i2); }
+
+        void Regenerate() { BipRegGraph::Regenerate(); }
+        
+        
+        /// Calculates counting numbers of inner regions based upon counting numbers of outer regions
+        void Calc_Counting_Numbers();
+        /// Check whether the counting numbers are valid
+        bool Check_Counting_Numbers();
+
+        /// Recompute all outer regions
+        void RecomputeORs();
+
+        /// Recompute all outer regions involving the variables in ns
+        void RecomputeORs( const VarSet & ns );
+
+        /// Recompute all outer regions involving factor I
+        void RecomputeOR( size_t I );
+
+        /// We have to overload FactorGraph::clamp because the corresponding outer regions have to be recomputed
+        void clamp( const Var &n, size_t i ) { FactorGraph::clamp( n, i ); RecomputeORs( n ); }
+
+        /// We have to overload FactorGraph::makeCavity because the corresponding outer regions have to be recomputed
+        void makeCavity( const Var &n ) { FactorGraph::makeCavity( n ); RecomputeORs( n ); }
+
+        /// We have to overload FactorGraph::makeFactorCavity because the corresponding outer regions have to be recomputed
+        void makeFactorCavity( size_t I ) { FactorGraph::makeFactorCavity( I ); RecomputeOR( I ); }
+
+        /// We have to overload FactorGraph::undoProbs because the corresponding outer regions have to be recomputed
+        void undoProbs( const VarSet &ns ) { FactorGraph::undoProbs( ns ); RecomputeORs( ns ); }
+
+        /// We have to overload FactorGraph::undoProb because the corresponding outer regions have to be recomputed
+        void undoProb( size_t I ) { FactorGraph::undoProb( I ); RecomputeOR( I ); }
+
+        /// If updateFactor is called, we know that factor I has been changed and we should recompute the outer regions involving I
+        void updatedFactor( size_t I ) { RecomputeOR( I ); }
+
+        /// Send RegionGraph to output stream
+        friend std::ostream & operator << ( std::ostream & os, const RegionGraph & rg );
+};
+
+
+} // end of namespace dai
+
+
+#endif
diff --git a/include/dai/treeep.h b/include/dai/treeep.h
new file mode 100644 (file)
index 0000000..900e906
--- /dev/null
@@ -0,0 +1,127 @@
+/*  Copyright (C) 2006-2008  Joris Mooij  [j dot mooij at science dot ru dot nl]
+    Radboud University Nijmegen, The Netherlands
+    
+    This file is part of libDAI.
+
+    libDAI is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    libDAI is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with libDAI; if not, write to the Free Software
+    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+
+#ifndef __defined_libdai_treeep_h
+#define __defined_libdai_treeep_h
+
+
+#include <vector>
+#include <string>
+#include <dai/daialg.h>
+#include <dai/varset.h>
+#include <dai/regiongraph.h>
+#include <dai/factorgraph.h>
+#include <dai/clustergraph.h>
+#include <dai/weightedgraph.h>
+#include <dai/jtree.h>
+#include <dai/enum.h>
+
+
+namespace dai {
+
+
+class TreeEPSubTree {
+    protected:
+        std::vector<Factor>  _Qa;
+        std::vector<Factor>  _Qb;
+        DEdgeVec             _RTree;
+        std::vector<size_t>  _a;             // _Qa[alpha]  <->  superTree._Qa[_a[alpha]]
+        std::vector<size_t>  _b;             // _Qb[beta]   <->  superTree._Qb[_b[beta]]
+                                        // _Qb[beta]   <->  _RTree[beta]    
+        const Factor *       _I;
+        VarSet               _ns;
+        VarSet               _nsrem;
+        double               _logZ;
+        
+        
+    public:
+        TreeEPSubTree() : _Qa(), _Qb(), _RTree(), _a(), _b(), _I(NULL), _ns(), _nsrem(), _logZ(0.0) {}
+        TreeEPSubTree( const TreeEPSubTree &x) : _Qa(x._Qa), _Qb(x._Qb), _RTree(x._RTree), _a(x._a), _b(x._b), _I(x._I), _ns(x._ns), _nsrem(x._nsrem), _logZ(x._logZ) {}
+        TreeEPSubTree & operator=( const TreeEPSubTree& x ) {
+            if( this != &x ) {
+                _Qa         = x._Qa;
+                _Qb         = x._Qb;
+                _RTree      = x._RTree;
+                _a          = x._a;
+                _b          = x._b;
+                _I          = x._I;
+                _ns         = x._ns;
+                _nsrem      = x._nsrem;
+                _logZ       = x._logZ;
+            }
+            return *this;
+        }
+
+        TreeEPSubTree( const DEdgeVec &subRTree, const DEdgeVec &jt_RTree, const std::vector<Factor> &jt_Qa, const std::vector<Factor> &jt_Qb, const Factor *I );
+        void init();
+        void InvertAndMultiply( const std::vector<Factor> &Qa, const std::vector<Factor> &Qb );
+        void HUGIN_with_I( std::vector<Factor> &Qa, std::vector<Factor> &Qb );
+        double logZ( const std::vector<Factor> &Qa, const std::vector<Factor> &Qb ) const;
+        const Factor *& I() { return _I; }
+};
+
+
+class TreeEP : public JTree {
+    protected:
+        std::map<size_t, TreeEPSubTree>  _Q;
+
+    public:
+        ENUM2(TypeType,ORG,ALT)
+        TypeType Type() const { return GetPropertyAs<TypeType>("type"); }
+        
+        TreeEP() : JTree(), _Q() {};
+        TreeEP( const TreeEP& x ) : JTree(x), _Q(x._Q) {
+            for( size_t I = 0; I < nrFactors(); I++ )
+                if( offtree( I ) )
+                    _Q[I].I() = &factor(I);
+        }
+        TreeEP* clone() const { return new TreeEP(*this); }
+        TreeEP & operator=( const TreeEP& x ) {
+            if( this != &x ) {
+                JTree::operator=(x);
+                _Q   = x._Q;
+                for( size_t I = 0; I < nrFactors(); I++ )
+                    if( offtree( I ) )
+                        _Q[I].I() = &factor(I);
+            }
+            return *this;
+        }
+        TreeEP( const FactorGraph &fg, const Properties &opts );
+        void ConstructRG( const DEdgeVec &tree );
+
+        static const char *Name;
+        std::string identify() const;
+        void init();
+        double run();
+        Complex logZ() const;
+
+        bool offtree(size_t I) const { return !_fac2OR.count(I); }
+
+        void init( const VarSet &/*ns*/ ) { init(); }
+        void undoProbs( const VarSet &ns ) { RegionGraph::undoProbs( ns ); init( ns ); }
+        bool checkProperties();
+};
+
+
+} // end of namespace dai
+
+
+#endif
diff --git a/include/dai/util.h b/include/dai/util.h
new file mode 100644 (file)
index 0000000..9356e8c
--- /dev/null
@@ -0,0 +1,42 @@
+/*  Copyright (C) 2006-2008  Joris Mooij  [j dot mooij at science dot ru dot nl]
+    Radboud University Nijmegen, The Netherlands
+    
+    This file is part of libDAI.
+
+    libDAI is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    libDAI is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with libDAI; if not, write to the Free Software
+    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+
+#ifndef __defined_libdai_util_h
+#define __defined_libdai_util_h
+
+
+#include <sys/times.h>
+#include <cstdio>
+
+
+namespace dai {
+
+
+clock_t toc();
+void rnd_seed( int seed );
+double rnd_uniform();
+double rnd_stdnormal();
+
+
+} // end of namespace dai
+
+
+#endif
diff --git a/include/dai/var.h b/include/dai/var.h
new file mode 100644 (file)
index 0000000..4391f5f
--- /dev/null
@@ -0,0 +1,80 @@
+/*  Copyright (C) 2006-2008  Joris Mooij  [j dot mooij at science dot ru dot nl]
+    Radboud University Nijmegen, The Netherlands
+    
+    This file is part of libDAI.
+
+    libDAI is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    libDAI is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with libDAI; if not, write to the Free Software
+    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+
+#ifndef __defined_libdai_var_h
+#define __defined_libdai_var_h
+
+
+#include <iostream>
+
+
+namespace dai {
+
+
+/// Represents a discrete variable
+class Var {
+    private:
+        /// Internal label of the variable
+        long    _label;
+
+        /// Number of possible values
+        size_t  _states;
+        
+    public:
+        /// Default constructor
+        Var() : _label(-1), _states(0) {};
+        /// Constructor
+        Var(long label, size_t states) : _label(label), _states(states) {};
+
+        /// Read access to label
+        long label() const { return _label; };
+        /// Access to label
+        long & label() { return _label; };
+
+        /// Read access to states
+        size_t states () const { return _states; };
+        /// Access to states
+        size_t& states () { return _states; };
+
+        /// Smaller-than operator (compares labels)
+        bool operator <  (const Var& n) const { return( _label <  n._label ); };
+        /// Larger-than operator (compares labels)
+        bool operator >  (const Var& n) const { return( _label >  n._label ); };
+        /// Smaller-than-or-equal-to operator (compares labels)
+        bool operator <= (const Var& n) const { return( _label <= n._label ); };
+        /// Larger-than-or-equal-to operator (compares labels)
+        bool operator >= (const Var& n) const { return( _label >= n._label ); };
+        /// Not-equal-to operator (compares labels)
+        bool operator != (const Var& n) const { return( _label != n._label ); };
+        /// Equal-to operator (compares labels)
+        bool operator == (const Var& n) const { return( _label == n._label ); };
+
+        /// Stream output operator
+        friend std::ostream& operator << (std::ostream& os, const Var& n) {
+            return( os << "[" << n.label() << "]" );
+        };
+};
+
+
+} // end of namespace dai
+
+
+#endif
diff --git a/include/dai/varset.h b/include/dai/varset.h
new file mode 100644 (file)
index 0000000..7c6cf61
--- /dev/null
@@ -0,0 +1,248 @@
+/*  Copyright (C) 2006-2008  Joris Mooij  [j dot mooij at science dot ru dot nl]
+    Radboud University Nijmegen, The Netherlands
+    
+    This file is part of libDAI.
+
+    libDAI is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    libDAI is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with libDAI; if not, write to the Free Software
+    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+
+#ifndef __defined_libdai_varset_h
+#define __defined_libdai_varset_h
+
+
+#include <set>
+#include <algorithm>
+#include <iostream>
+#include <cassert>
+#include <dai/var.h>
+
+
+namespace dai {
+
+
+/// VarSet represents a set of variables and is a descendant of set<Var>. 
+/// In addition, it provides an easy interface for set-theoretic operations
+/// by operator overloading.
+class VarSet : private std::set<Var> {
+    protected:
+        /// Product of number of states of all contained variables
+        size_t _statespace;
+
+        /// Check whether ns is a subset
+        bool includes( const VarSet& ns ) const {
+            return std::includes( begin(), end(), ns.begin(), ns.end() );
+        }
+
+        /// Calculate statespace
+        size_t calcStateSpace() {
+            _statespace = 1;
+            for( const_iterator i = begin(); i != end(); ++i )
+                _statespace *= i->states();
+            return _statespace;
+        }
+
+
+    public:
+        /// Default constructor
+        VarSet() : _statespace(0) {};
+
+        /// Construct a VarSet with one variable
+        VarSet( const Var &n ) : _statespace( n.states() ) { 
+            insert( n ); 
+        }
+
+        /// Construct a VarSet with two variables
+        VarSet( const Var &n1, const Var &n2 ) { 
+            insert( n1 ); 
+            insert( n2 ); 
+            calcStateSpace();
+        }
+
+        /// Construct from a set<Var>
+        VarSet( const std::set<Var> &ns ) {
+            std::set<Var>::operator=( ns );
+            calcStateSpace();
+        }
+
+        /// Copy constructor
+        VarSet( const VarSet &x ) : std::set<Var>( x ), _statespace( x._statespace ) {}
+
+        /// Assignment operator
+        VarSet & operator=( const VarSet &x ) {
+            if( this != &x ) {
+                std::set<Var>::operator=( x );
+                _statespace = x._statespace;
+            }
+            return *this;
+        }
+        
+
+        /// Return statespace, i.e. the product of the number of states of each variable
+        size_t stateSpace() const { 
+#ifdef DEBUG
+            size_t x = 1;
+            for( const_iterator i = begin(); i != end(); ++i )
+                x *= i->states();
+            assert( x == _statespace );
+#endif
+            return _statespace; 
+        }
+        
+
+        /// Erase one variable
+        VarSet& operator/= (const Var& n) { 
+            erase( n ); 
+            calcStateSpace();
+            return *this; 
+        }
+
+        /// Add one variable
+        VarSet& operator|= (const Var& n) {
+            insert( n ); 
+            calcStateSpace();
+            return *this;
+        }
+
+        /// Setminus operator (result contains all variables except those in ns)
+        VarSet operator/ (const VarSet& ns) const {
+            VarSet res;
+            std::set_difference( begin(), end(), ns.begin(), ns.end(), inserter( res, res.begin() ) );
+            res.calcStateSpace();
+            return res;
+        }
+
+        /// Set-union operator (result contains all variables plus those in ns)
+        VarSet operator| (const VarSet& ns) const {
+            VarSet res;
+            std::set_union( begin(), end(), ns.begin(), ns.end(), inserter( res, res.begin() ) );
+            res.calcStateSpace();
+            return res;
+        }
+
+        /// Set-intersection operator (result contains all variables that are also contained in ns)
+        VarSet operator& (const VarSet& ns) const {
+            VarSet res;
+            std::set_intersection( begin(), end(), ns.begin(), ns.end(), inserter( res, res.begin() ) );
+            res.calcStateSpace();
+            return res;
+        }
+        
+        /// Erases from *this all variables in ns
+        VarSet& operator/= (const VarSet& ns) {
+            return (*this = (*this / ns));
+        }
+
+        /// Adds to *this all variables in ns
+        VarSet& operator|= (const VarSet& ns) {
+            return (*this = (*this | ns));
+        }
+
+        /// Erases from *this all variables not in ns
+        VarSet& operator&= (const VarSet& ns) { 
+            return (*this = (*this & ns)); 
+        }
+        
+
+        /// Returns false if both *this and ns are empty
+        bool operator|| (const VarSet& ns) const { 
+            return !( this->empty() && ns.empty() );
+        }
+
+        /// Returns true if *this and ns contain common variables
+        bool operator&& (const VarSet& ns) const { 
+            return !( (*this & ns).empty() ); 
+        }
+
+        /// Returns true if *this is a subset of ns
+        bool operator<< (const VarSet& ns) const { 
+            return ns.includes( *this ); 
+        }
+
+        /// Returns true if ns is a subset of *this
+        bool operator>> (const VarSet& ns) const { 
+            return includes( ns ); 
+        }
+
+        /// Returns true if *this contains the variable n
+        bool operator&& (const Var& n) const { 
+            return( find( n ) == end() ? false : true ); 
+        }
+
+        
+        /// Sends a VarSet to an output stream
+        friend std::ostream& operator<< (std::ostream & os, const VarSet& ns) {
+            for( VarSet::const_iterator n = ns.begin(); n != ns.end(); n++)
+                os << *n;
+            return( os );
+        }
+
+        
+/*      The following makes part of the public interface of set<Var> available.
+ *      It is important to note that insert functions have to be overloaded,
+ *      because they have to recalculate the statespace. A different approach
+ *      would be to publicly inherit from set<Var> and only overload the insert
+ *      methods.
+ */
+        
+        // Additional interface from set<Var> that has to be provided
+        using std::set<Var>::const_iterator;
+        using std::set<Var>::iterator;
+        using std::set<Var>::const_reference;
+        using std::set<Var>::begin;
+        using std::set<Var>::end;
+        using std::set<Var>::size;
+        using std::set<Var>::empty;
+
+        /// Copy of set<Var>::insert which additionally calculates the new statespace
+        std::pair<iterator, bool> insert( const Var& x ) {
+            std::pair<iterator, bool> result = std::set<Var>::insert( x );
+            calcStateSpace();
+            return result;
+        }
+
+        /// Copy of set<Var>::insert which additionally calculates the new statespace
+        iterator insert( iterator pos, const value_type& x ) {
+            iterator result = std::set<Var>::insert( pos, x );
+            calcStateSpace();
+            return result;
+        }
+
+        /// Test for equality (ignore _statespace member)
+        friend bool operator==( const VarSet &a, const VarSet &b ) {
+            return operator==( (std::set<Var>)a, (std::set<Var>)b );
+        }
+
+        /// Test for inequality (ignore _statespace member)
+        friend bool operator!=( const VarSet &a, const VarSet &b ) {
+            return operator!=( (std::set<Var>)a, (std::set<Var>)b );
+        }
+
+        friend bool operator<( const VarSet &a, const VarSet &b ) {
+            return operator<( (std::set<Var>)a, (std::set<Var>)b );
+        }
+};
+
+
+/// For two Vars n1 and n2, the expression n1 | n2 gives the Varset containing n1 and n2
+inline VarSet operator| (const Var& n1, const Var& n2) {
+    return( VarSet(n1, n2) );
+}
+
+
+} // end of namespace dai
+
+
+#endif
diff --git a/include/dai/weightedgraph.h b/include/dai/weightedgraph.h
new file mode 100644 (file)
index 0000000..990d409
--- /dev/null
@@ -0,0 +1,173 @@
+/*  Copyright (C) 2006-2008  Joris Mooij  [j dot mooij at science dot ru dot nl]
+    Radboud University Nijmegen, The Netherlands
+    
+    This file is part of libDAI.
+
+    libDAI is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    libDAI is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with libDAI; if not, write to the Free Software
+    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+
+#ifndef __defined_libdai_weightedgraph_h
+#define __defined_libdai_weightedgraph_h
+
+
+#include <vector>
+#include <map>
+#include <iostream>
+#include <set>
+
+
+namespace dai {
+
+
+/// Directed edge
+class DEdge {
+    public:
+        size_t  n1, n2;
+    
+        DEdge() {}
+        DEdge( size_t m1, size_t m2 ) : n1(m1), n2(m2) {}
+        bool operator==( const DEdge &x ) const {
+            return ((n1 == x.n1) && (n2 == x.n2));
+        }
+        bool operator!=( const DEdge &x ) const {
+            return !(*this == x);
+        }
+        bool operator<( const DEdge &x ) const {
+            return( (n1 < x.n1) || ((n1 == x.n1) && (n2 < x.n2)) );
+        }
+        friend std::ostream & operator << (std::ostream & os, const DEdge & e) {
+            os << "(" << e.n1 << "," << e.n2 << ")";
+            return os;
+        }
+};
+
+
+/// Undirected edge
+class UEdge {
+    public:
+        size_t  n1, n2;
+    
+        UEdge() {}
+        UEdge( size_t m1, size_t m2 ) : n1(m1), n2(m2) {}
+        UEdge( const DEdge & e ) : n1(e.n1), n2(e.n2) {}
+        bool operator==( const UEdge &x ) {
+            return ((n1 == x.n1) && (n2 == x.n2)) || ((n1 == x.n2) && (n2 == x.n1));
+        }
+        bool operator<( const UEdge &x ) const {
+            size_t s = n1, l = n2;
+            if( s > l )
+                std::swap( s, l );
+            size_t xs = x.n1, xl = x.n2;
+            if( xs > xl )
+                std::swap( xs, xl );
+            return( (s < xs) || ((s == xs) && (l < xl)) );
+        }
+        friend std::ostream & operator << (std::ostream & os, const UEdge & e) {
+            if( e.n1 < e.n2 )
+                os << "{" << e.n1 << "," << e.n2 << "}";
+            else
+                os << "{" << e.n2 << "," << e.n1 << "}";
+            return os;
+        }
+};
+
+
+typedef std::vector<UEdge>  UEdgeVec;
+typedef std::vector<DEdge>  DEdgeVec;
+std::ostream & operator << (std::ostream & os, const DEdgeVec & rt);
+template<class T> class WeightedGraph : public std::map<UEdge, T> {};
+typedef std::set<UEdge>     Graph;
+
+
+/// Use Prim's algorithm to construct a maximal spanning tree from the weighted graph Graph
+template<typename T> DEdgeVec MaxSpanningTreePrim( const WeightedGraph<T> & Graph ) {
+    const long verbose = 0;
+
+    DEdgeVec result;
+    if( Graph.size() == 0 )
+        return result;
+    else {
+        // Make a copy
+        WeightedGraph<T> Gr = Graph;
+
+        // Nodes in the tree
+        std::set<size_t> treeV;
+
+        // Start with one node
+        treeV.insert( Gr.begin()->first.n1 );
+        
+        // Perform Prim's algorithm
+        while( Gr.size() ) {
+            typename WeightedGraph<T>::iterator largest = Gr.end();
+            
+            for( typename WeightedGraph<T>::iterator e = Gr.begin(); e != Gr.end(); ) {
+                if( verbose >= 1 )
+                    std::cout << "considering edge " << e->first << "...";
+                bool e1_in_treeV = treeV.count( e->first.n1 );
+                bool e2_in_treeV = treeV.count( e->first.n2 );
+                if( e1_in_treeV && e2_in_treeV ) {
+                    if( verbose >= 1 )
+                        std::cout << "red";
+                    Gr.erase( e++ );    // Nice trick! 
+                } else if( e1_in_treeV || e2_in_treeV ) {
+                    if( verbose >= 1 )
+                        std::cout << e->second;
+                    if( (largest == Gr.end()) || (e->second > largest->second) ) {
+                        largest = e;    // largest edge connected to the tree (until now)
+                        if( verbose >= 1 )
+                            std::cout << " and largest!";
+                    } 
+                    e++;
+                } else {
+                    if( verbose >= 1 )
+                        std::cout << "out of reach";
+                    e++;
+                }
+                if( verbose >= 1 )
+                    std::cout << std::endl;
+            }
+
+            if( largest != Gr.end() ) {
+                if( verbose >= 1 )
+                    std::cout << "largest = " << largest->first << std::endl;
+                // Add directed edge, pointing away from the root
+                if( treeV.count( largest->first.n1 ) ) {
+                    result.push_back( DEdge( largest->first.n1, largest->first.n2 ) );
+                    treeV.insert( largest->first.n2 );
+                } else {
+                    result.push_back( DEdge( largest->first.n2, largest->first.n1 ) );
+                    treeV.insert( largest->first.n1 );
+                }
+                Gr.erase( largest );
+            }
+        }
+
+        return result;
+    }
+}
+
+
+/// Calculate rooted tree from a tree T and a root
+DEdgeVec GrowRootedTree( const Graph & T, size_t Root );
+
+
+UEdgeVec RandomDRegularGraph( size_t N, size_t d );
+
+
+} // end of namespace dai
+
+
+#endif
diff --git a/include/dai/x2x.h b/include/dai/x2x.h
new file mode 100644 (file)
index 0000000..dbd9d9f
--- /dev/null
@@ -0,0 +1,71 @@
+/*  Copyright (C) 2006-2008  Joris Mooij  [j dot mooij at science dot ru dot nl]
+    Radboud University Nijmegen, The Netherlands
+    
+    This file is part of libDAI.
+
+    libDAI is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    libDAI is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with libDAI; if not, write to the Free Software
+    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+
+#ifndef __defined_libdai_x2x_h
+#define __defined_libdai_x2x_h
+
+
+#include <cmath>
+#include <cstring>
+
+
+namespace x2x {
+
+    // Probability tables store -1 first, then +1
+    /// Convert moments to cumulants upto order k
+    void m2c (int N, double *x, int k);
+
+    /// Convert cumulants to moments upto order k
+    void c2m (int N, double *x, int k);
+
+    /// Convert (generalized) weights to log probability or energy
+    void w2logp (int N, double *x);
+
+    /// Convert log probability or energy to (generalized) weights
+    void logp2w (int N, double *x);
+
+    /// Convert probability to moments
+    void p2m (int N, double *x);
+
+    /// Convert moments to probability
+    void m2p (int N, double *x);
+
+    /// Convert log probability to probability
+    void logp2p (int N, double *x);
+
+    /// Convert probability to log probability
+    void p2logp (int N, double *x);
+
+    /// Normalize a log probability table
+    void logpnorm (int N, double *x);
+
+    /// Normalize a probability table, use logpnorm whenever possible
+    void pnorm (int N, double *x);
+
+    /// Fills table with v for all entries with more than k indices
+    /// used for example when cumulants or moments are converted upto some order
+    void fill (int N, double *x, int k, double v);
+
+} // end of namespace x2x
+
+
+#endif
diff --git a/index.h b/index.h
deleted file mode 100644 (file)
index dc132d3..0000000
--- a/index.h
+++ /dev/null
@@ -1,159 +0,0 @@
-/*  Copyright (C) 2006-2008  Joris Mooij  [j dot mooij at science dot ru dot nl]
-    Radboud University Nijmegen, The Netherlands
-    
-    This file is part of libDAI.
-
-    libDAI is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    libDAI is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with libDAI; if not, write to the Free Software
-    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-
-#ifndef __INDEX_H__
-#define __INDEX_H__
-
-
-#include <vector>
-#include "varset.h"
-
-
-namespace dai {
-
-
-/* Example:
- *
- * Index i ({s_j_1,s_j_2,...,s_j_m}, {s_1,...,s_N});    // j_k in {1,...,N}
- * for( ; i>=0; ++i ) {
- *      // loops over all states of (s_1,...,s_N)
- *      // i is linear index of corresponding state of (s_j_1, ..., s_j_m)
- * }
- */
-
-
-class Index
-{
-private:
-    long _index;
-    std::vector<int> _count,_max,_sum;
-public:
-    Index () { _index=-1; };
-    Index (const VarSet& P, const VarSet& ns)
-    {
-        long sum=1;
-        VarSet::const_iterator j=ns.begin();
-        for(VarSet::const_iterator i=P.begin();i!=P.end();++i)
-        {
-            for(;j!=ns.end()&&j->label()<=i->label();++j)
-            {
-                _count.push_back(0);
-                _max.push_back(j->states());
-                _sum.push_back((i->label()==j->label())?sum:0);
-            };
-            sum*=i->states();
-        };
-        for(;j!=ns.end();++j)
-        {
-            _count.push_back(0);
-            _max.push_back(j->states());
-            _sum.push_back(0);
-        };
-        _index=0;
-    };
-    Index (const Index & ind) : _index(ind._index), _count(ind._count), _max(ind._max), _sum(ind._sum) {};
-    Index & operator=(const Index & ind) {
-        if(this!=&ind) {
-            _index = ind._index;
-            _count = ind._count;
-            _max = ind._max;
-            _sum = ind._sum;
-        }
-        return *this;
-    }
-    Index& clear ()
-    {
-        for(unsigned i=0;i!=_count.size();++i) _count[i]=0;
-        _index=0;
-        return(*this);
-    };
-    operator long () const { return(_index); };
-    Index& operator ++ ()
-    {
-        if(_index>=0)
-        {
-            unsigned i;
-            for(i=0;(i<_count.size())
-                    &&(_index+=_sum[i],++_count[i]==_max[i]);++i)
-            {
-                _index-=_sum[i]*_max[i];
-                _count[i]=0;
-            };
-            if(i==_count.size()) _index=-1;
-        };
-        return(*this);
-    };
-};
-
-
-class multind {
-    private:
-        std::vector<size_t> _dims;  // dimensions
-        std::vector<size_t> _pdims; // products of dimensions
-
-    public:
-        multind(const std::vector<size_t> di) {
-            _dims = di;
-            size_t prod = 1;
-            for( std::vector<size_t>::const_iterator i=di.begin(); i!=di.end(); i++ ) {
-                _pdims.push_back(prod);
-                prod = prod * (*i);
-            }
-            _pdims.push_back(prod);
-        }
-        multind(const VarSet& ns) {
-            _dims.reserve( ns.size() ); 
-            _pdims.reserve( ns.size() + 1 ); 
-            size_t prod = 1;
-            for( VarSet::const_iterator n = ns.begin(); n != ns.end(); n++ ) {
-                _pdims.push_back( prod );
-                prod *= n->states();
-                _dims.push_back( n->states() );
-            }
-            _pdims.push_back( prod );
-        }
-        std::vector<size_t> vi(size_t li) const {   // linear index to vector index
-            std::vector<size_t> v(_dims.size(),0);
-            assert(li < _pdims.back());
-            for( long j = v.size()-1; j >= 0; j-- ) {
-                size_t q = li / _pdims[j];
-                v[j] = q;
-                li = li - q * _pdims[j];
-            }
-            return v;
-        }
-        size_t li(const std::vector<size_t> vi) const { // linear index
-            size_t s = 0;
-            assert(vi.size() == _dims.size());
-            for( size_t j = 0; j < vi.size(); j++ ) 
-                s += vi[j] * _pdims[j];
-            return s;
-        }
-        size_t max() const { return( _pdims.back() ); };
-
-        // FIXME add an iterator, which increases a vector index just using addition
-};
-
-
-}
-
-
-#endif
diff --git a/jtree.cpp b/jtree.cpp
deleted file mode 100644 (file)
index 4ddb402..0000000
--- a/jtree.cpp
+++ /dev/null
@@ -1,512 +0,0 @@
-/*  Copyright (C) 2006-2008  Joris Mooij  [j dot mooij at science dot ru dot nl]
-    Radboud University Nijmegen, The Netherlands
-    
-    This file is part of libDAI.
-
-    libDAI is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    libDAI is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with libDAI; if not, write to the Free Software
-    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-
-#include <iostream>
-#include "jtree.h"
-
-
-namespace dai {
-
-
-using namespace std;
-
-
-const char *JTree::Name = "JTREE";
-
-
-bool JTree::checkProperties() {
-    if (!HasProperty("verbose") )
-        return false;
-    if( !HasProperty("updates") )
-        return false;
-    
-    ConvertPropertyTo<size_t>("verbose");
-    ConvertPropertyTo<UpdateType>("updates");
-
-    return true;
-}
-
-
-JTree::JTree( const FactorGraph &fg, const Properties &opts, bool automatic) : DAIAlgRG(fg, opts), _RTree(), _Qa(), _Qb(), _mes(), _logZ() {
-    assert( checkProperties() );
-
-    if( automatic ) {
-        ClusterGraph _cg;
-
-        // Copy factors
-        for( size_t I = 0; I < nrFactors(); I++ )
-            _cg.insert( factor(I).vars() );
-        if( Verbose() >= 3 )
-            cout << "Initial clusters: " << _cg << endl;
-
-        // Retain only maximal clusters
-        _cg.eraseNonMaximal();
-        if( Verbose() >= 3 )
-            cout << "Maximal clusters: " << _cg << endl;
-
-        vector<VarSet> ElimVec = _cg.VarElim_MinFill().eraseNonMaximal().toVector();
-        if( Verbose() >= 3 ) {
-            cout << "VarElim_MinFill result: {" << endl;
-            for( size_t i = 0; i < ElimVec.size(); i++ ) {
-                if( i != 0 )
-                    cout << ", ";
-                cout << ElimVec[i];
-            }
-            cout << "}" << endl;
-        }
-
-        GenerateJT( ElimVec );
-    }
-}
-
-
-void JTree::GenerateJT( const vector<VarSet> &Cliques ) {
-    // Construct a weighted graph (each edge is weighted with the cardinality 
-    // of the intersection of the nodes, where the nodes are the elements of
-    // Cliques).
-    WeightedGraph<int> JuncGraph;
-    for( size_t i = 0; i < Cliques.size(); i++ )
-        for( size_t j = i+1; j < Cliques.size(); j++ ) {
-            size_t w = (Cliques[i] & Cliques[j]).size();
-            JuncGraph[UEdge(i,j)] = w;
-        }
-    
-    // Construct maximal spanning tree using Prim's algorithm
-    _RTree = MaxSpanningTreePrim( JuncGraph );
-
-    // Construct corresponding region graph
-
-    // Create outer regions
-    ORs().reserve( Cliques.size() );
-    for( size_t i = 0; i < Cliques.size(); i++ )
-        ORs().push_back( FRegion( Factor(Cliques[i], 1.0), 1.0 ) );
-
-    // For each factor, find an outer region that subsumes that factor.
-    // Then, multiply the outer region with that factor.
-    for( size_t I = 0; I < nrFactors(); I++ ) {
-        size_t alpha;
-        for( alpha = 0; alpha < nr_ORs(); alpha++ )
-            if( OR(alpha).vars() >> factor(I).vars() ) {
-//              OR(alpha) *= factor(I);
-                _fac2OR[I] = alpha;
-                break;
-            }
-        assert( alpha != nr_ORs() );
-    }
-    RecomputeORs();
-
-    // Create inner regions and edges
-    IRs().reserve( _RTree.size() );
-    Redges().reserve( 2 * _RTree.size() );
-    for( size_t i = 0; i < _RTree.size(); i++ ) {
-        Redges().push_back( R_edge_t( _RTree[i].n1, IRs().size() ) );
-        Redges().push_back( R_edge_t( _RTree[i].n2, IRs().size() ) );
-        // inner clusters have counting number -1
-        IRs().push_back( Region( Cliques[_RTree[i].n1] & Cliques[_RTree[i].n2], -1.0 ) );
-    }
-
-    // Regenerate BipartiteGraph internals
-    Regenerate();
-
-    // Create messages and beliefs
-    _Qa.clear();
-    _Qa.reserve( nr_ORs() );
-    for( size_t alpha = 0; alpha < nr_ORs(); alpha++ )
-        _Qa.push_back( OR(alpha) );
-
-    _Qb.clear();
-    _Qb.reserve( nr_IRs() );
-    for( size_t beta = 0; beta < nr_IRs(); beta++ ) 
-        _Qb.push_back( Factor( IR(beta), 1.0 ) );
-
-    _mes.clear();
-    _mes.reserve( nr_Redges() );
-    for( size_t e = 0; e < nr_Redges(); e++ )
-        _mes.push_back( Factor( IR(Redge(e).second), 1.0 ) );
-
-    // Check counting numbers
-    Check_Counting_Numbers();
-
-    if( Verbose() >= 3 ) {
-        cout << "Resulting regiongraph: " << *this << endl;
-    }
-}
-
-
-string JTree::identify() const {
-    stringstream result (stringstream::out);
-    result << Name << GetProperties();
-    return result.str();
-}
-
-
-Factor JTree::belief( const VarSet &ns ) const {
-    vector<Factor>::const_iterator beta;
-    for( beta = _Qb.begin(); beta != _Qb.end(); beta++ )
-        if( beta->vars() >> ns )
-            break;
-    if( beta != _Qb.end() )
-        return( beta->marginal(ns) );
-    else {
-        vector<Factor>::const_iterator alpha;
-        for( alpha = _Qa.begin(); alpha != _Qa.end(); alpha++ )
-            if( alpha->vars() >> ns )
-                break;
-        assert( alpha != _Qa.end() );
-        return( alpha->marginal(ns) );
-    }
-}
-
-
-vector<Factor> JTree::beliefs() const {
-    vector<Factor> result;
-    for( size_t beta = 0; beta < nr_IRs(); beta++ )
-        result.push_back( _Qb[beta] );
-    for( size_t alpha = 0; alpha < nr_ORs(); alpha++ )
-        result.push_back( _Qa[alpha] );
-    return result;
-}
-
-
-Factor JTree::belief( const Var &n ) const {
-    return belief( (VarSet)n );
-}
-
-
-// Needs no init
-void JTree::runHUGIN() {
-    for( size_t alpha = 0; alpha < nr_ORs(); alpha++ )
-        _Qa[alpha] = OR(alpha);
-
-    for( size_t beta = 0; beta < nr_IRs(); beta++ )
-        _Qb[beta].fill( 1.0 );
-
-    // CollectEvidence
-    _logZ = 0.0;
-    for( size_t i = _RTree.size(); (i--) != 0; ) {
-//      Make outer region _RTree[i].n1 consistent with outer region _RTree[i].n2
-//      IR(i) = seperator OR(_RTree[i].n1) && OR(_RTree[i].n2)
-        Factor new_Qb = _Qa[_RTree[i].n2].part_sum( IR( i ) );
-        _logZ += log(new_Qb.normalize( Prob::NORMPROB ));
-        _Qa[_RTree[i].n1] *= new_Qb.divided_by( _Qb[i] ); 
-        _Qb[i] = new_Qb;
-    }
-    if( _RTree.empty() )
-        _logZ += log(_Qa[0].normalize( Prob::NORMPROB ) );
-    else
-        _logZ += log(_Qa[_RTree[0].n1].normalize( Prob::NORMPROB ));
-
-    // DistributeEvidence
-    for( size_t i = 0; i < _RTree.size(); i++ ) {
-//      Make outer region _RTree[i].n2 consistent with outer region _RTree[i].n1
-//      IR(i) = seperator OR(_RTree[i].n1) && OR(_RTree[i].n2)
-        Factor new_Qb = _Qa[_RTree[i].n1].marginal( IR( i ) );
-        _Qa[_RTree[i].n2] *= new_Qb.divided_by( _Qb[i] ); 
-        _Qb[i] = new_Qb;
-    }
-
-    // Normalize
-    for( size_t alpha = 0; alpha < nr_ORs(); alpha++ )
-        _Qa[alpha].normalize( Prob::NORMPROB );
-}
-
-
-// Really needs no init! Initial messages can be anything.
-void JTree::runShaferShenoy() {
-    // First pass
-    _logZ = 0.0;
-    for( size_t e = _RTree.size(); (e--) != 0; ) {
-        // send a message from _RTree[e].n2 to _RTree[e].n1
-        // or, actually, from the seperator IR(e) to _RTree[e].n1
-
-        size_t i = _RTree[e].n2;
-        size_t j = _RTree[e].n1;
-        
-        Factor piet = OR(i);
-        for( R_nb_cit k = nbOR(i).begin(); k != nbOR(i).end(); k++ )
-            if( *k != e )
-                piet *= message( i, *k );
-        message( j, e ) = piet.part_sum( IR(e) );
-        _logZ += log( message(j,e).normalize( Prob::NORMPROB ) );
-    }
-
-    // Second pass
-    for( size_t e = 0; e < _RTree.size(); e++ ) {
-        size_t i = _RTree[e].n1;
-        size_t j = _RTree[e].n2;
-        
-        Factor piet = OR(i);
-        for( R_nb_cit k = nbOR(i).begin(); k != nbOR(i).end(); k++ )
-            if( *k != e )
-                piet *= message( i, *k );
-        message( j, e ) = piet.marginal( IR(e) );
-    }
-
-    // Calculate beliefs
-    for( size_t alpha = 0; alpha < nr_ORs(); alpha++ ) {
-        Factor piet = OR(alpha);
-        for( R_nb_cit k = nbOR(alpha).begin(); k != nbOR(alpha).end(); k++ )
-            piet *= message( alpha, *k );
-        if( _RTree.empty() ) {
-            _logZ += log( piet.normalize( Prob::NORMPROB ) );
-            _Qa[alpha] = piet;
-        } else if( alpha == _RTree[0].n1 ) {
-            _logZ += log( piet.normalize( Prob::NORMPROB ) );
-            _Qa[alpha] = piet;
-        } else
-            _Qa[alpha] = piet.normalized( Prob::NORMPROB );
-    }
-
-    // Only for logZ (and for belief)...
-    for( size_t beta = 0; beta < nr_IRs(); beta++ ) 
-        _Qb[beta] = _Qa[nbIR(beta)[0]].marginal( IR(beta) );
-}
-
-
-double JTree::run() {
-    if( Updates() == UpdateType::HUGIN )
-        runHUGIN();
-    else if( Updates() == UpdateType::SHSH )
-        runShaferShenoy();
-    return 0.0;
-}
-
-
-Complex JTree::logZ() const {
-    Complex sum = 0.0;
-    for( size_t beta = 0; beta < nr_IRs(); beta++ )
-        sum += Complex(IR(beta).c()) * _Qb[beta].entropy();
-    for( size_t alpha = 0; alpha < nr_ORs(); alpha++ ) {
-        sum += Complex(OR(alpha).c()) * _Qa[alpha].entropy();
-        sum += (OR(alpha).log0() * _Qa[alpha]).totalSum();
-    }
-    return sum;
-}
-
-
-
-size_t JTree::findEfficientTree( const VarSet& ns, DEdgeVec &Tree, size_t PreviousRoot ) const {
-    // find new root clique (the one with maximal statespace overlap with ns)
-    size_t maxval = 0, maxalpha = 0;
-    for( size_t alpha = 0; alpha < nr_ORs(); alpha++ ) {
-        size_t val = (ns & OR(alpha).vars()).stateSpace();
-        if( val > maxval ) {
-            maxval = val;
-            maxalpha = alpha;
-        }
-    }
-
-//  for( size_t e = 0; e < _RTree.size(); e++ )
-//      cout << OR(_RTree[e].n1).vars() << "->" << OR(_RTree[e].n2).vars() << ",  ";
-//  cout << endl;
-    // grow new tree
-    Graph oldTree;
-    for( DEdgeVec::const_iterator e = _RTree.begin(); e != _RTree.end(); e++ )
-        oldTree.insert( UEdge(e->n1, e->n2) );
-    DEdgeVec newTree = GrowRootedTree( oldTree, maxalpha );
-//  cout << ns << ": ";
-//  for( size_t e = 0; e < newTree.size(); e++ )
-//      cout << OR(newTree[e].n1).vars() << "->" << OR(newTree[e].n2).vars() << ",  ";
-//  cout << endl;
-    
-    // identify subtree that contains variables of ns which are not in the new root
-    VarSet nsrem = ns / OR(maxalpha).vars();
-//  cout << "nsrem:" << nsrem << endl;
-    set<DEdge> subTree;
-    // for each variable in ns that is not in the root clique
-    for( VarSet::const_iterator n = nsrem.begin(); n != nsrem.end(); n++ ) {
-        // find first occurence of *n in the tree, which is closest to the root
-        size_t e = 0;
-        for( ; e != newTree.size(); e++ ) {
-            if( OR(newTree[e].n2).vars() && *n )
-                break;
-        }
-        assert( e != newTree.size() );
-
-        // track-back path to root and add edges to subTree
-        subTree.insert( newTree[e] );
-        size_t pos = newTree[e].n1;
-        for( ; e > 0; e-- )
-            if( newTree[e-1].n2 == pos ) {
-                subTree.insert( newTree[e-1] );
-                pos = newTree[e-1].n1;
-            }
-    }
-    if( PreviousRoot != (size_t)-1 && PreviousRoot != maxalpha) {
-        // find first occurence of PreviousRoot in the tree, which is closest to the new root
-        size_t e = 0;
-        for( ; e != newTree.size(); e++ ) {
-            if( newTree[e].n2 == PreviousRoot )
-                break;
-        }
-        assert( e != newTree.size() );
-
-        // track-back path to root and add edges to subTree
-        subTree.insert( newTree[e] );
-        size_t pos = newTree[e].n1;
-        for( ; e > 0; e-- )
-            if( newTree[e-1].n2 == pos ) {
-                subTree.insert( newTree[e-1] );
-                pos = newTree[e-1].n1;
-            }
-    }
-//  cout << "subTree: " << endl;
-//  for( set<DEdge>::const_iterator sTi = subTree.begin(); sTi != subTree.end(); sTi++ )
-//      cout << OR(sTi->n1).vars() << "->" << OR(sTi->n2).vars() << ",  ";
-//  cout << endl;
-
-    // Resulting Tree is a reordered copy of newTree
-    // First add edges in subTree to Tree
-    Tree.clear();
-    for( DEdgeVec::const_iterator e = newTree.begin(); e != newTree.end(); e++ )
-        if( subTree.count( *e ) ) {
-            Tree.push_back( *e );
-//          cout << OR(e->n1).vars() << "->" << OR(e->n2).vars() << ",  ";
-        }
-//  cout << endl;
-    // Then add edges pointing away from nsrem
-    // FIXME
-/*  for( DEdgeVec::const_iterator e = newTree.begin(); e != newTree.end(); e++ )
-        for( set<DEdge>::const_iterator sTi = subTree.begin(); sTi != subTree.end(); sTi++ )
-            if( *e != *sTi ) {
-                if( e->n1 == sTi->n1 || e->n1 == sTi->n2 ||
-                    e->n2 == sTi->n1 || e->n2 == sTi->n2 ) {
-                    Tree.push_back( *e );
-//                  cout << OR(e->n1).vars() << "->" << OR(e->n2).vars() << ",  ";
-                }
-            }*/
-    // FIXME
-/*  for( DEdgeVec::const_iterator e = newTree.begin(); e != newTree.end(); e++ )
-        if( find( Tree.begin(), Tree.end(), *e) == Tree.end() ) {
-            bool found = false;
-            for( VarSet::const_iterator n = nsrem.begin(); n != nsrem.end(); n++ )
-                if( (OR(e->n1).vars() && *n) ) {
-                    found = true;
-                    break;
-                }
-            if( found ) {
-                Tree.push_back( *e );
-                cout << OR(e->n1).vars() << "->" << OR(e->n2).vars() << ",  ";
-            }
-        }
-    cout << endl;*/
-    size_t subTreeSize = Tree.size();
-    // Then add remaining edges
-    for( DEdgeVec::const_iterator e = newTree.begin(); e != newTree.end(); e++ )
-        if( find( Tree.begin(), Tree.end(), *e ) == Tree.end() )
-            Tree.push_back( *e );
-
-    return subTreeSize;
-}
-
-
-// Cutset conditioning
-// assumes that run() has been called already
-Factor JTree::calcMarginal( const VarSet& ns ) {
-    vector<Factor>::const_iterator beta;
-    for( beta = _Qb.begin(); beta != _Qb.end(); beta++ )
-        if( beta->vars() >> ns )
-            break;
-    if( beta != _Qb.end() )
-        return( beta->marginal(ns) );
-    else {
-        vector<Factor>::const_iterator alpha;
-        for( alpha = _Qa.begin(); alpha != _Qa.end(); alpha++ )
-            if( alpha->vars() >> ns )
-                break;
-        if( alpha != _Qa.end() )
-            return( alpha->marginal(ns) );
-        else {
-            // Find subtree to do efficient inference
-            DEdgeVec T;
-            size_t Tsize = findEfficientTree( ns, T );
-
-            // Find remaining variables (which are not in the new root)
-            VarSet nsrem = ns / OR(T.front().n1).vars();
-            Factor Pns (ns, 0.0);
-            
-            multind mi( nsrem );
-
-            // Save _Qa and _Qb on the subtree
-            map<size_t,Factor> _Qa_old;
-            map<size_t,Factor> _Qb_old;
-            vector<size_t> b(Tsize, 0);
-            for( size_t i = Tsize; (i--) != 0; ) {
-                size_t alpha1 = T[i].n1;
-                size_t alpha2 = T[i].n2;
-                size_t beta;
-                for( beta = 0; beta < nr_IRs(); beta++ )
-                    if( UEdge( _RTree[beta].n1, _RTree[beta].n2 ) == UEdge( alpha1, alpha2 ) )
-                        break;
-                assert( beta != nr_IRs() );
-                b[i] = beta;
-
-                if( !_Qa_old.count( alpha1 ) )
-                    _Qa_old[alpha1] = _Qa[alpha1];
-                if( !_Qa_old.count( alpha2 ) )
-                    _Qa_old[alpha2] = _Qa[alpha2];
-                if( !_Qb_old.count( beta ) )
-                    _Qb_old[beta] = _Qb[beta];
-            }
-                
-            // For all states of nsrem
-            for( size_t j = 0; j < mi.max(); j++ ) {
-                vector<size_t> vi = mi.vi( j );
-                
-                // CollectEvidence
-                double logZ = 0.0;
-                for( size_t i = Tsize; (i--) != 0; ) {
-            //      Make outer region T[i].n1 consistent with outer region T[i].n2
-            //      IR(i) = seperator OR(T[i].n1) && OR(T[i].n2)
-
-                    size_t k = 0;
-                    for( VarSet::const_iterator n = nsrem.begin(); n != nsrem.end(); n++, k++ )
-                        if( _Qa[T[i].n2].vars() >> *n ) {
-                            Factor piet( *n, 0.0 );
-                            piet[vi[k]] = 1.0;
-                            _Qa[T[i].n2] *= piet; 
-                        }
-
-                    Factor new_Qb = _Qa[T[i].n2].part_sum( IR( b[i] ) );
-                    logZ += log(new_Qb.normalize( Prob::NORMPROB ));
-                    _Qa[T[i].n1] *= new_Qb.divided_by( _Qb[b[i]] ); 
-                    _Qb[b[i]] = new_Qb;
-                }
-                logZ += log(_Qa[T[0].n1].normalize( Prob::NORMPROB ));
-
-                Factor piet( nsrem, 0.0 );
-                piet[j] = exp(logZ);
-                Pns += piet * _Qa[T[0].n1].part_sum( ns / nsrem );      // OPTIMIZE ME
-
-                // Restore clamped beliefs
-                for( map<size_t,Factor>::const_iterator alpha = _Qa_old.begin(); alpha != _Qa_old.end(); alpha++ )
-                    _Qa[alpha->first] = alpha->second;
-                for( map<size_t,Factor>::const_iterator beta = _Qb_old.begin(); beta != _Qb_old.end(); beta++ )
-                    _Qb[beta->first] = beta->second;
-            }
-
-            return( Pns.normalized(Prob::NORMPROB) );
-        }
-    }
-}
-
-
-}
diff --git a/jtree.h b/jtree.h