annotate toolboxes/FullBNT-1.0.7/bnt/inference/dynamic/@cbk_inf_engine/junk @ 0:cc4b1211e677 tip

initial commit to HG from Changeset: 646 (e263d8a21543) added further path and more save "camirversion.m"
author Daniel Wolff
date Fri, 19 Aug 2016 13:07:06 +0200
parents
children
rev   line source
Daniel@0 1 function engine = cbk_inf_engine(bnet, varargin)
Daniel@0 2 % Just the same as bk_inf_engine, but you can specify overlapping clusters.
Daniel@0 3
Daniel@0 4 ss = length(bnet.intra);
Daniel@0 5 % set default params
Daniel@0 6 clusters = 'exact';
Daniel@0 7
Daniel@0 8 if nargin >= 2
Daniel@0 9 args = varargin;
Daniel@0 10 nargs = length(args);
Daniel@0 11 for i=1:2:nargs
Daniel@0 12 switch args{i},
Daniel@0 13 case 'clusters', clusters = args{i+1};
Daniel@0 14 otherwise, error(['unrecognized argument ' args{i}])
Daniel@0 15 end
Daniel@0 16 end
Daniel@0 17 end
Daniel@0 18
Daniel@0 19 if strcmp(clusters, 'exact')
Daniel@0 20 %clusters = { compute_interface_nodes(bnet.intra, bnet.inter) };
Daniel@0 21 clusters = { 1:ss };
Daniel@0 22 elseif strcmp(clusters, 'ff')
Daniel@0 23 clusters = num2cell(1:ss);
Daniel@0 24 end
Daniel@0 25
Daniel@0 26
Daniel@0 27 % We need to insert the prior on the clusters in slice 1,
Daniel@0 28 % and extract the posterior on the clusters in slice 2.
Daniel@0 29 % We don't need to care about the separators, b/c they're subsets of the clusters.
Daniel@0 30 C = length(clusters);
Daniel@0 31 clusters2 = cell(1,2*C);
Daniel@0 32 clusters2(1:C) = clusters;
Daniel@0 33 for c=1:C
Daniel@0 34 clusters2{c+C} = clusters{c} + ss;
Daniel@0 35 end
Daniel@0 36
Daniel@0 37 onodes = bnet.observed;
Daniel@0 38 obs_nodes = [onodes(:) onodes(:)+ss];
Daniel@0 39 engine.sub_engine = jtree_inf_engine(bnet, 'clusters', clusters2);
Daniel@0 40
Daniel@0 41 %FH >>>
Daniel@0 42 %Compute separators.
Daniel@0 43 ns = bnet.node_sizes(:,1);
Daniel@0 44 ns(onodes) = 1;
Daniel@0 45 [clusters, separators] = build_jt(clusters, 1:length(ns), ns);
Daniel@0 46 S = length(separators);
Daniel@0 47 engine.separators = separators;
Daniel@0 48
Daniel@0 49 %Compute size of clusters.
Daniel@0 50 cl_sizes = zeros(1,C);
Daniel@0 51 for c=1:C
Daniel@0 52 cl_sizes(c) = prod(ns(clusters{c}));
Daniel@0 53 end
Daniel@0 54
Daniel@0 55 %Assign separators to the smallest cluster subsuming them.
Daniel@0 56 engine.cluster_ass_to_separator = zeros(S, 1);
Daniel@0 57 for s=1:S
Daniel@0 58 subsuming_clusters = [];
Daniel@0 59 %find smaunk
Daniel@0 60
Daniel@0 61 for c=1:C
Daniel@0 62 if mysubset(separators{s}, clusters{c})
Daniel@0 63 subsuming_clusters(end+1) = c;
Daniel@0 64 end
Daniel@0 65 end
Daniel@0 66 c = argmin(cl_sizes(subsuming_clusters));
Daniel@0 67 engine.cluster_ass_to_separator(s) = subsuming_clusters(c);
Daniel@0 68 end
Daniel@0 69
Daniel@0 70 %<<< FH
Daniel@0 71
Daniel@0 72 engine.clq_ass_to_cluster = zeros(C, 2);
Daniel@0 73 for c=1:C
Daniel@0 74 engine.clq_ass_to_cluster(c,1) = clq_containing_nodes(engine.sub_engine, clusters{c});
Daniel@0 75 engine.clq_ass_to_cluster(c,2) = clq_containing_nodes(engine.sub_engine, clusters{c}+ss);
Daniel@0 76 end
Daniel@0 77 engine.clusters = clusters;
Daniel@0 78
Daniel@0 79 engine.clq_ass_to_node = zeros(ss, 2);
Daniel@0 80 for i=1:ss
Daniel@0 81 engine.clq_ass_to_node(i, 1) = clq_containing_nodes(engine.sub_engine, i);
Daniel@0 82 engine.clq_ass_to_node(i, 2) = clq_containing_nodes(engine.sub_engine, i+ss);
Daniel@0 83 end
Daniel@0 84
Daniel@0 85
Daniel@0 86
Daniel@0 87 % Also create an engine just for slice 1
Daniel@0 88 bnet1 = mk_bnet(bnet.intra1, bnet.node_sizes_slice, 'discrete', myintersect(bnet.dnodes, 1:ss), ...
Daniel@0 89 'equiv_class', bnet.equiv_class(:,1), 'observed', onodes);
Daniel@0 90 for i=1:max(bnet1.equiv_class)
Daniel@0 91 bnet1.CPD{i} = bnet.CPD{i};
Daniel@0 92 end
Daniel@0 93
Daniel@0 94 engine.sub_engine1 = jtree_inf_engine(bnet1, 'clusters', clusters);
Daniel@0 95
Daniel@0 96 engine.clq_ass_to_cluster1 = zeros(1,C);
Daniel@0 97 for c=1:C
Daniel@0 98 engine.clq_ass_to_cluster1(c) = clq_containing_nodes(engine.sub_engine1, clusters{c});
Daniel@0 99 end
Daniel@0 100
Daniel@0 101 engine.clq_ass_to_node1 = zeros(1, ss);
Daniel@0 102 for i=1:ss
Daniel@0 103 engine.clq_ass_to_node1(i) = clq_containing_nodes(engine.sub_engine1, i);
Daniel@0 104 end
Daniel@0 105
Daniel@0 106 engine.clpot = []; % this is where we store the results between enter_evidence and marginal_nodes
Daniel@0 107 engine.filter = [];
Daniel@0 108 engine.maximize = [];
Daniel@0 109 engine.T = [];
Daniel@0 110
Daniel@0 111 engine.bel = [];
Daniel@0 112 engine.bel_clpot = [];
Daniel@0 113 engine.slice1 = [];
Daniel@0 114 %engine.pot_type = 'cg';
Daniel@0 115 % hack for online inference so we can cope with hidden Gaussians and discrete
Daniel@0 116 % it will not affect the pot type used in enter_evidence
Daniel@0 117 engine.pot_type = determine_pot_type(bnet, onodes);
Daniel@0 118
Daniel@0 119 engine = class(engine, 'cbk_inf_engine', inf_engine(bnet));
Daniel@0 120
Daniel@0 121
Daniel@0 122
Daniel@0 123
Daniel@0 124 function [cliques, seps, jt_size] = build_jt(cliques, vars, ns)
Daniel@0 125 % BUILD_JT connects the cliques into a jtree, computes the respective
Daniel@0 126 % separators and the size of the resulting jtree.
Daniel@0 127 %
Daniel@0 128 % [cliques, seps, jt_size] = build_jt(cliques, vars, ns)
Daniel@0 129 % ns(i) has to hold the size of vars(i)
Daniel@0 130 % vars has to be a superset of the union of cliques.
Daniel@0 131
Daniel@0 132 %======== Compute the jtree with tool from BNT. This wants the vars to be 1:N.
Daniel@0 133 %==== Map from nodes to their indices.
Daniel@0 134 %disp('Computing jtree for cliques with vars and ns:');
Daniel@0 135 %cliques
Daniel@0 136 %vars
Daniel@0 137 %ns'
Daniel@0 138
Daniel@0 139 inv_nodes = sparse(1,max(vars));
Daniel@0 140 N = length(vars);
Daniel@0 141 for i=1:N
Daniel@0 142 inv_nodes(vars(i)) = i;
Daniel@0 143 end
Daniel@0 144
Daniel@0 145 tmp_cliques = cell(1,length(cliques));
Daniel@0 146 %==== Temporarily map clique vars to their indices.
Daniel@0 147 for i=1:length(cliques)
Daniel@0 148 tmp_cliques{i} = inv_nodes(cliques{i});
Daniel@0 149 end
Daniel@0 150
Daniel@0 151 %=== Compute the jtree, using BNT.
Daniel@0 152 [jtree, root, B, w] = cliques_to_jtree(tmp_cliques, ns);
Daniel@0 153
Daniel@0 154
Daniel@0 155 %======== Now, compute the separators between connected cliques and their weights.
Daniel@0 156 seps = {};
Daniel@0 157 s_w = [];
Daniel@0 158 [is,js] = find(jtree > 0);
Daniel@0 159 for k=1:length(is)
Daniel@0 160 i = is(k); j = js(k);
Daniel@0 161 sep = vars(find(B(i,:) & B(j,:))); % intersect(cliques{i}, cliques{j});
Daniel@0 162 if i>j | length(sep) == 0, continue; end;
Daniel@0 163 seps{end+1} = sep;
Daniel@0 164 s_w(end+1) = prod(ns(inv_nodes(seps{end})));
Daniel@0 165 end
Daniel@0 166
Daniel@0 167 cl_w = sum(w);
Daniel@0 168 sep_w = sum(s_w);
Daniel@0 169 assert(cl_w > sep_w, 'Weight of cliques must be bigger than weight of separators');
Daniel@0 170
Daniel@0 171 jt_size = cl_w + sep_w;
Daniel@0 172 % jt.cliques = cliques;
Daniel@0 173 % jt.seps = seps;
Daniel@0 174 % jt.size = jt_size;
Daniel@0 175 % jt.ns = ns';
Daniel@0 176 % jt;