Added functionality for reading files in the UAI approximate inference challenge...
[libdai.git] / utils / uai2fg.cpp
1 /* This file is part of libDAI - http://www.libdai.org/
2 *
3 * libDAI is licensed under the terms of the GNU General Public License version
4 * 2, or (at your option) any later version. libDAI is distributed without any
5 * warranty. See the file COPYING for more details.
6 *
7 * Copyright (C) 2008-2010 Joris Mooij [joris dot mooij at libdai dot org]
8 */
9
10
11 #include <iostream>
12 #include <fstream>
13 #include <cstdlib>
14 #include <dai/alldai.h>
15 #include <dai/io.h>
16
17
18 using namespace std;
19 using namespace dai;
20
21
22 int main( int argc, char *argv[] ) {
23 if ( argc != 4 ) {
24 cout << "This program is part of libDAI - http://www.libdai.org/" << endl << endl;
25 cout << "Usage: ./uai2fg <basename> <surgery> <verbose>" << endl << endl;
26 cout << "Converts input files in the UAI 2006/2008/2010 approximate inference evaluation format" << endl;
27 cout << "(see http://graphmod.ics.uci.edu/uai08/ and http://www.cs.huji.ac.il/project/UAI10/)" << endl;
28 cout << "to the libDAI factor graph format." << endl << endl;
29 cout << "Reads factor graph <basename.uai> and evidence <basename.uai.evid>" << endl;
30 cout << "and writes the resulting clamped factor graphs to <basename.X.fg>," << endl;
31 cout << "where X=0,1,2,... enumerates the different evidence cases." << endl << endl;
32 cout << "If surgery!=0, uses surgery on the factor graph (recommended)," << endl;
33 cout << "otherwise, just adds delta factors to the factor graph." << endl;
34 return 1;
35 } else {
36 string basename( argv[1] );
37 bool surgery = fromString<size_t>( argv[2] );
38 size_t verbose = fromString<size_t>( argv[3] );
39 string uainame = basename + ".uai";
40 string evidname = uainame + ".evid";
41
42 // output command line options
43 if( verbose ) {
44 cout << "Factorgraph filename: " << uainame << endl;
45 cout << "Evidence filename: " << evidname << endl;
46 cout << "Output basename: " << basename << endl;
47 cout << "Surgery: " << surgery << endl;
48 }
49
50 // read factor graph
51 vector<Var> vars;
52 vector<Factor> facs0;
53 vector<Permute> permutations;
54 if( verbose )
55 cout << "Reading factor graph..." << endl;
56 ReadUaiAieFactorGraphFile( uainame.c_str(), verbose, vars, facs0, permutations );
57 if( verbose )
58 cout << "Successfully read factor graph" << endl;
59
60 // read evidence
61 if( verbose )
62 cout << "Reading evidence..." << endl;
63 vector<map<size_t,size_t> > evid = ReadUaiAieEvidenceFile( evidname.c_str(), verbose );
64 if( verbose )
65 cout << "Successfully read " << evid.size() << " evidence cases" << endl;
66
67 // build output file names
68 vector<string> fgnames;
69 fgnames.reserve( evid.size() );
70 for( size_t ev = 0; ev < evid.size(); ev++ )
71 fgnames.push_back( basename + '.' + toString(ev) + ".fg" );
72
73 // construct clamped factor graphs which reflect observed evidence cases
74 if( verbose )
75 cout << "Constructing clamped factor graphs..." << endl;
76 vector<FactorGraph> fgs;
77 fgs.reserve( evid.size() );
78 for( size_t ev = 0; ev < evid.size(); ev++ ) {
79 if( verbose )
80 cout << " Evidence case " << ev << "..." << endl;
81 // copy vector of factors
82 vector<Factor> facs( facs0 );
83
84 // change factor graph to reflect observed evidence
85 if( verbose )
86 cout << " Applying evidence..." << endl;
87 if( surgery ) {
88 // replace factors with clamped variables with slices
89 for( size_t I = 0; I < facs.size(); I++ ) {
90 for( map<size_t,size_t>::const_iterator e = evid[ev].begin(); e != evid[ev].end(); e++ ) {
91 if( facs[I].vars() >> vars[e->first] ) {
92 if( verbose >= 2 )
93 cout << " Clamping " << e->first << " to value " << e->second << " in factor " << I << " = " << facs[I].vars() << endl;
94 facs[I] = facs[I].slice( vars[e->first], e->second );
95 if( verbose >= 2 )
96 cout << " ...remaining vars: " << facs[I].vars() << endl;
97 }
98 }
99 }
100 // remove empty factors
101 Real logZcorr = 0.0;
102 for( vector<Factor>::iterator I = facs.begin(); I != facs.end(); )
103 if( I->vars().size() == 0 ) {
104 logZcorr += std::log( (Real)(*I)[0] );
105 I = facs.erase( I );
106 } else
107 I++;
108 // multiply with logZcorr constant
109 if( facs.size() == 0 )
110 facs.push_back( Factor( VarSet(), std::exp(logZcorr) ) );
111 else
112 facs.front() *= std::exp(logZcorr);
113 }
114 // add delta factors corresponding to observed variable values
115 for( map<size_t,size_t>::const_iterator e = evid[ev].begin(); e != evid[ev].end(); e++ )
116 facs.push_back( createFactorDelta( vars[e->first], e->second ) );
117
118 // construct clamped factor graph
119 if( verbose )
120 cout << " Constructing factor graph..." << endl;
121 fgs.push_back( FactorGraph( facs.begin(), facs.end(), vars.begin(), vars.end(), facs.size(), vars.size() ) );
122
123 // write it to a file
124 if( verbose )
125 cout << " Saving factor graph as " << fgnames[ev] << "..." << endl;
126 fgs[ev].WriteToFile( fgnames[ev].c_str() );
127 }
128
129 if( verbose )
130 cout << "Done!" << endl;
131 }
132
133 return 0;
134 }