diff options
Diffstat (limited to 'sourcecodes/bnt-master/BNT/inference/dynamic/@jtree_dbn_inf_engine')
25 files changed, 1466 insertions, 0 deletions
diff --git a/sourcecodes/bnt-master/BNT/inference/dynamic/@jtree_dbn_inf_engine/Broken/CVS/Entries b/sourcecodes/bnt-master/BNT/inference/dynamic/@jtree_dbn_inf_engine/Broken/CVS/Entries new file mode 100644 index 00000000..3baa09c7 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/dynamic/@jtree_dbn_inf_engine/Broken/CVS/Entries @@ -0,0 +1,6 @@ +/enter_soft_evidence1.m/1.1.1.1/Wed May 29 15:59:56 2002// +/enter_soft_evidence2.m/1.1.1.1/Wed May 29 15:59:56 2002// +/enter_soft_evidence3.m/1.1.1.1/Wed May 29 15:59:56 2002// +/enter_soft_evidence4.m/1.1.1.1/Wed May 29 15:59:56 2002// +/marginal_nodes.m/1.1.1.1/Wed May 29 15:59:56 2002// +D diff --git a/sourcecodes/bnt-master/BNT/inference/dynamic/@jtree_dbn_inf_engine/Broken/CVS/Repository b/sourcecodes/bnt-master/BNT/inference/dynamic/@jtree_dbn_inf_engine/Broken/CVS/Repository new file mode 100644 index 00000000..a9b61e36 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/dynamic/@jtree_dbn_inf_engine/Broken/CVS/Repository @@ -0,0 +1 @@ +FullBNT/BNT/inference/dynamic/@jtree_dbn_inf_engine/Broken diff --git a/sourcecodes/bnt-master/BNT/inference/dynamic/@jtree_dbn_inf_engine/Broken/CVS/Root b/sourcecodes/bnt-master/BNT/inference/dynamic/@jtree_dbn_inf_engine/Broken/CVS/Root new file mode 100644 index 00000000..f3bd14a6 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/dynamic/@jtree_dbn_inf_engine/Broken/CVS/Root @@ -0,0 +1 @@ +:ext:nsaunier@bnt.cvs.sourceforge.net:/cvsroot/bnt diff --git a/sourcecodes/bnt-master/BNT/inference/dynamic/@jtree_dbn_inf_engine/Broken/enter_soft_evidence1.m b/sourcecodes/bnt-master/BNT/inference/dynamic/@jtree_dbn_inf_engine/Broken/enter_soft_evidence1.m new file mode 100644 index 00000000..8f82b57e --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/dynamic/@jtree_dbn_inf_engine/Broken/enter_soft_evidence1.m @@ -0,0 +1,119 @@ +function [clpot, loglik] = enter_soft_evidence(engine, CPDpot, observed, pot_type) +% ENTER_SOFT_EVIDENCE Add the specified soft evidence to the network (jtree_dbn) +% [clpot, loglik] = enter_soft_evidence(engine, CPDpot, observed, pot_type, filter) + +[ss T] = size(CPDpot); +Q = length(engine.jtree_struct.cliques); +clpot = cell(Q,T); % clpot{t} contains evidence from slices (t-1, t) +seppot = cell(Q,Q,T); +ll = zeros(1,Q); +logscale = zeros(1,T); +bnet = bnet_from_engine(engine); + +% Forwards pass. +% Compute distribution on clq C, +% where C is the out interface to (t-1,t). +% Then pass this to clq D, where D is the in inferface to (t+1,t). +% Then propagate from D to later slices. + +C = engine.out_clq; +assert(C==engine.jtree_struct.root_clq); +D = engine.in_clq; +slice1 = 1:ss; +slice2 = slice1 + ss; +for t=2:T + if t==2 + clqs = engine.jtree_struct.clq_ass_to_node([slice1 slice2]); + pots = CPDpot(:,t-1:t); + else + %clqs = [D; engine.clq_ass_to_node(:,2)]; + clqs = [D engine.jtree_struct.clq_ass_to_node(slice2)]; + phiC = set_domain_pot(phiC, engine.interface); % shift back to slice 1 + pots = [ {phiC}; CPDpot(:,t)]; % CPDpot domains are always slice 2 + end + [clpot(:,t), seppot(:,:,t)] = init_pot(engine.jtree_struct.cliques, clqs, pots, pot_type, ... + find(observed(:,t-1:t)), bnet.node_sizes(:), bnet.cnodes); + [clpot(:,t), seppot(:,:,t)] = collect_evidence(clpot(:,t), seppot(:,:,t), engine.maximize, ... + engine.jtree_struct.postorder, ... + engine.jtree_struct.postorder_parents,... + engine.jtree_struct.separator); + + for c=1:Q + [clpot{c,t}, ll(c)] = normalize_pot(clpot{c,t}); + end + logscale(t) = ll(C); + + phiC = marginalize_pot(clpot{C,t}, engine.interface+ss, engine.maximize); +end + + + +% Backwards pass. +% Pass evidence from clq C to clq D, +% where C is the in interface to (t,t+1) and D is the out inferface to (t-1,t) +% Then propagate evidence from D to earlier slices. +C = engine.in_clq; +D = engine.out_clq; +for t=T:-1:2 + [clpot(:,t), seppot(:,:,t)] = distribute_evidence(clpot(:,t), seppot(:,:,t), engine.maximize, ... + engine.jtree_struct.preorder, ... + engine.jtree_struct.preorder_children, ... + engine.jtree_struct.separator); + for c=1:Q + [clpot{c,t}, ll(c)] = normalize_pot(clpot{c,t}); + end + logscale(t) = ll(C); + + if t >= 3 + phiC = marginalize_pot(clpot{C,t}, engine.interface, engine.maximize); + phiC = set_domain_pot(phiC, engine.interface+ss); % shift forward to slice 2 + phiD = marginalize_pot(clpot{D,t-1}, engine.interface+ss, engine.maximize); + ratio = divide_by_pot(phiC, phiD); + clpot{D,t-1} = multiply_by_pot(clpot{D,t-1}, ratio); + end +end + +loglik = sum(logscale); + + +%%%%%%% +function [clpot, seppot] = init_pot(cliques, clqs, pots, pot_type, onodes, ns, cnodes); + +% Set the clique potentials to all 1s +C = length(cliques); +clpot = cell(1,C); +for i=1:C + clpot{i} = mk_initial_pot(pot_type, cliques{i}, ns, cnodes, onodes); +end + +% Multiply on specified potentials +for i=1:length(clqs) + c = clqs(i); + clpot{c} = multiply_by_pot(clpot{c}, pots{i}); +end + +seppot = cell(C,C); % implicitely initialized to 1 + + +%%%% +function [clpot, seppot] = collect_evidence(clpot, seppot, maximize, postorder, postorder_parents,... + separator) +for n=postorder %postorder(1:end-1) + for p=postorder_parents{n} + %clpot{p} = divide_by_pot(clpot{n}, seppot{p,n}); % dividing by 1 is redundant + seppot{p,n} = marginalize_pot(clpot{n}, separator{p,n}, maximize); + clpot{p} = multiply_by_pot(clpot{p}, seppot{p,n}); + end +end + + +%%%% +function [clpot, seppot] = distribute_evidence(clpot, seppot, maximize, preorder, preorder_children,... + separator) +for n=preorder + for c=preorder_children{n} + clpot{c} = divide_by_pot(clpot{c}, seppot{n,c}); + seppot{n,c} = marginalize_pot(clpot{n}, separator{n,c}, maximize); + clpot{c} = multiply_by_pot(clpot{c}, seppot{n,c}); + end +end diff --git a/sourcecodes/bnt-master/BNT/inference/dynamic/@jtree_dbn_inf_engine/Broken/enter_soft_evidence2.m b/sourcecodes/bnt-master/BNT/inference/dynamic/@jtree_dbn_inf_engine/Broken/enter_soft_evidence2.m new file mode 100644 index 00000000..0adfef0d --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/dynamic/@jtree_dbn_inf_engine/Broken/enter_soft_evidence2.m @@ -0,0 +1,143 @@ +function [clpot, loglik] = enter_soft_evidence(engine, CPDpot, observed, pot_type) +% ENTER_SOFT_EVIDENCE Add the specified soft evidence to the network (jtree_dbn) +% [clpot, loglik] = enter_soft_evidence(engine, CPDpot, observed, pot_type, filter) + +[ss T] = size(CPDpot); +Q = length(engine.jtree_struct.cliques); +clpot = cell(Q,T); % clpot{t} contains evidence from slices (t-1, t) +seppot = cell(Q,Q,T); +ll = zeros(1,Q); +logscale = ones(1,T); % log(logscale(1)) = 0 +bnet = bnet_from_engine(engine); + +slice1 = 1:ss; +slice2 = slice1+ss; + +% calibrate each 2-slice jtree in isolation +for t=2:T + if t==2 + clqs = engine.jtree_struct.clq_ass_to_node([slice1 slice2]); + pots = CPDpot(:,t-1:t); + else + clqs = engine.jtree_struct.clq_ass_to_node(slice2); + pots = CPDpot(:,t); % CPDpot domains are always slice 2 + end + [clpot(:,t), sepot(:,:,t)] = init_pot(engine.jtree_struct.cliques, clqs, pots, pot_type, ... + find(observed(:,t-1:t)), bnet.node_sizes(:), bnet.cnodes); + [clpot(:,t), seppot(:,:,t)] = collect_evidence(clpot(:,t), seppot(:,:,t), engine.maximize, ... + engine.jtree_struct.postorder, ... + engine.jtree_struct.postorder_parents,... + engine.jtree_struct.separator); + [clpot(:,t), seppot(:,:,t)] = distribute_evidence(clpot(:,t), seppot(:,:,t), engine.maximize, ... + engine.jtree_struct.preorder, ... + engine.jtree_struct.preorder_children, ... + engine.jtree_struct.separator); +end + +% Forwards pass. +% Compute distribution on clq C, +% where C is the out interface to (t-1,t). +% Then pass this to clq D, where D is the in inferface to (t+1,t). +% Then propagate from D to later slices. + +C = engine.out_clq; +D = engine.in_clq; +for t=2:T-1 + phiC = marginalize_pot(clpot{C,t}, engine.interface+ss, engine.maximize); + phiC = set_domain_pot(phiC, engine.interface); % shift back to slice 1 + phiD = marginalize_pot(clpot{D,t+1}, engine.interface, engine.maximize); + ratio = divide_by_pot(phiC, phiD); + clpot{D,t+1} = multiply_by_pot(clpot{D,t+1}, ratio); + + [clpot(:,t), seppot(:,:,t)] = distribute_evidence(clpot(:,t), seppot(:,:,t), engine.maximize, ... + engine.jtree_struct.preorder, ... + engine.jtree_struct.preorder_children, ... + engine.jtree_struct.separator); + for c=1:Q + [clpot{c,t}, ll(c)] = normalize_pot(clpot{c,t}); + end + logscale(t) = ll(1); +end + +% Backwards pass. +% Pass evidence from clq C to clq D, +% where C is the in interface to (t,t+1) and D is the out inferface to (t-1,t) +% Then propagate evidence from D to earlier slices. +C = engine.in_clq; +D = engine.out_clq; +for t=T:-1:2 + [clpot(:,t), seppot(:,:,t)] = collect_evidence(clpot(:,t), seppot(:,:,t), engine.maximize, ... + engine.jtree_struct.postorder, ... + engine.jtree_struct.postorder_parents,... + engine.jtree_struct.separator); + for c=1:Q + [clpot{c,t}, ll(c)] = normalize_pot(clpot{c,t}); + end + logscale(t) = ll(1); + + if t >= 3 + phiC = marginalize_pot(clpot{C,t}, engine.interface, engine.maximize); + phiC = set_domain_pot(phiC, engine.interface+ss); % shift forward to slice 2 + phiD = marginalize_pot(clpot{D,t-1}, engine.interface+ss, engine.maximize); + ratio = divide_by_pot(phiC, phiD); + clpot{D,t-1} = multiply_by_pot(clpot{D,t-1}, ratio); + end +end + +loglik = sum(logscale); + +%%%%%%%%%% + +function [clpot, seppot] = calibrate(engine, clpot, seppot) + + [clpot(:,t), seppot(:,:,t)] = collect_evidence(clpot(:,t), seppot(:,:,t), engine.maximize, ... + engine.jtree_struct.postorder, ... + engine.jtree_struct.postorder_parents,... + engine.jtree_struct.separator); + [clpot(:,t), seppot(:,:,t)] = distribute_evidence(clpot(:,t), seppot(:,:,t), engine.maximize, ... + engine.jtree_struct.preorder, ... + engine.jtree_struct.preorder_children, ... + engine.jtree_struct.separator); + + +%%%%%%% +function [clpot, seppot] = init_pot(cliques, clqs, pots, pot_type, onodes, ns, cnodes); + +% Set the clique potentials to all 1s +C = length(cliques); +clpot = cell(1,C); +for i=1:C + clpot{i} = mk_initial_pot(pot_type, cliques{i}, ns, cnodes, onodes); +end + +% Multiply on specified potentials +for i=1:length(clqs) + c = clqs(i); + clpot{c} = multiply_by_pot(clpot{c}, pots{i}); +end + +seppot = cell(C,C); % implicitely initialized to 1 + + +%%%% +function [clpot, seppot] = collect_evidence(clpot, seppot, maximize, postorder, postorder_parents,... + separator) +for n=postorder %postorder(1:end-1) + for p=postorder_parents{n} + %clpot{p} = divide_by_pot(clpot{n}, seppot{p,n}); % dividing by 1 is redundant + seppot{p,n} = marginalize_pot(clpot{n}, separator{p,n}, maximize); + clpot{p} = multiply_by_pot(clpot{p}, seppot{p,n}); + end +end + + +%%%% +function [clpot, seppot] = distribute_evidence(clpot, seppot, maximize, preorder, preorder_children,... + separator) +for n=preorder + for c=preorder_children{n} + clpot{c} = divide_by_pot(clpot{c}, seppot{n,c}); + seppot{n,c} = marginalize_pot(clpot{n}, separator{n,c}, maximize); + clpot{c} = multiply_by_pot(clpot{c}, seppot{n,c}); + end +end diff --git a/sourcecodes/bnt-master/BNT/inference/dynamic/@jtree_dbn_inf_engine/Broken/enter_soft_evidence3.m b/sourcecodes/bnt-master/BNT/inference/dynamic/@jtree_dbn_inf_engine/Broken/enter_soft_evidence3.m new file mode 100644 index 00000000..c1189460 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/dynamic/@jtree_dbn_inf_engine/Broken/enter_soft_evidence3.m @@ -0,0 +1,125 @@ +function [clpot, loglik] = enter_soft_evidence(engine, CPDpot, observed, pot_type) +% ENTER_SOFT_EVIDENCE Add the specified soft evidence to the network (jtree_dbn) +% [clpot, loglik] = enter_soft_evidence(engine, CPDpot, observed, pot_type, filter) + +[ss T] = size(CPDpot); +Q = length(engine.jtree_struct.cliques); +clpot = cell(Q,T); % clpot{t} contains evidence from slices (t-1, t) +seppot = cell(Q,Q,T); +ll = zeros(1,Q); +logscale = zeros(1,T); +bnet = bnet_from_engine(engine); + +% Forwards pass. +% Compute distribution on clq C, +% where C is the out interface to (t-1,t). +% Then pass this to clq D, where D is the in inferface to (t+1,t). +% Then propagate from D to later slices. + +C = engine.out_clq; +assert(C==engine.jtree_struct.root_clq); +D = engine.in_clq; +slice1 = 1:ss; +slice2 = slice1 + ss; +Ntransient = length(engine.transient); +trans = cell(Ntransient,1); +for t=2:T + if t==2 + clqs = engine.jtree_struct.clq_ass_to_node([slice1 slice2]); + pots = CPDpot(:,t-1:t); + else + %clqs = [D; engine.clq_ass_to_node(:,2)]; + clqs = [D engine.jtree_struct.clq_ass_to_node([engine.transient slice2])]; + phiC = set_domain_pot(phiC, engine.interface); % shift back to slice 1 + for i=1:Ntransient + trans{i} = CPDpot{engine.transient(i), t-1}; + trans{i} = set_domain_pot(trans{i}, domain_pot(trans{i})-ss); % shift back to slice 1 + end + pots = [ {phiC}; trans; CPDpot(:,t)]; + end + [clpot(:,t), seppot(:,:,t)] = init_pot(engine.jtree_struct.cliques, clqs, pots, pot_type, ... + find(observed(:,t-1:t)), bnet.node_sizes(:), bnet.cnodes); + [clpot(:,t), seppot(:,:,t)] = collect_evidence(clpot(:,t), seppot(:,:,t), engine.maximize, ... + engine.jtree_struct.postorder, ... + engine.jtree_struct.postorder_parents,... + engine.jtree_struct.separator); + + for c=1:Q + [clpot{c,t}, ll(c)] = normalize_pot(clpot{c,t}); + end + logscale(t) = ll(C); + + phiC = marginalize_pot(clpot{C,t}, engine.interface+ss, engine.maximize); +end + + + +% Backwards pass. +% Pass evidence from clq C to clq D, +% where C is the in interface to (t,t+1) and D is the out inferface to (t-1,t) +% Then propagate evidence from D to earlier slices. +C = engine.in_clq; +D = engine.out_clq; +for t=T:-1:2 + [clpot(:,t), seppot(:,:,t)] = distribute_evidence(clpot(:,t), seppot(:,:,t), engine.maximize, ... + engine.jtree_struct.preorder, ... + engine.jtree_struct.preorder_children, ... + engine.jtree_struct.separator); + for c=1:Q + [clpot{c,t}, ll(c)] = normalize_pot(clpot{c,t}); + end + logscale(t) = ll(C); + + if t >= 3 + phiC = marginalize_pot(clpot{C,t}, engine.interface, engine.maximize); + phiC = set_domain_pot(phiC, engine.interface+ss); % shift forward to slice 2 + phiD = marginalize_pot(clpot{D,t-1}, engine.interface+ss, engine.maximize); + ratio = divide_by_pot(phiC, phiD); + clpot{D,t-1} = multiply_by_pot(clpot{D,t-1}, ratio); + end +end + +loglik = sum(logscale); + + +%%%%%%% +function [clpot, seppot] = init_pot(cliques, clqs, pots, pot_type, onodes, ns, cnodes); + +% Set the clique potentials to all 1s +C = length(cliques); +clpot = cell(1,C); +for i=1:C + clpot{i} = mk_initial_pot(pot_type, cliques{i}, ns, cnodes, onodes); +end + +% Multiply on specified potentials +for i=1:length(clqs) + c = clqs(i); + clpot{c} = multiply_by_pot(clpot{c}, pots{i}); +end + +seppot = cell(C,C); % implicitely initialized to 1 + + +%%%% +function [clpot, seppot] = collect_evidence(clpot, seppot, maximize, postorder, postorder_parents,... + separator) +for n=postorder %postorder(1:end-1) + for p=postorder_parents{n} + %clpot{p} = divide_by_pot(clpot{n}, seppot{p,n}); % dividing by 1 is redundant + seppot{p,n} = marginalize_pot(clpot{n}, separator{p,n}, maximize); + clpot{p} = multiply_by_pot(clpot{p}, seppot{p,n}); + end +end + + +%%%% +function [clpot, seppot] = distribute_evidence(clpot, seppot, maximize, preorder, preorder_children,... + separator) +for n=preorder + for c=preorder_children{n} + clpot{c} = divide_by_pot(clpot{c}, seppot{n,c}); + seppot{n,c} = marginalize_pot(clpot{n}, separator{n,c}, maximize); + clpot{c} = multiply_by_pot(clpot{c}, seppot{n,c}); + end +end diff --git a/sourcecodes/bnt-master/BNT/inference/dynamic/@jtree_dbn_inf_engine/Broken/enter_soft_evidence4.m b/sourcecodes/bnt-master/BNT/inference/dynamic/@jtree_dbn_inf_engine/Broken/enter_soft_evidence4.m new file mode 100644 index 00000000..a4ec90c6 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/dynamic/@jtree_dbn_inf_engine/Broken/enter_soft_evidence4.m @@ -0,0 +1,149 @@ +function [clpot, loglik] = enter_soft_evidence(engine, CPDpot, observed, pot_type) +% ENTER_SOFT_EVIDENCE Add the specified soft evidence to the network (jtree_dbn) +% [clpot, loglik] = enter_soft_evidence(engine, CPDpot, observed, pot_type, filter) + +[ss T] = size(CPDpot); +Q = length(engine.jtree_struct.cliques); +clpot = cell(Q,T); % clpot{t} contains evidence from slices (t-1, t) +seppot = cell(Q,Q,T); +ll = zeros(1,Q); +logscale = ones(1,T); % log(logscale(1)) = 0 +bnet = bnet_from_engine(engine); + +slice1 = 1:ss; +slice2 = slice1+ss; +Ntransient = length(engine.transient); +trans = cell(Ntransient,1); + +% calibrate each 2-slice jtree in isolation +for t=2:T + if t==2 + clqs = engine.jtree_struct.clq_ass_to_node([slice1 slice2]); + pots = CPDpot(:,t-1:t); + else + clqs = engine.jtree_struct.clq_ass_to_node([engine.transient slice2]); + for i=1:Ntransient + trans{i} = CPDpot{engine.transient(i), t-1}; + trans{i} = set_domain_pot(trans{i}, domain_pot(trans{i})-ss); % shift back to slice 1 + end + pots = [ trans; CPDpot(:,t)]; + end + [clpot(:,t), sepot(:,:,t)] = init_pot(engine.jtree_struct.cliques, clqs, pots, pot_type, ... + find(observed(:,t-1:t)), bnet.node_sizes(:), bnet.cnodes); + [clpot(:,t), seppot(:,:,t)] = collect_evidence(clpot(:,t), seppot(:,:,t), engine.maximize, ... + engine.jtree_struct.postorder, ... + engine.jtree_struct.postorder_parents,... + engine.jtree_struct.separator); + [clpot(:,t), seppot(:,:,t)] = distribute_evidence(clpot(:,t), seppot(:,:,t), engine.maximize, ... + engine.jtree_struct.preorder, ... + engine.jtree_struct.preorder_children, ... + engine.jtree_struct.separator); +end + +% Forwards pass. +% Compute distribution on clq C, +% where C is the out interface to (t-1,t). +% Then pass this to clq D, where D is the in inferface to (t+1,t). +% Then propagate from D to later slices. + +C = engine.out_clq; +D = engine.in_clq; +for t=2:T-1 + phiC = marginalize_pot(clpot{C,t}, engine.interface+ss, engine.maximize); + phiC = set_domain_pot(phiC, engine.interface); % shift back to slice 1 + phiD = marginalize_pot(clpot{D,t+1}, engine.interface, engine.maximize); + ratio = divide_by_pot(phiC, phiD); + clpot{D,t+1} = multiply_by_pot(clpot{D,t+1}, ratio); + + [clpot(:,t), seppot(:,:,t)] = distribute_evidence(clpot(:,t), seppot(:,:,t), engine.maximize, ... + engine.jtree_struct.preorder, ... + engine.jtree_struct.preorder_children, ... + engine.jtree_struct.separator); + for c=1:Q + [clpot{c,t}, ll(c)] = normalize_pot(clpot{c,t}); + end + logscale(t) = ll(1); +end + +% Backwards pass. +% Pass evidence from clq C to clq D, +% where C is the in interface to (t,t+1) and D is the out inferface to (t-1,t) +% Then propagate evidence from D to earlier slices. +C = engine.in_clq; +D = engine.out_clq; +for t=T:-1:2 + [clpot(:,t), seppot(:,:,t)] = collect_evidence(clpot(:,t), seppot(:,:,t), engine.maximize, ... + engine.jtree_struct.postorder, ... + engine.jtree_struct.postorder_parents,... + engine.jtree_struct.separator); + for c=1:Q + [clpot{c,t}, ll(c)] = normalize_pot(clpot{c,t}); + end + logscale(t) = ll(1); + + if t >= 3 + phiC = marginalize_pot(clpot{C,t}, engine.interface, engine.maximize); + phiC = set_domain_pot(phiC, engine.interface+ss); % shift forward to slice 2 + phiD = marginalize_pot(clpot{D,t-1}, engine.interface+ss, engine.maximize); + ratio = divide_by_pot(phiC, phiD); + clpot{D,t-1} = multiply_by_pot(clpot{D,t-1}, ratio); + end +end + +loglik = sum(logscale); + +%%%%%%%%%% + +function [clpot, seppot] = calibrate(engine, clpot, seppot) + + [clpot(:,t), seppot(:,:,t)] = collect_evidence(clpot(:,t), seppot(:,:,t), engine.maximize, ... + engine.jtree_struct.postorder, ... + engine.jtree_struct.postorder_parents,... + engine.jtree_struct.separator); + [clpot(:,t), seppot(:,:,t)] = distribute_evidence(clpot(:,t), seppot(:,:,t), engine.maximize, ... + engine.jtree_struct.preorder, ... + engine.jtree_struct.preorder_children, ... + engine.jtree_struct.separator); + + +%%%%%%% +function [clpot, seppot] = init_pot(cliques, clqs, pots, pot_type, onodes, ns, cnodes); + +% Set the clique potentials to all 1s +C = length(cliques); +clpot = cell(1,C); +for i=1:C + clpot{i} = mk_initial_pot(pot_type, cliques{i}, ns, cnodes, onodes); +end + +% Multiply on specified potentials +for i=1:length(clqs) + c = clqs(i); + clpot{c} = multiply_by_pot(clpot{c}, pots{i}); +end + +seppot = cell(C,C); % implicitely initialized to 1 + + +%%%% +function [clpot, seppot] = collect_evidence(clpot, seppot, maximize, postorder, postorder_parents,... + separator) +for n=postorder %postorder(1:end-1) + for p=postorder_parents{n} + %clpot{p} = divide_by_pot(clpot{n}, seppot{p,n}); % dividing by 1 is redundant + seppot{p,n} = marginalize_pot(clpot{n}, separator{p,n}, maximize); + clpot{p} = multiply_by_pot(clpot{p}, seppot{p,n}); + end +end + + +%%%% +function [clpot, seppot] = distribute_evidence(clpot, seppot, maximize, preorder, preorder_children,... + separator) +for n=preorder + for c=preorder_children{n} + clpot{c} = divide_by_pot(clpot{c}, seppot{n,c}); + seppot{n,c} = marginalize_pot(clpot{n}, separator{n,c}, maximize); + clpot{c} = multiply_by_pot(clpot{c}, seppot{n,c}); + end +end diff --git a/sourcecodes/bnt-master/BNT/inference/dynamic/@jtree_dbn_inf_engine/Broken/marginal_nodes.m b/sourcecodes/bnt-master/BNT/inference/dynamic/@jtree_dbn_inf_engine/Broken/marginal_nodes.m new file mode 100644 index 00000000..fe1d38f6 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/dynamic/@jtree_dbn_inf_engine/Broken/marginal_nodes.m @@ -0,0 +1,51 @@ +function marginal = marginal_nodes(engine, nodes, t, fam) +% MARGINAL_NODES Compute the marginal on the specified query nodes (bk) +% +% marginal = marginal_nodes(engine, i, t) +% returns Pr(X(i,t) | Y(1:T)), where X(i,t) is the i'th node in the t'th slice. +% +% marginal = marginal_nodes(engine, query, t) +% returns Pr(X(query(1),t), ... X(query(end),t) | Y(1:T)), +% where 't' specifies the time slice of the earliest node in the query. +% 'query' cannot span more than 2 time slices. +% +% Example: +% Consider a DBN with 2 nodes per slice. +% Then t=2, nodes=[1 3] refers to node 1 in slice 2 and node 1 in slice 3. + +if nargin < 3, t = 1; end +if nargin < 4, fam = 0; else fam = 1; end + + +% clpot{t} contains slice t-1 and t +% Example +% clpot #: 1 2 3 +% slices: 1 1,2 2,3 +% For filtering, we must take care not to take future evidence into account. +% For smoothing, clpot{1} does not exist. + +bnet = bnet_from_engine(engine); +ss = length(bnet.intra); + +if t < engine.T + slice = t+1; + nodes2 = nodes; +else % earliest t is T, so all nodes fit in one slice + slice = engine.T; + nodes2 = nodes + ss; +end + +c = clq_containing_nodes(engine.jtree_engine, nodes2, fam); +assert(c >= 1); + +%disp(['computing marginal on ' num2str(nodes) ' t = ' num2str(t)]); +%disp(['using ' num2str(nodes2) ' slice = ' num2str(slice) 'clq = ' num2str(c)]); + +bigpot = engine.clpot{c, slice}; + +pot = marginalize_pot(bigpot, nodes2, engine.maximize); +marginal = pot_to_marginal(pot); + +% we convert the domain to the unrolled numbering system +% so that update_ess extracts the right evidence. +marginal.domain = nodes+(t-1)*ss; diff --git a/sourcecodes/bnt-master/BNT/inference/dynamic/@jtree_dbn_inf_engine/CVS/Entries b/sourcecodes/bnt-master/BNT/inference/dynamic/@jtree_dbn_inf_engine/CVS/Entries new file mode 100644 index 00000000..aea2a602 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/dynamic/@jtree_dbn_inf_engine/CVS/Entries @@ -0,0 +1,6 @@ +/enter_evidence.m/1.1.1.1/Sat Jan 11 18:41:30 2003// +/enter_soft_evidence.m/1.1.1.1/Thu Feb 19 01:12:08 2004// +/jtree_dbn_inf_engine.m/1.1.1.1/Thu Nov 14 16:32:00 2002// +/marginal_family.m/1.1.1.1/Wed May 29 15:59:56 2002// +/marginal_nodes.m/1.1.1.1/Fri Nov 22 23:51:58 2002// +D diff --git a/sourcecodes/bnt-master/BNT/inference/dynamic/@jtree_dbn_inf_engine/CVS/Entries.Log b/sourcecodes/bnt-master/BNT/inference/dynamic/@jtree_dbn_inf_engine/CVS/Entries.Log new file mode 100644 index 00000000..2fb9e4b6 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/dynamic/@jtree_dbn_inf_engine/CVS/Entries.Log @@ -0,0 +1,2 @@ +A D/Broken//// +A D/Old//// diff --git a/sourcecodes/bnt-master/BNT/inference/dynamic/@jtree_dbn_inf_engine/CVS/Repository b/sourcecodes/bnt-master/BNT/inference/dynamic/@jtree_dbn_inf_engine/CVS/Repository new file mode 100644 index 00000000..590182fa --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/dynamic/@jtree_dbn_inf_engine/CVS/Repository @@ -0,0 +1 @@ +FullBNT/BNT/inference/dynamic/@jtree_dbn_inf_engine diff --git a/sourcecodes/bnt-master/BNT/inference/dynamic/@jtree_dbn_inf_engine/CVS/Root b/sourcecodes/bnt-master/BNT/inference/dynamic/@jtree_dbn_inf_engine/CVS/Root new file mode 100644 index 00000000..f3bd14a6 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/dynamic/@jtree_dbn_inf_engine/CVS/Root @@ -0,0 +1 @@ +:ext:nsaunier@bnt.cvs.sourceforge.net:/cvsroot/bnt diff --git a/sourcecodes/bnt-master/BNT/inference/dynamic/@jtree_dbn_inf_engine/Old/CVS/Entries b/sourcecodes/bnt-master/BNT/inference/dynamic/@jtree_dbn_inf_engine/Old/CVS/Entries new file mode 100644 index 00000000..0bc2d941 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/dynamic/@jtree_dbn_inf_engine/Old/CVS/Entries @@ -0,0 +1,6 @@ +/enter_soft_evidence_nonint.m/1.1.1.1/Wed May 29 15:59:56 2002// +/enter_soft_evidence_trans.m/1.1.1.1/Wed May 29 15:59:56 2002// +/jtree_dbn_inf_engine.m/1.1.1.1/Wed May 29 15:59:56 2002// +/jtree_dbn_inf_engine1.m/1.1.1.1/Wed May 29 15:59:56 2002// +/jtree_dbn_inf_engine2.m/1.1.1.1/Wed May 29 15:59:56 2002// +D diff --git a/sourcecodes/bnt-master/BNT/inference/dynamic/@jtree_dbn_inf_engine/Old/CVS/Repository b/sourcecodes/bnt-master/BNT/inference/dynamic/@jtree_dbn_inf_engine/Old/CVS/Repository new file mode 100644 index 00000000..0b90d866 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/dynamic/@jtree_dbn_inf_engine/Old/CVS/Repository @@ -0,0 +1 @@ +FullBNT/BNT/inference/dynamic/@jtree_dbn_inf_engine/Old diff --git a/sourcecodes/bnt-master/BNT/inference/dynamic/@jtree_dbn_inf_engine/Old/CVS/Root b/sourcecodes/bnt-master/BNT/inference/dynamic/@jtree_dbn_inf_engine/Old/CVS/Root new file mode 100644 index 00000000..f3bd14a6 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/dynamic/@jtree_dbn_inf_engine/Old/CVS/Root @@ -0,0 +1 @@ +:ext:nsaunier@bnt.cvs.sourceforge.net:/cvsroot/bnt diff --git a/sourcecodes/bnt-master/BNT/inference/dynamic/@jtree_dbn_inf_engine/Old/enter_soft_evidence_nonint.m b/sourcecodes/bnt-master/BNT/inference/dynamic/@jtree_dbn_inf_engine/Old/enter_soft_evidence_nonint.m new file mode 100644 index 00000000..72641580 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/dynamic/@jtree_dbn_inf_engine/Old/enter_soft_evidence_nonint.m @@ -0,0 +1,135 @@ +function [clpot, loglik] = enter_soft_evidence(engine, CPDpot, observed, pot_type) +% ENTER_SOFT_EVIDENCE Add the specified soft evidence to the network (jtree_dbn) +% [clpot, loglik] = enter_soft_evidence(engine, CPDpot, observed, pot_type, filter) + +[ss T] = size(CPDpot); +Q = length(engine.jtree_struct.cliques); +clpot = cell(Q,T); % clpot{t} contains evidence from slices (t-1, t) +seppot = cell(Q,Q,T); +ll = zeros(1,Q); +logscale = zeros(1,T); +bnet = bnet_from_engine(engine); + +% Forwards pass. +% Compute distribution on clq C, +% where C is the out interface to (t-1,t). +% Then pass this to clq D, where D is the in inferface to (t+1,t). +% Then propagate from D to later slices. + +C = engine.out_clq; +assert(C==engine.jtree_struct.root_clq); +D = engine.in_clq; +slice1 = 1:ss; +slice2 = slice1 + ss; +Nnonint = length(engine.nonint); +nonint = cell(Nnonint, 1); +for t=1:T + if t==1 + pots = [CPDpot(:,1); CPDpot(engine.interface, 2)]; + clqs = engine.jtree_struct.clq_ass_to_node([slice1 engine.interface+ss]); + obs = find(observed(:,1:2)); + elseif t==T + clqs = [D engine.jtree_struct.clq_ass_to_node(engine.nonint)]; + phiC = set_domain_pot(phiC, engine.interface); % shift back to slice 1 + for i=1:Nnonint + nonint{i} = CPDpot{engine.nonint(i), t}; + nonint{i} = set_domain_pot(nonint{i}, domain_pot(nonint{i})-ss); % shift back to slice 1 + end + pots = [ {phiC}; nonint]; + obs = find(observed(:,T)); + else + clqs = [D engine.jtree_struct.clq_ass_to_node([engine.nonint engine.interface+ss])]; + phiC = set_domain_pot(phiC, engine.interface); % shift back to slice 1 + for i=1:Nnonint + nonint{i} = CPDpot{engine.nonint(i), t}; + nonint{i} = set_domain_pot(nonint{i}, domain_pot(nonint{i})-ss); % shift back to slice 1 + end + pots = [ {phiC}; nonint; CPDpot(engine.interface, t+1)]; + obs = find(observed(:,t:t+1)); + end + [clpot(:,t), seppot(:,:,t)] = init_pot(engine.jtree_struct.cliques, clqs, pots, pot_type, ... + obs, bnet.node_sizes(:), bnet.cnodes); + [clpot(:,t), seppot(:,:,t)] = collect_evidence(clpot(:,t), seppot(:,:,t), engine.maximize, ... + engine.jtree_struct.postorder, ... + engine.jtree_struct.postorder_parents,... + engine.jtree_struct.separator); + + for c=1:Q + [clpot{c,t}, ll(c)] = normalize_pot(clpot{c,t}); + end + logscale(t) = ll(C); + + phiC = marginalize_pot(clpot{C,t}, engine.interface+ss, engine.maximize); +end + + + +% Backwards pass. +% Pass evidence from clq C to clq D, +% where C is the in interface to (t,t+1) and D is the out inferface to (t-1,t) +% Then propagate evidence from D to earlier slices. +C = engine.in_clq; +D = engine.out_clq; +for t=T:-1:1 + [clpot(:,t), seppot(:,:,t)] = distribute_evidence(clpot(:,t), seppot(:,:,t), engine.maximize, ... + engine.jtree_struct.preorder, ... + engine.jtree_struct.preorder_children, ... + engine.jtree_struct.separator); + for c=1:Q + [clpot{c,t}, ll(c)] = normalize_pot(clpot{c,t}); + end + %logscale(t) = ll(C); + + if t >= 2 + phiC = marginalize_pot(clpot{C,t}, engine.interface, engine.maximize); + phiC = set_domain_pot(phiC, engine.interface+ss); % shift forward to slice 2 + phiD = marginalize_pot(clpot{D,t-1}, engine.interface+ss, engine.maximize); + ratio = divide_by_pot(phiC, phiD); + clpot{D,t-1} = multiply_by_pot(clpot{D,t-1}, ratio); + end +end + +loglik = sum(logscale); + + +%%%%%%% +function [clpot, seppot] = init_pot(cliques, clqs, pots, pot_type, onodes, ns, cnodes); + +% Set the clique potentials to all 1s +C = length(cliques); +clpot = cell(1,C); +for i=1:C + clpot{i} = mk_initial_pot(pot_type, cliques{i}, ns, cnodes, onodes); +end + +% Multiply on specified potentials +for i=1:length(clqs) + c = clqs(i); + clpot{c} = multiply_by_pot(clpot{c}, pots{i}); +end + +seppot = cell(C,C); % implicitely initialized to 1 + + +%%%% +function [clpot, seppot] = collect_evidence(clpot, seppot, maximize, postorder, postorder_parents,... + separator) +for n=postorder %postorder(1:end-1) + for p=postorder_parents{n} + %clpot{p} = divide_by_pot(clpot{n}, seppot{p,n}); % dividing by 1 is redundant + seppot{p,n} = marginalize_pot(clpot{n}, separator{p,n}, maximize); + clpot{p} = multiply_by_pot(clpot{p}, seppot{p,n}); + end +end + + +%%%% +function [clpot, seppot] = distribute_evidence(clpot, seppot, maximize, preorder, preorder_children,... + separator) +for n=preorder + for c=preorder_children{n} + clpot{c} = divide_by_pot(clpot{c}, seppot{n,c}); + seppot{n,c} = marginalize_pot(clpot{n}, separator{n,c}, maximize); + clpot{c} = multiply_by_pot(clpot{c}, seppot{n,c}); + end +end diff --git a/sourcecodes/bnt-master/BNT/inference/dynamic/@jtree_dbn_inf_engine/Old/enter_soft_evidence_trans.m b/sourcecodes/bnt-master/BNT/inference/dynamic/@jtree_dbn_inf_engine/Old/enter_soft_evidence_trans.m new file mode 100644 index 00000000..b9c85b80 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/dynamic/@jtree_dbn_inf_engine/Old/enter_soft_evidence_trans.m @@ -0,0 +1,135 @@ +function [clpot, loglik] = enter_soft_evidence(engine, CPDpot, observed, pot_type) +% ENTER_SOFT_EVIDENCE Add the specified soft evidence to the network (jtree_dbn) +% [clpot, loglik] = enter_soft_evidence(engine, CPDpot, observed, pot_type, filter) + +[ss T] = size(CPDpot); +Q = length(engine.jtree_struct.cliques); +clpot = cell(Q,T); % clpot{t} contains evidence from slices (t-1, t) +seppot = cell(Q,Q,T); +ll = zeros(1,Q); +logscale = zeros(1,T); +bnet = bnet_from_engine(engine); + +% Forwards pass. +% Compute distribution on clq C, +% where C is the out interface to (t-1,t). +% Then pass this to clq D, where D is the in inferface to (t+1,t). +% Then propagate from D to later slices. + +C = engine.out_clq; +assert(C==engine.jtree_struct.root_clq); +D = engine.in_clq; +slice1 = 1:ss; +slice2 = slice1 + ss; +Ntransient = length(engine.transient); +trans = cell(Ntransient,1); +for t=1:T + if t==1 + pots = [CPDpot(:,1); CPDpot(engine.persist, 2)]; + clqs = engine.jtree_struct.clq_ass_to_node([slice1 engine.persist+ss]); + obs = find(observed(:,1:2)); + elseif t==T + clqs = [D engine.jtree_struct.clq_ass_to_node(engine.transient)]; + phiC = set_domain_pot(phiC, engine.interface); % shift back to slice 1 + for i=1:Ntransient + trans{i} = CPDpot{engine.transient(i), t}; + trans{i} = set_domain_pot(trans{i}, domain_pot(trans{i})-ss); % shift back to slice 1 + end + pots = [ {phiC}; trans]; + obs = find(observed(:,T)); + else + clqs = [D engine.jtree_struct.clq_ass_to_node([engine.transient engine.persist+ss])]; + phiC = set_domain_pot(phiC, engine.interface); % shift back to slice 1 + for i=1:Ntransient + trans{i} = CPDpot{engine.transient(i), t}; + trans{i} = set_domain_pot(trans{i}, domain_pot(trans{i})-ss); % shift back to slice 1 + end + pots = [ {phiC}; trans; CPDpot(engine.persist, t+1)]; + obs = find(observed(:,t:t+1)); + end + [clpot(:,t), seppot(:,:,t)] = init_pot(engine.jtree_struct.cliques, clqs, pots, pot_type, ... + obs, bnet.node_sizes(:), bnet.cnodes); + [clpot(:,t), seppot(:,:,t)] = collect_evidence(clpot(:,t), seppot(:,:,t), engine.maximize, ... + engine.jtree_struct.postorder, ... + engine.jtree_struct.postorder_parents,... + engine.jtree_struct.separator); + + for c=1:Q + [clpot{c,t}, ll(c)] = normalize_pot(clpot{c,t}); + end + logscale(t) = ll(C); + + phiC = marginalize_pot(clpot{C,t}, engine.interface+ss, engine.maximize); +end + + + +% Backwards pass. +% Pass evidence from clq C to clq D, +% where C is the in interface to (t,t+1) and D is the out inferface to (t-1,t) +% Then propagate evidence from D to earlier slices. +C = engine.in_clq; +D = engine.out_clq; +for t=T:-1:1 + [clpot(:,t), seppot(:,:,t)] = distribute_evidence(clpot(:,t), seppot(:,:,t), engine.maximize, ... + engine.jtree_struct.preorder, ... + engine.jtree_struct.preorder_children, ... + engine.jtree_struct.separator); + for c=1:Q + [clpot{c,t}, ll(c)] = normalize_pot(clpot{c,t}); + end + %logscale(t) = ll(C); + + if t >= 2 + phiC = marginalize_pot(clpot{C,t}, engine.interface, engine.maximize); + phiC = set_domain_pot(phiC, engine.interface+ss); % shift forward to slice 2 + phiD = marginalize_pot(clpot{D,t-1}, engine.interface+ss, engine.maximize); + ratio = divide_by_pot(phiC, phiD); + clpot{D,t-1} = multiply_by_pot(clpot{D,t-1}, ratio); + end +end + +loglik = sum(logscale); + + +%%%%%%% +function [clpot, seppot] = init_pot(cliques, clqs, pots, pot_type, onodes, ns, cnodes); + +% Set the clique potentials to all 1s +C = length(cliques); +clpot = cell(1,C); +for i=1:C + clpot{i} = mk_initial_pot(pot_type, cliques{i}, ns, cnodes, onodes); +end + +% Multiply on specified potentials +for i=1:length(clqs) + c = clqs(i); + clpot{c} = multiply_by_pot(clpot{c}, pots{i}); +end + +seppot = cell(C,C); % implicitely initialized to 1 + + +%%%% +function [clpot, seppot] = collect_evidence(clpot, seppot, maximize, postorder, postorder_parents,... + separator) +for n=postorder %postorder(1:end-1) + for p=postorder_parents{n} + %clpot{p} = divide_by_pot(clpot{n}, seppot{p,n}); % dividing by 1 is redundant + seppot{p,n} = marginalize_pot(clpot{n}, separator{p,n}, maximize); + clpot{p} = multiply_by_pot(clpot{p}, seppot{p,n}); + end +end + + +%%%% +function [clpot, seppot] = distribute_evidence(clpot, seppot, maximize, preorder, preorder_children,... + separator) +for n=preorder + for c=preorder_children{n} + clpot{c} = divide_by_pot(clpot{c}, seppot{n,c}); + seppot{n,c} = marginalize_pot(clpot{n}, separator{n,c}, maximize); + clpot{c} = multiply_by_pot(clpot{c}, seppot{n,c}); + end +end diff --git a/sourcecodes/bnt-master/BNT/inference/dynamic/@jtree_dbn_inf_engine/Old/jtree_dbn_inf_engine.m b/sourcecodes/bnt-master/BNT/inference/dynamic/@jtree_dbn_inf_engine/Old/jtree_dbn_inf_engine.m new file mode 100644 index 00000000..5b5cc8ba --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/dynamic/@jtree_dbn_inf_engine/Old/jtree_dbn_inf_engine.m @@ -0,0 +1,67 @@ +function engine = jtree_dbn_inf_engine(bnet, varargin) +% JTREE_DBN_INF_ENGINE Junction tree inference algorithm for DBNs. + +ss = length(bnet.intra); + +onodes = []; + +if nargin >= 2 + args = varargin; + nargs = length(args); + for i=1:2:nargs + switch args{i}, + case 'observed', onodes = args{i+1}; + end + end +end + +[int, engine.persist, engine.transient] = compute_interface_nodes(bnet.intra, bnet.inter); +%engine.interface = engine.persist; % WRONG! +engine.interface = int; +engine.nonint = mysetdiff(1:ss, int); + +if 0 + % Create a 2 slice jtree + % We force there to be cliques containing the in and out interfaces for slices t and t+1. + obs_nodes = [onodes(:) onodes(:)+ss]; + engine.jtree_engine = jtree_inf_engine(bnet, 'observed', obs_nodes(:), ... + 'clusters', {int, int+ss}, 'root', int+ss); +else + % Create a "1.5 slice" jtree, containing slice 1 and the interface nodes of slice 2 + nodes15 = [1:ss int+ss]; + N = length(nodes15); + dag15 = bnet.dag(nodes15, nodes15); + ns15 = bnet.node_sizes(nodes15); + eclass15 = bnet.equiv_class(nodes15); + discrete_bitv = zeros(1,2*ss); + discrete_bitv(bnet.dnodes) = 1; + discrete15 = find(discrete_bitv(nodes15)); + bnet15 = mk_bnet(dag15, ns15, 'equiv_class', eclass15, 'discrete', discrete15); + bnet15.CPD = bnet.CPD; % CPDs for non-interface nodes in slice 2 will not be used + obs_bitv = zeros(1, 2*ss); + obs_bitv([onodes onodes+ss]) = 1; + obs_nodes15 = find(obs_bitv(nodes15)); + int_bitv = zeros(1,ss); + int_bitv(int) = 1; + engine.jtree_engine = jtree_inf_engine(bnet15, 'observed', obs_nodes15(:), ... + 'clusters', {int, int+ss}, 'root', int+ss); +end + +engine.in_clq = clq_containing_nodes(engine.jtree_engine, int); +engine.out_clq = clq_containing_nodes(engine.jtree_engine, int+ss); + +engine.clq_ass_to_node = zeros(ss, 2); +for i=1:ss + engine.clq_ass_to_node(i, 1) = clq_containing_nodes(engine.jtree_engine, i); + engine.clq_ass_to_node(i, 2) = clq_containing_nodes(engine.jtree_engine, i+ss); +end + +engine.jtree_struct = struct(engine.jtree_engine); % violate object privacy + +% stuff needed by marginal_nodes +engine.clpot = []; +engine.maximize = []; +engine.T = []; + +engine = class(engine, 'jtree_dbn_inf_engine', inf_engine(bnet)); + diff --git a/sourcecodes/bnt-master/BNT/inference/dynamic/@jtree_dbn_inf_engine/Old/jtree_dbn_inf_engine1.m b/sourcecodes/bnt-master/BNT/inference/dynamic/@jtree_dbn_inf_engine/Old/jtree_dbn_inf_engine1.m new file mode 100644 index 00000000..5edad836 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/dynamic/@jtree_dbn_inf_engine/Old/jtree_dbn_inf_engine1.m @@ -0,0 +1,62 @@ +function engine = jtree_dbn_inf_engine(bnet, varargin) +% JTREE_DBN_INF_ENGINE Junction tree inference algorithm for DBNs. + +ss = length(bnet.intra); + +onodes = []; + +if nargin >= 2 + args = varargin; + nargs = length(args); + for i=1:2:nargs + switch args{i}, + case 'observed', onodes = args{i+1}; + end + end +end + +[int, engine.persist, engine.transient] = compute_interface_nodes(bnet.intra, bnet.inter); +%engine.interface = engine.persist; % WRONG! +engine.interface = int; +engine.nonint = mysetdiff(1:ss, int); + +if 1 + % Create a 2 slice jtree + % We force there to be cliques containing the in and out interfaces for slices t and t+1. + obs_nodes = [onodes(:) onodes(:)+ss]; + engine.jtree_engine = jtree_inf_engine(bnet, 'observed', obs_nodes(:), ... + 'clusters', {int, int+ss}, 'root', int+ss); +else + % Create a "1.5 slice" jtree, containing slice 1 and the interface nodes of slice 2 + % To keep the node numbering the same, we simply disconnect the non-interface nodes + % from slice 2. + intra15 = bnet.intra; + for i=engine.nonint(:)' + intra15(i,:) = 0; + intra15(:,i) = 0; + end + bnet15 = mk_dbn(intra15, bnet.inter, bnet.node_sizes_slice, bnet.dnodes_slice, ... + bnet.equiv_class(:,1), bnet.equiv_class(:,2), bnet.intra); + obs_nodes = [onodes(:) onodes(:)+ss]; + engine.jtree_engine = jtree_inf_engine(bnet15, 'observed', obs_nodes(:), ... + 'clusters', {int, int+ss}, 'root', int+ss); +end + +engine.in_clq = clq_containing_nodes(engine.jtree_engine, int); +engine.out_clq = clq_containing_nodes(engine.jtree_engine, int+ss); + +engine.clq_ass_to_node = zeros(ss, 2); +for i=1:ss + engine.clq_ass_to_node(i, 1) = clq_containing_nodes(engine.jtree_engine, i); + engine.clq_ass_to_node(i, 2) = clq_containing_nodes(engine.jtree_engine, i+ss); +end + +engine.jtree_struct = struct(engine.jtree_engine); % violate object privacy + +% stuff needed by marginal_nodes +engine.clpot = []; +engine.maximize = []; +engine.T = []; + +engine = class(engine, 'jtree_dbn_inf_engine', inf_engine(bnet)); + diff --git a/sourcecodes/bnt-master/BNT/inference/dynamic/@jtree_dbn_inf_engine/Old/jtree_dbn_inf_engine2.m b/sourcecodes/bnt-master/BNT/inference/dynamic/@jtree_dbn_inf_engine/Old/jtree_dbn_inf_engine2.m new file mode 100644 index 00000000..68ac2aff --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/dynamic/@jtree_dbn_inf_engine/Old/jtree_dbn_inf_engine2.m @@ -0,0 +1,57 @@ +function engine = jtree_dbn_inf_engine(bnet, varargin) +% JTREE_DBN_INF_ENGINE Junction tree inference algorithm for DBNs. + +ss = length(bnet.intra); + +onodes = []; + +if nargin >= 2 + args = varargin; + nargs = length(args); + for i=1:2:nargs + switch args{i}, + case 'observed', onodes = args{i+1}; + end + end +end + +[int, engine.persist, engine.transient] = compute_interface_nodes(bnet.intra, bnet.inter); +%engine.interface = engine.persist; % WRONG! +engine.interface = int; +engine.nonint = mysetdiff(1:ss, int); + + +% Create a 2 slice jtree +% We force there to be cliques containing the in and out interfaces for slices t and t+1. +obs_nodes = [onodes(:) onodes(:)+ss]; +engine.jtree_engine = jtree_inf_engine(bnet, 'observed', obs_nodes(:), ... + 'clusters', {int, int+ss}, 'root', int+ss); + +engine.in_clq = clq_containing_nodes(engine.jtree_engine, int); +engine.out_clq = clq_containing_nodes(engine.jtree_engine, int+ss); +engine.jtree_struct = struct(engine.jtree_engine); % violate object privacy + + + +% Also create an engine just for slice 1 +bnet1 = mk_bnet(bnet.intra1, bnet.node_sizes_slice, bnet.dnodes, bnet.equiv_class(:,1)); +for i=1:max(bnet1.equiv_class) + bnet1.CPD{i} = bnet.CPD{i}; +end + +engine.jtree_engine1 = jtree_inf_engine(bnet1, 'observed', onodes, 'clusters', {int}, ... + 'root', int); + +engine.in_clq1 = clq_containing_nodes(engine.jtree_engine1, int); +engine.jtree_struct1 = struct(engine.jtree_engine1); % violate object privacy + + + + +% stuff needed by marginal_nodes +engine.clpot = []; +engine.T = []; +engine.maximize = []; + +engine = class(engine, 'jtree_dbn_inf_engine', inf_engine(bnet)); + diff --git a/sourcecodes/bnt-master/BNT/inference/dynamic/@jtree_dbn_inf_engine/enter_evidence.m b/sourcecodes/bnt-master/BNT/inference/dynamic/@jtree_dbn_inf_engine/enter_evidence.m new file mode 100644 index 00000000..e21bb07d --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/dynamic/@jtree_dbn_inf_engine/enter_evidence.m @@ -0,0 +1,70 @@ +function [engine, loglik] = enter_evidence(engine, evidence, varargin) +% ENTER_EVIDENCE Add the specified evidence to the network (jtree_dbn) +% [engine, loglik] = enter_evidence(engine, evidence, ...) +% +% evidence{i,t} = [] if if X(i,t) is hidden, and otherwise contains its observed value (scalar or column vector) +% +% The following optional arguments can be specified in the form of name/value pairs: +% [default value in brackets] +% +% maximize - if 1, does max-product instead of sum-product [engine.maximize] +% softCPDpot{n,t} - use soft potential for node n instead of its CPD; set to [] to use CPD +% soft_evidence_nodes(i,1:2) = [n t] means the i'th piece of soft evidence is on node n in slice t +% soft_evidence{i} - prob distribution over values for soft_evidence_nodes(i,:) +% +% e.g., engine = enter_evidence(engine, ev, 'maximize', 1) + + +% for add_ev in marginal_nodes +T = size(evidence, 2); +engine.evidence = evidence; +bnet = bnet_from_engine(engine); +ss = length(bnet.node_sizes_slice); +ns = bnet.node_sizes_slice(:); +engine.node_sizes = repmat(ns, [1 T]); +softCPDpot = cell(ss,T); +soft_evidence = {}; +soft_evidence_nodes = []; + +% parse optional params +args = varargin; +nargs = length(args); +if nargs > 0 + for i=1:2:nargs + switch args{i}, + case 'maximize', engine.maximize = args{i+1}; + case 'softCPDpot', softCPDpot = args{i+1}; + case 'soft_evidence', soft_evidence = args{i+1}; + case 'soft_evidence_nodes', soft_evidence_nodes = args{i+1}; + otherwise, + error(['invalid argument name ' args{i}]); + end + end +end + +engine.jtree_engine = set_fields(engine.jtree_engine, 'maximize', engine.maximize); +engine.jtree_engine1 = set_fields(engine.jtree_engine1, 'maximize', engine.maximize); + +[ss T] = size(evidence); +engine.T = T; +observed_bitv = ~isemptycell(evidence); +onodes = find(observed_bitv); +pot_type = determine_pot_type(bnet, onodes); +CPDpot = convert_dbn_CPDs_to_pots(bnet, evidence, pot_type, softCPDpot); + +if ~isempty(soft_evidence_nodes) + nsoft = size(soft_evidence_nodes,1); + for i=1:nsoft + n = soft_evidence_nodes(i,1); + t = soft_evidence_nodes(i,2); + if t==1 + dom = n; + else + dom = n+ss; + end + pot = dpot(dom, ns(n), soft_evidence{i}); + CPDpot{n,t} = multiply_by_pot(CPDpot{n,t}, pot); + end +end + +[engine.clpot, loglik] = enter_soft_evidence(engine, CPDpot, observed_bitv, pot_type); diff --git a/sourcecodes/bnt-master/BNT/inference/dynamic/@jtree_dbn_inf_engine/enter_soft_evidence.m b/sourcecodes/bnt-master/BNT/inference/dynamic/@jtree_dbn_inf_engine/enter_soft_evidence.m new file mode 100644 index 00000000..5ffc55b0 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/dynamic/@jtree_dbn_inf_engine/enter_soft_evidence.m @@ -0,0 +1,126 @@ +function [clpot, loglik] = enter_soft_evidence(engine, CPDpot, observed, pot_type) +% ENTER_SOFT_EVIDENCE Add the specified soft evidence to the network (jtree_dbn) +% [clpot, loglik] = enter_soft_evidence(engine, CPDpot, observed, pot_type) + +scale = 1; +verbose = 0; + +[ss T] = size(CPDpot); +Q = length(engine.jtree_struct.cliques); +clpot = cell(Q,T); % clpot{t} contains evidence from slices (t-1, t) +seppot = cell(Q,Q,T); +ll = zeros(1,Q); +logscale = zeros(1,T); +bnet = bnet_from_engine(engine); +root = engine.jtree_struct.root_clq; + +% Forwards pass. +% Compute distribution on clq C, +% where C is the out interface to (t-1,t). +% Then pass this to clq D, where D is the in inferface to (t+1,t). + +% Then propagate from D to later slices. + +slice1 = 1:ss; +slice2 = slice1 + ss; +transient = engine.transient; +persist = engine.persist; +Ntransient = length(transient); +trans = cell(Ntransient,1); +if verbose, fprintf('forward pass\n'); end +for t=1:T + if verbose, fprintf('%d ', t); end + if t==1 + pots = [CPDpot(:,1); CPDpot(persist, 2)]; + clqs = engine.jtree_struct.clq_ass_to_node([slice1 persist+ss]); + obs = find(observed(:,1:2)); + elseif t==T + clqs = [engine.in_clq1 engine.jtree_struct1.clq_ass_to_node(transient)]; + phi = set_domain_pot(phi, engine.interface); % shift back to slice 1 + for i=1:Ntransient + trans{i} = CPDpot{transient(i), t}; + trans{i} = set_domain_pot(trans{i}, domain_pot(trans{i})-ss); % shift back to slice 1 + end + pots = [ {phi}; trans]; + obs = find(observed(:,T)); + else + clqs = [engine.in_clq engine.jtree_struct.clq_ass_to_node([transient persist+ss])]; + phi = set_domain_pot(phi, engine.interface); % shift back to slice 1 + for i=1:Ntransient + trans{i} = CPDpot{transient(i), t}; + trans{i} = set_domain_pot(trans{i}, domain_pot(trans{i})-ss); % shift back to slice 1 + end + pots = [ {phi}; trans; CPDpot(persist, t+1)]; + obs = find(observed(:,t:t+1)); + end + + if t < T + [clpot(1:Q,t), seppot(1:Q,1:Q,t)] = init_pot(engine.jtree_engine, clqs, pots, pot_type, obs); + [clpot(1:Q,t), seppot(1:Q,1:Q,t)] = collect_evidence(engine.jtree_engine, clpot(1:Q,t), seppot(1:Q,1:Q,t)); + else + Q = length(engine.jtree_struct1.cliques); + root = engine.jtree_struct1.root_clq; + [clpot(1:Q,t), seppot(1:Q,1:Q,t)] = init_pot(engine.jtree_engine1, clqs, pots, pot_type, obs); + [clpot(1:Q,t), seppot(1:Q,1:Q,t)] = collect_evidence(engine.jtree_engine1, clpot(1:Q,t), seppot(1:Q,1:Q,t)); + end + + + if scale + for c=1:Q + [clpot{c,t}, ll(c)] = normalize_pot(clpot{c,t}); + end + logscale(t) = ll(root); + end + + if t < T + % bug fix by Bob Welch 30 Jan 04 + phi = marginalize_pot(clpot{engine.out_clq,t}, engine.interface+ss,engine.maximize); + %phi = marginalize_pot(clpot{root,t}, engine.interface+ss, engine.maximize); + end +end + +if scale +loglik = sum(logscale); +else +loglik = []; +end + + +% Backwards pass. +% Pass evidence from clq C to clq D, +% where C is the in interface to (t,t+1) and D is the out inferface to (t-1,t) +% Then propagate evidence from D to earlier slices. +% (C and D are reversed names from the tech report!) +D = engine.out_clq; +if verbose, fprintf('\nbackwards pass\n'); end +for t=T:-1:1 + if verbose, fprintf('%d ', t); end + + if t == T + Q = length(engine.jtree_struct1.cliques); + C = engine.in_clq1; + [clpot(1:Q,t), seppot(1:Q,1:Q,t)] = distribute_evidence(engine.jtree_engine1, clpot(1:Q,t), seppot(1:Q,1:Q,t)); + else + Q = length(engine.jtree_struct.cliques); + C = engine.in_clq; + [clpot(1:Q,t), seppot(1:Q,1:Q,t)] = distribute_evidence(engine.jtree_engine, clpot(1:Q,t), seppot(1:Q,1:Q,t)); + end + + if scale + for c=1:Q + [clpot{c,t}, ll(c)] = normalize_pot(clpot{c,t}); + end + end + + if t >= 2 + phiC = marginalize_pot(clpot{C,t}, engine.interface, engine.maximize); + phiC = set_domain_pot(phiC, engine.interface+ss); % shift forward to slice 2 + phiD = marginalize_pot(clpot{D,t-1}, engine.interface+ss, engine.maximize); + ratio = divide_by_pot(phiC, phiD); + clpot{D,t-1} = multiply_by_pot(clpot{D,t-1}, ratio); + end +end +if verbose, fprintf('\n'); end + + + diff --git a/sourcecodes/bnt-master/BNT/inference/dynamic/@jtree_dbn_inf_engine/jtree_dbn_inf_engine.m b/sourcecodes/bnt-master/BNT/inference/dynamic/@jtree_dbn_inf_engine/jtree_dbn_inf_engine.m new file mode 100644 index 00000000..c49ba4c4 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/dynamic/@jtree_dbn_inf_engine/jtree_dbn_inf_engine.m @@ -0,0 +1,109 @@ +function engine = jtree_dbn_inf_engine(bnet, varargin) +% JTREE_DBN_INF_ENGINE Junction tree inference algorithm for DBNs. +% engine = jtree_inf_engine(bnet, ...) +% +% The following optional arguments can be specified in the form of name/value pairs: +% [default value in brackets] +% +% clusters - specifies variables that must be grouped in the 1.5 slice DBN +% maximize - 1 means max-product, 0 means sum-product [0] +% +% e.g., engine = jtree_dbn_inf_engine(dbn, 'clusters', {[1 2]}); +% +% This uses all of slice t-1 plus the backwards interface of slice t. +% By contrast, jtree_2TBN_inf_engine in the online directory uses +% the forwards interface of slice t-1 plus all of slice t. +% See my thesis for details. + +ss = length(bnet.intra); + +engine.maximize = 0; +clusters = {}; + +args = varargin; +for i=1:2:length(args) + switch args{i}, + case 'clusters', clusters = args{i+1}; + case 'maximize', engine.maximize = args{i+1}; + otherwise, error(['unrecognized argument ' args{i}]) + end +end + + +engine.evidence = []; +engine.node_sizes = []; + +[int, engine.persist, engine.transient] = compute_interface_nodes(bnet.intra, bnet.inter); +engine.interface = int; +engine.nonint = mysetdiff(1:ss, int); + +onodes = bnet.observed; + +if 0 + % Create a 2 slice jtree + % We force there to be cliques containing the in and out interfaces for slices t and t+1. + obs_nodes = [onodes(:) onodes(:)+ss]; + engine.jtree_engine = jtree_inf_engine(bnet, 'observed', obs_nodes(:), ... + 'clusters', {int, int+ss}, 'root', int+ss); +else + % Create a "1.5 slice" jtree, containing slice 1 and the interface nodes of slice 2 + % To keep the node numbering the same, we simply disconnect the non-interface nodes + % from slice 2, and set their size to 1. + % We do this to speed things up, and so that the likelihood is computed correctly - we do not need to do + % this if we just want to compute marginals. + intra15 = bnet.intra; + for i=engine.nonint(:)' + intra15(i,:) = 0; + intra15(:,i) = 0; + end + dag15 = [bnet.intra bnet.inter; + zeros(ss) intra15]; + ns = bnet.node_sizes(:); + ns(engine.nonint+ss) = 1; % disconnected nodes get size 1 + obs_nodes = [onodes(:) onodes(:)+ss]; + bnet15 = mk_bnet(dag15, ns, 'discrete', bnet.dnodes, 'equiv_class', bnet.equiv_class(:), ... + 'observed', obs_nodes(:)); + + %bnet15 = mk_dbn(intra15, bnet.inter, bnet.node_sizes_slice, bnet.dnodes_slice, ... + % bnet.equiv_class(:,1), bnet.equiv_class(:,2), bnet.intra); + % with the dbn, we can't independently control the sizes of slice 2 nodes + + if 1 + % use unconstrained elimination, + % but force there to be a clique containing both interfaces + clusters(end+1:end+2) = {int, int+ss}; + engine.jtree_engine = jtree_inf_engine(bnet15, 'clusters', clusters, 'root', int+ss); + else + % Use constrained elimination - this induces a clique that contain the 2nd interface, + % but not the first. + % Hence we throw in the first interface as an extra. + stages = {1:ss, [1:ss]+ss}; + clusters(end+1:end+2) = {int, int+ss}; + engine.jtree_engine = jtree_inf_engine(bnet15, 'clusters', clusters, ... + 'stages', stages, 'root', int+ss); + end +end + +engine.in_clq = clq_containing_nodes(engine.jtree_engine, int); +engine.out_clq = clq_containing_nodes(engine.jtree_engine, int+ss); +engine.jtree_struct = struct(engine.jtree_engine); % violate object privacy + + +% 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.jtree_engine1 = jtree_inf_engine(bnet1, 'clusters', {int}, 'root', int); + +engine.in_clq1 = clq_containing_nodes(engine.jtree_engine1, int); +engine.jtree_struct1 = struct(engine.jtree_engine1); % violate object privacy + +% stuff needed by marginal_nodes +engine.clpot = []; +engine.T = []; + +engine = class(engine, 'jtree_dbn_inf_engine', inf_engine(bnet)); + diff --git a/sourcecodes/bnt-master/BNT/inference/dynamic/@jtree_dbn_inf_engine/marginal_family.m b/sourcecodes/bnt-master/BNT/inference/dynamic/@jtree_dbn_inf_engine/marginal_family.m new file mode 100644 index 00000000..1fe59f61 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/dynamic/@jtree_dbn_inf_engine/marginal_family.m @@ -0,0 +1,26 @@ +function m = marginal_family(engine, i, t, add_ev) +% MARGINAL_FAMILY Compute the marginal on the specified family (jtree_dbn) +% marginal = marginal_family(engine, i, t) + +% This is just like inf_engine/marginal_family, except when we call +% marginal_nodes, we provide a 4th argument, to tell it's a family. + +if nargin < 3, t = 1; end +if nargin < 4, add_ev = 0; end + +bnet = bnet_from_engine(engine); +if t==1 + m = marginal_nodes(engine, family(bnet.dag, i), t, add_ev, 1); +else + ss = length(bnet.intra); + fam = family(bnet.dag, i+ss); + if any(fam<=ss) + % i has a parent in the preceeding slice + % Hence the lowest numbered slice containing the family is t-1 + m = marginal_nodes(engine, fam, t-1, add_ev, 1); + else + % The family all fits inside slice t + % Hence shift the indexes back to slice 1 + m = marginal_nodes(engine, fam-ss, t, add_ev, 1); + end +end diff --git a/sourcecodes/bnt-master/BNT/inference/dynamic/@jtree_dbn_inf_engine/marginal_nodes.m b/sourcecodes/bnt-master/BNT/inference/dynamic/@jtree_dbn_inf_engine/marginal_nodes.m new file mode 100644 index 00000000..c9a40488 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/dynamic/@jtree_dbn_inf_engine/marginal_nodes.m @@ -0,0 +1,66 @@ +function marginal = marginal_nodes(engine, nodes, t, add_ev, fam) +% MARGINAL_NODES Compute the marginal on the specified query nodes (bk) +% +% marginal = marginal_nodes(engine, i, t) +% returns Pr(X(i,t) | Y(1:T)), where X(i,t) is the i'th node in the t'th slice. +% +% marginal = marginal_nodes(engine, query, t) +% returns Pr(X(query(1),t), ... X(query(end),t) | Y(1:T)), +% where 't' specifies the time slice of the earliest node in the query. +% 'query' cannot span more than 2 time slices. +% +% Example: +% Consider a DBN with 2 nodes per slice. +% Then t=2, nodes=[1 3] refers to node 1 in slice 2 and node 1 in slice 3. +% +% marginal = marginal_nodes(engine, nodes, t, add_ev, fam) +% add_ev is an optional argument; if 1, we will "inflate" the marginal of observed nodes +% to their original size, adding 0s to the positions which contradict the evidence + +if nargin < 3, t = 1; end +if nargin < 4, add_ev = 0; end +if nargin < 5, fam = 0; end + +bnet = bnet_from_engine(engine); +ss = length(bnet.intra); + +if t==1 | t==engine.T + slice = t; + nodes2 = nodes; +elseif mysubset(nodes, engine.persist) + slice = t-1; + nodes2 = nodes+ss; +else + slice = t; + nodes2 = nodes; +end + +%disp(['computing marginal on ' num2str(nodes) ' t = ' num2str(t) ' fam = ' num2str(fam)]); + +if t==engine.T + c = clq_containing_nodes(engine.jtree_engine1, nodes2, fam); +else + c = clq_containing_nodes(engine.jtree_engine, nodes2, fam); +end +if c == -1 + error(['no clique contains ' nodes2]) +end + + +%disp(['using ' num2str(nodes2) ' slice = ' num2str(slice) ' clq = ' num2str(c)]); + +bigpot = engine.clpot{c, slice}; + +pot = marginalize_pot(bigpot, nodes2, engine.maximize); +%pot = normalize_pot(pot); +marginal = pot_to_marginal(pot); + + +% we convert the domain to the unrolled numbering system +% so that add_ev_to_dmarginal (maybe called in update_ess) extracts the right evidence. +marginal.domain = nodes+(t-1)*ss; + +if add_ev + marginal = add_ev_to_dmarginal(marginal, engine.evidence, engine.node_sizes); +end + |
