New git HEAD version
[libdai.git] / src / alldai.cpp
1 /* This file is part of libDAI - http://www.libdai.org/
2 *
3 * Copyright (c) 2006-2011, The libDAI authors. All rights reserved.
4 *
5 * Use of this source code is governed by a BSD-style license that can be found in the LICENSE file.
6 */
7
8
9 #include <string>
10 #include <fstream>
11 #include <dai/alldai.h>
12 #include <dai/properties.h>
13 #include <dai/exceptions.h>
14
15
16 namespace dai {
17
18
19 using namespace std;
20
21
22 class _builtinInfAlgs : public std::map<std::string, InfAlg *> {
23 public:
24 _builtinInfAlgs() {
25 operator[]( ExactInf().name() ) = new ExactInf;
26 #ifdef DAI_WITH_BP
27 operator[]( BP().name() ) = new BP;
28 #endif
29 #ifdef DAI_WITH_FBP
30 operator[]( FBP().name() ) = new FBP;
31 #endif
32 #ifdef DAI_WITH_TRWBP
33 operator[]( TRWBP().name() ) = new TRWBP;
34 #endif
35 #ifdef DAI_WITH_MF
36 operator[]( MF().name() ) = new MF;
37 #endif
38 #ifdef DAI_WITH_HAK
39 operator[]( HAK().name() ) = new HAK;
40 #endif
41 #ifdef DAI_WITH_LC
42 operator[]( LC().name() ) = new LC;
43 #endif
44 #ifdef DAI_WITH_TREEEP
45 operator[]( TreeEP().name() ) = new TreeEP;
46 #endif
47 #ifdef DAI_WITH_JTREE
48 operator[]( JTree().name() ) = new JTree;
49 #endif
50 #ifdef DAI_WITH_MR
51 operator[]( MR().name() ) = new MR;
52 #endif
53 #ifdef DAI_WITH_GIBBS
54 operator[]( Gibbs().name() ) = new Gibbs;
55 #endif
56 #ifdef DAI_WITH_CBP
57 operator[]( CBP().name() ) = new CBP;
58 #endif
59 #ifdef DAI_WITH_DECMAP
60 operator[]( DecMAP().name() ) = new DecMAP;
61 #endif
62 #ifdef DAI_WITH_GLC
63 operator[]( GLC().name() ) = new GLC;
64 #endif
65
66 }
67
68 ~_builtinInfAlgs() {
69 for( iterator it = begin(); it != end(); it++ )
70 delete it->second;
71 }
72 };
73
74
75 static _builtinInfAlgs allBuiltinInfAlgs;
76
77
78 std::map<std::string, InfAlg *>& builtinInfAlgs() {
79 return allBuiltinInfAlgs;
80 }
81
82
83 std::set<std::string> builtinInfAlgNames() {
84 std::set<std::string> algNames;
85 for( _builtinInfAlgs::const_iterator it = allBuiltinInfAlgs.begin(); it != allBuiltinInfAlgs.end(); it++ )
86 algNames.insert( it->first );
87 return algNames;
88 }
89
90
91 InfAlg *newInfAlg( const std::string &name, const FactorGraph &fg, const PropertySet &opts ) {
92 _builtinInfAlgs::const_iterator i = allBuiltinInfAlgs.find( name );
93 if( i == allBuiltinInfAlgs.end() )
94 DAI_THROWE(UNKNOWN_DAI_ALGORITHM, "Unknown inference algorithm: " + name);
95 InfAlg *ia = i->second;
96 return ia->construct( fg, opts );
97 }
98
99
100 InfAlg *newInfAlgFromString( const std::string &nameOpts, const FactorGraph &fg ) {
101 pair<string,PropertySet> no = parseNameProperties( nameOpts );
102 return newInfAlg( no.first, fg, no.second );
103 }
104
105
106 InfAlg *newInfAlgFromString( const std::string &nameOpts, const FactorGraph &fg, const std::map<std::string,std::string> &aliases ) {
107 pair<string,PropertySet> no = parseNameProperties( nameOpts, aliases );
108 return newInfAlg( no.first, fg, no.second );
109 }
110
111
112 std::pair<std::string, PropertySet> parseNameProperties( const std::string &s ) {
113 string::size_type pos = s.find_first_of('[');
114 string name;
115 PropertySet opts;
116 if( pos == string::npos ) {
117 name = s;
118 } else {
119 name = s.substr(0,pos);
120
121 stringstream ss;
122 ss << s.substr(pos,s.length());
123 ss >> opts;
124 }
125 return make_pair(name,opts);
126 }
127
128
129 std::pair<std::string, PropertySet> parseNameProperties( const std::string &s, const std::map<std::string,std::string> &aliases ) {
130 // break string into method[properties]
131 pair<string,PropertySet> ps = parseNameProperties(s);
132 bool looped = false;
133
134 // as long as 'method' is an alias, update:
135 while( aliases.find(ps.first) != aliases.end() && !looped ) {
136 string astr = aliases.find(ps.first)->second;
137 pair<string,PropertySet> aps = parseNameProperties(astr);
138 if( aps.first == ps.first )
139 looped = true;
140 // override aps properties by ps properties
141 aps.second.set( ps.second );
142 // replace ps by aps
143 ps = aps;
144 // repeat until method name == alias name ('looped'), or
145 // there is no longer an alias 'method'
146 }
147
148 return ps;
149 }
150
151
152 std::map<std::string,std::string> readAliasesFile( const std::string &filename ) {
153 // Read aliases
154 map<string,string> result;
155 ifstream infile;
156 infile.open( filename.c_str() );
157 if( infile.is_open() ) {
158 while( true ) {
159 string line;
160 getline( infile,line );
161 if( infile.fail() )
162 break;
163 if( (!line.empty()) && (line[0] != '#') ) {
164 string::size_type pos = line.find(':',0);
165 if( pos == string::npos )
166 DAI_THROWE(INVALID_ALIAS,"Invalid alias '" + line + "'");
167 else {
168 string::size_type posl = line.substr(0, pos).find_last_not_of(" \t");
169 string key = line.substr(0, posl + 1);
170 string::size_type posr = line.substr(pos + 1, line.length()).find_first_not_of(" \t");
171 string val = line.substr(pos + 1 + posr, line.length());
172 result[key] = val;
173 }
174 }
175 }
176 infile.close();
177 } else
178 DAI_THROWE(CANNOT_READ_FILE,"Error opening aliases file " + filename);
179 return result;
180 }
181
182
183 } // end of namespace dai