1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
|
function engine = bk_inf_engine(bnet, varargin)
% BK_INF_ENGINE Boyen-Koller approximate inference algorithm for DBNs.
%
% In the BK algorithm, the belief state is represented as a product of marginals,
% even though the factors may not be independent.
%
% engine = bk_inf_engine(bnet, ...)
%
% The following optional arguments can be specified in the form of name/value pairs:
% [default value in brackets]
%
% clusters - if a cell array, clusters{i} specifies the terms in the i'th factor.
% - 'exact' means create one cluster that contains all the nodes in a slice [exact]
% - 'ff' means create one cluster per node (ff = fully factorised).
%
%
% For details, see
% - "Tractable Inference for Complex Stochastic Processes", X. Boyen and D. Koller, UAI 98.
% - "Approximate learning of dynamic models", X. Boyen and D. Koller, NIPS 98.
% (The UAI98 paper discusses filtering and theory, and the NIPS98 paper discusses smoothing.)
ss = length(bnet.intra);
% set default params
clusters = 'exact';
if nargin >= 2
args = varargin;
nargs = length(args);
for i=1:2:nargs
switch args{i},
case 'clusters', clusters = args{i+1};
otherwise, error(['unrecognized argument ' args{i}])
end
end
end
if strcmp(clusters, 'exact')
%clusters = { compute_interface_nodes(bnet.intra, bnet.inter) };
clusters = { 1:ss };
elseif strcmp(clusters, 'ff')
clusters = num2cell(1:ss);
end
% We need to insert the prior on the clusters in slice 1,
% and extract the posterior on the clusters in slice 2.
C = length(clusters);
clusters2 = cell(1,2*C);
clusters2(1:C) = clusters;
for c=1:C
clusters2{c+C} = clusters{c} + ss;
end
onodes = bnet.observed;
obs_nodes = [onodes(:) onodes(:)+ss];
engine.sub_engine = jtree_inf_engine(bnet, 'clusters', clusters2);
engine.clq_ass_to_cluster = zeros(C, 2);
for c=1:C
engine.clq_ass_to_cluster(c,1) = clq_containing_nodes(engine.sub_engine, clusters{c});
engine.clq_ass_to_cluster(c,2) = clq_containing_nodes(engine.sub_engine, clusters{c}+ss);
end
engine.clusters = clusters;
engine.clq_ass_to_node = zeros(ss, 2);
for i=1:ss
engine.clq_ass_to_node(i, 1) = clq_containing_nodes(engine.sub_engine, i);
engine.clq_ass_to_node(i, 2) = clq_containing_nodes(engine.sub_engine, i+ss);
end
% Also create an engine just for slice 1
bnet1 = mk_bnet(bnet.intra1, bnet.node_sizes_slice, 'discrete', myintersect(bnet.dnodes, 1:ss), ...
'equiv_class', bnet.equiv_class(:,1), 'observed', onodes);
for i=1:max(bnet1.equiv_class)
bnet1.CPD{i} = bnet.CPD{i};
end
engine.sub_engine1 = jtree_inf_engine(bnet1, 'clusters', clusters);
engine.clq_ass_to_cluster1 = zeros(1,C);
for c=1:C
engine.clq_ass_to_cluster1(c) = clq_containing_nodes(engine.sub_engine1, clusters{c});
end
engine.clq_ass_to_node1 = zeros(1, ss);
for i=1:ss
engine.clq_ass_to_node1(i) = clq_containing_nodes(engine.sub_engine1, i);
end
engine.clpot = []; % this is where we store the results between enter_evidence and marginal_nodes
engine.filter = [];
engine.maximize = [];
engine.T = [];
engine.bel = [];
engine.bel_clpot = [];
engine.slice1 = [];
%engine.pot_type = 'cg';
% hack for online inference so we can cope with hidden Gaussians and discrete
% it will not affect the pot type used in enter_evidence
engine.pot_type = determine_pot_type(bnet, onodes);
engine = class(engine, 'bk_inf_engine', inf_engine(bnet));
|