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