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