Improve documentation of all .props structs.
-Improve documentation of inference algorithm constructors (indicate constraints on factor graph)
-
Write a concept/notations page for the documentation,
explaining the concepts of "state" (index into a
multi-dimensional array, e.g., one corresponding
# Doxygen will generate a detailed section even if there is only a brief
# description.
-ALWAYS_DETAILED_SEC = NO
+ALWAYS_DETAILED_SEC = YES
# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all
# inherited members of a class in the documentation of that class as if those
# The TAB_SIZE tag can be used to set the number of spaces in a tab.
# Doxygen uses this value to replace tabs by spaces in code fragments.
-TAB_SIZE = 8
+TAB_SIZE = 4
# This tag can be used to specify a number of aliases that acts
# as commands in the documentation. An alias has the form "name=value".
# If the EXTRACT_PRIVATE tag is set to YES all private members of a class
# will be included in the documentation.
-EXTRACT_PRIVATE = NO
+EXTRACT_PRIVATE = YES
# If the EXTRACT_STATIC tag is set to YES all static members of a file
# will be included in the documentation.
# If set to NO (the default) these classes will be included in the various
# overviews. This option has no effect if EXTRACT_ALL is enabled.
-HIDE_UNDOC_CLASSES = NO
+HIDE_UNDOC_CLASSES = YES
# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all
# friend (class|struct|union) declarations.
DAI_WITH_JTREE \
DAI_WITH_MR \
DAI_WITH_CBP \
- DAI_DEBUG \
- DAI_DEBASSERT
+ DAI_DEBUG
# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then
# this tag can be used to specify a list of macro names that should be expanded.
# The macro definition that is found in the sources will be used.
# Use the PREDEFINED tag if you want to use a different macro definition.
-EXPAND_AS_DEFINED = DAI_ENUM
+EXPAND_AS_DEFINED =
# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then
# doxygen's preprocessor will remove all function-like macros that are alone
* \param fg The FactorGraph that the algorithm should be applied to.
* \param opts A PropertySet specifying the options for the algorithm.
* \return Returns a pointer to the new InfAlg object; it is the responsibility of the caller to delete it later.
+ * \throw UNKNOWN_DAI_ALGORITHM if the requested name is not known/compiled in.
*/
InfAlg *newInfAlg( const std::string &name, const FactorGraph &fg, const PropertySet &opts );
/** \param nameOpts The name and options of the inference algorithm (should be in the format "name[key1=val1,key2=val2,...,keyn=valn]").
* \param fg The FactorGraph that the algorithm should be applied to.
* \return Returns a pointer to the new InfAlg object; it is the responsibility of the caller to delete it later.
- * \todo Support aliases like in testdai
+ * \throw UNKNOWN_DAI_ALGORITHM if the requested name is not known/compiled in.
+ * \todo Support aliases like in testdai.cpp
*/
InfAlg *newInfAlgFromString( const std::string &nameOpts, const FactorGraph &fg );
UpdateType updates;
/// Set members from PropertySet
+ /** \throw UNKNOWN_PROPERTY_TYPE if a Property key is not recognized
+ * \throw NOT_ALL_PROPERTIES_SPECIFIED if an expected Property is missing
+ */
void set(const PropertySet &opts);
/// Get members into PropertySet
PropertySet get() const;
/// \file
-/// \brief Defines the BipartiteGraph class
+/// \brief Defines the BipartiteGraph class, which represents a bipartite graph
#ifndef __defined_libdai_bipgraph_h
/// Used internally by isTree()
struct levelType {
- std::vector<size_t> ind1; // indices of nodes of type 1
- std::vector<size_t> ind2; // indices of nodes of type 2
+ /// Indices of nodes of type 1
+ std::vector<size_t> ind1;
+ /// Indices of nodes of type 2
+ std::vector<size_t> ind2;
};
// OBSOLETE
std::string clamp_outfile;
/// Set members from PropertySet
+ /** \throw UNKNOWN_PROPERTY_TYPE if a Property key is not recognized
+ * \throw NOT_ALL_PROPERTIES_SPECIFIED if an expected Property is missing
+ */
void set(const PropertySet &opts);
/// Get members into PropertySet
PropertySet get() const;
/// \todo At present, CBP::getInfAlg() only returns a BP instance
InfAlg* getInfAlg();
- /// Sets variable beliefs, factor beliefs and log partition sum
+ /// Sets variable beliefs, factor beliefs and log partition sum to the specified values
/** \param bs should be a concatenation of the variable beliefs followed by the factor beliefs
+ * \param logZ log partition sum
*/
void setBeliefs( const std::vector<Factor> &bs, Real logZ );
/// \file
-/// \brief Defines class ClusterGraph, which is mainly useful for the junction tree algorithm
+/// \brief Defines class ClusterGraph, which is used by JTree, TreeEP and HAK
#ifndef __defined_libdai_clustergraph_h
/// \file
-/// \brief Defines abstract base class InfAlg, its descendant DAIAlg<>, the specializations DAIAlgFG and DAIAlgRG and some generic inference methods.
+/// \brief Defines the general interface for inference methods in libDAI (classes InfAlg, DaiAlg<>, DaiAlgFG and DaiAlgRG).
#ifndef __defined_libdai_daialg_h
/// Initializes all data structures corresponding to some set of variables.
/** This method can be used to do a partial initialization after a part of the factor graph has changed.
* Instead of initializing all data structures, it only initializes those involving the variables in \a vs.
+ * \throw NOT_IMPLEMENTED if not implemented/supported
*/
virtual void init( const VarSet &vs ) = 0;
/// Returns the (approximate) marginal probability distribution of a set of variables.
/** \note Before this method is called, run() should have been called.
+ * \throw NOT_IMPLEMENTED if not implemented/supported
*/
virtual Factor belief( const VarSet &vs ) const = 0;
/// \name Backup/restore mechanism for factors
//@{
/// Make a backup copy of factor \a I
+ /** \throw MULTIPLE_UNDO if a backup already exists
+ */
virtual void backupFactor( size_t I ) = 0;
/// Make backup copies of all factors involving the variables in \a vs
+ /** \throw MULTIPLE_UNDO if a backup already exists
+ */
virtual void backupFactors( const VarSet &vs ) = 0;
/// Restore factor \a I from its backup copy
* where each of those sections follows the format described in the next
* subsection.
*
- * \subsection fileformats-sharedparameters Shared parameters section in EM file
+ * \subsection fileformats-emalg-sharedparameters Shared parameters section in EM file
*
* A shared parameters section of an .em file starts with a single line
* consisting of the name of a ParameterEstimation subclass
* Then, each of these factors is specified on separate lines (possibly
* seperated by empty lines), where each line consists of several fields
* seperated by a space or a tab character. The first field contains
- * the index of the factor in the factor graph. The
- * following fields specify the ordering of the variables on which that
- * factor depends, i.e., they form a permutation of the labels of the
- * variables belonging to that factor. The permutation corresponds to the
- * mapping from the ordering of the variables that is used in the
- * SharedParameters object to the canonical ordering of the variables
- * (i.e., sorted ascendingly according to their labels) which is used in
- * the internal representation of the Factor object.
+ * the index of the factor in the factor graph. The following fields should
+ * contain the variable labels of the variables on which that factor depends,
+ * in a specific ordering. This ordering can be different from the canonical
+ * ordering of the variables used internally in libDAI (which would be sorted
+ * ascendingly according to the variable labels). The odering of the variables
+ * specifies the implicit ordering of the shared parameters: when iterating
+ * over all shared parameters, the corresponding index of the first variable
+ * changes fastest (in the inner loop), and the corresponding index of the
+ * last variable changes slowest (in the outer loop). By choosing the right
+ * ordering, it is possible to let different factors (depending on different
+ * variables) share parameters in parameter learning using EM.
*/
/** \page license License
/// \file
-/// \brief Defines classes related to Expectation Maximization: EMAlg, ParameterEstimation, CondProbEstimation and SharedParameters
+/// \brief Defines classes related to Expectation Maximization (EMAlg, ParameterEstimation, CondProbEstimation and SharedParameters)
namespace dai {
/** \param method Name of the subclass that should be constructed;
* \param p Parameters passed to constructor of subclass.
* \note \a method should either be in the default registry or should be registered first using registerMethod().
+ * \throw UNKNOWN_PARAMETER_ESTIMATION_METHOD if the requested \a method is not registered.
*/
static ParameterEstimation* construct( const std::string &method, const PropertySet &p );
private:
/// Maps factor indices to the corresponding VarSets
std::map<FactorIndex, VarSet> _varsets;
- /// Maps factor indices to the corresponding Permute objects that permute the desired ordering into the canonical ordering
+ /// Maps factor indices to the corresponding Permute objects that permute the canonical ordering into the desired ordering
std::map<FactorIndex, Permute> _perms;
/// Maps factor indices to the corresponding desired variable orderings
FactorOrientations _varorders;
/// Indicates whether \c *this gets ownership of _estimation
bool _ownEstimation;
- /// Calculates the permutation that permutes the variables in varorder into the canonical ordering
- /** \param varorder Given ordering of variables
- * \param outVS Contains variables in \varorder represented as a VarSet
- * \return Permute object for permuting variables in varorder into the canonical libDAI ordering
+ /// Calculates the permutation that permutes the canonical ordering into the desired ordering
+ /** \param varOrder Desired ordering of variables
+ * \param outVS Contains variables in \a varOrder represented as a VarSet
+ * \return Permute object for permuting variables in varOrder from the canonical libDAI ordering into the desired ordering
*/
- static Permute calculatePermutation( const std::vector<Var> &varorder, VarSet &outVS );
+ static Permute calculatePermutation( const std::vector<Var> &varOrder, VarSet &outVS );
/// Initializes _varsets and _perms from _varorders and checks whether their state spaces correspond with _estimation.probSize()
void setPermsAndVarSetsFromVarOrders();
/// Construct a SharedParameters object from an input stream \a is and a factor graph \a fg
/** \see \ref fileformats-emalg-sharedparameters
+ * \throw INVALID_EMALG_FILE if the input stream is not valid
*/
SharedParameters( std::istream &is, const FactorGraph &fg );
*/
class MaximizationStep {
private:
+ /// Vector of parameter estimation tasks of which this maximization step consists
std::vector<SharedParameters> _params;
public:
namespace dai {
-/// Stores joint state of a set of variables
-typedef std::map<Var, size_t> Observation;
-
-
/// Stores a data set consisting of multiple samples, where each sample is the observed joint state of some variables.
/** \note Each sample can describe the joint state of a different set of variables,
* in order to be able to deal with missing data.
* \author Charles Vaske
*/
class Evidence {
+ public:
+ /// Stores joint state of a set of variables
+ typedef std::map<Var, size_t> Observation;
+
private:
/// Each sample is an observed joint state of some variables
std::vector<Observation> _samples;
/** \param is Input stream in .tab file format, describing joint observations of variables in \a fg
* \param fg Factor graph describing the corresponding variables
* \see \ref fileformats-evidence
+ * \throw INVALID_EVIDENCE_FILE if the input stream is not valid
*/
void addEvidenceTabFile( std::istream& is, FactorGraph& fg );
/// Assertion mechanism similar to DAI_ASSERT which is only active if DAI_DEBUG is defined
#define DAI_DEBASSERT(x) do {DAI_ASSERT(x);} while(0)
#else
-#define DAI_DEBASSERT(X) do {} while(0)
+#define DAI_DEBASSERT(x) do {} while(0)
#endif
/// \file
-/// \brief Defines the FactorGraph class
+/// \brief Defines the FactorGraph class, which represents factor graphs (e.g., Bayesian networks or Markov random fields)
#ifndef __defined_libdai_factorgraph_h
}
/// Makes a backup of the \a I 'th factor
+ /** \throw MULTIPLE_UNDO if a backup already exists
+ */
void backupFactor( size_t I );
/// Restores the \a I 'th factor from the backup (it should be backed up first)
void restoreFactor( size_t I );
/// Backup the factors specified by indices in \a facs
+ /** \throw MULTIPLE_UNDO if a backup already exists
+ */
virtual void backupFactors( const std::set<size_t> & facs );
/// Restore all factors to the backup copies
virtual void restoreFactors();
/// Makes a backup of all factors connected to a set of variables
+ /** \throw MULTIPLE_UNDO if a backup already exists
+ */
void backupFactors( const VarSet &ns );
/// Restores all factors connected to a set of variables from their backups
//@{
/// Reads a factor graph from a file
/** \see \ref fileformats-factorgraph
+ * \throw CANNOT_READ_FILE if the file cannot be opened
+ * \throw INVALID_FACTORGRAPH_FILE if the file is not valid
*/
void ReadFromFile( const char *filename );
/// Writes a factor graph to a file
/** \see \ref fileformats-factorgraph
+ * \throw CANNOT_WRITE_FILE if the file cannot be written
*/
void WriteToFile( const char *filename, size_t precision=15 ) const;
/// Reads a factor graph from an input stream
/** \see \ref fileformats-factorgraph
+ * \throw INVALID_FACTORGRAPH_FILE if the input stream is not valid
*/
friend std::istream& operator>> (std::istream &is, FactorGraph &fg );
/** \param fg factor graph (which has to be connected);
* \param opts parameters;
* \param automatic if \c true, construct the junction tree automatically, using the MinFill heuristic.
+ * \throw FACTORGRAPH_NOT_CONNECTED if \a fg is not connected
*/
JTree( const FactorGraph &fg, const PropertySet &opts, bool automatic=true );
//@}
MR() : DAIAlgFG(), supported(), con(), nb(), tJ(), theta(), M(), kindex(), cors(), N(), Mag(), _maxdiff(), _iters(), props() {}
/// Construct from FactorGraph \a fg and PropertySet \a opts
+ /** \note This implementation only deals with binary variables and pairwise interactions.
+ * \throw NOT_IMPLEMENTED if \a fg has factors depending on three or more variables or has variables with more than two possible states.
+ */
MR( const FactorGraph &fg, const PropertySet &opts );
/// Calculate sum over all even/odd subsets B of \a A of _tJ(j,B) appM(j,B)
/** \param j variable index
* \param A subset of neighbors of variable \a j
+ * \param sum_even on return, will contain the sum over all even subsets
+ * \param sum_odd on return, will contain the sum over all odd subsets
*/
void sum_subs(size_t j, sub_nb A, Real *sum_even, Real *sum_odd);
};
/// \file
-/// \brief Defines TProb<> and Prob classes which represent (probability) vectors
+/// \brief Defines TProb<> and Prob classes which represent (probability) vectors (e.g., probability distributions of discrete random variables)
#ifndef __defined_libdai_prob_h
}
/// Returns normalized copy of \c *this, using the specified norm
+ /** \throw NOT_NORMALIZABLE if the norm is zero
+ */
TProb<T> normalized( NormType norm = NORMPROB ) const {
T Z = 0;
if( norm == NORMPROB )
}
/// Normalizes vector using the specified norm
+ /** \throw NOT_NORMALIZABLE if the norm is zero
+ */
T normalize( NormType norm=NORMPROB ) {
T Z = 0;
if( norm == NORMPROB )
/// \file
-/// \brief Defines the Property and PropertySet classes
+/// \brief Defines the Property and PropertySet classes, which are mainly used for managing parameters of inference algorithms
#ifndef __defined_libdai_properties_h
/// Reads a PropertySet object from an input stream.
/** It expects a string in the format <tt>"[key1=val1,key2=val2,...,keyn=valn]"</tt>.
* Values are stored as strings.
+ * \throw MALFORMED_PROPERTY if the string is not in the expected format
*/
friend std::istream& operator>> ( std::istream& is, PropertySet& ps );
//@}
/// \file
-/// \brief Defines classes Region, FRegion and RegionGraph.
+/// \brief Defines classes Region, FRegion and RegionGraph, which implement a particular subclass of region graphs.
#ifndef __defined_libdai_regiongraph_h
private:
/// Stores the data structures needed to efficiently update the approximation of an off-tree factor
+ /// \todo Write documentation
class TreeEPSubTree {
private:
std::vector<Factor> _Qa;
}
/// Construct from FactorGraph \a fg and PropertySet \a opts
+ /** \note The factor graph has to be connected.
+ * \throw FACTORGRAPH_NOT_CONNECTED if \a fg is not connected
+ */
TreeEP( const FactorGraph &fg, const PropertySet &opts );
$text .= <<EOF;
/// Set members from PropertySet
+ /** \\throw UNKNOWN_PROPERTY_TYPE if a Property key is not recognized
+ * \\throw NOT_ALL_PROPERTIES_SPECIFIED if an expected Property is missing
+ */
void set(const PropertySet &opts);
/// Get members into PropertySet
PropertySet get() const;
}
-Permute SharedParameters::calculatePermutation( const std::vector<Var> &varorder, VarSet &outVS ) {
- // Collect all labels and dimensions, and order them in vs
- std::vector<size_t> dims;
- dims.reserve( varorder.size() );
- std::vector<long> labels;
- labels.reserve( varorder.size() );
- for( size_t i = 0; i < varorder.size(); i++ ) {
- dims.push_back( varorder[i].states() );
- labels.push_back( varorder[i].label() );
- outVS |= varorder[i];
- }
-
- // Construct the sigma array for the permutation object
- std::vector<size_t> sigma;
- sigma.reserve( dims.size() );
- for( VarSet::iterator set_iterator = outVS.begin(); sigma.size() < dims.size(); ++set_iterator )
- sigma.push_back( find(labels.begin(), labels.end(), set_iterator->label()) - labels.begin() );
-
- return Permute( dims, sigma );
+Permute SharedParameters::calculatePermutation( const std::vector<Var> &varOrder, VarSet &outVS ) {
+ outVS = VarSet( varOrder.begin(), varOrder.end(), varOrder.size() );
+ return Permute( varOrder );
}
// Lookup the factor in the factorgraph
if( fields.size() < 1 )
- DAI_THROW(INVALID_EMALG_FILE);
+ DAI_THROWE(INVALID_EMALG_FILE,"Empty line unexpected");
std::istringstream iss;
iss.str( fields[0] );
size_t factor;
iss >> factor;
const VarSet &vs = fg.factor(factor).vars();
if( fields.size() != vs.size() + 1 )
- DAI_THROW(INVALID_EMALG_FILE);
+ DAI_THROWE(INVALID_EMALG_FILE,"Number of fields does not match factor size");
// Construct the vector of Vars
std::vector<Var> var_order;
if( vsi->label() == label )
break;
if( vsi == vs.end() )
- DAI_THROW(INVALID_EMALG_FILE);
+ DAI_THROWE(INVALID_EMALG_FILE,"Specified variables do not match the factor variables");
var_order.push_back( *vsi );
}
_varorders[factor] = var_order;
Factor b = alg.belief(vs);
Prob p( b.states(), 0.0 );
for( size_t entry = 0; entry < b.states(); ++entry )
- p[entry] = b[perm.convertLinearIndex(entry)];
+ p[entry] = b[perm.convertLinearIndex(entry)]; // apply inverse permutation
_estimation->addSufficientStatistics( p );
}
}
for( Evidence::const_iterator e = _evidence.begin(); e != _evidence.end(); ++e ) {
InfAlg* clamped = _estep.clone();
// Apply evidence
- for( Observation::const_iterator i = e->begin(); i != e->end(); ++i )
+ for( Evidence::Observation::const_iterator i = e->begin(); i != e->end(); ++i )
clamped->clamp( clamped->fg().findVar(i->first), i->second );
clamped->init();
clamped->run();
getline (is,line);
if( is.fail() )
- DAI_THROW(INVALID_FACTORGRAPH_FILE);
+ DAI_THROWE(INVALID_FACTORGRAPH_FILE,"Expecting empty line");
map<long,size_t> vardims;
for( size_t I = 0; I < nr_Factors; I++ ) {
cerr << " dimensions: " << dims << endl;
// add the Factor
- VarSet I_vars;
+ vector<Var> Ivars;
+ Ivars.reserve( nr_members );
for( size_t mi = 0; mi < nr_members; mi++ ) {
map<long,size_t>::iterator vdi = vardims.find( labels[mi] );
if( vdi != vardims.end() ) {
DAI_THROWE(INVALID_FACTORGRAPH_FILE,"Variable with label " + boost::lexical_cast<string>(labels[mi]) + " has inconsistent dimensions.");
} else
vardims[labels[mi]] = dims[mi];
- I_vars |= Var(labels[mi], dims[mi]);
+ Ivars.push_back( Var(labels[mi], dims[mi]) );
}
- facs.push_back( Factor( I_vars, (Real)0 ) );
-
- // calculate permutation sigma (internally, members are sorted)
- vector<size_t> 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 )
- cerr << " sigma: " << sigma << endl;
+ facs.push_back( Factor( VarSet( Ivars.begin(), Ivars.end(), Ivars.size() ), (Real)0 ) );
- // calculate multindices
- Permute permindex( dims, sigma );
+ // calculate permutation object
+ Permute permindex( Ivars );
// read values
size_t nr_nonzeros;
getline(is,line);
is >> val;
- // store value, but permute indices first according
- // to internal representation
+ // store value, but permute indices first according to internal representation
facs.back()[permindex.convertLinearIndex( li )] = val;
}
}
TreeEP::TreeEP( const FactorGraph &fg, const PropertySet &opts ) : JTree(fg, opts("updates",string("HUGIN")), false), _maxdiff(0.0), _iters(0), props(), _Q() {
setProperties( opts );
- DAI_ASSERT( fg.isConnected() );
+ if( !isConnected() )
+ DAI_THROW(FACTORGRAPH_NOT_CONNECTED);
if( opts.hasKey("tree") ) {
construct( opts.GetAs<RootedTree>("tree") );