Hello Lei Zhang,

thank you for your interest in my package. I've not yet reached the
stage of writing documentation because the internal structure of the
package is still fluctuating too much. Further, my personal priorities
are doing research and finishing my PhD, not writing software. Finally,
I waited until I knew that at least somebody would be interested in
using the package.

So, it seems that I now really have to start writing documentation :)

Before doing that, I'll try to get you up and running. First, it helps
to know C++ and STL. The package can be used using the command line or
matlab interface, but the most flexibility is obtained by invoking it 
directly from C++ programs. The matlab interface is currently broken
for older MatLab versions, unfortunately, but I'm working on that.

Let's try to do this interactively. I'll assume that you have some
experience in building C++ packages. First, download the package and
unpack it. Then, try the quick start (in the README file):

Quick start
-----------
You need:
- a recent version of gcc (version 3.4 at least)
- the Boost C++ libraries
- GNU make

To build the source, do:
    
    make

If the build was successful, you can test the example program:

    ./example tests/alarm.fg

or the more elaborate test program:

    tests/test --aliases tests/aliases.conf --filename tests/alarm.fg --methods JTREE_HUGIN BP_SEQMAX


If this works, you can already do quite a lot with the package.
The example.cpp program illustrates some basic usage. Have a look
at the source. I'll explain it step-by-step, skipping obvious 
stuff (assuming you're familiar with C++):

  #include "alldai.h"

This include is enough to be able to use the whole library.

        FactorGraph fg;

This creates a FactorGraph object fg. It starts as an empty factor graph.
The functionality of the FactorGraph object can be found in factorgraph.h
and factorgraph.cpp. By the way, see the doc/ folder for automatically
created documentation (using doxygen) which contains nice HTML files that
enable you to browse the various data structures and class hierarchies.

        if( fg.ReadFromFile(argv[1]) ) {

FactorGraph::ReadFromFile tries to read the factor graph structure from a
file (all example factor graphs included have extension .fg). Some example
factor graphs are supplied in the directory test/ 
(alarm.fg, hoi1.fg, hoi2.fg, hoi3.fg, hoi4.fg, testfast.fg).

            cout << "Error reading " << argv[1] << endl;
            return 2;

If an error occurs, exit.

        } else {
            size_t  maxiter = 1000;
            double  tol = 1e-9;
            size_t  verb = 1;

fg now contains the factor graph in the file that was specified in the
command line. The variables above are parameters for the approximate
inference algorithm: the maximum number of iterations is 1000, the
tolerance used to detect convergence is 1e-9, and verbosity is 1
(0 means quiet, 3 means a lot of output running over the screen
during operation).

            Properties opts;

Now we are preparing a Properties object that contains
the various parameters of an approximate inference algorithm.

            opts.Set("maxiter",maxiter);
            opts.Set("tol",tol);
            opts.Set("verbose",verb);

A properties object contains <key,value> pairs, where value can be
of various types and key is a string. These properties are expected by
the Loopy BP algorithm.

            JTree jt( fg, opts("updates",string("HUGIN")) );

However, first we want to run JunctionTree to do exact inference so that we
know the exact marginals. We first create an object of class JTree,
which is build from the FactorGraph fg and the Properties objects opts above.
Actually, JTree expects two properties: "verbose" and "updates", where
"updates" can have value "HUGIN" or "SHSH" (respectively Hugin-type updates
or Shafer-Shenoy type updates). In my experience, HUGIN is a little faster,
so we'll use that. The operator() is overloaded for a Properties object to 
make it easy to add various <key,value> pairs; the new (temporary) object
opts("updates",string("HUGIN")) consists of the four keys "maxiter",
"tol", "verbose" and "updates", together with their respective values.

            jt.init();

Now we initialize the junction tree. Each inference method can be used as
follows: first, construct it. Then, invoke the init() method. Finally,
invoke the run() method to do the actual computation.

            jt.run();

This runs the junction tree algorithm on the FactorGraph fg.

            cout << "Exact single node marginals:" << endl;
            for( size_t i = 0; i < fg.nrVars(); i++ )
                cout << jt.belief(fg.var(i)) << endl;

Here we output the single node marginals computed by the jt object.
Variables can be accessed by their index which runs from 
0 .. fg.nrVars()-1. The ith variable is obtained by using fg.var(i).
The marginal (in this case the exact marginal) corresponding to that 
variable is returned by jt.belief(fg.var(i)).

Now we are going to do the same using Loopy BP instead of junction tree.

            BP bp(fg, opts("updates",string("SEQMAX")));

First we construct a BP object from the FactorGraph fg. Apart from the
"maxiter", "tol" and "verbose" properties, BP also expects an
"updates" property which specifies the message update scheme to be used
and can have four values: 
"SEQFIX" (sequential, fixed order), 
"SEQRND" (sequential, random order),
"SEQMAX" (sequential, maximum residual order, see [1])
"PARAL"  (parallel)
In my experience, SEQMAX is often the best choice.

            bp.init();

After constructing the bp object, it needs to be initialized.

            bp.run();

And then we can run the Loopy BP algorithm.

            cout << "Exact single node marginals:" << endl;

Ooops, that is an error: please replace "Exact" by "Loopy BP"
since we are now going to report the Loopy BP single node
marginals:

            for( size_t i = 0; i < fg.nrVars(); i++ )
                cout << bp.belief(fg.var(i)) << endl;


OK, please let me know whether you've succeeded in getting the
example program to compile and whether everything was sufficiently
clear up to now. If you've any questions already, just ask...

The next "lesson" will be the file format of the factorgraph files
so that you can run BP and other algorithms on your own factor
graphs.

Best regards,

Joris


On Tue, Feb 27, 2007 at 04:16:21PM -0800, zl wrote:
> Hello Joris Mooij,
> 
> I know from your website that you are developing the libDAI package
> for Factor Graph. I need a package to be able to do inference in Factor
> Graph. Your package seems to be able to do this. However, there are not
> many documentation in this package. I know from my advisor, Prof. Qiang Ji,
> that you are writing some documentation for your package. Can you send me
> some explanation/comments that you have finished? I am planning to use the loopy belief
> propagation at first. Any document/example that can help me to quickly learn and use
> your package is appreciated.
> 
> Thank you in advance!
> 
> best wishes,
> Lei Zhang
> ECSE department
> Rensselaer Polytechnic Institute
