Cleaned up BBP and improved documentation of include/dai/bbp.h
[libdai.git] / src / cbp.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) 2009 Frederik Eaton [frederik at ofb dot net]
8 */
9
10
11 #include <iostream>
12 #include <sstream>
13 #include <map>
14 #include <set>
15 #include <algorithm>
16
17 #include <dai/util.h>
18 #include <dai/properties.h>
19 #include <dai/gibbs.h>
20 #include <dai/bp.h>
21 #include <dai/cbp.h>
22 #include <dai/bbp.h>
23
24
25 namespace dai {
26
27
28 using namespace std;
29 using boost::shared_ptr;
30
31
32 const char *CBP::Name = "CBP";
33
34
35 void CBP::setBeliefs( const std::vector<Factor> &bs, Real logZ ) {
36 size_t i = 0;
37 _beliefsV.clear();
38 _beliefsV.reserve( nrVars() );
39 _beliefsF.clear();
40 _beliefsF.reserve( nrFactors() );
41 for( i = 0; i < nrVars(); i++ )
42 _beliefsV.push_back( bs[i] );
43 for( ; i < nrVars() + nrFactors(); i++ )
44 _beliefsF.push_back( bs[i] );
45 _logZ = logZ;
46 }
47
48
49 void CBP::construct() {
50 _beliefsV.clear();
51 _beliefsV.reserve(nrVars());
52 for( size_t i = 0; i < nrVars(); i++ )
53 _beliefsV.push_back( Factor(var(i)).normalized() );
54
55 _beliefsF.clear();
56 _beliefsF.reserve(nrFactors());
57 for( size_t I = 0; I < nrFactors(); I++ ) {
58 Factor f = factor(I);
59 f.fill(1); f.normalize();
60 _beliefsF.push_back( f );
61 }
62
63 // to compute average level
64 _sum_level = 0;
65 _num_leaves = 0;
66
67 _maxdiff = 0;
68 _iters = 0;
69
70 if( props.clamp_outfile.length() > 0 ) {
71 _clamp_ofstream = shared_ptr<ofstream>(new ofstream( props.clamp_outfile.c_str(), ios_base::out|ios_base::trunc ));
72 *_clamp_ofstream << "# COUNT LEVEL VAR STATE" << endl;
73 }
74 }
75
76
77 /// Calculates a vector of mixtures p * b + (1-p) * c
78 static vector<Factor> mixBeliefs( Real p, const vector<Factor> &b, const vector<Factor> &c ) {
79 vector<Factor> out;
80 DAI_ASSERT( b.size() == c.size() );
81 out.reserve( b.size() );
82 Real pc = 1 - p;
83 for( size_t i = 0; i < b.size(); i++ )
84 // probably already normalized, but do it again just in case
85 out.push_back( b[i].normalized() * p + c[i].normalized() * pc );
86 return out;
87 }
88
89
90 Real CBP::run() {
91 size_t seed = props.rand_seed;
92 if( seed > 0 )
93 rnd_seed( seed );
94
95 InfAlg *bp = getInfAlg();
96 bp->init();
97 bp->run();
98 _iters += bp->Iterations();
99
100 vector<Factor> beliefs_out;
101 Real lz_out;
102 size_t choose_count=0;
103 runRecurse( bp, bp->logZ(), vector<size_t>(0), _num_leaves, choose_count, _sum_level, lz_out, beliefs_out );
104 if( props.verbose >= 1 )
105 cerr << "CBP average levels = " << (_sum_level / _num_leaves) << ", leaves = " << _num_leaves << endl;
106 setBeliefs( beliefs_out, lz_out );
107 return 0.0;
108 }
109
110
111 /// \todo Eventually this allow other inference algorithms that BP to be selected, via a property
112 InfAlg* CBP::getInfAlg() {
113 PropertySet bpProps;
114 bpProps.Set("updates", props.updates);
115 bpProps.Set("tol", props.tol);
116 bpProps.Set("maxiter", props.maxiter);
117 bpProps.Set("verbose", props.verbose);
118 bpProps.Set("logdomain", false);
119 bpProps.Set("damping", (Real)0.0);
120 BP *bp = new BP( *this, bpProps );
121 bp->recordSentMessages = true;
122 bp->init();
123 return bp;
124 }
125
126
127 void CBP::runRecurse( InfAlg *bp, Real orig_logZ, vector<size_t> clamped_vars_list, size_t &num_leaves,
128 size_t &choose_count, Real &sum_level, Real &lz_out, vector<Factor>& beliefs_out) {
129 // choose a variable/states to clamp:
130 size_t i;
131 vector<size_t> xis;
132 Real maxVar = 0.0;
133 bool found;
134 bool clampingVar = (Clamping() == Properties::ClampType::CLAMP_VAR);
135
136 if( Recursion() == Properties::RecurseType::REC_LOGZ && recTol() > 0 && exp( bp->logZ() - orig_logZ ) < recTol() )
137 found = false;
138 else
139 found = chooseNextClampVar( bp, clamped_vars_list, i, xis, &maxVar );
140
141 if( !found ) {
142 num_leaves++;
143 sum_level += clamped_vars_list.size();
144 beliefs_out = bp->beliefs();
145 lz_out = bp->logZ();
146 return;
147 }
148
149 choose_count++;
150 if( props.clamp_outfile.length() > 0 )
151 *_clamp_ofstream << choose_count << "\t" << clamped_vars_list.size() << "\t" << i << "\t" << xis[0] << endl;
152
153 if( clampingVar )
154 foreach( size_t xi, xis )
155 DAI_ASSERT(/*0<=xi &&*/ xi < var(i).states() );
156 else
157 foreach( size_t xI, xis )
158 DAI_ASSERT(/*0<=xI &&*/ xI < factor(i).states() );
159 // - otherwise, clamp and recurse, saving margin estimates for each
160 // clamp setting. afterwards, combine estimates.
161
162 // compute complement of 'xis'
163 vector<size_t> cmp_xis = complement( xis, clampingVar ? var(i).states() : factor(i).states() );
164
165 /// \todo could do this more efficiently with a nesting version of saveProbs/undoProbs
166 Real lz;
167 vector<Factor> b;
168 InfAlg *bp_c = bp->clone();
169 if( clampingVar ) {
170 bp_c->fg().clampVar( i, xis );
171 bp_c->init( var(i) );
172 } else {
173 bp_c->fg().clampFactor( i, xis );
174 bp_c->init( factor(i).vars() );
175 }
176 bp_c->run();
177 _iters += bp_c->Iterations();
178
179 lz = bp_c->logZ();
180 b = bp_c->beliefs();
181
182 Real cmp_lz;
183 vector<Factor> cmp_b;
184 InfAlg *cmp_bp_c = bp->clone();
185 if( clampingVar ) {
186 cmp_bp_c->fg().clampVar( i, cmp_xis );
187 cmp_bp_c->init(var(i));
188 } else {
189 cmp_bp_c->fg().clampFactor( i, cmp_xis );
190 cmp_bp_c->init( factor(i).vars() );
191 }
192 cmp_bp_c->run();
193 _iters += cmp_bp_c->Iterations();
194
195 cmp_lz = cmp_bp_c->logZ();
196 cmp_b = cmp_bp_c->beliefs();
197
198 Real p = unSoftMax( lz, cmp_lz );
199 Real bp__d = 0.0;
200
201 if( Recursion() == Properties::RecurseType::REC_BDIFF && recTol() > 0 ) {
202 vector<Factor> combined_b( mixBeliefs( p, b, cmp_b ) );
203 Real new_lz = logSumExp( lz,cmp_lz );
204 bp__d = dist( bp->beliefs(), combined_b, nrVars() );
205 if( exp( new_lz - orig_logZ) * bp__d < recTol() ) {
206 num_leaves++;
207 sum_level += clamped_vars_list.size();
208 beliefs_out = combined_b;
209 lz_out = new_lz;
210 return;
211 }
212 }
213
214 // either we are not doing REC_BDIFF or the distance was large
215 // enough to recurse:
216 runRecurse( bp_c, orig_logZ, clamped_vars_list, num_leaves, choose_count, sum_level, lz, b );
217 runRecurse( cmp_bp_c, orig_logZ, clamped_vars_list, num_leaves, choose_count, sum_level, cmp_lz, cmp_b );
218
219 p = unSoftMax( lz, cmp_lz );
220
221 beliefs_out = mixBeliefs( p, b, cmp_b );
222 lz_out = logSumExp( lz, cmp_lz );
223
224 if( props.verbose >= 2 ) {
225 Real d = dist( bp->beliefs(), beliefs_out, nrVars() );
226 cerr << "Distance (clamping " << i << "): " << d;
227 if( Recursion() == Properties::RecurseType::REC_BDIFF )
228 cerr << "; bp_dual predicted " << bp__d;
229 cerr << "; max_adjoint = " << maxVar << "; logZ = " << lz_out << " (in " << bp->logZ() << ") (orig " << orig_logZ << "); p = " << p << "; level = " << clamped_vars_list.size() << endl;
230 }
231
232 delete bp_c;
233 delete cmp_bp_c;
234 }
235
236
237 // 'xis' must be sorted
238 bool CBP::chooseNextClampVar( InfAlg *bp, vector<size_t> &clamped_vars_list, size_t &i, vector<size_t> &xis, Real *maxVarOut ) {
239 Real tiny = 1.0e-14;
240 if( props.verbose >= 3 )
241 cerr << "clamped_vars_list" << clamped_vars_list << endl;
242 if( clamped_vars_list.size() >= maxClampLevel() )
243 return false;
244 if( ChooseMethod() == Properties::ChooseMethodType::CHOOSE_RANDOM ) {
245 if( Clamping() == Properties::ClampType::CLAMP_VAR ) {
246 int t = 0, t1 = 100;
247 do {
248 i = rnd( nrVars() );
249 t++;
250 } while( abs( bp->beliefV(i).p().max() - 1) < tiny && t < t1 );
251 if( t == t1 ) {
252 return false;
253 // die("Too many levels requested in CBP");
254 }
255 // only pick probable values for variable
256 size_t xi;
257 do {
258 xi = rnd( var(i).states() );
259 t++;
260 } while( bp->beliefV(i).p()[xi] < tiny && t < t1 );
261 DAI_ASSERT( t < t1 );
262 xis.resize( 1, xi );
263 // DAI_ASSERT(!_clamped_vars.count(i)); // not true for >2-ary variables
264 DAI_IFVERB(2, "CHOOSE_RANDOM at level " << clamped_vars_list.size() << " chose variable " << i << " state " << xis[0] << endl);
265 } else {
266 int t = 0, t1 = 100;
267 do {
268 i = rnd( nrFactors() );
269 t++;
270 } while( abs( bp->beliefF(i).p().max() - 1) < tiny && t < t1 );
271 if( t == t1 )
272 return false;
273 // die("Too many levels requested in CBP");
274 // only pick probable values for variable
275 size_t xi;
276 do {
277 xi = rnd( factor(i).states() );
278 t++;
279 } while( bp->beliefF(i).p()[xi] < tiny && t < t1 );
280 DAI_ASSERT( t < t1 );
281 xis.resize( 1, xi );
282 // DAI_ASSERT(!_clamped_vars.count(i)); // not true for >2-ary variables
283 DAI_IFVERB(2, endl<<"CHOOSE_RANDOM chose factor "<<i<<" state "<<xis[0]<<endl);
284 }
285 } else if( ChooseMethod() == Properties::ChooseMethodType::CHOOSE_MAXENT ) {
286 if( Clamping() == Properties::ClampType::CLAMP_VAR ) {
287 Real max_ent = -1.0;
288 int win_k = -1, win_xk = -1;
289 for( size_t k = 0; k < nrVars(); k++ ) {
290 Real ent=bp->beliefV(k).entropy();
291 if( max_ent < ent ) {
292 max_ent = ent;
293 win_k = k;
294 win_xk = bp->beliefV(k).p().argmax().first;
295 }
296 }
297 DAI_ASSERT( win_k >= 0 );
298 DAI_ASSERT( win_xk >= 0 );
299 i = win_k;
300 xis.resize( 1, win_xk );
301 DAI_IFVERB(2, endl<<"CHOOSE_MAXENT chose variable "<<i<<" state "<<xis[0]<<endl);
302 if( bp->beliefV(i).p()[xis[0]] < tiny ) {
303 DAI_IFVERB(2, "Warning: CHOOSE_MAXENT found unlikely state, not recursing");
304 return false;
305 }
306 } else {
307 Real max_ent = -1.0;
308 int win_k = -1, win_xk = -1;
309 for( size_t k = 0; k < nrFactors(); k++ ) {
310 Real ent = bp->beliefF(k).entropy();
311 if( max_ent < ent ) {
312 max_ent = ent;
313 win_k = k;
314 win_xk = bp->beliefF(k).p().argmax().first;
315 }
316 }
317 DAI_ASSERT( win_k >= 0 );
318 DAI_ASSERT( win_xk >= 0 );
319 i = win_k;
320 xis.resize( 1, win_xk );
321 DAI_IFVERB(2, endl<<"CHOOSE_MAXENT chose factor "<<i<<" state "<<xis[0]<<endl);
322 if( bp->beliefF(i).p()[xis[0]] < tiny ) {
323 DAI_IFVERB(2, "Warning: CHOOSE_MAXENT found unlikely state, not recursing");
324 return false;
325 }
326 }
327 } else if( ChooseMethod()==Properties::ChooseMethodType::CHOOSE_BP_L1 ||
328 ChooseMethod()==Properties::ChooseMethodType::CHOOSE_BP_CFN ) {
329 bool doL1 = (ChooseMethod() == Properties::ChooseMethodType::CHOOSE_BP_L1);
330 vector<size_t> state;
331 if( !doL1 && BBP_cost_function().needGibbsState() )
332 state = getGibbsState( bp->fg(), 2*bp->Iterations() );
333 // try clamping each variable manually
334 DAI_ASSERT( Clamping() == Properties::ClampType::CLAMP_VAR );
335 Real max_cost = 0.0;
336 int win_k = -1, win_xk = -1;
337 for( size_t k = 0; k < nrVars(); k++ ) {
338 for( size_t xk = 0; xk < var(k).states(); xk++ ) {
339 if( bp->beliefV(k)[xk] < tiny )
340 continue;
341 InfAlg *bp1 = bp->clone();
342 bp1->clamp( k, xk );
343 bp1->init( var(k) );
344 bp1->run();
345 Real cost = 0;
346 if( doL1 )
347 for( size_t j = 0; j < nrVars(); j++ )
348 cost += dist( bp->beliefV(j), bp1->beliefV(j), Prob::DISTL1 );
349 else
350 cost = BBP_cost_function().evaluate( *bp1, &state );
351 if( cost > max_cost || win_k == -1 ) {
352 max_cost = cost;
353 win_k = k;
354 win_xk = xk;
355 }
356 delete bp1;
357 }
358 }
359 DAI_ASSERT( win_k >= 0 );
360 DAI_ASSERT( win_xk >= 0 );
361 i = win_k;
362 xis.resize( 1, win_xk );
363 } else if( ChooseMethod() == Properties::ChooseMethodType::CHOOSE_BBP ) {
364 Real mvo;
365 if( !maxVarOut )
366 maxVarOut = &mvo;
367 bool clampingVar = (Clamping() == Properties::ClampType::CLAMP_VAR);
368 pair<size_t, size_t> cv = bbpFindClampVar( *bp, clampingVar, props.bbp_props, BBP_cost_function(), &mvo );
369
370 // if slope isn't big enough then don't clamp
371 if( mvo < minMaxAdj() )
372 return false;
373
374 size_t xi = cv.second;
375 i = cv.first;
376 #define VAR_INFO (clampingVar?"variable ":"factor ") \
377 << i << " state " << xi \
378 << " (p=" << (clampingVar?bp->beliefV(i)[xi]:bp->beliefF(i)[xi]) \
379 << ", entropy = " << (clampingVar?bp->beliefV(i):bp->beliefF(i)).entropy() \
380 << ", maxVar = "<< mvo << ")"
381 Prob b = ( clampingVar ? bp->beliefV(i).p() : bp->beliefF(i).p());
382 if( b[xi] < tiny ) {
383 cerr << "Warning, at level " << clamped_vars_list.size() << ", bbpFindClampVar found unlikely " << VAR_INFO << endl;
384 return false;
385 }
386 if( abs(b[xi] - 1) < tiny ) {
387 cerr << "Warning at level " << clamped_vars_list.size() << ", bbpFindClampVar found overly likely " << VAR_INFO << endl;
388 return false;
389 }
390
391 xis.resize( 1, xi );
392 if( clampingVar )
393 DAI_ASSERT(/*0<=xi &&*/ xi < var(i).states() );
394 else
395 DAI_ASSERT(/*0<=xi &&*/ xi < factor(i).states() );
396 DAI_IFVERB(2, "CHOOSE_BBP (num clamped = " << clamped_vars_list.size() << ") chose " << i << " state " << xi << endl);
397 } else
398 DAI_THROW(UNKNOWN_ENUM_VALUE);
399 clamped_vars_list.push_back( i );
400 return true;
401 }
402
403
404 void CBP::printDebugInfo() {
405 DAI_PV(_beliefsV);
406 DAI_PV(_beliefsF);
407 DAI_PV(_logZ);
408 }
409
410
411 //----------------------------------------------------------------
412
413
414 /** Function which takes a factor graph as input, runs Gibbs and BP_dual,
415 * creates and runs a BBP object, finds best variable, returns
416 * (variable,state) pair for clamping
417 */
418 pair<size_t, size_t> bbpFindClampVar( const InfAlg &in_bp, bool clampingVar, const PropertySet &bbp_props, const BBPCostFunction &cfn, Real *maxVarOut ) {
419 BBP bbp( &in_bp, bbp_props );
420 bbp.initCostFnAdj( cfn, NULL );
421 bbp.run();
422
423 // find and return the (variable,state) with the largest adj_psi_V
424 size_t argmax_var = 0;
425 size_t argmax_var_state = 0;
426 Real max_var = 0;
427 if( clampingVar ) {
428 for( size_t i = 0; i < in_bp.fg().nrVars(); i++ ) {
429 Prob adj_psi_V = bbp.adj_psi_V(i);
430 if(0) {
431 // helps to account for amount of movement possible in variable
432 // i's beliefs? seems not..
433 adj_psi_V *= in_bp.beliefV(i).entropy();
434 }
435 if(0){
436 // adj_psi_V *= Prob(in_bp.fg().var(i).states(),1.0)-in_bp.beliefV(i).p();
437 adj_psi_V *= in_bp.beliefV(i).p();
438 }
439 // try to compensate for effect on same variable (doesn't work)
440 // adj_psi_V[gibbs.state()[i]] -= bp_dual.beliefV(i)[gibbs.state()[i]]/10;
441 pair<size_t,Real> argmax_state = adj_psi_V.argmax();
442
443 if( i == 0 || argmax_state.second > max_var ) {
444 argmax_var = i;
445 max_var = argmax_state.second;
446 argmax_var_state = argmax_state.first;
447 }
448 }
449 DAI_ASSERT(/*0 <= argmax_var_state &&*/
450 argmax_var_state < in_bp.fg().var(argmax_var).states() );
451 } else {
452 for( size_t I = 0; I < in_bp.fg().nrFactors(); I++ ) {
453 Prob adj_psi_F = bbp.adj_psi_F(I);
454 if(0) {
455 // helps to account for amount of movement possible in variable
456 // i's beliefs? seems not..
457 adj_psi_F *= in_bp.beliefF(I).entropy();
458 }
459 // try to compensate for effect on same variable (doesn't work)
460 // adj_psi_V[gibbs.state()[i]] -= bp_dual.beliefV(i)[gibbs.state()[i]]/10;
461 pair<size_t,Real> argmax_state = adj_psi_F.argmax();
462
463 if( I == 0 || argmax_state.second > max_var ) {
464 argmax_var = I;
465 max_var = argmax_state.second;
466 argmax_var_state = argmax_state.first;
467 }
468 }
469 DAI_ASSERT(/*0 <= argmax_var_state &&*/
470 argmax_var_state < in_bp.fg().factor(argmax_var).states() );
471 }
472 if( maxVarOut )
473 *maxVarOut = max_var;
474 return make_pair( argmax_var, argmax_var_state );
475 }
476
477
478 vector<size_t> complement( vector<size_t> &xis, size_t n_states ) {
479 vector<size_t> cmp_xis( 0 );
480 size_t j = 0;
481 for( size_t xi = 0; xi < n_states; xi++ ) {
482 while( j < xis.size() && xis[j] < xi )
483 j++;
484 if( j >= xis.size() || xis[j] > xi )
485 cmp_xis.push_back(xi);
486 }
487 DAI_ASSERT( xis.size()+cmp_xis.size() == n_states );
488 return cmp_xis;
489 }
490
491
492 Real unSoftMax( Real a, Real b ) {
493 if( a > b )
494 return 1.0 / (1.0 + exp(b-a));
495 else
496 return exp(a-b) / (exp(a-b) + 1.0);
497 }
498
499
500 Real logSumExp( Real a, Real b ) {
501 if( a > b )
502 return a + log1p( exp( b-a ) );
503 else
504 return b + log1p( exp( a-b ) );
505 }
506
507
508 Real dist( const vector<Factor> &b1, const vector<Factor> &b2, size_t nv ) {
509 Real d = 0.0;
510 for( size_t k = 0; k < nv; k++ )
511 d += dist( b1[k], b2[k], Prob::DISTLINF );
512 return d;
513 }
514
515
516 } // end of namespace dai
517
518
519 /* {{{ GENERATED CODE: DO NOT EDIT. Created by
520 ./scripts/regenerate-properties include/dai/cbp.h src/cbp.cpp
521 */
522 namespace dai {
523
524 void CBP::Properties::set(const PropertySet &opts)
525 {
526 const std::set<PropertyKey> &keys = opts.keys();
527 std::set<PropertyKey>::const_iterator i;
528 for(i=keys.begin(); i!=keys.end(); i++) {
529 if(*i == "verbose") continue;
530 if(*i == "tol") continue;
531 if(*i == "updates") continue;
532 if(*i == "maxiter") continue;
533 if(*i == "rec_tol") continue;
534 if(*i == "max_levels") continue;
535 if(*i == "min_max_adj") continue;
536 if(*i == "choose") continue;
537 if(*i == "recursion") continue;
538 if(*i == "clamp") continue;
539 if(*i == "bbp_props") continue;
540 if(*i == "bbp_cfn") continue;
541 if(*i == "rand_seed") continue;
542 if(*i == "clamp_outfile") continue;
543 DAI_THROWE(UNKNOWN_PROPERTY_TYPE, "CBP: Unknown property " + *i);
544 }
545 if(!opts.hasKey("tol"))
546 DAI_THROWE(NOT_ALL_PROPERTIES_SPECIFIED,"CBP: Missing property \"tol\" for method \"CBP\"");
547 if(!opts.hasKey("updates"))
548 DAI_THROWE(NOT_ALL_PROPERTIES_SPECIFIED,"CBP: Missing property \"updates\" for method \"CBP\"");
549 if(!opts.hasKey("maxiter"))
550 DAI_THROWE(NOT_ALL_PROPERTIES_SPECIFIED,"CBP: Missing property \"maxiter\" for method \"CBP\"");
551 if(!opts.hasKey("rec_tol"))
552 DAI_THROWE(NOT_ALL_PROPERTIES_SPECIFIED,"CBP: Missing property \"rec_tol\" for method \"CBP\"");
553 if(!opts.hasKey("min_max_adj"))
554 DAI_THROWE(NOT_ALL_PROPERTIES_SPECIFIED,"CBP: Missing property \"min_max_adj\" for method \"CBP\"");
555 if(!opts.hasKey("choose"))
556 DAI_THROWE(NOT_ALL_PROPERTIES_SPECIFIED,"CBP: Missing property \"choose\" for method \"CBP\"");
557 if(!opts.hasKey("recursion"))
558 DAI_THROWE(NOT_ALL_PROPERTIES_SPECIFIED,"CBP: Missing property \"recursion\" for method \"CBP\"");
559 if(!opts.hasKey("clamp"))
560 DAI_THROWE(NOT_ALL_PROPERTIES_SPECIFIED,"CBP: Missing property \"clamp\" for method \"CBP\"");
561 if(!opts.hasKey("bbp_props"))
562 DAI_THROWE(NOT_ALL_PROPERTIES_SPECIFIED,"CBP: Missing property \"bbp_props\" for method \"CBP\"");
563 if(!opts.hasKey("bbp_cfn"))
564 DAI_THROWE(NOT_ALL_PROPERTIES_SPECIFIED,"CBP: Missing property \"bbp_cfn\" for method \"CBP\"");
565 if(opts.hasKey("verbose")) {
566 verbose = opts.getStringAs<size_t>("verbose");
567 } else {
568 verbose = 0;
569 }
570 tol = opts.getStringAs<Real>("tol");
571 updates = opts.getStringAs<UpdateType>("updates");
572 maxiter = opts.getStringAs<size_t>("maxiter");
573 rec_tol = opts.getStringAs<Real>("rec_tol");
574 if(opts.hasKey("max_levels")) {
575 max_levels = opts.getStringAs<size_t>("max_levels");
576 } else {
577 max_levels = 10;
578 }
579 min_max_adj = opts.getStringAs<Real>("min_max_adj");
580 choose = opts.getStringAs<ChooseMethodType>("choose");
581 recursion = opts.getStringAs<RecurseType>("recursion");
582 clamp = opts.getStringAs<ClampType>("clamp");
583 bbp_props = opts.getStringAs<PropertySet>("bbp_props");
584 bbp_cfn = opts.getStringAs<BBPCostFunction>("bbp_cfn");
585 if(opts.hasKey("rand_seed")) {
586 rand_seed = opts.getStringAs<size_t>("rand_seed");
587 } else {
588 rand_seed = 0;
589 }
590 if(opts.hasKey("clamp_outfile")) {
591 clamp_outfile = opts.getStringAs<std::string>("clamp_outfile");
592 } else {
593 clamp_outfile = "";
594 }
595 }
596 PropertySet CBP::Properties::get() const {
597 PropertySet opts;
598 opts.Set("verbose", verbose);
599 opts.Set("tol", tol);
600 opts.Set("updates", updates);
601 opts.Set("maxiter", maxiter);
602 opts.Set("rec_tol", rec_tol);
603 opts.Set("max_levels", max_levels);
604 opts.Set("min_max_adj", min_max_adj);
605 opts.Set("choose", choose);
606 opts.Set("recursion", recursion);
607 opts.Set("clamp", clamp);
608 opts.Set("bbp_props", bbp_props);
609 opts.Set("bbp_cfn", bbp_cfn);
610 opts.Set("rand_seed", rand_seed);
611 opts.Set("clamp_outfile", clamp_outfile);
612 return opts;
613 }
614 string CBP::Properties::toString() const {
615 stringstream s(stringstream::out);
616 s << "[";
617 s << "verbose=" << verbose << ",";
618 s << "tol=" << tol << ",";
619 s << "updates=" << updates << ",";
620 s << "maxiter=" << maxiter << ",";
621 s << "rec_tol=" << rec_tol << ",";
622 s << "max_levels=" << max_levels << ",";
623 s << "min_max_adj=" << min_max_adj << ",";
624 s << "choose=" << choose << ",";
625 s << "recursion=" << recursion << ",";
626 s << "clamp=" << clamp << ",";
627 s << "bbp_props=" << bbp_props << ",";
628 s << "bbp_cfn=" << bbp_cfn << ",";
629 s << "rand_seed=" << rand_seed << ",";
630 s << "clamp_outfile=" << clamp_outfile;
631 s << "]";
632 return s.str();
633 }
634 } // end of namespace dai
635 /* }}} END OF GENERATED CODE */