wolffd@0
|
1 function engine = belprop_gdl_inf_engine(gdl, varargin)
|
wolffd@0
|
2 % BELPROP_GDL_INF_ENGINE Make a belief propagation inference engine for a GDL graph
|
wolffd@0
|
3 % engine = belprop_gdl_inf_engine(gdl_graph, ...)
|
wolffd@0
|
4 %
|
wolffd@0
|
5 % If the GDL graph is a tree, this will give exact results.
|
wolffd@0
|
6 %
|
wolffd@0
|
7 % The following optional arguments can be specified in the form of name/value pairs:
|
wolffd@0
|
8 % [default in brackets]
|
wolffd@0
|
9 % e.g., engine = belprop_inf_engine(gdl, 'tol', 1e-2, 'max_iter', 10)
|
wolffd@0
|
10 %
|
wolffd@0
|
11 % protocol - 'tree' means send messages up then down the tree,
|
wolffd@0
|
12 % 'parallel' means use synchronous updates ['parallel']
|
wolffd@0
|
13 % max_iter - max. num. iterations [ 2*num_nodes ]
|
wolffd@0
|
14 % momentum - weight assigned to old message in convex combination (useful for damping oscillations) [0]
|
wolffd@0
|
15 % tol - tolerance used to assess convergence [1e-3]
|
wolffd@0
|
16 % maximize - 1 means use max-product, 0 means use sum-product [0]
|
wolffd@0
|
17
|
wolffd@0
|
18
|
wolffd@0
|
19 engine = init_fields;
|
wolffd@0
|
20 engine = class(engine, 'belprop_gdl_inf_engine');
|
wolffd@0
|
21
|
wolffd@0
|
22 % set default params
|
wolffd@0
|
23 N = length(gdl.G);
|
wolffd@0
|
24 engine.protocol = 'parallel';
|
wolffd@0
|
25 engine.max_iter = 2*N;
|
wolffd@0
|
26 engine.momentum = 0;
|
wolffd@0
|
27 engine.tol = 1e-3;
|
wolffd@0
|
28 engine.maximize = 0;
|
wolffd@0
|
29
|
wolffd@0
|
30 engine = set_params(engine, varargin);
|
wolffd@0
|
31
|
wolffd@0
|
32 engine.gdl = gdl;
|
wolffd@0
|
33
|
wolffd@0
|
34 if strcmp(engine.protocol, 'tree')
|
wolffd@0
|
35 % Make a rooted tree, so there is a fixed message passing order.
|
wolffd@0
|
36 root = N;
|
wolffd@0
|
37 [engine.tree, engine.preorder, engine.postorder, height, cyclic] = mk_rooted_tree(gdl.G, root);
|
wolffd@0
|
38 assert(~cyclic);
|
wolffd@0
|
39 end
|
wolffd@0
|
40
|
wolffd@0
|
41 % store results computed by enter_evidence here
|
wolffd@0
|
42 ndoms = length(gdl.doms);
|
wolffd@0
|
43 nvars = length(gdl.vars);
|
wolffd@0
|
44 engine.marginal_domains = cell(1, ndoms);
|
wolffd@0
|
45
|
wolffd@0
|
46 % to compute the marginal on each variable, we need to know which domain to marginalize
|
wolffd@0
|
47 % and we want to choose the lightest. We compute the weight once we have seen the evidence.
|
wolffd@0
|
48 engine.dom_weight = [];
|
wolffd@0
|
49 engine.evidence = [];
|
wolffd@0
|
50
|
wolffd@0
|
51
|
wolffd@0
|
52 %%%%%%%%%
|
wolffd@0
|
53
|
wolffd@0
|
54 function engine = init_fields()
|
wolffd@0
|
55
|
wolffd@0
|
56 engine.protocol = [];
|
wolffd@0
|
57 engine.gdl = [];
|
wolffd@0
|
58 engine.max_iter = [];
|
wolffd@0
|
59 engine.momentum = [];
|
wolffd@0
|
60 engine.tol = [];
|
wolffd@0
|
61 engine.maximize = [];
|
wolffd@0
|
62 engine.marginal_domains = [];
|
wolffd@0
|
63 engine.evidence = [];
|
wolffd@0
|
64 engine.tree = [];
|
wolffd@0
|
65 engine.preorder = [];
|
wolffd@0
|
66 engine.postorder = [];
|
wolffd@0
|
67 engine.dom_weight = [];
|