diff options
Diffstat (limited to 'sourcecodes/bnt-master/BNT/inference/static/@jtree_inf_engine')
24 files changed, 679 insertions, 0 deletions
diff --git a/sourcecodes/bnt-master/BNT/inference/static/@jtree_inf_engine/CVS/Entries b/sourcecodes/bnt-master/BNT/inference/static/@jtree_inf_engine/CVS/Entries new file mode 100644 index 00000000..8a9c45e2 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@jtree_inf_engine/CVS/Entries @@ -0,0 +1,14 @@ +/cliques_from_engine.m/1.1.1.1/Wed May 29 15:59:56 2002// +/clq_containing_nodes.m/1.1.1.1/Wed May 29 15:59:56 2002// +/collect_evidence.m/1.1.1.1/Wed May 29 15:59:56 2002// +/distribute_evidence.m/1.1.1.1/Mon Jun 17 21:00:08 2002// +/enter_evidence.m/1.1.1.1/Mon Jun 17 20:59:30 2002// +/enter_soft_evidence.m/1.1.1.1/Wed May 29 15:59:56 2002// +/find_max_config.m/1.1.1.1/Mon Jun 17 23:14:52 2002// +/find_mpe.m/1.1.1.1/Mon Jun 17 23:14:08 2002// +/init_pot.m/1.1.1.1/Sun Jun 16 19:34:56 2002// +/jtree_inf_engine.m/1.1.1.1/Fri Oct 31 22:37:48 2003// +/marginal_family.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// +/set_fields.m/1.1.1.1/Wed May 29 15:59:56 2002// +D diff --git a/sourcecodes/bnt-master/BNT/inference/static/@jtree_inf_engine/CVS/Entries.Log b/sourcecodes/bnt-master/BNT/inference/static/@jtree_inf_engine/CVS/Entries.Log new file mode 100644 index 00000000..24f16336 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@jtree_inf_engine/CVS/Entries.Log @@ -0,0 +1 @@ +A D/Old//// diff --git a/sourcecodes/bnt-master/BNT/inference/static/@jtree_inf_engine/CVS/Repository b/sourcecodes/bnt-master/BNT/inference/static/@jtree_inf_engine/CVS/Repository new file mode 100644 index 00000000..c25f18d5 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@jtree_inf_engine/CVS/Repository @@ -0,0 +1 @@ +FullBNT/BNT/inference/static/@jtree_inf_engine diff --git a/sourcecodes/bnt-master/BNT/inference/static/@jtree_inf_engine/CVS/Root b/sourcecodes/bnt-master/BNT/inference/static/@jtree_inf_engine/CVS/Root new file mode 100644 index 00000000..f3bd14a6 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@jtree_inf_engine/CVS/Root @@ -0,0 +1 @@ +:ext:nsaunier@bnt.cvs.sourceforge.net:/cvsroot/bnt diff --git a/sourcecodes/bnt-master/BNT/inference/static/@jtree_inf_engine/Old/CVS/Entries b/sourcecodes/bnt-master/BNT/inference/static/@jtree_inf_engine/Old/CVS/Entries new file mode 100644 index 00000000..5d0e75e3 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@jtree_inf_engine/Old/CVS/Entries @@ -0,0 +1,5 @@ +/collect_evidence.m/1.1.1.1/Wed May 29 15:59:56 2002// +/distribute_evidence.m/1.1.1.1/Wed May 29 15:59:56 2002// +/enter_evidence.m/1.1.1.1/Wed May 29 15:59:56 2002// +/enter_soft_evidence.m/1.1.1.1/Wed May 29 15:59:56 2002// +D diff --git a/sourcecodes/bnt-master/BNT/inference/static/@jtree_inf_engine/Old/CVS/Repository b/sourcecodes/bnt-master/BNT/inference/static/@jtree_inf_engine/Old/CVS/Repository new file mode 100644 index 00000000..cf59323d --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@jtree_inf_engine/Old/CVS/Repository @@ -0,0 +1 @@ +FullBNT/BNT/inference/static/@jtree_inf_engine/Old diff --git a/sourcecodes/bnt-master/BNT/inference/static/@jtree_inf_engine/Old/CVS/Root b/sourcecodes/bnt-master/BNT/inference/static/@jtree_inf_engine/Old/CVS/Root new file mode 100644 index 00000000..f3bd14a6 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@jtree_inf_engine/Old/CVS/Root @@ -0,0 +1 @@ +:ext:nsaunier@bnt.cvs.sourceforge.net:/cvsroot/bnt diff --git a/sourcecodes/bnt-master/BNT/inference/static/@jtree_inf_engine/Old/collect_evidence.m b/sourcecodes/bnt-master/BNT/inference/static/@jtree_inf_engine/Old/collect_evidence.m new file mode 100644 index 00000000..2f7757f1 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@jtree_inf_engine/Old/collect_evidence.m @@ -0,0 +1,29 @@ +function engine = collect_evidence(engine, root) + +if isempty(engine.postorder{root}) + % this is the first time we have collected to this root + % memoize the order + [jtree, preorder, postorder] = mk_rooted_tree(engine.jtree, root); + postorder_parents = cell(1,length(postorder)); + for n=postorder(1:end-1) + postorder_parents{n} = parents(jtree, n); + end + engine.postorder{root} = postorder; + engine.postorder_parents{root} = postorder_parents; +else + postorder = engine.postorder{root}; + postorder_parents = engine.postorder_parents{root}; +end + +C = length(engine.clpot); +seppot = cell(C, C); +% separators are implicitely initialized to 1s + +% collect to root (node to parents) +for n=postorder(1:end-1) + for p=postorder_parents{n} + %clpot{p} = divide_by_pot(clpot{n}, seppot{p,n}); % dividing by 1 is redundant + engine.seppot{p,n} = marginalize_pot(engine.clpot{n}, engine.separator{p,n}, engine.maximize); + engine.clpot{p} = multiply_by_pot(engine.clpot{p}, engine.seppot{p,n}); + end +end diff --git a/sourcecodes/bnt-master/BNT/inference/static/@jtree_inf_engine/Old/distribute_evidence.m b/sourcecodes/bnt-master/BNT/inference/static/@jtree_inf_engine/Old/distribute_evidence.m new file mode 100644 index 00000000..f8d78be4 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@jtree_inf_engine/Old/distribute_evidence.m @@ -0,0 +1,26 @@ +function engine = distribute_evidence(engine, root) + +if isempty(engine.preorder{root}) + % this is the first time we have distributed from this root + % memoize the order + [jtree, preorder, postorder] = mk_rooted_tree(engine.jtree, root); + preorder_children = cell(1,length(preorder)); + for n=preorder + preorder_children{n} = children(jtree, n); + end + engine.preorder{root} = preorder; + engine.preorder_children{root} = preorder_children; +else + preorder = engine.preorder{root}; + preorder_children = engine.preorder_children{root}; +end + + +% distribute from root (node to children) +for n=preorder(:)' + for c=preorder_children{n}(:)' + engine.clpot{c} = divide_by_pot(engine.clpot{c}, engine.seppot{n,c}); + engine.seppot{n,c} = marginalize_pot(engine.clpot{n}, engine.separator{n,c}, engine.maximize); + engine.clpot{c} = multiply_by_pot(engine.clpot{c}, engine.seppot{n,c}); + end +end diff --git a/sourcecodes/bnt-master/BNT/inference/static/@jtree_inf_engine/Old/enter_evidence.m b/sourcecodes/bnt-master/BNT/inference/static/@jtree_inf_engine/Old/enter_evidence.m new file mode 100644 index 00000000..aafeeecb --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@jtree_inf_engine/Old/enter_evidence.m @@ -0,0 +1,107 @@ +function [engine, loglik] = enter_evidence(engine, evidence, varargin) +% ENTER_EVIDENCE Add the specified evidence to the network (jtree) +% [engine, loglik] = enter_evidence(engine, evidence, ...) +% +% evidence{i} = [] if X(i) 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 [0] +% soft - a cell array of soft/virtual evidence; +% soft{i} is a prob. distrib. over i's values, or [] [ cell(1,N) ] +% +% e.g., engine = enter_evidence(engine, ev, 'soft', soft_ev) +% +% For backwards compatibility with BNT2, you can also specify the parameters in the following order +% engine = enter_evidence(engine, ev, soft_ev) + +bnet = bnet_from_engine(engine); +ns = bnet.node_sizes(:); +N = length(bnet.dag); + +% set default params +exclude = []; +soft_evidence = cell(1,N); +maximize = 0; + +% parse optional params +args = varargin; +nargs = length(args); +if nargs > 0 + if iscell(args{1}) + soft_evidence = args{1}; + else + for i=1:2:nargs + switch args{i}, + case 'soft', soft_evidence = args{i+1}; + case 'maximize', maximize = args{i+1}; + otherwise, + error(['invalid argument name ' args{i}]); + end + end + end +end + +engine.maximize = maximize; + +onodes = find(~isemptycell(evidence)); +hnodes = find(isemptycell(evidence)); +pot_type = determine_pot_type(bnet, onodes); + if strcmp(pot_type, 'cg') + check_for_cd_arcs(onodes, bnet.cnodes, bnet.dag); +end + + +hard_nodes = 1:N; +soft_nodes = find(~isemptycell(soft_evidence)); +S = length(soft_nodes); +if S > 0 + assert(pot_type == 'd'); + assert(mysubset(soft_nodes, bnet.dnodes)); +end + +% Evaluate CPDs with evidence, and convert to potentials +pot = cell(1, N+S); +for n=1:N + fam = family(bnet.dag, n); + e = bnet.equiv_class(n); + pot{n} = convert_to_pot(bnet.CPD{e}, pot_type, fam(:), evidence); +end + +for i=1:S + n = soft_nodes(i); + pot{N+i} = dpot(n, ns(n), soft_evidence{n}); +end + +%clqs = engine.clq_ass_to_node([hard_nodes soft_nodes]); +%[clpot, loglik] = enter_soft_evidence(engine, clqs, pot, onodes, pot_type); +%engine.clpot = clpot; % save the results for marginal_nodes + + +clique = engine.clq_ass_to_node([hard_nodes soft_nodes]); +potential = pot; + + +% Set the clique potentials to all 1s +C = length(engine.cliques); +for i=1:C + engine.clpot{i} = mk_initial_pot(pot_type, engine.cliques{i}, ns, bnet.cnodes, onodes); +end + +% Multiply on specified potentials +for i=1:length(clique) + c = clique(i); + engine.clpot{c} = multiply_by_pot(engine.clpot{c}, potential{i}); +end + +root = 1; % arbitrary +engine = collect_evidence(engine, root); +engine = distribute_evidence(engine, root); + +ll = zeros(1, C); +for i=1:C + [engine.clpot{i}, ll(i)] = normalize_pot(engine.clpot{i}); +end +loglik = ll(1); % we can extract the likelihood from any clique + diff --git a/sourcecodes/bnt-master/BNT/inference/static/@jtree_inf_engine/Old/enter_soft_evidence.m b/sourcecodes/bnt-master/BNT/inference/static/@jtree_inf_engine/Old/enter_soft_evidence.m new file mode 100644 index 00000000..59671415 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@jtree_inf_engine/Old/enter_soft_evidence.m @@ -0,0 +1,19 @@ +function [clpot, loglik] = enter_soft_evidence(engine, clique, potential, onodes, pot_type) +% ENTER_SOFT_EVIDENCE Add the specified potentials to the network (jtree) +% [clpot, loglik] = enter_soft_evidence(engine, clique, potential, onodes, pot_type, maximize) +% +% We multiply potential{i} onto clique(i) before propagating. +% We return all the modified clique potentials. + +[clpot, seppot] = init_pot(engine, clique, potential, pot_type, onodes); +[clpot, seppot] = collect_evidence(engine, clpot, seppot); +[clpot, seppot] = distribute_evidence(engine, clpot, seppot); + +C = length(clpot); +ll = zeros(1, C); +for i=1:C + [clpot{i}, ll(i)] = normalize_pot(clpot{i}); +end +loglik = ll(1); % we can extract the likelihood from any clique + + diff --git a/sourcecodes/bnt-master/BNT/inference/static/@jtree_inf_engine/cliques_from_engine.m b/sourcecodes/bnt-master/BNT/inference/static/@jtree_inf_engine/cliques_from_engine.m new file mode 100644 index 00000000..cd9d871d --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@jtree_inf_engine/cliques_from_engine.m @@ -0,0 +1,5 @@ +function cliques = cliques_from_engine(engine) +% CLIQUES_FROM_ENGINE Return the cliques stored inside the inf. engine (jtree) +% cliques = cliques_from_engine(engine) + +cliques = engine.cliques; diff --git a/sourcecodes/bnt-master/BNT/inference/static/@jtree_inf_engine/clq_containing_nodes.m b/sourcecodes/bnt-master/BNT/inference/static/@jtree_inf_engine/clq_containing_nodes.m new file mode 100644 index 00000000..8904fa49 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@jtree_inf_engine/clq_containing_nodes.m @@ -0,0 +1,24 @@ +function c = clq_containing_nodes(engine, nodes, fam) +% CLQ_CONTAINING_NODES Find the lightest clique (if any) that contains the set of nodes +% c = clq_containing_nodes(engine, nodes, family) +% +% If the optional 'family' argument is specified, it means nodes = family(nodes(end)). +% (This is useful since clq_ass_to_node is not accessible to outsiders.) +% Returns c=-1 if there is no such clique. + +if nargin < 3, fam = 0; else fam = 1; end + +if length(nodes)==1 + c = engine.clq_ass_to_node(nodes(1)); +%elseif fam +% c = engine.clq_ass_to_node(nodes(end)); +else + B = engine.cliques_bitv; + w = engine.clique_weight; + clqs = find(all(B(:,nodes), 2)); % all selected columns must be 1 + if isempty(clqs) + c = -1; + else + c = clqs(argmin(w(clqs))); + end +end diff --git a/sourcecodes/bnt-master/BNT/inference/static/@jtree_inf_engine/collect_evidence.m b/sourcecodes/bnt-master/BNT/inference/static/@jtree_inf_engine/collect_evidence.m new file mode 100644 index 00000000..03c00edf --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@jtree_inf_engine/collect_evidence.m @@ -0,0 +1,12 @@ +function [clpot, seppot] = collect_evidence(engine, clpot, seppot) +% COLLECT_EVIDENCE Do message passing from leaves to root (children then parents) +% [clpot, seppot] = collect_evidence(engine, clpot, seppot) + +for n=engine.postorder %postorder(1:end-1) + for p=engine.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}, engine.separator{p,n}, engine.maximize); + clpot{p} = multiply_by_pot(clpot{p}, seppot{p,n}); + end +end + diff --git a/sourcecodes/bnt-master/BNT/inference/static/@jtree_inf_engine/distribute_evidence.m b/sourcecodes/bnt-master/BNT/inference/static/@jtree_inf_engine/distribute_evidence.m new file mode 100644 index 00000000..403b8970 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@jtree_inf_engine/distribute_evidence.m @@ -0,0 +1,11 @@ +function [clpot, seppot] = distribute_evidence(engine, clpot, seppot) +% DISTRIBUTE_EVIDENCE Do message passing from root to leaves (parents then children) +% [clpot, seppot] = distribute_evidence(engine, clpot, seppot) + +for n=engine.preorder + for c=engine.preorder_children{n} + clpot{c} = divide_by_pot(clpot{c}, seppot{n,c}); + seppot{n,c} = marginalize_pot(clpot{n}, engine.separator{n,c}, engine.maximize); + clpot{c} = multiply_by_pot(clpot{c}, seppot{n,c}); + end +end diff --git a/sourcecodes/bnt-master/BNT/inference/static/@jtree_inf_engine/enter_evidence.m b/sourcecodes/bnt-master/BNT/inference/static/@jtree_inf_engine/enter_evidence.m new file mode 100644 index 00000000..c85d03a7 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@jtree_inf_engine/enter_evidence.m @@ -0,0 +1,88 @@ +function [engine, loglik] = enter_evidence(engine, evidence, varargin) +% ENTER_EVIDENCE Add the specified evidence to the network (jtree) +% [engine, loglik] = enter_evidence(engine, evidence, ...) +% +% evidence{i} = [] if X(i) 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] +% +% soft - a cell array of soft/virtual evidence; +% soft{i} is a prob. distrib. over i's values, or [] [ cell(1,N) ] +% +% e.g., engine = enter_evidence(engine, ev, 'soft', soft_ev) + +bnet = bnet_from_engine(engine); +ns = bnet.node_sizes(:); +N = length(bnet.dag); + +engine.evidence = evidence; % store this for marginal_nodes with add_ev option +engine.maximize = 0; + +% set default params +exclude = []; +soft_evidence = cell(1,N); + +% parse optional params +args = varargin; +nargs = length(args); +for i=1:2:nargs + switch args{i}, + case 'soft', soft_evidence = args{i+1}; + case 'maximize', engine.maximize = args{i+1}; + otherwise, + error(['invalid argument name ' args{i}]); + end +end + +onodes = find(~isemptycell(evidence)); +hnodes = find(isemptycell(evidence)); +pot_type = determine_pot_type(bnet, onodes); + if strcmp(pot_type, 'cg') + check_for_cd_arcs(onodes, bnet.cnodes, bnet.dag); +end + +if is_mnet(bnet) + pot = engine.user_pot; + clqs = engine.nums_ass_to_user_clqs; +else + % Evaluate CPDs with evidence, and convert to potentials + pot = cell(1, N); + for n=1:N + fam = family(bnet.dag, n); + e = bnet.equiv_class(n); + if isempty(bnet.CPD{e}) + error(['must define CPD ' num2str(e)]) + else + pot{n} = convert_to_pot(bnet.CPD{e}, pot_type, fam(:), evidence); + end + end + clqs = engine.clq_ass_to_node(1:N); +end + +% soft evidence +soft_nodes = find(~isemptycell(soft_evidence)); +S = length(soft_nodes); +if S > 0 + assert(pot_type == 'd'); + assert(mysubset(soft_nodes, bnet.dnodes)); +end +for i=1:S + n = soft_nodes(i); + pot{end+1} = dpot(n, ns(n), soft_evidence{n}); +end +clqs = [clqs engine.clq_ass_to_node(soft_nodes)]; + + +[clpot, seppot] = init_pot(engine, clqs, pot, pot_type, onodes); +[clpot, seppot] = collect_evidence(engine, clpot, seppot); +[clpot, seppot] = distribute_evidence(engine, clpot, seppot); + +C = length(clpot); +ll = zeros(1, C); +for i=1:C + [clpot{i}, ll(i)] = normalize_pot(clpot{i}); +end +loglik = ll(1); % we can extract the likelihood from any clique + +engine.clpot = clpot; diff --git a/sourcecodes/bnt-master/BNT/inference/static/@jtree_inf_engine/enter_soft_evidence.m b/sourcecodes/bnt-master/BNT/inference/static/@jtree_inf_engine/enter_soft_evidence.m new file mode 100644 index 00000000..0a4346c6 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@jtree_inf_engine/enter_soft_evidence.m @@ -0,0 +1,21 @@ +function [clpot, loglik] = enter_soft_evidence(engine, clique, potential, onodes, pot_type) +% ENTER_SOFT_EVIDENCE Add the specified potentials to the network (jtree) +% [clpot, loglik] = enter_soft_evidence(engine, clique, potential, onodes, pot_type, maximize) +% +% We multiply potential{i} onto clique(i) before propagating. +% We return all the modified clique potentials. + +% only used by BK! + +[clpot, seppot] = init_pot(engine, clique, potential, pot_type, onodes); +[clpot, seppot] = collect_evidence(engine, clpot, seppot); +[clpot, seppot] = distribute_evidence(engine, clpot, seppot); + +C = length(clpot); +ll = zeros(1, C); +for i=1:C + [clpot{i}, ll(i)] = normalize_pot(clpot{i}); +end +loglik = ll(1); % we can extract the likelihood from any clique + + diff --git a/sourcecodes/bnt-master/BNT/inference/static/@jtree_inf_engine/find_max_config.m b/sourcecodes/bnt-master/BNT/inference/static/@jtree_inf_engine/find_max_config.m new file mode 100644 index 00000000..5053b1e8 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@jtree_inf_engine/find_max_config.m @@ -0,0 +1,35 @@ +function [mpe, clpot, seppot] = find_max_config(engine, clpot, seppot, evidence) +% FIND_MAX_CONFIG Backwards pass of Viterbi fro jtree +% function [mpe, clpot, seppot] = find_max_config(engine, clpot, seppot, evidence) +% See Cowell99 p98 + +bnet = bnet_from_engine(engine); +nnodes = length(bnet.dag); +mpe = cell(1, nnodes); +maximize = 1; + +c = engine.root_clq; +pot = struct(clpot{c}); % violate object privacy +dom = pot.domain; +[indices, clpot{c}] = find_most_prob_entry(clpot{c}); +mpe(dom) = num2cell(indices); + +for n=engine.preorder + for c=engine.preorder_children{n} + clpot{c} = divide_by_pot(clpot{c}, seppot{n,c}); + seppot{n,c} = marginalize_pot(clpot{n}, engine.separator{n,c}, maximize); + clpot{c} = multiply_by_pot(clpot{c}, seppot{n,c}); + + pot = struct(clpot{c}); % violate object privacy + dom = pot.domain; + [indices, clpot{c}] = find_most_prob_entry(clpot{c}); + mpe(dom) = num2cell(indices); + end +end + +obs_nodes = find(~isemptycell(evidence)); +% indices for observed nodes will be 1 - need to overwrite these +mpe(obs_nodes) = evidence(obs_nodes); + + + diff --git a/sourcecodes/bnt-master/BNT/inference/static/@jtree_inf_engine/find_mpe.m b/sourcecodes/bnt-master/BNT/inference/static/@jtree_inf_engine/find_mpe.m new file mode 100644 index 00000000..8a46c1ed --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@jtree_inf_engine/find_mpe.m @@ -0,0 +1,71 @@ +function mpe = find_mpe(engine, evidence, varargin) +% FIND_MPE Find the most probable explanation of the data (assignment to the hidden nodes) +% function mpe = find_mpe(engine, evidence,...) +% +% evidence{i} = [] if X(i) 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] +% +% soft - a cell array of soft/virtual evidence; +% soft{i} is a prob. distrib. over i's values, or [] [ cell(1,N) ] +% + +bnet = bnet_from_engine(engine); +ns = bnet.node_sizes(:); +N = length(bnet.dag); + +engine.evidence = evidence; + +% set default params +exclude = []; +soft_evidence = cell(1,N); + +% parse optional params +args = varargin; +nargs = length(args); +for i=1:2:nargs + switch args{i}, + case 'soft', soft_evidence = args{i+1}; + otherwise, + error(['invalid argument name ' args{i}]); + end +end +engine.maximize = 1; + +onodes = find(~isemptycell(evidence)); +hnodes = find(isemptycell(evidence)); +pot_type = determine_pot_type(bnet, onodes); + if strcmp(pot_type, 'cg') + check_for_cd_arcs(onodes, bnet.cnodes, bnet.dag); +end + +hard_nodes = 1:N; +soft_nodes = find(~isemptycell(soft_evidence)); +S = length(soft_nodes); +if S > 0 + assert(pot_type == 'd'); + assert(mysubset(soft_nodes, bnet.dnodes)); +end + +% Evaluate CPDs with evidence, and convert to potentials +pot = cell(1, N+S); +for n=1:N + fam = family(bnet.dag, n); + e = bnet.equiv_class(n); + if isempty(bnet.CPD{e}) + error(['must define CPD ' num2str(e)]) + else + pot{n} = convert_to_pot(bnet.CPD{e}, pot_type, fam(:), evidence); + end +end + +for i=1:S + n = soft_nodes(i); + pot{N+i} = dpot(n, ns(n), soft_evidence{n}); +end +clqs = engine.clq_ass_to_node([hard_nodes soft_nodes]); + +[clpot, seppot] = init_pot(engine, clqs, pot, pot_type, onodes); +[clpot, seppot] = collect_evidence(engine, clpot, seppot); +mpe = find_max_config(engine, clpot, seppot, evidence); % instead of distribute evidence diff --git a/sourcecodes/bnt-master/BNT/inference/static/@jtree_inf_engine/init_pot.m b/sourcecodes/bnt-master/BNT/inference/static/@jtree_inf_engine/init_pot.m new file mode 100644 index 00000000..857e6266 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@jtree_inf_engine/init_pot.m @@ -0,0 +1,20 @@ +function [clpot, seppot] = init_pot(engine, clqs, pots, pot_type, onodes, ndx) +% INIT_POT Initialise potentials with evidence (jtree_inf) +% function [clpot, seppot] = init_pot(engine, clqs, pots, pot_type, onodes) + +cliques = engine.cliques; +bnet = bnet_from_engine(engine); +% 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}, bnet.node_sizes(:), bnet.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 diff --git a/sourcecodes/bnt-master/BNT/inference/static/@jtree_inf_engine/jtree_inf_engine.m b/sourcecodes/bnt-master/BNT/inference/static/@jtree_inf_engine/jtree_inf_engine.m new file mode 100644 index 00000000..dd744dc0 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@jtree_inf_engine/jtree_inf_engine.m @@ -0,0 +1,141 @@ +function engine = jtree_inf_engine(bnet, varargin) +% JTREE_INF_ENGINE Junction tree inference engine +% engine = jtree_inf_engine(bnet, ...) +% +% The following optional arguments can be specified in the form of name/value pairs: +% [default value in brackets] +% +% clusters - a cell array of sets of nodes we want to ensure are in the same clique (in addition to families) [ {} ] +% root - the root of the junction tree will be a clique that contains this set of nodes [N] +% stages - stages{t} is a set of nodes we want to eliminate before stages{t+1}, ... [ {1:N} ] +% +% e.g., engine = jtree_inf_engine(bnet, 'maximize', 1); +% +% For more details on the junction tree algorithm, see +% - "Probabilistic networks and expert systems", Cowell, Dawid, Lauritzen and Spiegelhalter, Springer, 1999 +% - "Inference in Belief Networks: A procedural guide", C. Huang and A. Darwiche, +% Intl. J. Approximate Reasoning, 15(3):225-263, 1996. + + +% set default params +N = length(bnet.dag); +clusters = {}; +root = N; +stages = { 1:N }; +maximize = 0; + +if nargin >= 2 + args = varargin; + nargs = length(args); + if ~isstr(args{1}) + error('the interface to jtree has changed; now, onodes is not allowed and all optional params must be passed by name') + end + for i=1:2:nargs + switch args{i}, + case 'clusters', clusters = args{i+1}; + case 'root', root = args{i+1}; + case 'stages', stages = args{i+1}; + case 'maximize', maximize = args{i+1}; + otherwise, + error(['invalid argument name ' args{i}]); + end + end +end + +engine = init_fields; +engine = class(engine, 'jtree_inf_engine', inf_engine(bnet)); + +engine.maximize = maximize; + +onodes = bnet.observed; + +%[engine.jtree, dummy, engine.cliques, B, w, elim_order, moral_edges, fill_in_edges, strong] = ... +% dag_to_jtree(bnet, onodes, stages, clusters); + +porder = determine_elim_constraints(bnet, onodes); +strong = ~isempty(porder); +ns = bnet.node_sizes(:); +ns(onodes) = 1; % observed nodes have only 1 possible value +[engine.jtree, root2, engine.cliques, B, w] = ... + graph_to_jtree(moralize(bnet.dag), ns, porder, stages, clusters); + + +engine.cliques_bitv = B; +engine.clique_weight = w; +C = length(engine.cliques); +engine.clpot = cell(1,C); + +% Compute the separators between connected cliques. +[is,js] = find(engine.jtree > 0); +engine.separator = cell(C,C); +for k=1:length(is) + i = is(k); j = js(k); + engine.separator{i,j} = find(B(i,:) & B(j,:)); % intersect(cliques{i}, cliques{j}); +end + +% A node can be a member of many cliques, but is assigned to exactly one, to avoid +% double-counting its CPD. We assign node i to clique c if c is the "lightest" clique that +% contains i's family, so it can accomodate its CPD. + +engine.clq_ass_to_node = zeros(1, N); +for i=1:N + %c = clq_containing_nodes(engine, family(bnet.dag, i)); + clqs_containing_family = find(all(B(:,family(bnet.dag, i)), 2)); % all selected columns must be 1 + c = clqs_containing_family(argmin(w(clqs_containing_family))); + engine.clq_ass_to_node(i) = c; +end + +% Make the jtree rooted, so there is a fixed message passing order. +if strong + % the last clique is guaranteed to be a strong root + % engine.root_clq = length(engine.cliques); + + % --- 4/17/2010, by Wei Sun (George Mason University): + % It has been proved that the last clique is not necessary to be the + % strong root, instead, a clique called interface clique, that contains + % all discrete parents and at least one continuous node from a connected + % continuous component in a CLG, is guaranteed to be a strong root. + engine.root_clq = findroot(bnet, engine.cliques) ; +else + % jtree_dbn_inf_engine requires the root to contain the interface. + % This may conflict with the strong root requirement! *********** BUG ************* + engine.root_clq = clq_containing_nodes(engine, root); + if engine.root_clq <= 0 + error(['no clique contains ' num2str(root)]); + end +end + +[engine.jtree, engine.preorder, engine.postorder] = mk_rooted_tree(engine.jtree, engine.root_clq); + +% collect +engine.postorder_parents = cell(1,length(engine.postorder)); +for n=engine.postorder(:)' + engine.postorder_parents{n} = parents(engine.jtree, n); +end +% distribute +engine.preorder_children = cell(1,length(engine.preorder)); +for n=engine.preorder(:)' + engine.preorder_children{n} = children(engine.jtree, n); +end + + + +%%%%%%%% + +function engine = init_fields() + +engine.jtree = []; +engine.cliques = []; +engine.separator = []; +engine.cliques_bitv = []; +engine.clique_weight = []; +engine.clpot = []; +engine.clq_ass_to_node = []; +engine.root_clq = []; +engine.preorder = []; +engine.postorder = []; +engine.preorder_children = []; +engine.postorder_parents = []; +engine.maximize = []; +engine.evidence = []; + diff --git a/sourcecodes/bnt-master/BNT/inference/static/@jtree_inf_engine/marginal_family.m b/sourcecodes/bnt-master/BNT/inference/static/@jtree_inf_engine/marginal_family.m new file mode 100644 index 00000000..eff60ca2 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@jtree_inf_engine/marginal_family.m @@ -0,0 +1,11 @@ +function marginal = marginal_family(engine, i, add_ev) +% MARGINAL_FAMILY Compute the marginal on the specified family (jtree) +% marginal = marginal_family(engine, i) + +if nargin < 3, add_ev = 0; end +assert(~add_ev); + +bnet = bnet_from_engine(engine); +fam = family(bnet.dag, i); +c = engine.clq_ass_to_node(i); +marginal = pot_to_marginal(marginalize_pot(engine.clpot{c}, fam)); diff --git a/sourcecodes/bnt-master/BNT/inference/static/@jtree_inf_engine/marginal_nodes.m b/sourcecodes/bnt-master/BNT/inference/static/@jtree_inf_engine/marginal_nodes.m new file mode 100644 index 00000000..6413172c --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@jtree_inf_engine/marginal_nodes.m @@ -0,0 +1,22 @@ +function marginal = marginal_nodes(engine, query, add_ev) +% MARGINAL_NODES Compute the marginal on the specified query nodes (jtree) +% marginal = marginal_nodes(engine, query, add_ev) +% +% 'query' must be a subset of some clique; an error will be raised if not. +% 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, add_ev = 0; end + +c = clq_containing_nodes(engine, query); +if c == -1 + error(['no clique contains ' num2str(query)]); +end +marginal = pot_to_marginal(marginalize_pot(engine.clpot{c}, query, engine.maximize)); + +if add_ev + bnet = bnet_from_engine(engine); + %marginal = add_ev_to_dmarginal(marginal, engine.evidence, bnet.node_sizes); + marginal = add_evidence_to_gmarginal(marginal, engine.evidence, bnet.node_sizes, bnet.cnodes); +end + diff --git a/sourcecodes/bnt-master/BNT/inference/static/@jtree_inf_engine/set_fields.m b/sourcecodes/bnt-master/BNT/inference/static/@jtree_inf_engine/set_fields.m new file mode 100644 index 00000000..e75cfa45 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@jtree_inf_engine/set_fields.m @@ -0,0 +1,13 @@ +function engine = set_fields(engine, varargin) +% SET_FIELDS Set the fields for a generic engine +% engine = set_fields(engine, name/value pairs) +% +% e.g., engine = set_fields(engine, 'maximize', 1) + +args = varargin; +nargs = length(args); +for i=1:2:nargs + switch args{i}, + case 'maximize', engine.maximize = args{i+1}; + end +end |
