Documentation improvement, interface changes and new example:
authorJoris Mooij <joris.mooij@tuebingen.mpg.de>
Mon, 19 Oct 2009 16:03:04 +0000 (18:03 +0200)
committerJoris Mooij <joris.mooij@tuebingen.mpg.de>
Mon, 19 Oct 2009 16:03:04 +0000 (18:03 +0200)
* Renamed Permute::convert_linear_index into Permute::convertLinearIndex
  (and provided an alias for backwards compatibility)
* Added examples/example_permute.cpp
* Improved documentation of include/dai/index.h

14 files changed:
ChangeLog
Makefile
OBSOLETE
examples/example_permute.cpp [new file with mode: 0644]
examples/example_permute.out [new file with mode: 0644]
examples/example_varset.cpp
include/dai/factor.h
include/dai/index.h
include/dai/prob.h
include/dai/util.h
include/dai/varset.h
src/emalg.cpp
src/factorgraph.cpp
src/matlab/matlab.cpp

index e28f7e0..9d5b639 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,6 @@
+* Renamed Permute::convert_linear_index into Permute::convertLinearIndex
+  (and provided an alias for backwards compatibility)
+* Added examples/example_permute.cpp
 * Added TProb<T>::divided_by(const TProb<T>&) const
 * Fixed bug in BipartiteGraph::eraseEdge()
 * Added python and octave ports for examples/example_sprinkler.cpp
index 85b32dd..7ff3579 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -103,7 +103,7 @@ MEX:=$(MEX) $(CCLIB) $(CCINC) $(MEXFLAGS)
 
 all : $(TARGETS)
 
-examples : examples/example$(EE) examples/example_bipgraph$(EE) examples/example_varset$(EE) examples/example_sprinkler$(EE)
+examples : examples/example$(EE) examples/example_bipgraph$(EE) examples/example_varset$(EE) examples/example_permute$(EE) examples/example_sprinkler$(EE)
 
 matlabs : matlab/dai$(ME) matlab/dai_readfg$(ME) matlab/dai_writefg$(ME) matlab/dai_potstrength$(ME)
 
@@ -202,6 +202,9 @@ examples/example_bipgraph$(EE) : examples/example_bipgraph.cpp $(HEADERS) $(LIB)
 examples/example_varset$(EE) : examples/example_varset.cpp $(HEADERS) $(LIB)/libdai$(LE)
        $(CC) $(CCO)examples/example_varset$(EE) examples/example_varset.cpp $(LIBS)
 
+examples/example_permute$(EE) : examples/example_permute.cpp $(HEADERS) $(LIB)/libdai$(LE)
+       $(CC) $(CCO)examples/example_permute$(EE) examples/example_permute.cpp $(LIBS)
+
 examples/example_sprinkler$(EE) : examples/example_sprinkler.cpp $(HEADERS) $(LIB)/libdai$(LE)
        $(CC) $(CCO)examples/example_sprinkler$(EE) examples/example_sprinkler.cpp $(LIBS)
 
