Improved documentation of include/dai/index.h
authorJoris Mooij <joris.mooij@tuebingen.mpg.de>
Mon, 19 Oct 2009 19:53:11 +0000 (21:53 +0200)
committerJoris Mooij <joris.mooij@tuebingen.mpg.de>
Mon, 19 Oct 2009 19:53:11 +0000 (21:53 +0200)
TODO
include/dai/index.h
src/bbp.cpp
src/bp.cpp
src/bp_dual.cpp

diff --git a/TODO b/TODO
index cdb7ee1..3c3bb0a 100644 (file)
--- a/TODO
+++ b/TODO
@@ -2,7 +2,6 @@ To do for the next release (0.2.3):
 
 Improve documentation:
 
-       index.h
        factor.h
        weightedgraph.h
        factorgraph.h
@@ -27,3 +26,10 @@ Improve documentation:
        evidence.h
        emalg.h
        doc.h
+
+Write a concept/notations page for the documentation,
+explaing the concepts of "state" (index into a 
+multi-dimensional array, e.g., one corresponding
+to the Cartesian product of statespaces of variables)
+and "linear index". This should make it easier to
+document index.h and varset.h
index ee6998b..7077e10 100644 (file)
@@ -11,8 +11,7 @@
 
 
 /// \file
-/// \brief Defines the IndexFor, multifor, Permute and State classes
-/// \todo Improve documentation of IndexFor
+/// \brief Defines the IndexFor, multifor, Permute and State classes, which all deal with indexing multi-dimensional arrays
 
 
 #ifndef __defined_libdai_index_h
