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