@@ -303,7 +306,7 @@ ifneq ($(OS),WINDOWS)
 clean :
        -rm *$(OE)
        -rm matlab/*$(ME)
-       -rm examples/example$(EE) examples/example_bipgraph$(EE) examples/example_varset$(EE) examples/example_sprinkler$(EE)
+       -rm examples/example$(EE) examples/example_bipgraph$(EE) examples/example_varset$(EE) examples/example_permute$(EE) examples/example_sprinkler$(EE)
        -rm tests/testdai$(EE) tests/testem/testem$(EE) tests/testbbp$(EE)
        -rm utils/fg2dot$(EE) utils/createfg$(EE) utils/fginfo$(EE)
        -rm -R doc
index d4f22b8..ae6ac04 100644 (file)
--- a/OBSOLETE
+++ b/OBSOLETE
@@ -20,3 +20,4 @@ const Edge& BipartiteGraph::edge(size_t e) const;
 const std::vector<Edge>& BipartiteGraph::edges() const;
 size_t BipartiteGraph::VV2E(size_t n1, size_t n2) const;
 size_t BipartiteGraph::nr_edges() const;
+size_t Permute::convert_linear_index( size_t li ) const;
diff --git a/examples/example_permute.cpp b/examples/example_permute.cpp
new file mode 100644 (file)
index 0000000..c3b87c0
--- /dev/null
@@ -0,0 +1,84 @@
+/*  This file is part of libDAI - http://www.libdai.org/
+ *
+ *  libDAI is licensed under the terms of the GNU General Public License version
+ *  2, or (at your option) any later version. libDAI is distributed without any
+ *  warranty. See the file COPYING for more details.
+ *
+ *  Copyright (C) 2008-2009  Joris Mooij  [joris dot mooij at libdai dot org]
+ */
+
+
+#include <dai/varset.h>
+#include <dai/index.h>
+#include <iostream>
+#include <iomanip>
+
+using namespace std;
+using namespace dai;
+
+int main() {
+    Var x0(0, 2);   // Define binary  variable x0 (with label 0)
+    Var x1(1, 3);   // Define ternary variable x1 (with label 1)
+    Var x2(2, 2);   // Define binary  variable x2 (with label 2)
+
+    // Define vector V = (x1, x2, x0)
+    vector<Var> V;      // Define a vector of variables
+    V.push_back( x1 );  // V[0] = x1;
+    V.push_back( x2 );  // V[1] = x2;
+    V.push_back( x0 );  // V[2] = x0;
+    cout << "V = " << V << endl; // Note that the elements of X are not necessarily ordered according to their labels
+
+    // Define set X = {x0, x1, x2}
+    VarSet X; // empty
+    X |= x2;  // X = {x2}
+    X |= x0;  // X = {x0, x2}
+    X |= x1;  // X = {x0, x1, x2}
+    cout << "X = " << X << endl; // Note that the elements of X are ordered according to their labels
+
+    cout << "Note that the ordering of the variables in X is the canonical ordering" << endl;
+    cout << "(ascendingly according to their labels) but the ordering in V is different." << endl << endl;
+
+    // N = number of variables in V (and X)
+    size_t N = V.size();
+
+    // Define a Permute object based on the variables in V
+    Permute sigma(V);
+    // Each Var in V corresponds with a dimension in a multi-dimensional array.
+    // The permutation sigma permutes these dimensions from the canonical ordering
+    // (sorted ascendingly on the label of the variable, i.e., the same ordering as
+    // in X) into the ordering these variables have in V.
+    cout << "The permutation between both variable orderings is sigma = " << sigma.sigma() << ", or more verbosely:" << endl;
+    for( size_t n = 0; n < N; n++ )
+        cout << "  sigma[" << n << "] = " << sigma[n] << endl;
+    cout << "This means that variable V[sigma[n]] should correspond with the n'th variable in X (for n=0,...," << (N-1) << ")...";
+    // Check whether the permutation works as advertised
+    VarSet::const_iterator X_n = X.begin();
+    for( size_t n = 0; n < N; n++, X_n++ )
+        DAI_ASSERT( V[sigma[n]] == *X_n );
+    cout << "OK. " << endl << endl;
+
+    // Iterate over the joint states of the variables, according to the ordering in V
+    cout << "The states of the variables x0,x1,x2 are, according to the ordering in V:" << endl;
+    cout << "SV:  x0:  x1:  x2:" << endl;
+    std::vector<size_t> ranges;
+    for( size_t i = 0; i < V.size(); i++ )
+        ranges.push_back( V[i].states() );
+    for( multifor SV(ranges); SV.valid(); ++SV )
+        cout << setw(2) << (size_t)SV << "    " << SV[sigma[0]] << "    " << SV[sigma[1]] << "    " << SV[sigma[2]] << endl;
+    cout << endl;
+
+    // Iterate over the joint states of the variables, according to the canonical ordering in X
+    cout << "The states of the variables x0,x1,x2 are, according to the canonical ordering in X:" << endl;
+    cout << "SX:  x0:  x1:  x2:" << endl;
+    for( State SX(X); SX.valid(); SX++ )
+        cout << setw(2) << SX << "    " << SX(x0) << "    " << SX(x1) << "    " << SX(x2) << endl;
+    cout << endl;
+
+    // The main functionality of the Permute object is to calculate the induced permutation of linear indices of joint states
+    cout << "The permutation sigma induces the following permutation of linear indices of joint states:" << endl;
+    cout << "SV:  SX:" << endl;
+    for( size_t li = 0; li < X.nrStates(); li++ )
+        cout << setw(2) << li << "   " << setw(2) << sigma.convertLinearIndex( li ) << endl;
+
+    return 0;
+}
diff --git a/examples/example_permute.out b/examples/example_permute.out
new file mode 100644 (file)
index 0000000..46449d0
--- /dev/null
@@ -0,0 +1,55 @@
+V = (x1, x2, x0)
+X = {x0, x1, x2}
+Note that the ordering of the variables in X is the canonical ordering
+(ascendingly according to their labels) but the ordering in V is different.
+
+The permutation between both variable orderings is sigma = (2, 0, 1), or more verbosely:
+  sigma[0] = 2
+  sigma[1] = 0
+  sigma[2] = 1
+This means that variable V[sigma[n]] should correspond with the n'th variable in X (for n=0,...,2)...OK. 
+
+The states of the variables x0,x1,x2 are, according to the ordering in V:
+SV:  x0:  x1:  x2:
+ 0    0    0    0
+ 1    0    1    0
+ 2    0    2    0
+ 3    0    0    1
+ 4    0    1    1
+ 5    0    2    1
+ 6    1    0    0
+ 7    1    1    0
+ 8    1    2    0
+ 9    1    0    1
+10    1    1    1
+11    1    2    1
+
+The states of the variables x0,x1,x2 are, according to the canonical ordering in X:
+SX:  x0:  x1:  x2:
+ 0    0    0    0
+ 1    1    0    0
+ 2    0    1    0
+ 3    1    1    0
+ 4    0    2    0
+ 5    1    2    0
+ 6    0    0    1
+ 7    1    0    1
+ 8    0    1    1
+ 9    1    1    1
+10    0    2    1
+11    1    2    1
+
+The permutation sigma induces the following permutation of linear indices of joint states:
+SV:  SX:
+ 0    0
+ 1    2
+ 2    4
+ 3    6
+ 4    8
+ 5   10
+ 6    1
+ 7    3
+ 8    5
+ 9    7
+10    9
+11   11
index a2ac006..d272b0c 100644 (file)
@@ -9,6 +9,7 @@
 
 
 #include <dai/varset.h>