@@ -31,21 +30,24 @@ namespace dai {
 /// Tool for looping over the states of several variables.
 /** The class IndexFor is an important tool for indexing Factor entries.
  *  Its usage can best be explained by an example.
- *  Assume indexVars, forVars are both VarSets.
+ *  Assume \a indexVars, \a forVars are both VarSet 's.
  *  Then the following code:
  *  \code
  *      IndexFor i( indexVars, forVars );
- *      for( ; i >= 0; ++i ) {
- *          // use long(i)
+ *      size_t iter = 0;
+ *      for( ; i.valid(); i++, iter++ ) {
+ *          cout << "State of forVars: " << forVars.calcStates( iter ) << "; ";
+ *          cout << "state of indexVars: " << indexVars.calcStates( long(i) ) << endl;
  *      }
  *  \endcode
- *  loops over all joint states of the variables in forVars,
- *  and (long)i is equal to the linear index of the corresponding
- *  state of indexVars, where the variables in indexVars that are
- *  not in forVars assume their zero'th value.
+ *  loops over all joint states of the variables in \a forVars,
+ *  and <tt>(long)i</tt> equals the linear index of the corresponding
+ *  state of \a indexVars, where the variables in \a indexVars that are
+ *  not in \a forVars assume their zero'th value.
  *  \idea Optimize all indices as follows: keep a cache of all (or only
  *  relatively small) indices that have been computed (use a hash). Then,
- *  instead of computing on the fly, use the precomputed ones.
+ *  instead of computing on the fly, use the precomputed ones. Here the
+ *  labels of the variables don't matter, but the ranges of the variables do.
  */
 class IndexFor {
     private:
@@ -56,19 +58,17 @@ class IndexFor {
         std::vector<long>   _sum;
 
         /// For each variable in forVars, the current state
-        std::vector<size_t> _count;
+        std::vector<size_t> _state;
 
         /// For each variable in forVars, its number of possible values
         std::vector<size_t> _ranges;
 
     public:
         /// Default constructor
-        IndexFor() {
-            _index = -1;
-        }
+        IndexFor() : _index(-1) {}
 
-        /// Constructor
-        IndexFor( const VarSet& indexVars, const VarSet& forVars ) : _count( forVars.size(), 0 ) {
+        /// Construct IndexFor object from \a indexVars and \a forVars
+        IndexFor( const VarSet& indexVars, const VarSet& forVars ) : _state( forVars.size(), 0 ) {
             long sum = 1;
 
             _ranges.reserve( forVars.size() );
@@ -89,41 +89,64 @@ class IndexFor {
             _index = 0;
         }
 
-        /// Sets the index back to zero
-        IndexFor& clear() {
-            fill( _count.begin(), _count.end(), 0 );
+        /// Resets the state
+        IndexFor& reset() {
+            fill( _state.begin(), _state.end(), 0 );
             _index = 0;
             return( *this );
         }
 
-        /// Conversion to long
+        // OBSOLETE
+        /// Conversion to \c long: returns linear index of the current state of indexVars
         operator long () const {
             return( _index );
         }
 
-        /// Pre-increment operator
+        // NEW VERSION
+        /*
+        /// Conversion to \c size_t: returns linear index of the current state of indexVars
+        operator size_t() const {
+            DAI_ASSERT( valid() );
+            return( _index );
+        }
+        */
+
+        /// Increments the current state of \a forVars (prefix)
         IndexFor& operator++ () {
             if( _index >= 0 ) {
                 size_t i = 0;
 
-                while( i < _count.size() ) {
+                while( i < _state.size() ) {
                     _index += _sum[i];
-                    if( ++_count[i] < _ranges[i] )
+                    if( ++_state[i] < _ranges[i] )
                         break;
                     _index -= _sum[i] * _ranges[i];
-                    _count[i] = 0;
+                    _state[i] = 0;
                     i++;
                 }
 
-                if( i == _count.size() )
+                if( i == _state.size() )
                     _index = -1;
             }
             return( *this );
         }
+
+        /// Increments the current state of \a forVars (postfix)
+        void operator++( int ) {
+            operator++();
+        }
+
+        /// Returns \c true if the current state is valid
+        bool valid() const {
+            return( _index >= 0 );
+        }
 };
 
 
 /// Tool for calculating permutations of linear indices of multi-dimensional arrays.
+/** \note This is mainly useful for converting indices into multi-dimensional arrays 
+ *  corresponding to joint states of variables to and from the canonical ordering used in libDAI.
+ */
 class Permute {
     private:
         /// Stores the number of possible values of all indices
index 084b7d5..96f8b19 100644 (file)
@@ -96,7 +96,7 @@ void BBP::RegenerateInds() {
         foreach( const Neighbor &I, _fg->nbV(i) ) {
             _ind_t index;
             index.reserve( _fg->factor(I).states() );
-            for( IndexFor k(_fg->var(i), _fg->factor(I).vars()); k >= 0; ++k )
+            for( IndexFor k(_fg->var(i), _fg->factor(I).vars()); k.valid(); ++k )
                 index.push_back( k );
             _indices[i].push_back( index );
         }
index a953666..e3043cc 100644 (file)
@@ -106,7 +106,7 @@ void BP::construct() {
 
             if( DAI_BP_FAST ) {
                 newEP.index.reserve( factor(I).states() );
-                for( IndexFor k( var(i), factor(I).vars() ); k >= 0; ++k )
+                for( IndexFor k( var(i), factor(I).vars() ); k.valid(); ++k )
                     newEP.index.push_back( k );
             }
 
index 6f4bdd7..d282d2d 100644 (file)
@@ -92,14 +92,14 @@ void BP_dual::calcNewM( size_t i, size_t _I ) {
         if( j != i ) { // for all j in I \ i
             Prob &n = msgN(j,j.dual);
             IndexFor ind( fg().var(j), fg().factor(I).vars() );
-            for( size_t x = 0; ind >= 0; x++, ++ind )
+            for( size_t x = 0; ind.valid(); x++, ++ind )
                 prod[x] *= n[ind];
         }
     // Marginalize onto i
     Prob marg( fg().var(i).states(), 0.0 );
     // ind is the precalculated Index(i,I) i.e. to x_I == k corresponds x_i == ind[k]
     IndexFor ind( fg().var(i), fg().factor(I).vars() );
-    for( size_t x = 0; ind >= 0; x++, ++ind )
+    for( size_t x = 0; ind.valid(); x++, ++ind )
         marg[ind] += prod[x];
 
     _msgs.Zm[i][_I] = marg.normalize();
@@ -141,7 +141,7 @@ void BP_dual::calcBeliefF( size_t I ) {
     foreach( const Neighbor &j, fg().nbF(I) ) {
         IndexFor ind( fg().var(j), fg().factor(I).vars() );
         Prob n( msgN(j,j.dual) );
-        for( size_t x = 0; ind >= 0; x++, ++ind )
+        for( size_t x = 0; ind.valid(); x++, ++ind )
             prod[x] *= n[ind];
     }
     _beliefs.Zb2[I] = prod.normalize();