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