+#include <dai/index.h>
 #include <iostream>
 
 using namespace std;
@@ -30,7 +31,7 @@ int main() {
     cout << "VarSet " << X << " has " << X.nrStates() << " states (joint assignments of its variables)." << endl << endl;
 
     cout << "States of VarSets correspond to states of their constituent Vars:" << endl;
-    cout << "  state of x0:   state of x1:   state of X:" << endl;
+    cout << "  state of x0:   state of x1:   (linear) state of X:" << endl;
     for( size_t s1 = 0; s1 < x1.states(); s1++ ) // for all states s1 of x1
         for( size_t s0 = 0; s0 < x0.states(); s0++ ) { // for all states s0 of x0
             // store s0 and s1 in a map "states"
@@ -46,7 +47,7 @@ int main() {
         }
 
     cout << endl << "And vice versa:" << endl;
-    cout << "  state of x0:   state of x1:   state of X:" << endl;
+    cout << "  state of x0:   state of x1:   (linear) state of X:" << endl;
     for( size_t S = 0; S < X.nrStates(); S++ ) { // for all (joint) states of X
         // calculate states of x0 and x1 corresponding to state S of X
         map<Var,size_t> states = X.calcStates(S);
@@ -58,5 +59,12 @@ int main() {
         DAI_ASSERT( X.calcState(X.calcStates(S)) == S );
     }
 
+    cout << endl << "Iterating over all joint states using the State class:" << endl;
+    cout << "  state of x0:   state of x1:   (linear) state of X:   state of X (as a map):" << endl;
+    for( State S(X); S.valid(); S++ ) {
+        // output state of X and corresponding states of x0, x1
+        cout << "    " << S(x0) << "              " << S(x1) << "              " << S << "                      " << S.get() << endl;
+    }
+
     return 0;
 }
index 7fe40e9..9556fc6 100644 (file)
@@ -106,7 +106,7 @@ template <typename T> class TFactor {
         TFactor( const std::vector<Var> &vars, const std::vector<T> &p ) : _vs(vars.begin(), vars.end(), vars.size()), _p(p.size()) {
             Permute permindex(vars);
             for( size_t li = 0; li < p.size(); ++li )
-                _p[permindex.convert_linear_index(li)] = p[li];
+                _p[permindex.convertLinearIndex(li)] = p[li];
         }
 
         /// Constructs TFactor depending on the variable v, with uniform distribution
index 7bb3bad..ee6998b 100644 (file)
@@ -11,8 +11,8 @@
 
 
 /// \file
-/// \brief Defines the IndexFor, MultiFor, Permute and State classes
-/// \todo Improve documentation
+/// \brief Defines the IndexFor, multifor, Permute and State classes
+/// \todo Improve documentation of IndexFor
 
 
 #ifndef __defined_libdai_index_h
@@ -59,7 +59,7 @@ class IndexFor {
         std::vector<size_t> _count;
 
         /// For each variable in forVars, its number of possible values
-        std::vector<size_t> _dims;
+        std::vector<size_t> _ranges;
 
     public:
         /// Default constructor
@@ -71,19 +71,19 @@ class IndexFor {
         IndexFor( const VarSet& indexVars, const VarSet& forVars ) : _count( forVars.size(), 0 ) {
             long sum = 1;
 
-            _dims.reserve( forVars.size() );
+            _ranges.reserve( forVars.size() );
             _sum.reserve( forVars.size() );
 
             VarSet::const_iterator j = forVars.begin();
             for( VarSet::const_iterator i = indexVars.begin(); i != indexVars.end(); ++i ) {
                 for( ; j != forVars.end() && *j <= *i; ++j ) {
-                    _dims.push_back( j->states() );
+                    _ranges.push_back( j->states() );
                     _sum.push_back( (*i == *j) ? sum : 0 );
                 }
                 sum *= i->states();
             }
             for( ; j != forVars.end(); ++j ) {
-                _dims.push_back( j->states() );
+                _ranges.push_back( j->states() );
                 _sum.push_back( 0 );
             }
             _index = 0;
@@ -108,9 +108,9 @@ class IndexFor {
 
                 while( i < _count.size() ) {
                     _index += _sum[i];
-                    if( ++_count[i] < _dims[i] )
+                    if( ++_count[i] < _ranges[i] )
                         break;
-                    _index -= _sum[i] * _dims[i];
+                    _index -= _sum[i] * _ranges[i];
                     _count[i] = 0;
                     i++;
                 }
@@ -123,172 +123,216 @@ class IndexFor {
 };
 
 
-/// MultiFor makes it easy to perform a dynamic number of nested for loops.
+/// Tool for calculating permutations of linear indices of multi-dimensional arrays.
+class Permute {
+    private:
+        /// Stores the number of possible values of all indices
+        std::vector<size_t>  _ranges;
+        /// Stores the permutation
+        std::vector<size_t>  _sigma;
+
+    public:
+        /// Default constructor
+        Permute() : _ranges(), _sigma() {}
+
+        /// Construct from vector of index ranges and permutation
+        Permute( const std::vector<size_t> &rs, const std::vector<size_t> &sigma ) : _ranges(rs), _sigma(sigma) {
+            DAI_ASSERT( _ranges.size() == _sigma.size() );
+        }
+
+        /// Construct from vector of variables.
+        /** The implied permutation maps the index of each variable in \a vars according to the canonical ordering 
+         *  (i.e., sorted ascendingly according to their label) to the index it has in \a vars.
+         */
+        Permute( const std::vector<Var> &vars ) : _ranges(vars.size()), _sigma(vars.size()) {
+            for( size_t i = 0; i < vars.size(); ++i )
+                _ranges[i] = vars[i].states();
+            VarSet vs( vars.begin(), vars.end(), vars.size() );
+            VarSet::const_iterator vs_i = vs.begin();
+            for( size_t i = 0; i < vs.size(); ++i, ++vs_i )
+                _sigma[i] = find( vars.begin(), vars.end(), *vs_i ) - vars.begin();
+        }
+
+        /// Calculates a permuted linear index.
+        /** Converts the linear index \a li to a vector index, permutes its 
+         *  components, and converts it back to a linear index.
+         */
+        size_t convertLinearIndex( size_t li ) const {
+            size_t N = _ranges.size();
+
+            // calculate vector index corresponding to linear index
+            std::vector<size_t> vi;
+            vi.reserve( N );
+            size_t prod = 1;
+            for( size_t k = 0; k < N; k++ ) {
+                vi.push_back( li % _ranges[k] );
+                li /= _ranges[k];
+                prod *= _ranges[k];
+            }
+
+            // convert permuted vector index to corresponding linear index
+            prod = 1;
+            size_t sigma_li = 0;
+            for( size_t k = 0; k < N; k++ ) {
+                sigma_li += vi[_sigma[k]] * prod;
+                prod *= _ranges[_sigma[k]];
+            }
+
+            return sigma_li;
+        }
+
+        // OBSOLETE
+        /// For backwards compatibility (to be removed soon)
+        size_t convert_linear_index( size_t li ) const { return convertLinearIndex(li); }
+
+        /// Returns const reference to the permutation
+        const std::vector<size_t>& sigma() const { return _sigma; }
+
+        /// Returns reference to the permutation
+        std::vector<size_t>& sigma() { return _sigma; }
+
+        /// Returns the result of applying the permutation on \a i
+        size_t operator[]( size_t i ) const {
+#ifdef DAI_DEBUG
+            return _sigma.at(i);
+#else
+            return _sigma[i];
+#endif
+        }
+};
+
+
+/// multifor makes it easy to perform a dynamic number of nested \c for loops.
 /** An example of the usage is as follows:
  *  \code
- *  std::vector<size_t> dims;
- *  dims.push_back( 3 );
- *  dims.push_back( 4 );
- *  dims.push_back( 5 );
- *  for( MultiFor s(dims); s.valid(); ++s )
- *      cout << "linear index: " << (size_t)s << " corresponds to indices " << s[0] << ", " << s[1] << ", " << s[2] << endl;
+ *  std::vector<size_t> ranges;
+ *  ranges.push_back( 3 );
+ *  ranges.push_back( 4 );
+ *  ranges.push_back( 5 );
+ *  for( multifor s(ranges); s.valid(); ++s )
+ *      cout << "linear index: " << (size_t)s << " corresponds to indices " << s[2] << ", " << s[1] << ", " << s[0] << endl;
  *  \endcode
  *  which would be equivalent to:
  *  \code
  *  size_t s = 0;
- *  for( size_t s0 = 0; s0 < 3; s0++ )
+ *  for( size_t s2 = 0; s2 < 5; s2++ )
  *      for( size_t s1 = 0; s1 < 4; s1++ )
- *          for( size_t s2 = 0; s2 < 5; s++, s2++ )
- *              cout << "linear index: " << (size_t)s << " corresponds to indices " << s0 << ", " << s1 << ", " << s2 << endl;
+ *          for( size_t s0 = 0; s0 < 3; s++, s0++ )
+ *              cout << "linear index: " << (size_t)s << " corresponds to indices " << s2 << ", " << s1 << ", " << s0 << endl;
  *  \endcode
  */
-class MultiFor {
+class multifor {
     private:
-        std::vector<size_t>  _dims;
-        std::vector<size_t>  _states;
-        long                 _state;
+        /// Stores the number of possible values of all indices
+        std::vector<size_t>  _ranges;
+        /// Stores the current values of all indices
+        std::vector<size_t>  _indices;
+        /// Stores the current linear index
+        long                 _linear_index;
 
     public:
         /// Default constructor
-        MultiFor() : _dims(), _states(), _state(0) {}
+        multifor() : _ranges(), _indices(), _linear_index(0) {}
 
-        /// Initialize from vector of index dimensions
-        MultiFor( const std::vector<size_t> &d ) : _dims(d), _states(d.size(),0), _state(0) {}
+        /// Initialize from vector of index ranges
+        multifor( const std::vector<size_t> &d ) : _ranges(d), _indices(d.size(),0), _linear_index(0) {}
 
-        /// Return linear state
+        /// Returns linear index (i.e., the index in the Cartesian product space)
         operator size_t() const {
-            DAI_ASSERT( valid() );
-            return( _state );
+            DAI_DEBASSERT( valid() );
+            return( _linear_index );
         }
 
-        /// Return k'th index
+        /// Returns \a k 'th index
         size_t operator[]( size_t k ) const {
-            DAI_ASSERT( valid() );
-            DAI_ASSERT( k < _states.size() );
-            return _states[k];
+            DAI_DEBASSERT( valid() );
+            DAI_DEBASSERT( k < _indices.size() );
+            return _indices[k];
         }
 
-        /// Prefix increment operator
-        MultiFor & operator++() {
+        /// Increments the current indices (prefix)
+        multifor & operator++() {
             if( valid() ) {
-                _state++;
+                _linear_index++;
                 size_t i;
-                for( i = 0; i != _states.size(); i++ ) {
-                    if( ++(_states[i]) < _dims[i] )
+                for( i = 0; i != _indices.size(); i++ ) {
+                    if( ++(_indices[i]) < _ranges[i] )
                         break;
-                    _states[i] = 0;
+                    _indices[i] = 0;
                 }
-                if( i == _states.size() )
-                    _state = -1;
+                if( i == _indices.size() )
+                    _linear_index = -1;
             }
             return *this;
         }
 
-        /// Postfix increment operator
+        /// Increments the current indices (postfix)
         void operator++( int ) {
             operator++();
         }
 
-        /// Returns true if the current state is valid
+        /// Returns \c true if the current indices are valid
         bool valid() const {
-            return( _state >= 0 );
-        }
-};
-
-
-/// Tool for calculating permutations of multiple indices.
-class Permute {
-    private:
-        std::vector<size_t>  _dims;
-        std::vector<size_t>  _sigma;
-
-    public:
-        /// Default constructor
-        Permute() : _dims(), _sigma() {}
-
-        /// Construct from vector of index dimensions and permutation sigma
-        Permute( const std::vector<size_t> &d, const std::vector<size_t> &sigma ) : _dims(d), _sigma(sigma) {
-            DAI_ASSERT( _dims.size() == _sigma.size() );
-        }
-
-        /// Construct from vector of variables
-        Permute( const std::vector<Var> &vars ) : _dims(vars.size()), _sigma(vars.size()) {
-            VarSet vs( vars.begin(), vars.end(), vars.size() );
-            for( size_t i = 0; i < vars.size(); ++i )
-                _dims[i] = vars[i].states();
-            VarSet::const_iterator set_iter = vs.begin();
-            for( size_t i = 0; i < vs.size(); ++i, ++set_iter )
-                _sigma[i] = find( vars.begin(), vars.end(), *set_iter ) - vars.begin();
-        }
-
-        /// Calculates a permuted linear index.
-        /** Converts the linear index li to a vector index
-         *  corresponding with the dimensions in _dims, permutes it according to sigma,
-         *  and converts it back to a linear index  according to the permuted dimensions.
-         */
-        size_t convert_linear_index( size_t li ) const {
-            size_t N = _dims.size();
-
-            // calculate vector index corresponding to linear index
-            std::vector<size_t> vi;
-            vi.reserve( N );
-            size_t prod = 1;
-            for( size_t k = 0; k < N; k++ ) {
-                vi.push_back( li % _dims[k] );
-                li /= _dims[k];
-                prod *= _dims[k];
-            }
-
-            // convert permuted vector index to corresponding linear index
-            prod = 1;
-            size_t sigma_li = 0;
-            for( size_t k = 0; k < N; k++ ) {
-                sigma_li += vi[_sigma[k]] * prod;
-                prod *= _dims[_sigma[k]];
-            }
-
-            return sigma_li;
+            return( _linear_index >= 0 );
         }
 };
 
 
-/// Contains the joint state of variables within a VarSet and useful things to do with this information.
-/** This is very similar to a MultiFor, but tailored for Vars and Varsets.
+/// Makes it easy to iterate over all possible joint states of variables within a VarSet.
+/** A joint state of several variables can be represented in two different ways, by a map that maps each variable
+ *  to its own state, or by an integer that gives the index of the joint state in the canonical enumeration.
+ *
+ *  Both representations are useful, and the main functionality provided by the State class is to simplify iterating
+ *  over the various joint states of a VarSet and to provide access to the current state in both representations.
+ *
+ *  \note The same functionality could be achieved by simply iterating over the linear state and using VarSet::calcStates,
+ *  but the State class offers a more efficient implementation.
+ *
+ *  \note A State is very similar to a \link multifor \endlink, but tailored for Var 's and VarSet 's.
+ *
+ *  \see VarSet::calcState, VarSet::calcStates
  */
 class State {
     private:
+        /// Type for representing a joint state of some variables as a map, which maps each variable to its state
         typedef std::map<Var, size_t> states_type;
 
+        /// Current state (represented linearly)
         long                          state;
+
+        /// Current state (represented as a map)
         states_type                   states;
 
     public:
         /// Default constructor
         State() : state(0), states() {}
 
-        /// Initialize from VarSet
+        /// Initialize from VarSet, resetting the current state
         State( const VarSet &vs ) : state(0) {
             for( VarSet::const_iterator v = vs.begin(); v != vs.end(); v++ )
                 states[*v] = 0;
         }
 
-        /// Return linear state
+        /// Return current linear state
         operator size_t() const {
             DAI_ASSERT( valid() );
             return( state );
         }
 
-        /// Return state of variable n, or zero if n is not in this State
-        size_t operator() ( const Var &n ) const {
+        /// Return current state represented as a map
+        const states_type& get() const { return states; }
+
+        /// Return current state of variable \a v, or 0 if \a v is not in \c *this
+        size_t operator() ( const Var &v ) const {
             DAI_ASSERT( valid() );
-            states_type::const_iterator entry = states.find( n );
+            states_type::const_iterator entry = states.find( v );
             if( entry == states.end() )
                 return 0;
             else
                 return entry->second;
         }
 
-        /// Return linear state of variables in varset, setting them to zero if they are not in this State
+        /// Return linear state of variables in \a vs, assuming that variables that are not in \c *this are in state 0
         size_t operator() ( const VarSet &vs ) const {
             DAI_ASSERT( valid() );
             size_t vs_state = 0;
@@ -302,7 +346,7 @@ class State {
             return vs_state;
         }
 
-        /// Prefix increment operator
+        /// Increments the current state (prefix)
         void operator++( ) {
             if( valid() ) {
                 state++;
@@ -318,19 +362,36 @@ class State {
             }
         }
 
-        /// Postfix increment operator
+        /// Increments the current state (postfix)
         void operator++( int ) {
             operator++();
         }
 
-        /// Returns true if the current state is valid
+        /// Returns \c true if the current state is valid
         bool valid() const {
             return( state >= 0 );
         }
+
+        /// Resets the current state (to the joint state represented by linear state 0)
+        void reset() {
+            state = 0;
+            for( states_type::iterator s = states.begin(); s != states.end(); s++ )
+                s->second = 0;
+        }
 };
 
 
 } // end of namespace dai
 
 
+/** \example example_permute.cpp
+ *  This example shows how to use the Permute, multifor and State classes.
+ *
+ *  \section Output
+ *  \verbinclude examples/example_permute.out
+ *
+ *  \section Source
+ */
+
+
 #endif
index 04b566b..3660b16 100644 (file)
@@ -208,7 +208,7 @@ template <typename T> class TProb {
             return Z;
         }
 
-        /// Returns true if one or more entries are NaN
+        /// Returns \c true if one or more entries are NaN
         bool hasNaNs() const {
             bool foundnan = false;
             for( typename std::vector<T>::const_iterator x = _p.begin(); x != _p.end(); x++ )
@@ -219,7 +219,7 @@ template <typename T> class TProb {
             return foundnan;
         }
 
-        /// Returns true if one or more entries are negative
+        /// Returns \c true if one or more entries are negative
         bool hasNegatives() const {
             return (std::find_if( _p.begin(), _p.end(), std::bind2nd( std::less<T>(), (T)0 ) ) != _p.end());
         }
@@ -237,7 +237,7 @@ template <typename T> class TProb {
         }
 
         /// Lexicographical comparison
-        /** \pre this->size() == q.size()
+        /** \pre <tt>this->size() == q.size()</tt>
          */
         bool operator<= (const TProb<T> & q) const {
             DAI_DEBASSERT( size() == q.size() );
@@ -282,7 +282,7 @@ template <typename T> class TProb {
         }
 
         /// Returns pointwise logarithm
-        /** If zero==true, uses log(0)==0; otherwise, log(0)==-Inf.
+        /** If \a zero == \c true, uses <tt>log(0)==0</tt>; otherwise, <tt>log(0)==-Inf</tt>.
          */
         TProb<T> log(bool zero=false) const {
             TProb<T> l(*this);
@@ -291,7 +291,7 @@ template <typename T> class TProb {
         }
 
         /// Returns pointwise inverse
-        /** If zero==true; uses 1/0==0, otherwise 1/0==Inf.
+        /** If \a zero == \c true, uses <tt>1/0==0</tt>; otherwise, <tt>1/0==Inf</tt>.
          */
         TProb<T> inverse(bool zero=true) const {
             TProb<T> inv;
@@ -335,7 +335,7 @@ template <typename T> class TProb {
         }
 
         /// Applies logarithm pointwise
-        /** If zero==true, uses log(0)==0; otherwise, log(0)==-Inf.
+        /** If \a zero == \c true, uses <tt>log(0)==0</tt>; otherwise, <tt>log(0)==-Inf</tt>.
          */
         const TProb<T>& takeLog(bool zero=false) {
             if( zero ) {
@@ -466,7 +466,7 @@ template <typename T> class TProb {
     /// \name Operations with other equally-sized vectors
     //@{
         /// Pointwise addition with \a q
-        /** \pre this->size() == q.size()
+        /** \pre <tt>this->size() == q.size()</tt>
          */
         TProb<T>& operator+= (const TProb<T> & q) {
             DAI_DEBASSERT( size() == q.size() );
@@ -475,7 +475,7 @@ template <typename T> class TProb {
         }
 
         /// Pointwise subtraction of \a q
-        /** \pre this->size() == q.size()
+        /** \pre <tt>this->size() == q.size()</tt>
          */
         TProb<T>& operator-= (const TProb<T> & q) {
             DAI_DEBASSERT( size() == q.size() );
@@ -484,7 +484,7 @@ template <typename T> class TProb {
         }
 
         /// Pointwise multiplication with \a q
-        /** \pre this->size() == q.size()
+        /** \pre <tt>this->size() == q.size()</tt>
          */
         TProb<T>& operator*= (const TProb<T> & q) {
             DAI_DEBASSERT( size() == q.size() );
@@ -493,7 +493,7 @@ template <typename T> class TProb {
         }
 
         /// Pointwise division by \a q, where division by 0 yields 0
-        /** \pre this->size() == q.size()
+        /** \pre <tt>this->size() == q.size()</tt>
          *  \see divide(const TProb<T> &)
          */
         TProb<T>& operator/= (const TProb<T> & q) {
@@ -508,7 +508,7 @@ template <typename T> class TProb {
         }
 
         /// Pointwise division by \a q, where division by 0 yields +Inf
-        /** \pre this->size() == q.size()
+        /** \pre <tt>this->size() == q.size()</tt>
          *  \see operator/=(const TProb<T> &)
          */
         TProb<T>& divide (const TProb<T> & q) {
@@ -521,7 +521,7 @@ template <typename T> class TProb {
     /// \name Transformations with other equally-sized vectors
     //@{
         /// Returns sum of \c *this and \a q
-        /** \pre this->size() == q.size()
+        /** \pre <tt>this->size() == q.size()</tt>
          */
         TProb<T> operator+ (const TProb<T> & q) const {
             DAI_DEBASSERT( size() == q.size() );
@@ -531,7 +531,7 @@ template <typename T> class TProb {
         }
 
         /// Return \c *this minus \a q
-        /** \pre this->size() == q.size()
+        /** \pre <tt>this->size() == q.size()</tt>
          */
         TProb<T> operator- (const TProb<T> & q) const {
             DAI_DEBASSERT( size() == q.size() );
@@ -541,7 +541,7 @@ template <typename T> class TProb {
         }
 
         /// Return product of \c *this with \a q
-        /** \pre this->size() == q.size()
+        /** \pre <tt>this->size() == q.size()</tt>
          */
         TProb<T> operator* (const TProb<T> & q) const {
             DAI_DEBASSERT( size() == q.size() );
@@ -551,7 +551,7 @@ template <typename T> class TProb {
         }
 
         /// Returns quotient of \c *this with \a q, where division by 0 yields +Inf
-        /** \pre this->size() == q.size()
+        /** \pre <tt>this->size() == q.size()</tt>
          *  \see divided_by(const TProb<T> &)
          */
         TProb<T> operator/ (const TProb<T> & q) const {
@@ -562,7 +562,7 @@ template <typename T> class TProb {
         }
 
         /// Pointwise division by \a q, where division by 0 yields 0
-        /** \pre this->size() == q.size()
+        /** \pre <tt>this->size() == q.size()</tt>
          *  \see operator/(const TProb<T> &)
          */
         TProb<T> divided_by (const TProb<T> & q) const {
@@ -577,7 +577,7 @@ template <typename T> class TProb {
 
 /// Returns distance between \a p and \a q, measured using distance measure \a dt
 /** \relates TProb
- *  \pre this->size() == q.size()
+ *  \pre <tt>this->size() == q.size()</tt>
  */
 template<typename T> T dist( const TProb<T> &p, const TProb<T> &q, typename TProb<T>::DistType dt ) {
     DAI_DEBASSERT( p.size() == q.size() );
@@ -615,16 +615,17 @@ template<typename T> T dist( const TProb<T> &p, const TProb<T> &q, typename TPro
 /// Writes a TProb<T> to an output stream
 /** \relates TProb
  */
-template<typename T> std::ostream& operator<< (std::ostream& os, const TProb<T>& P) {
+template<typename T> std::ostream& operator<< (std::ostream& os, const TProb<T>& p) {
     os << "[";
-    std::copy( P.p().begin(), P.p().end(), std::ostream_iterator<T>(os, " ") );
+    std::copy( p.p().begin(), p.p().end(), std::ostream_iterator<T>(os, " ") );
     os << "]";
     return os;
 }
 
 
-/// Returns the TProb<T> containing the pointwise minimum of a and b (which should have equal size)
+/// Returns the pointwise minimum of \a a and \a b
 /** \relates TProb
+ *  \pre <tt>this->size() == q.size()</tt>
  */
 template<typename T> TProb<T> min( const TProb<T> &a, const TProb<T> &b ) {
     DAI_ASSERT( a.size() == b.size() );
@@ -638,8 +639,9 @@ template<typename T> TProb<T> min( const TProb<T> &a, const TProb<T> &b ) {
 }
 
 
-/// Returns the TProb<T> containing the pointwise maximum of a and b (which should have equal size)
+/// Returns the pointwise maximum of \a a and \a b
 /** \relates TProb
+ *  \pre <tt>this->size() == q.size()</tt>
  */
 template<typename T> TProb<T> max( const TProb<T> &a, const TProb<T> &b ) {
     DAI_ASSERT( a.size() == b.size() );
index 480c3ef..e2b4f13 100644 (file)
@@ -158,7 +158,7 @@ std::ostream& operator << (std::ostream& os, const std::vector<T> & x) {
 template<class T>
 std::ostream& operator << (std::ostream& os, const std::set<T> & x) {
     os << "{";
-   for( typename std::set<T>::const_iterator it = x.begin(); it != x.end(); it++ )
+    for( typename std::set<T>::const_iterator it = x.begin(); it != x.end(); it++ )
         os << (it != x.begin() ? ", " : "") << *it;
     os << "}";
     return os;
index b277bee..4f62a87 100644 (file)
@@ -154,7 +154,7 @@ class VarSet : public SmallSet<Var> {
         friend std::ostream& operator<<( std::ostream &os, const VarSet &vs )  {
             os << "{";
             for( VarSet::const_iterator v = vs.begin(); v != vs.end(); v++ )
-                os << (v != vs.begin() ? "," : "") << *v;
+                os << (v != vs.begin() ? ", " : "") << *v;
             os << "}";
             return( os );
         }
@@ -166,7 +166,7 @@ class VarSet : public SmallSet<Var> {
 
 
 /** \example example_varset.cpp
- *  This example shows how to use the Var and VarSet classes. It also explains the concept of "states" for VarSets.
+ *  This example shows how to use the Var, VarSet and State classes. It also explains the concept of "states" for VarSets.
  *
  *  \section Output
  *  \verbinclude examples/example_varset.out
index fbe8d8f..815d900 100644 (file)
@@ -199,7 +199,7 @@ void SharedParameters::collectSufficientStatistics( InfAlg &alg ) {
         Factor b = alg.belief(vs);
         Prob p( b.states(), 0.0 );
         for( size_t entry = 0; entry < b.states(); ++entry )
-            p[entry] = b[perm.convert_linear_index(entry)];
+            p[entry] = b[perm.convertLinearIndex(entry)];
         _estimation->addSufficientStatistics( p );
     }
 }
@@ -213,7 +213,7 @@ void SharedParameters::setParameters( FactorGraph &fg ) {
 
         Factor f( vs, 0.0 );
         for( size_t entry = 0; entry < f.states(); ++entry )
-            f[perm.convert_linear_index(entry)] = p[entry];
+            f[perm.convertLinearIndex(entry)] = p[entry];
 
         fg.setFactor( i->first, f );
     }
@@ -232,7 +232,7 @@ void SharedParameters::collectParameters( const FactorGraph &fg, std::vector<Rea
     DAI_ASSERT( f.vars() == _varsets[I] );
     const Permute &perm = _perms[I];
     for( size_t val_index = 0; val_index < f.states(); ++val_index )
-        outVals.push_back( f[perm.convert_linear_index(val_index)] );
+        outVals.push_back( f[perm.convertLinearIndex(val_index)] );
 }
 
 
index 2f0577b..b5a0ae6 100644 (file)
@@ -199,7 +199,7 @@ std::istream& operator>> ( std::istream& is, FactorGraph &fg ) {
 
             // store value, but permute indices first according
             // to internal representation
-            facs.back()[permindex.convert_linear_index( li  )] = val;
+            facs.back()[permindex.convertLinearIndex( li )] = val;
         }
     }
 
index a2b9e87..1e1c313 100644 (file)
@@ -119,7 +119,7 @@ vector<Factor> mx2Factors(const mxArray *psi, long verbose) {
         }
         Permute permindex( di, perm );
         for( size_t li = 0; li < prod; li++ )
-            factors.back()[permindex.convert_linear_index(li)] = factordata[li];
+            factors.back()[permindex.convertLinearIndex(li)] = factordata[li];
     }
 
     if( verbose >= 3 ) {
@@ -166,7 +166,7 @@ Factor mx2Factor(const mxArray *psi) {
     }
     Permute permindex( di, perm );
     for( size_t li = 0; li < prod; li++ )
-        factor[permindex.convert_linear_index(li)] = factordata[li];
+        factor[permindex.convertLinearIndex(li)] = factordata[li];
 
     return( factor );
 }